diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 7 | ||||
-rw-r--r-- | common/cmd_bdinfo.c | 10 | ||||
-rw-r--r-- | common/cmd_dfu.c | 81 | ||||
-rw-r--r-- | common/cmd_ext2.c | 219 | ||||
-rw-r--r-- | common/cmd_ext4.c | 237 | ||||
-rw-r--r-- | common/cmd_ext_common.c | 259 | ||||
-rw-r--r-- | common/cmd_fdt.c | 13 | ||||
-rw-r--r-- | common/cmd_flash.c | 3 | ||||
-rw-r--r-- | common/cmd_mmc.c | 3 | ||||
-rw-r--r-- | common/cmd_nand.c | 25 | ||||
-rw-r--r-- | common/cmd_nvedit.c | 194 | ||||
-rw-r--r-- | common/cmd_spi.c | 2 | ||||
-rw-r--r-- | common/dlmalloc.c | 10 | ||||
-rw-r--r-- | common/env_common.c | 39 | ||||
-rw-r--r-- | common/env_mmc.c | 64 | ||||
-rw-r--r-- | common/env_nand.c | 10 | ||||
-rw-r--r-- | common/flash.c | 3 | ||||
-rw-r--r-- | common/hush.c | 107 | ||||
-rw-r--r-- | common/image.c | 7 | ||||
-rw-r--r-- | common/usb_hub.c | 14 | ||||
-rw-r--r-- | common/usb_storage.c | 58 |
21 files changed, 1022 insertions, 343 deletions
diff --git a/common/Makefile b/common/Makefile index 3d62775dc0..22e8a6fb35 100644 --- a/common/Makefile +++ b/common/Makefile @@ -86,7 +86,13 @@ COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o +COBJS-$(CONFIG_CMD_EXT4) += cmd_ext4.o COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o +ifdef CONFIG_CMD_EXT4 +COBJS-y += cmd_ext_common.o +else +COBJS-$(CONFIG_CMD_EXT2) += cmd_ext_common.o +endif COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o @@ -184,6 +190,7 @@ COBJS-$(CONFIG_MENU) += menu.o COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o +COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o endif ifdef CONFIG_SPL_BUILD diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 42f08fdd0d..23bd8a5098 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -216,15 +216,15 @@ int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) print_num("flashstart ", bd->bi_flashstart); print_num("CONFIG_SYS_MONITOR_BASE ", CONFIG_SYS_MONITOR_BASE); print_num("CONFIG_ENV_ADDR ", CONFIG_ENV_ADDR); - printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%lx (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, + printf("CONFIG_SYS_RELOC_MONITOR_BASE = 0x%x (%d)\n", CONFIG_SYS_RELOC_MONITOR_BASE, CONFIG_SYS_MONITOR_LEN); - printf("CONFIG_SYS_MALLOC_BASE = 0x%lx (%d)\n", CONFIG_SYS_MALLOC_BASE, + printf("CONFIG_SYS_MALLOC_BASE = 0x%x (%d)\n", CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN); - printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, + printf("CONFIG_SYS_INIT_SP_OFFSET = 0x%x (%d)\n", CONFIG_SYS_INIT_SP_OFFSET, CONFIG_SYS_STACK_SIZE); - printf("CONFIG_SYS_PROM_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_PROM_OFFSET, + printf("CONFIG_SYS_PROM_OFFSET = 0x%x (%d)\n", CONFIG_SYS_PROM_OFFSET, CONFIG_SYS_PROM_SIZE); - printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%lx (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, + printf("CONFIG_SYS_GBL_DATA_OFFSET = 0x%x (%d)\n", CONFIG_SYS_GBL_DATA_OFFSET, GENERATED_GBL_DATA_SIZE); #if defined(CONFIG_CMD_NET) diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c new file mode 100644 index 0000000000..62fb8904cf --- /dev/null +++ b/common/cmd_dfu.c @@ -0,0 +1,81 @@ +/* + * cmd_dfu.c -- dfu command + * + * Copyright (C) 2012 Samsung Electronics + * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> + * Lukasz Majewski <l.majewski@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <dfu.h> +#include <asm/errno.h> +#include <g_dnl.h> + +static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *str_env; + char s[] = "dfu"; + char *env_bkp; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + + str_env = getenv("dfu_alt_info"); + if (str_env == NULL) { + printf("%s: \"dfu_alt_info\" env variable not defined!\n", + __func__); + return CMD_RET_FAILURE; + } + + env_bkp = strdup(str_env); + ret = dfu_config_entities(env_bkp, argv[1], + (int)simple_strtoul(argv[2], NULL, 10)); + if (ret) + return CMD_RET_FAILURE; + + if (strcmp(argv[3], "list") == 0) { + dfu_show_entities(); + goto done; + } + + board_usb_init(); + g_dnl_register(s); + while (1) { + if (ctrlc()) + goto exit; + + usb_gadget_handle_interrupts(); + } +exit: + g_dnl_unregister(); +done: + dfu_free_entities(); + free(env_bkp); + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, + "Device Firmware Upgrade", + "<interface> <dev> [list]\n" + " - device firmware upgrade on a device <dev>\n" + " attached to interface <interface>\n" + " [list] - list available alt settings" +); diff --git a/common/cmd_ext2.c b/common/cmd_ext2.c index 79b1e2fb62..c27d9c7ede 100644 --- a/common/cmd_ext2.c +++ b/common/cmd_ext2.c @@ -1,4 +1,9 @@ /* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * (C) Copyright 2004 * esd gmbh <www.esd-electronics.com> * Reinhard Arlt <reinhard.arlt@esd-electronics.com> @@ -33,225 +38,35 @@ * Ext2fs support */ #include <common.h> -#include <part.h> -#include <config.h> -#include <command.h> -#include <image.h> -#include <linux/ctype.h> -#include <asm/byteorder.h> -#include <ext2fs.h> -#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) -#include <usb.h> -#endif - -#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION) -#error DOS or EFI partition support must be selected -#endif - -/* #define EXT2_DEBUG */ - -#ifdef EXT2_DEBUG -#define PRINTF(fmt,args...) printf (fmt ,##args) -#else -#define PRINTF(fmt,args...) -#endif +#include <ext_common.h> int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = "/"; - int dev=0; - int part=1; - char *ep; - block_dev_desc_t *dev_desc=NULL; - int part_length; - - if (argc < 3) - return CMD_RET_USAGE; - - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - - if (dev_desc == NULL) { - printf ("\n** Block device %s %d not supported\n", argv[1], dev); - return 1; - } - - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - if (argc == 4) - filename = argv[3]; - - PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename); - - if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (!ext2fs_mount(part_length)) { - printf ("** Bad ext2 partition or disk - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (ext2fs_ls (filename)) { - printf ("** Error ext2fs_ls() **\n"); - ext2fs_close(); - return 1; - }; - - ext2fs_close(); + if (do_ext_ls(cmdtp, flag, argc, argv)) + return -1; return 0; } -U_BOOT_CMD( - ext2ls, 4, 1, do_ext2ls, - "list files in a directory (default /)", - "<interface> <dev[:part]> [directory]\n" - " - list files from 'dev' on 'interface' in a 'directory'" -); - /****************************************************************************** * Ext2fs boot command intepreter. Derived from diskboot */ int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = NULL; - char *ep; - int dev, part = 1; - ulong addr = 0, part_length; - int filelen; - disk_partition_t info; - block_dev_desc_t *dev_desc = NULL; - char buf [12]; - unsigned long count; - char *addr_str; - - switch (argc) { - case 3: - addr_str = getenv("loadaddr"); - if (addr_str != NULL) - addr = simple_strtoul (addr_str, NULL, 16); - else - addr = CONFIG_SYS_LOAD_ADDR; - - filename = getenv ("bootfile"); - count = 0; - break; - case 4: - addr = simple_strtoul (argv[3], NULL, 16); - filename = getenv ("bootfile"); - count = 0; - break; - case 5: - addr = simple_strtoul (argv[3], NULL, 16); - filename = argv[4]; - count = 0; - break; - case 6: - addr = simple_strtoul (argv[3], NULL, 16); - filename = argv[4]; - count = simple_strtoul (argv[5], NULL, 16); - break; - - default: - return CMD_RET_USAGE; - } - - if (!filename) { - puts ("** No boot file defined **\n"); - return 1; - } - - dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc==NULL) { - printf ("** Block device %s %d not supported\n", argv[1], dev); - return 1; - } - if (*ep) { - if (*ep != ':') { - puts ("** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part); - - if (part != 0) { - if (get_partition_info (dev_desc, part, &info)) { - printf ("** Bad partition %d **\n", part); - return 1; - } - - if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { - printf ("** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - printf ("Loading file \"%s\" " - "from %s device %d:%d (%.32s)\n", - filename, - argv[1], dev, part, info.name); - } else { - printf ("Loading file \"%s\" from %s device %d\n", - filename, argv[1], dev); - } - - - if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { - printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part); - ext2fs_close(); - return 1; - } - - if (!ext2fs_mount(part_length)) { - printf ("** Bad ext2 partition or disk - %s %d:%d **\n", - argv[1], dev, part); - ext2fs_close(); - return 1; - } - - filelen = ext2fs_open(filename); - if (filelen < 0) { - printf("** File not found %s\n", filename); - ext2fs_close(); - return 1; - } - if ((count < filelen) && (count != 0)) { - filelen = count; - } - - if (ext2fs_read((char *)addr, filelen) != filelen) { - printf("** Unable to read \"%s\" from %s %d:%d **\n", - filename, argv[1], dev, part); - ext2fs_close(); - return 1; - } - - ext2fs_close(); - - /* Loading ok, update default load address */ - load_addr = addr; - - printf ("%d bytes read\n", filelen); - sprintf(buf, "%X", filelen); - setenv("filesize", buf); + if (do_ext_load(cmdtp, flag, argc, argv)) + return -1; return 0; } U_BOOT_CMD( + ext2ls, 4, 1, do_ext2ls, + "list files in a directory (default /)", + "<interface> <dev[:part]> [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'" +); + +U_BOOT_CMD( ext2load, 6, 0, do_ext2load, "load binary file from a Ext2 filesystem", "<interface> <dev[:part]> [addr] [filename] [bytes]\n" diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c new file mode 100644 index 0000000000..77094c4ebb --- /dev/null +++ b/common/cmd_ext4.c @@ -0,0 +1,237 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Ext4fs support + * made from existing cmd_ext2.c file of Uboot + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG <www.elinos.com> + * Pavel Bartusek <pba@sysgo.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Changelog: + * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c + * file in uboot. Added ext4fs ls load and write support. + */ + +#include <common.h> +#include <part.h> +#include <config.h> +#include <command.h> +#include <image.h> +#include <linux/ctype.h> +#include <asm/byteorder.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <linux/stat.h> +#include <malloc.h> + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include <usb.h> +#endif + +#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION) +#error DOS or EFI partition support must be selected +#endif + +uint64_t total_sector; +uint64_t part_offset; +#if defined(CONFIG_CMD_EXT4_WRITE) +static uint64_t part_size; +static uint16_t cur_part = 1; +#endif + +#define DOS_PART_MAGIC_OFFSET 0x1fe +#define DOS_FS_TYPE_OFFSET 0x36 +#define DOS_FS32_TYPE_OFFSET 0x52 + +int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (do_ext_load(cmdtp, flag, argc, argv)) + return -1; + + return 0; +} + +int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + if (do_ext_ls(cmdtp, flag, argc, argv)) + return -1; + + return 0; +} + +#if defined(CONFIG_CMD_EXT4_WRITE) +static int ext4_register_device(block_dev_desc_t *dev_desc, int part_no) +{ + unsigned char buffer[SECTOR_SIZE]; + disk_partition_t info; + + if (!dev_desc->block_read) + return -1; + + /* check if we have a MBR (on floppies we have only a PBR) */ + if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *) buffer) != 1) { + printf("** Can't read from device %d **\n", dev_desc->dev); + return -1; + } + if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 || + buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) { + /* no signature found */ + return -1; + } + + /* First we assume there is a MBR */ + if (!get_partition_info(dev_desc, part_no, &info)) { + part_offset = info.start; + cur_part = part_no; + part_size = info.size; + } else if ((strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], + "FAT", 3) == 0) || (strncmp((char *)&buffer + [DOS_FS32_TYPE_OFFSET], + "FAT32", 5) == 0)) { + /* ok, we assume we are on a PBR only */ + cur_part = 1; + part_offset = 0; + } else { + printf("** Partition %d not valid on device %d **\n", + part_no, dev_desc->dev); + return -1; + } + + return 0; +} + +int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *filename = "/"; + int part_length; + unsigned long part = 1; + int dev; + char *ep; + unsigned long ram_address; + unsigned long file_size; + disk_partition_t info; + struct ext_filesystem *fs; + + if (argc < 6) + return cmd_usage(cmdtp); + + dev = (int)simple_strtoul(argv[2], &ep, 16); + ext4_dev_desc = get_dev(argv[1], dev); + if (ext4_dev_desc == NULL) { + printf("Block device %s %d not supported\n", argv[1], dev); + return 1; + } + if (init_fs(ext4_dev_desc)) + return 1; + + fs = get_fs(); + if (*ep) { + if (*ep != ':') { + puts("Invalid boot device, use `dev[:part]'\n"); + goto fail; + } + part = simple_strtoul(++ep, NULL, 16); + } + + /* get the filename */ + filename = argv[3]; + + /* get the address in hexadecimal format (string to int) */ + ram_address = simple_strtoul(argv[4], NULL, 16); + + /* get the filesize in base 10 format */ + file_size = simple_strtoul(argv[5], NULL, 10); + + /* set the device as block device */ + part_length = ext4fs_set_blk_dev(fs->dev_desc, part); + if (part_length == 0) { + printf("Bad partition - %s %d:%lu\n", argv[1], dev, part); + goto fail; + } + + /* register the device and partition */ + if (ext4_register_device(fs->dev_desc, part) != 0) { + printf("Unable to use %s %d:%lu for fattable\n", + argv[1], dev, part); + goto fail; + } + + /* get the partition information */ + if (!get_partition_info(fs->dev_desc, part, &info)) { + total_sector = (info.size * info.blksz) / SECTOR_SIZE; + fs->total_sect = total_sector; + } else { + printf("error : get partition info\n"); + goto fail; + } + + /* mount the filesystem */ + if (!ext4fs_mount(part_length)) { + printf("Bad ext4 partition %s %d:%lu\n", argv[1], dev, part); + goto fail; + } + + /* start write */ + if (ext4fs_write(filename, (unsigned char *)ram_address, file_size)) { + printf("** Error ext4fs_write() **\n"); + goto fail; + } + ext4fs_close(); + deinit_fs(fs->dev_desc); + + return 0; + +fail: + ext4fs_close(); + deinit_fs(fs->dev_desc); + + return 1; +} + +U_BOOT_CMD(ext4write, 6, 1, do_ext4_write, + "create a file in the root directory", + "<interface> <dev[:part]> [Absolute filename path] [Address] [sizebytes]\n" + " - create a file in / directory"); + +#endif + +U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls, + "list files in a directory (default /)", + "<interface> <dev[:part]> [directory]\n" + " - list files from 'dev' on 'interface' in a 'directory'"); + +U_BOOT_CMD(ext4load, 6, 0, do_ext4_load, + "load binary file from a Ext4 filesystem", + "<interface> <dev[:part]> [addr] [filename] [bytes]\n" + " - load binary file 'filename' from 'dev' on 'interface'\n" + " to address 'addr' from ext4 filesystem"); diff --git a/common/cmd_ext_common.c b/common/cmd_ext_common.c new file mode 100644 index 0000000000..56ee9a55b0 --- /dev/null +++ b/common/cmd_ext_common.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT2/4 filesystem implementation in Uboot by + * Uma Shankar <uma.shankar@samsung.com> + * Manjunatha C Achar <a.manjunatha@samsung.com> + * + * Ext4fs support + * made from existing cmd_ext2.c file of Uboot + * + * (C) Copyright 2004 + * esd gmbh <www.esd-electronics.com> + * Reinhard Arlt <reinhard.arlt@esd-electronics.com> + * + * made from cmd_reiserfs by + * + * (C) Copyright 2003 - 2004 + * Sysgo Real-Time Solutions, AG <www.elinos.com> + * Pavel Bartusek <pba@sysgo.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Changelog: + * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c + * file in uboot. Added ext4fs ls load and write support. + */ + +#include <common.h> +#include <part.h> +#include <config.h> +#include <command.h> +#include <image.h> +#include <linux/ctype.h> +#include <asm/byteorder.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <linux/stat.h> +#include <malloc.h> + +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) +#include <usb.h> +#endif + +#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION) +#error DOS or EFI partition support must be selected +#endif + +#define DOS_PART_MAGIC_OFFSET 0x1fe +#define DOS_FS_TYPE_OFFSET 0x36 +#define DOS_FS32_TYPE_OFFSET 0x52 + +int do_ext_load(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + char *filename = NULL; + char *ep; + int dev; + unsigned long part = 1; + ulong addr = 0; + ulong part_length; + int filelen; + disk_partition_t info; + struct ext_filesystem *fs; + char buf[12]; + unsigned long count; + const char *addr_str; + + count = 0; + addr = simple_strtoul(argv[3], NULL, 16); + filename = getenv("bootfile"); + switch (argc) { + case 3: + addr_str = getenv("loadaddr"); + if (addr_str != NULL) + addr = simple_strtoul(addr_str, NULL, 16); + else + addr = CONFIG_SYS_LOAD_ADDR; + + break; + case 4: + break; + case 5: + filename = argv[4]; + break; + case 6: + filename = argv[4]; + count = simple_strtoul(argv[5], NULL, 16); + break; + + default: + return cmd_usage(cmdtp); + } + + if (!filename) { + puts("** No boot file defined **\n"); + return 1; + } + + dev = (int)simple_strtoul(argv[2], &ep, 16); + ext4_dev_desc = get_dev(argv[1], dev); + if (ext4_dev_desc == NULL) { + printf("** Block device %s %d not supported\n", argv[1], dev); + return 1; + } + if (init_fs(ext4_dev_desc)) + return 1; + + fs = get_fs(); + if (*ep) { + if (*ep != ':') { + puts("** Invalid boot device, use `dev[:part]' **\n"); + goto fail; + } + part = simple_strtoul(++ep, NULL, 16); + } + + if (part != 0) { + if (get_partition_info(fs->dev_desc, part, &info)) { + printf("** Bad partition %lu **\n", part); + goto fail; + } + + if (strncmp((char *)info.type, BOOT_PART_TYPE, + strlen(BOOT_PART_TYPE)) != 0) { + printf("** Invalid partition type \"%s\"" + " (expect \"" BOOT_PART_TYPE "\")\n", info.type); + goto fail; + } + printf("Loading file \"%s\" " + "from %s device %d:%lu %s\n", + filename, argv[1], dev, part, info.name); + } else { + printf("Loading file \"%s\" from %s device %d\n", + filename, argv[1], dev); + } + + part_length = ext4fs_set_blk_dev(fs->dev_desc, part); + if (part_length == 0) { + printf("**Bad partition - %s %d:%lu **\n", argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + if (!ext4fs_mount(part_length)) { + printf("** Bad ext2 partition or disk - %s %d:%lu **\n", + argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + filelen = ext4fs_open(filename); + if (filelen < 0) { + printf("** File not found %s\n", filename); + ext4fs_close(); + goto fail; + } + if ((count < filelen) && (count != 0)) + filelen = count; + + if (ext4fs_read((char *)addr, filelen) != filelen) { + printf("** Unable to read \"%s\" from %s %d:%lu **\n", + filename, argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + ext4fs_close(); + deinit_fs(fs->dev_desc); + /* Loading ok, update default load address */ + load_addr = addr; + + printf("%d bytes read\n", filelen); + sprintf(buf, "%X", filelen); + setenv("filesize", buf); + + return 0; +fail: + deinit_fs(fs->dev_desc); + return 1; +} + +int do_ext_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + const char *filename = "/"; + int dev; + unsigned long part = 1; + char *ep; + struct ext_filesystem *fs; + int part_length; + if (argc < 3) + return cmd_usage(cmdtp); + + dev = (int)simple_strtoul(argv[2], &ep, 16); + + ext4_dev_desc = get_dev(argv[1], dev); + + if (ext4_dev_desc == NULL) { + printf("\n** Block device %s %d not supported\n", argv[1], dev); + return 1; + } + + if (init_fs(ext4_dev_desc)) + return 1; + + fs = get_fs(); + if (*ep) { + if (*ep != ':') { + puts("\n** Invalid boot device, use `dev[:part]' **\n"); + goto fail; + } + part = simple_strtoul(++ep, NULL, 16); + } + + if (argc == 4) + filename = argv[3]; + + part_length = ext4fs_set_blk_dev(fs->dev_desc, part); + if (part_length == 0) { + printf("** Bad partition - %s %d:%lu **\n", argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + if (!ext4fs_mount(part_length)) { + printf("** Bad ext2 partition or disk - %s %d:%lu **\n", + argv[1], dev, part); + ext4fs_close(); + goto fail; + } + + if (ext4fs_ls(filename)) { + printf("** Error extfs_ls() **\n"); + ext4fs_close(); + goto fail; + }; + + ext4fs_close(); + deinit_fs(fs->dev_desc); + return 0; + +fail: + deinit_fs(fs->dev_desc); + return 1; +} diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 9a5c53ec06..e2225c4d5c 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -114,10 +114,21 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) } } + return CMD_RET_SUCCESS; + } + + if (!working_fdt) { + puts( + "No FDT memory address configured. Please configure\n" + "the FDT address via \"fdt addr <address>\" command.\n" + "Aborting!\n"); + return CMD_RET_FAILURE; + } + /* * Move the working_fdt */ - } else if (strncmp(argv[1], "mo", 2) == 0) { + if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; diff --git a/common/cmd_flash.c b/common/cmd_flash.c index 0e9b2e3c74..e55d366c65 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -443,7 +443,8 @@ int flash_sect_erase (ulong addr_first, ulong addr_last) rcode = flash_erase (info, s_first[bank], s_last[bank]); } } - printf ("Erased %d sectors\n", erased); + if (rcode == 0) + printf("Erased %d sectors\n", erased); } else if (rcode == 0) { puts ("Error: start and/or end address" " not on sector boundary\n"); diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 750509da5e..79a1088f3b 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -144,8 +144,7 @@ int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( mmcinfo, 1, 0, do_mmcinfo, "display MMC info", - " - device number of the device to dislay info of\n" - "" + "- dislay info of the current MMC device" ); int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index a91ccf4df3..e24ed7f9c4 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -48,8 +48,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) last = off; - datbuf = malloc(nand->writesize); - oobbuf = malloc(nand->oobsize); + datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize); + oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize); if (!datbuf || !oobbuf) { puts("No memory for page buffer\n"); return 1; @@ -231,12 +231,18 @@ print: #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK static void print_status(ulong start, ulong end, ulong erasesize, int status) { + /* + * Micron NAND flash (e.g. MT29F4G08ABADAH4) BLOCK LOCK READ STATUS is + * not the same as others. Instead of bit 1 being lock, it is + * #lock_tight. To make the driver support either format, ignore bit 1 + * and use only bit 0 and bit 2. + */ printf("%08lx - %08lx: %08lx blocks %s%s%s\n", start, end - 1, (end - start) / erasesize, ((status & NAND_LOCK_STATUS_TIGHT) ? "TIGHT " : ""), - ((status & NAND_LOCK_STATUS_LOCK) ? "LOCK " : ""), + (!(status & NAND_LOCK_STATUS_UNLOCK) ? "LOCK " : ""), ((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : "")); } @@ -749,11 +755,18 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 0; } - if (strcmp(cmd, "unlock") == 0) { + if (strncmp(cmd, "unlock", 5) == 0) { + int allexcept = 0; + + s = strchr(cmd, '.'); + + if (s && !strcmp(s, ".allexcept")) + allexcept = 1; + if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0) return 1; - if (!nand_unlock(&nand_info[dev], off, size)) { + if (!nand_unlock(&nand_info[dev], off, size, allexcept)) { puts("NAND flash successfully unlocked\n"); } else { puts("Error unlocking NAND flash, " @@ -807,7 +820,7 @@ U_BOOT_CMD( "\n" "nand lock [tight] [status]\n" " bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section" + "nand unlock[.allexcept] [offset] [size] - unlock section" #endif #ifdef CONFIG_ENV_OFFSET_OOB "\n" diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index fd05e725d7..3474bc6094 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -198,31 +198,20 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, #endif /* - * Set a new environment variable, - * or replace or delete an existing one. + * Perform consistency checking before setting, replacing, or deleting an + * environment variable, then (if successful) apply the changes to internals so + * to make them effective. Code for this function was taken out of + * _do_env_set(), which now calls it instead. + * Also called as a callback function by himport_r(). + * Returns 0 in case of success, 1 in case of failure. + * When (flag & H_FORCE) is set, do not print out any error message and force + * overwriting of write-once variables. */ -int _do_env_set(int flag, int argc, char * const argv[]) + +int env_check_apply(const char *name, const char *oldval, + const char *newval, int flag) { - int i, len; int console = -1; - char *name, *value, *s; - ENTRY e, *ep; - - name = argv[1]; - - if (strchr(name, '=')) { - printf("## Error: illegal character '=' in variable name" - "\"%s\"\n", name); - return 1; - } - - env_id++; - /* - * search if variable with this name already exists - */ - e.key = name; - e.data = NULL; - hsearch_r(e, FIND, &ep, &env_htab); /* Check for console redirection */ if (strcmp(name, "stdin") == 0) @@ -233,60 +222,75 @@ int _do_env_set(int flag, int argc, char * const argv[]) console = stderr; if (console != -1) { - if (argc < 3) { /* Cannot delete it! */ - printf("Can't delete \"%s\"\n", name); + if ((newval == NULL) || (*newval == '\0')) { + /* We cannot delete stdin/stdout/stderr */ + if ((flag & H_FORCE) == 0) + printf("Can't delete \"%s\"\n", name); return 1; } #ifdef CONFIG_CONSOLE_MUX - i = iomux_doenv(console, argv[2]); - if (i) - return i; + if (iomux_doenv(console, newval)) + return 1; #else /* Try assigning specified device */ - if (console_assign(console, argv[2]) < 0) + if (console_assign(console, newval) < 0) return 1; #ifdef CONFIG_SERIAL_MULTI - if (serial_assign(argv[2]) < 0) + if (serial_assign(newval) < 0) return 1; #endif #endif /* CONFIG_CONSOLE_MUX */ } /* - * Some variables like "ethaddr" and "serial#" can be set only - * once and cannot be deleted; also, "ver" is readonly. + * Some variables like "ethaddr" and "serial#" can be set only once and + * cannot be deleted, unless CONFIG_ENV_OVERWRITE is defined. */ - if (ep) { /* variable exists */ #ifndef CONFIG_ENV_OVERWRITE + if (oldval != NULL && /* variable exists */ + (flag & H_FORCE) == 0) { /* and we are not forced */ if (strcmp(name, "serial#") == 0 || (strcmp(name, "ethaddr") == 0 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) - && strcmp(ep->data, MK_STR(CONFIG_ETHADDR)) != 0 + && strcmp(oldval, MK_STR(CONFIG_ETHADDR)) != 0 #endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */ )) { printf("Can't overwrite \"%s\"\n", name); return 1; } + } #endif + /* + * When we change baudrate, or we are doing an env default -a + * (which will erase all variables prior to calling this), + * we want the baudrate to actually change - for real. + */ + if (oldval != NULL || /* variable exists */ + (flag & H_NOCLEAR) == 0) { /* or env is clear */ /* * Switch to new baudrate if new baudrate is supported */ if (strcmp(name, "baudrate") == 0) { - int baudrate = simple_strtoul(argv[2], NULL, 10); + int baudrate = simple_strtoul(newval, NULL, 10); int i; for (i = 0; i < N_BAUDRATES; ++i) { if (baudrate == baudrate_table[i]) break; } if (i == N_BAUDRATES) { - printf("## Baudrate %d bps not supported\n", - baudrate); + if ((flag & H_FORCE) == 0) + printf("## Baudrate %d bps not " + "supported\n", baudrate); return 1; } + if (gd->baudrate == baudrate) { + /* If unchanged, we just say it's OK */ + return 0; + } printf("## Switch baudrate to %d bps and" - "press ENTER ...\n", baudrate); + "press ENTER ...\n", baudrate); udelay(50000); gd->baudrate = baudrate; #if defined(CONFIG_PPC) || defined(CONFIG_MCF52x2) @@ -300,9 +304,62 @@ int _do_env_set(int flag, int argc, char * const argv[]) } } + /* + * Some variables should be updated when the corresponding + * entry in the environment is changed + */ + if (strcmp(name, "loadaddr") == 0) { + load_addr = simple_strtoul(newval, NULL, 16); + return 0; + } +#if defined(CONFIG_CMD_NET) + else if (strcmp(name, "bootfile") == 0) { + copy_filename(BootFile, newval, sizeof(BootFile)); + return 0; + } +#endif + return 0; +} + +/* + * Set a new environment variable, + * or replace or delete an existing one. +*/ +int _do_env_set(int flag, int argc, char * const argv[]) +{ + int i, len; + char *name, *value, *s; + ENTRY e, *ep; + + name = argv[1]; + value = argv[2]; + + if (strchr(name, '=')) { + printf("## Error: illegal character '='" + "in variable name \"%s\"\n", name); + return 1; + } + + env_id++; + /* + * search if variable with this name already exists + */ + e.key = name; + e.data = NULL; + hsearch_r(e, FIND, &ep, &env_htab); + + /* + * Perform requested checks. Notice how since we are overwriting + * a single variable, we need to set H_NOCLEAR + */ + if (env_check_apply(name, ep ? ep->data : NULL, value, H_NOCLEAR)) { + debug("check function did not approve, refusing\n"); + return 1; + } + /* Delete only ? */ if (argc < 3 || argv[2] == NULL) { - int rc = hdelete_r(name, &env_htab); + int rc = hdelete_r(name, &env_htab, 0); return !rc; } @@ -337,20 +394,6 @@ int _do_env_set(int flag, int argc, char * const argv[]) return 1; } - /* - * Some variables should be updated when the corresponding - * entry in the environment is changed - */ - if (strcmp(argv[1], "loadaddr") == 0) { - load_addr = simple_strtoul(argv[2], NULL, 16); - return 0; - } -#if defined(CONFIG_CMD_NET) - else if (strcmp(argv[1], "bootfile") == 0) { - copy_filename(BootFile, argv[2], sizeof(BootFile)); - return 0; - } -#endif return 0; } @@ -613,14 +656,41 @@ int envmatch(uchar *s1, int i2) return -1; } -static int do_env_default(cmd_tbl_t *cmdtp, int flag, +static int do_env_default(cmd_tbl_t *cmdtp, int __flag, int argc, char * const argv[]) { - if (argc != 2 || strcmp(argv[1], "-f") != 0) - return CMD_RET_USAGE; + int all = 0, flag = 0; - set_default_env("## Resetting to default environment\n"); - return 0; + debug("Initial value for argc=%d\n", argc); + while (--argc > 0 && **++argv == '-') { + char *arg = *argv; + + while (*++arg) { + switch (*arg) { + case 'a': /* default all */ + all = 1; + break; + case 'f': /* force */ + flag |= H_FORCE; + break; + default: + return cmd_usage(cmdtp); + } + } + } + debug("Final value for argc=%d\n", argc); + if (all && (argc == 0)) { + /* Reset the whole environment */ + set_default_env("## Resetting to default environment\n"); + return 0; + } + if (!all && (argc > 0)) { + /* Reset individual variables */ + set_default_vars(argc, argv); + return 0; + } + + return cmd_usage(cmdtp); } static int do_env_delete(cmd_tbl_t *cmdtp, int flag, @@ -872,7 +942,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, addr = (char *)ep->data; } - if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR) == 0) { + if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR, + 0, NULL, 0 /* do_apply */) == 0) { error("Environment import failed: errno = %d\n", errno); return 1; } @@ -950,15 +1021,20 @@ U_BOOT_CMD( #if defined(CONFIG_CMD_ASKENV) "ask name [message] [size] - ask for environment variable\nenv " #endif - "default -f - reset default environment\n" + "default [-f] -a - [forcibly] reset default environment\n" + "env default [-f] var [...] - [forcibly] reset variable(s) to their default values\n" #if defined(CONFIG_CMD_EDITENV) "env edit name - edit environment variable\n" #endif +#if defined(CONFIG_CMD_EXPORTENV) "env export [-t | -b | -c] [-s size] addr [var ...] - export environment\n" +#endif #if defined(CONFIG_CMD_GREPENV) "env grep string [...] - search environment\n" #endif +#if defined(CONFIG_CMD_IMPORTENV) "env import [-d] [-t | -b | -c] addr [size] - import environment\n" +#endif "env print [name ...] - print environment\n" #if defined(CONFIG_CMD_RUN) "env run var [...] - run commands in an environment variable\n" diff --git a/common/cmd_spi.c b/common/cmd_spi.c index 8c623c9fcf..eba5fb83da 100644 --- a/common/cmd_spi.c +++ b/common/cmd_spi.c @@ -89,7 +89,7 @@ int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) cs = bus; bus = CONFIG_DEFAULT_SPI_BUS; } - if (*cp == '.'); + if (*cp == '.') mode = simple_strtoul(cp+1, NULL, 10); } if (argc >= 3) diff --git a/common/dlmalloc.c b/common/dlmalloc.c index c645d7314b..1d7e527b9d 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1487,11 +1487,11 @@ static mbinptr av_[NAV * 2 + 2] = { #ifdef CONFIG_NEEDS_MANUAL_RELOC void malloc_bin_reloc (void) { - unsigned long *p = (unsigned long *)(&av_[2]); - int i; - for (i=2; i<(sizeof(av_)/sizeof(mbinptr)); ++i) { - *p++ += gd->reloc_off; - } + mbinptr *p = &av_[2]; + size_t i; + + for (i = 2; i < ARRAY_SIZE(av_); ++i, ++p) + *p = (mbinptr)((ulong)*p + gd->reloc_off); } #endif diff --git a/common/env_common.c b/common/env_common.c index d9e990dbbe..3e46c260df 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -80,6 +80,9 @@ const uchar default_environment[] = { #ifdef CONFIG_ETH5ADDR "eth5addr=" MK_STR(CONFIG_ETH5ADDR) "\0" #endif +#ifdef CONFIG_ETHPRIME + "ethprime=" CONFIG_ETHPRIME "\0" +#endif #ifdef CONFIG_IPADDR "ipaddr=" MK_STR(CONFIG_IPADDR) "\0" #endif @@ -133,7 +136,9 @@ const uchar default_environment[] = { "\0" }; -struct hsearch_data env_htab; +struct hsearch_data env_htab = { + .apply = env_check_apply, +}; static uchar __env_get_char_spec(int index) { @@ -175,6 +180,11 @@ const uchar *env_get_addr(int index) void set_default_env(const char *s) { + /* + * By default, do not apply changes as they will eventually + * be applied by someone else + */ + int do_apply = 0; if (sizeof(default_environment) > ENV_SIZE) { puts("*** Error - default environment is too large\n\n"); return; @@ -186,6 +196,14 @@ void set_default_env(const char *s) "using default environment\n\n", s + 1); } else { + /* + * This set_to_default was explicitly asked for + * by the user, as opposed to being a recovery + * mechanism. Therefore we check every single + * variable and apply changes to the system + * right away (e.g. baudrate, console). + */ + do_apply = 1; puts(s); } } else { @@ -193,12 +211,26 @@ void set_default_env(const char *s) } if (himport_r(&env_htab, (char *)default_environment, - sizeof(default_environment), '\0', 0) == 0) + sizeof(default_environment), '\0', 0, + 0, NULL, do_apply) == 0) error("Environment import failed: errno = %d\n", errno); gd->flags |= GD_FLG_ENV_READY; } + +/* [re]set individual variables to their value in the default environment */ +int set_default_vars(int nvars, char * const vars[]) +{ + /* + * Special use-case: import from default environment + * (and use \0 as a separator) + */ + return himport_r(&env_htab, (const char *)default_environment, + sizeof(default_environment), '\0', H_NOCLEAR, + nvars, vars, 1 /* do_apply */); +} + /* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. @@ -218,7 +250,8 @@ int env_import(const char *buf, int check) } } - if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0)) { + if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, + 0, NULL, 0 /* do_apply */)) { gd->flags |= GD_FLG_ENV_READY; return 1; } diff --git a/common/env_mmc.c b/common/env_mmc.c index be2f2be205..a2ff90bf48 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -75,9 +75,28 @@ static int init_mmc_for_env(struct mmc *mmc) return -1; } +#ifdef CONFIG_SYS_MMC_ENV_PART + if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) { + if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, + CONFIG_SYS_MMC_ENV_PART)) { + puts("MMC partition switch failed\n"); + return -1; + } + } +#endif + return 0; } +static void fini_mmc_for_env(struct mmc *mmc) +{ +#ifdef CONFIG_SYS_MMC_ENV_PART + if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) + mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV, + mmc->part_num); +#endif +} + #ifdef CONFIG_CMD_SAVEENV static inline int write_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) @@ -100,26 +119,38 @@ int saveenv(void) char *res; struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); u32 offset; + int ret; - if (init_mmc_for_env(mmc) || mmc_get_env_addr(mmc, &offset)) + if (init_mmc_for_env(mmc)) return 1; + if (mmc_get_env_addr(mmc, &offset)) { + ret = 1; + goto fini; + } + res = (char *)&env_new->data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); - return 1; + ret = 1; + goto fini; } env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE); printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV); if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) { puts("failed\n"); - return 1; + ret = 1; + goto fini; } puts("done\n"); - return 0; + ret = 0; + +fini: + fini_mmc_for_env(mmc); + return ret; } #endif /* CONFIG_CMD_SAVEENV */ @@ -143,13 +174,30 @@ void env_relocate_spec(void) ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); u32 offset; + int ret; - if (init_mmc_for_env(mmc) || mmc_get_env_addr(mmc, &offset)) - return set_default_env(NULL); + if (init_mmc_for_env(mmc)) { + ret = 1; + goto err; + } - if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) - return set_default_env(NULL); + if (mmc_get_env_addr(mmc, &offset)) { + ret = 1; + goto fini; + } + + if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) { + ret = 1; + goto fini; + } env_import(buf, 1); + ret = 0; + +fini: + fini_mmc_for_env(mmc); +err: + if (ret) + set_default_env(NULL); #endif } diff --git a/common/env_nand.c b/common/env_nand.c index e8daec9712..79e8033705 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -226,7 +226,7 @@ int saveenv(void) int saveenv(void) { int ret = 0; - env_t env_new; + ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); ssize_t len; char *res; nand_erase_options_t nand_erase_options; @@ -238,20 +238,20 @@ int saveenv(void) if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE) return 1; - res = (char *)&env_new.data; + res = (char *)&env_new->data; len = hexport_r(&env_htab, '\0', &res, ENV_SIZE, 0, NULL); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; } - env_new.crc = crc32(0, env_new.data, ENV_SIZE); + env_new->crc = crc32(0, env_new->data, ENV_SIZE); puts("Erasing Nand...\n"); if (nand_erase_opts(&nand_info[0], &nand_erase_options)) return 1; puts("Writing to Nand... "); - if (writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new)) { + if (writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new)) { puts("FAILED!\n"); return 1; } @@ -398,7 +398,7 @@ void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) int ret; - char buf[CONFIG_ENV_SIZE]; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); #if defined(CONFIG_ENV_OFFSET_OOB) ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset); diff --git a/common/flash.c b/common/flash.c index 781cb9c4a2..8244ba2ddd 100644 --- a/common/flash.c +++ b/common/flash.c @@ -221,6 +221,9 @@ void flash_perror (int err) case ERR_PROG_ERROR: puts ("General Flash Programming Error\n"); break; + case ERR_ABORTED: + puts("Flash Programming Aborted\n"); + break; default: printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err); break; diff --git a/common/hush.c b/common/hush.c index 1eff182efa..4c84c2f501 100644 --- a/common/hush.c +++ b/common/hush.c @@ -127,6 +127,7 @@ #endif #endif #define SPECIAL_VAR_SYMBOL 03 +#define SUBSTED_VAR_SYMBOL 04 #ifndef __U_BOOT__ #define FLAG_EXIT_FROM_LOOP 1 #define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */ @@ -499,6 +500,7 @@ static void remove_bg_job(struct pipe *pi); /* local variable support */ static char **make_list_in(char **inp, char *name); static char *insert_var_value(char *inp); +static char *insert_var_value_sub(char *inp, int tag_subst); #ifndef __U_BOOT__ /* Table of built-in functions. They can be forked or not, depending on @@ -2743,13 +2745,50 @@ static int parse_group(o_string *dest, struct p_context *ctx, static char *lookup_param(char *src) { char *p; + char *sep; + char *default_val = NULL; + int assign = 0; + int expand_empty = 0; if (!src) return NULL; - p = getenv(src); - if (!p) - p = get_local_var(src); + sep = strchr(src, ':'); + + if (sep) { + *sep = '\0'; + if (*(sep + 1) == '-') + default_val = sep+2; + if (*(sep + 1) == '=') { + default_val = sep+2; + assign = 1; + } + if (*(sep + 1) == '+') { + default_val = sep+2; + expand_empty = 1; + } + } + + p = getenv(src); + if (!p) + p = get_local_var(src); + + if (!p || strlen(p) == 0) { + p = default_val; + if (assign) { + char *var = malloc(strlen(src)+strlen(default_val)+2); + if (var) { + sprintf(var, "%s=%s", src, default_val); + set_local_var(var, 0); + } + free(var); + } + } else if (expand_empty) { + p += strlen(p); + } + + if (sep) + *sep = ':'; return p; } @@ -3051,6 +3090,21 @@ int parse_stream(o_string *dest, struct p_context *ctx, return 1; break; #endif + case SUBSTED_VAR_SYMBOL: + dest->nonnull = 1; + while (ch = b_getch(input), ch != EOF && + ch != SUBSTED_VAR_SYMBOL) { + debug_printf("subst, pass=%d\n", ch); + if (input->__promptme == 0) + return 1; + b_addchr(dest, ch); + } + debug_printf("subst, term=%d\n", ch); + if (ch == EOF) { + syntax(); + return 1; + } + break; default: syntax(); /* this is really an internal logic error */ return 1; @@ -3092,6 +3146,10 @@ void update_ifs_map(void) mapset((uchar *)"\\$'\"`", 3); /* never flow through */ mapset((uchar *)"<>;&|(){}#", 1); /* flow through if quoted */ #else + { + uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0}; + mapset(subst, 3); /* never flow through */ + } mapset((uchar *)"\\$'\"", 3); /* never flow through */ mapset((uchar *)";&|#", 1); /* flow through if quoted */ #endif @@ -3431,25 +3489,57 @@ final_return: static char *insert_var_value(char *inp) { + return insert_var_value_sub(inp, 0); +} + +static char *insert_var_value_sub(char *inp, int tag_subst) +{ int res_str_len = 0; int len; int done = 0; char *p, *p1, *res_str = NULL; while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) { + /* check the beginning of the string for normal charachters */ if (p != inp) { + /* copy any charachters to the result string */ len = p - inp; res_str = xrealloc(res_str, (res_str_len + len)); strncpy((res_str + res_str_len), inp, len); res_str_len += len; } inp = ++p; + /* find the ending marker */ p = strchr(inp, SPECIAL_VAR_SYMBOL); *p = '\0'; + /* look up the value to substitute */ if ((p1 = lookup_param(inp))) { - len = res_str_len + strlen(p1); + if (tag_subst) + len = res_str_len + strlen(p1) + 2; + else + len = res_str_len + strlen(p1); res_str = xrealloc(res_str, (1 + len)); - strcpy((res_str + res_str_len), p1); + if (tag_subst) { + /* + * copy the variable value to the result + * string + */ + strcpy((res_str + res_str_len + 1), p1); + + /* + * mark the replaced text to be accepted as + * is + */ + res_str[res_str_len] = SUBSTED_VAR_SYMBOL; + res_str[res_str_len + 1 + strlen(p1)] = + SUBSTED_VAR_SYMBOL; + } else + /* + * copy the variable value to the result + * string + */ + strcpy((res_str + res_str_len), p1); + res_str_len = len; } *p = SPECIAL_VAR_SYMBOL; @@ -3513,9 +3603,14 @@ static char * make_string(char ** inp) char *str = NULL; int n; int len = 2; + char *noeval_str; + int noeval = 0; + noeval_str = get_local_var("HUSH_NO_EVAL"); + if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0') + noeval = 1; for (n = 0; inp[n]; n++) { - p = insert_var_value(inp[n]); + p = insert_var_value_sub(inp[n], noeval); str = xrealloc(str, (len + strlen(p))); if (n) { strcat(str, " "); diff --git a/common/image.c b/common/image.c index 0c601bbc45..f084d2baed 100644 --- a/common/image.c +++ b/common/image.c @@ -2043,13 +2043,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } - if (type == IH_TYPE_KERNEL) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE)) { + (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) @@ -2058,7 +2058,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_RAMDISK)) { fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) diff --git a/common/usb_hub.c b/common/usb_hub.c index f35ad95324..32750e8d05 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -43,6 +43,7 @@ #include <common.h> #include <command.h> #include <asm/processor.h> +#include <asm/unaligned.h> #include <linux/ctype.h> #include <asm/byteorder.h> #include <asm/unaligned.h> @@ -269,6 +270,7 @@ static int usb_hub_configure(struct usb_device *dev) int i; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ); unsigned char *bitmap; + short hubCharacteristics; struct usb_hub_descriptor *descriptor; struct usb_hub_device *hub; #ifdef USB_HUB_DEBUG @@ -304,8 +306,9 @@ static int usb_hub_configure(struct usb_device *dev) } memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); /* adjust 16bit values */ - hub->desc.wHubCharacteristics = - le16_to_cpu(descriptor->wHubCharacteristics); + put_unaligned(le16_to_cpu(get_unaligned( + &descriptor->wHubCharacteristics)), + &hub->desc.wHubCharacteristics); /* set the bitmap */ bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; /* devices not removable by default */ @@ -322,7 +325,8 @@ static int usb_hub_configure(struct usb_device *dev) dev->maxchild = descriptor->bNbrPorts; USB_HUB_PRINTF("%d ports detected\n", dev->maxchild); - switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) { + hubCharacteristics = get_unaligned(&hub->desc.wHubCharacteristics); + switch (hubCharacteristics & HUB_CHAR_LPSM) { case 0x00: USB_HUB_PRINTF("ganged power switching\n"); break; @@ -335,12 +339,12 @@ static int usb_hub_configure(struct usb_device *dev) break; } - if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) + if (hubCharacteristics & HUB_CHAR_COMPOUND) USB_HUB_PRINTF("part of a compound device\n"); else USB_HUB_PRINTF("standalone hub\n"); - switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) { + switch (hubCharacteristics & HUB_CHAR_OCPM) { case 0x00: USB_HUB_PRINTF("global over-current protection\n"); break; diff --git a/common/usb_storage.c b/common/usb_storage.c index bdc306f587..4aeed827c1 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -136,6 +136,7 @@ struct us_data { struct usb_device *pusb_dev; /* this usb_device */ unsigned int flags; /* from filter initially */ +# define USB_READY (1 << 0) unsigned char ifnum; /* interface number */ unsigned char ep_in; /* in endpoint */ unsigned char ep_out; /* out ....... */ @@ -155,11 +156,16 @@ struct us_data { trans_cmnd transport; /* transport routine */ }; +#ifdef CONFIG_USB_EHCI /* - * The U-Boot EHCI driver cannot handle more than 5 page aligned buffers - * of 4096 bytes in a transfer without running itself out of qt_buffers + * The U-Boot EHCI driver can handle any transfer length as long as there is + * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are + * limited to 65535 blocks. */ -#define USB_MAX_XFER_BLK(start, blksz) (((4096 * 5) - (start % 4096)) / blksz) +#define USB_MAX_XFER_BLK 65535 +#else +#define USB_MAX_XFER_BLK 20 +#endif static struct us_data usb_stor[USB_MAX_STOR_DEV]; @@ -693,7 +699,8 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us) usb_stor_BBB_reset(us); return USB_STOR_TRANSPORT_FAILED; } - mdelay(5); + if (!(us->flags & USB_READY)) + mdelay(5); pipein = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); pipeout = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* DATA phase + error handling */ @@ -958,8 +965,10 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss) srb->cmd[1] = srb->lun << 5; srb->datalen = 0; srb->cmdlen = 12; - if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) + if (ss->transport(srb, ss) == USB_STOR_TRANSPORT_GOOD) { + ss->flags |= USB_READY; return 0; + } usb_request_sense(srb, ss); mdelay(100); } while (retries--); @@ -1046,7 +1055,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor, unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, void *buffer) { - unsigned long start, blks, buf_addr, max_xfer_blk; + unsigned long start, blks, buf_addr; unsigned short smallblks; struct usb_device *dev; struct us_data *ss; @@ -1074,12 +1083,6 @@ unsigned long usb_stor_read(int device, unsigned long blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; - if (usb_test_unit_ready(srb, ss)) { - printf("Device NOT ready\n Request Sense returned %02X %02X" - " %02X\n", srb->sense_buf[2], srb->sense_buf[12], - srb->sense_buf[13]); - return 0; - } USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx" " buffer %lx\n", device, start, blks, buf_addr); @@ -1088,14 +1091,12 @@ unsigned long usb_stor_read(int device, unsigned long blknr, /* XXX need some comment here */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - max_xfer_blk = USB_MAX_XFER_BLK(buf_addr, - usb_dev_desc[device].blksz); - if (blks > max_xfer_blk) - smallblks = (unsigned short) max_xfer_blk; + if (blks > USB_MAX_XFER_BLK) + smallblks = USB_MAX_XFER_BLK; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == max_xfer_blk) + if (smallblks == USB_MAX_XFER_BLK) usb_show_progress(); srb->datalen = usb_dev_desc[device].blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1111,12 +1112,13 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); + ss->flags &= ~USB_READY; USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= max_xfer_blk) + if (blkcnt >= USB_MAX_XFER_BLK) debug("\n"); return blkcnt; } @@ -1124,7 +1126,7 @@ retry_it: unsigned long usb_stor_write(int device, unsigned long blknr, unsigned long blkcnt, const void *buffer) { - unsigned long start, blks, buf_addr, max_xfer_blk; + unsigned long start, blks, buf_addr; unsigned short smallblks; struct usb_device *dev; struct us_data *ss; @@ -1153,12 +1155,6 @@ unsigned long usb_stor_write(int device, unsigned long blknr, buf_addr = (unsigned long)buffer; start = blknr; blks = blkcnt; - if (usb_test_unit_ready(srb, ss)) { - printf("Device NOT ready\n Request Sense returned %02X %02X" - " %02X\n", srb->sense_buf[2], srb->sense_buf[12], - srb->sense_buf[13]); - return 0; - } USB_STOR_PRINTF("\nusb_write: dev %d startblk %lx, blccnt %lx" " buffer %lx\n", device, start, blks, buf_addr); @@ -1169,14 +1165,12 @@ unsigned long usb_stor_write(int device, unsigned long blknr, */ retry = 2; srb->pdata = (unsigned char *)buf_addr; - max_xfer_blk = USB_MAX_XFER_BLK(buf_addr, - usb_dev_desc[device].blksz); - if (blks > max_xfer_blk) - smallblks = (unsigned short) max_xfer_blk; + if (blks > USB_MAX_XFER_BLK) + smallblks = USB_MAX_XFER_BLK; else smallblks = (unsigned short) blks; retry_it: - if (smallblks == max_xfer_blk) + if (smallblks == USB_MAX_XFER_BLK) usb_show_progress(); srb->datalen = usb_dev_desc[device].blksz * smallblks; srb->pdata = (unsigned char *)buf_addr; @@ -1192,12 +1186,13 @@ retry_it: blks -= smallblks; buf_addr += srb->datalen; } while (blks != 0); + ss->flags &= ~USB_READY; USB_STOR_PRINTF("usb_write: end startblk %lx, blccnt %x buffer %lx\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ - if (blkcnt >= max_xfer_blk) + if (blkcnt >= USB_MAX_XFER_BLK) debug("\n"); return blkcnt; @@ -1403,6 +1398,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, cap[0] = 2880; cap[1] = 0x200; } + ss->flags &= ~USB_READY; USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n", cap[0], cap[1]); #if 0 |