From 352ef3f1b613cb711c51ec962d2cc1eafff1bf95 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 4 Apr 2013 15:53:14 +0200 Subject: flash: Add optional verify-after-write feature Sometimes it might make sense to verify the written data to NOR flash. This patch adds this feature. To enable this verify-after-write, you need to define CONFIG_FLASH_VERIFY in your board config header. Please note that this option is useless in nearly all cases, since such flash programming errors usually are detected earlier while unprotecting/erasing/programming. Please only enable this option if you really know what you are doing. Signed-off-by: Stefan Roese --- common/flash.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'common') diff --git a/common/flash.c b/common/flash.c index 8244ba2..0c57a3f 100644 --- a/common/flash.c +++ b/common/flash.c @@ -149,6 +149,9 @@ flash_write (char *src, ulong addr, ulong cnt) flash_info_t *info_first = addr2info (addr); flash_info_t *info_last = addr2info (end ); flash_info_t *info; + __maybe_unused char *src_orig = src; + __maybe_unused char *addr_orig = (char *)addr; + __maybe_unused ulong cnt_orig = cnt; if (cnt == 0) { return (ERR_OK); @@ -185,6 +188,14 @@ flash_write (char *src, ulong addr, ulong cnt) addr += len; src += len; } + +#if defined(CONFIG_FLASH_VERIFY) + if (memcmp(src_orig, addr_orig, cnt_orig)) { + printf("\nVerify failed!\n"); + return ERR_PROG_ERROR; + } +#endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */ + return (ERR_OK); #endif /* CONFIG_SPD823TS */ } -- cgit v1.1 From a733b06b69d2cb058c4363952bc0793b1f514305 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 26 Apr 2013 02:53:43 +0000 Subject: sandbox: Switch over to generic board Add generic board support for sandbox. and remove the old board init code. Select CONFIG_SYS_GENERIC_BOARD for sandbox now that this is supported. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- common/board_f.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- common/board_r.c | 8 ++++++-- 2 files changed, 48 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 00ca811..2045055 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -49,9 +49,11 @@ #include #endif +#include #include #include #include +#include #include #ifdef CONFIG_MP #include @@ -61,6 +63,9 @@ #include #include #endif +#ifdef CONFIG_SANDBOX +#include +#endif #include /* @@ -155,6 +160,7 @@ static int init_baud_rate(void) static int display_text_info(void) { +#ifndef CONFIG_SANDBOX ulong bss_start, bss_end; #ifdef CONFIG_SYS_SYM_OFFSETS @@ -166,6 +172,7 @@ static int display_text_info(void) #endif debug("U-Boot code: %08X -> %08lX BSS: -> %08lX\n", CONFIG_SYS_TEXT_BASE, bss_start, bss_end); +#endif #ifdef CONFIG_MODEM_SUPPORT debug("Modem Support enabled\n"); @@ -284,6 +291,8 @@ static int setup_mon_len(void) { #ifdef CONFIG_SYS_SYM_OFFSETS gd->mon_len = _bss_end_ofs; +#elif defined(CONFIG_SANDBOX) + gd->mon_len = (ulong)&_end - (ulong)_init; #else /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */ gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; @@ -296,6 +305,17 @@ __weak int arch_cpu_init(void) return 0; } +#ifdef CONFIG_SANDBOX +static int setup_ram_buf(void) +{ + gd->arch.ram_buf = os_malloc(CONFIG_SYS_SDRAM_SIZE); + assert(gd->arch.ram_buf); + gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + + return 0; +} +#endif + static int setup_fdt(void) { #ifdef CONFIG_OF_EMBED @@ -470,7 +490,7 @@ static int reserve_malloc(void) static int reserve_board(void) { gd->dest_addr_sp -= sizeof(bd_t); - gd->bd = (bd_t *)gd->dest_addr_sp; + gd->bd = (bd_t *)map_sysmem(gd->dest_addr_sp, sizeof(bd_t)); memset(gd->bd, '\0', sizeof(bd_t)); debug("Reserving %zu Bytes for Board Info at: %08lx\n", sizeof(bd_t), gd->dest_addr_sp); @@ -489,7 +509,7 @@ static int setup_machine(void) static int reserve_global_data(void) { gd->dest_addr_sp -= sizeof(gd_t); - gd->new_gd = (gd_t *)gd->dest_addr_sp; + gd->new_gd = (gd_t *)map_sysmem(gd->dest_addr_sp, sizeof(gd_t)); debug("Reserving %zu Bytes for Global Data at: %08lx\n", sizeof(gd_t), gd->dest_addr_sp); return 0; @@ -506,9 +526,9 @@ static int reserve_fdt(void) gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); gd->dest_addr_sp -= gd->fdt_size; - gd->new_fdt = (void *)gd->dest_addr_sp; - debug("Reserving %lu Bytes for FDT at: %p\n", - gd->fdt_size, gd->new_fdt); + gd->new_fdt = map_sysmem(gd->dest_addr_sp, gd->fdt_size); + debug("Reserving %lu Bytes for FDT at: %08lx\n", + gd->fdt_size, gd->dest_addr_sp); } return 0; @@ -709,8 +729,9 @@ static int setup_reloc(void) memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); debug("Relocation Offset is: %08lx\n", gd->reloc_off); - debug("Relocating to %08lx, new gd at %p, sp at %08lx\n", - gd->dest_addr, gd->new_gd, gd->dest_addr_sp); + debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n", + gd->dest_addr, (ulong)map_to_sysmem(gd->new_gd), + gd->dest_addr_sp); return 0; } @@ -736,6 +757,8 @@ static int jump_to_copy(void) * (CPU cache) */ board_init_f_r_trampoline(gd->start_addr_sp); +#elif defined(CONFIG_SANDBOX) + board_init_r(gd->new_gd, 0); #else relocate_code(gd->dest_addr_sp, gd->new_gd, gd->dest_addr); #endif @@ -758,6 +781,9 @@ static init_fnc_t init_sequence_f[] = { !defined(CONFIG_MPC86xx) && !defined(CONFIG_X86) zero_global_data, #endif +#ifdef CONFIG_SANDBOX + setup_ram_buf, +#endif setup_fdt, setup_mon_len, #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) @@ -816,8 +842,11 @@ static init_fnc_t init_sequence_f[] = { init_baud_rate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ -#if defined(CONFIG_X86) && defined(CONFIG_OF_CONTROL) - prepare_fdt, /* TODO(sjg@chromium.org): remove */ +#ifdef CONFIG_SANDBOX + sandbox_early_getopt_check, +#endif +#ifdef CONFIG_OF_CONTROL + fdtdec_prepare_fdt, #endif display_options, /* say that we are here */ display_text_info, /* show debugging info if required */ @@ -1007,5 +1036,9 @@ void board_init_f_r(void) void hang(void) { puts("### ERROR ### Please RESET the board ###\n"); +#ifdef CONFIG_SANDBOX + os_exit(0); +#else for (;;); +#endif } diff --git a/common/board_r.c b/common/board_r.c index 2b17fa6..f801e41 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -136,7 +136,7 @@ static int initr_reloc_global_data(void) { #ifdef CONFIG_SYS_SYM_OFFSETS monitor_flash_len = _end_ofs; -#else +#elif !defined(CONFIG_SANDBOX) monitor_flash_len = (ulong)&__init_end - gd->dest_addr; #endif #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) @@ -264,7 +264,8 @@ static int initr_malloc(void) /* The malloc area is immediately below the monitor copy in DRAM */ malloc_start = gd->dest_addr - TOTAL_MALLOC_LEN; - mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN); + mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN), + TOTAL_MALLOC_LEN); return 0; } @@ -691,6 +692,9 @@ static int initr_modem(void) static int run_main_loop(void) { +#ifdef CONFIG_SANDBOX + sandbox_main_loop_init(); +#endif /* main_loop() can return to retry autoboot, if so just run it again */ for (;;) main_loop(); -- cgit v1.1 From f828bf25fe02f0d7148a9180988ab4d5681b8195 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:41 +0000 Subject: sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file With sandbox it is tricky to add an FDT to the image at build time (or later) since we build an ELF file, not a plain binary, and the address space of the whole U-Boot is not accessible in the emulated memory map of sandbox. Sandbox can read files directly from the host, though, so add an option to read an FDT from a host file on start-up. Signed-off-by: Simon Glass --- common/board_f.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 2045055..3a6638f 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -31,6 +31,7 @@ #include #include #include +#include #if defined(CONFIG_CMD_IDE) #include #endif @@ -305,6 +306,55 @@ __weak int arch_cpu_init(void) return 0; } +#ifdef CONFIG_OF_HOSTFILE + +#define CHECK(x) err = (x); if (err) goto failed; + +/* Create an empty device tree blob */ +static int make_empty_fdt(void *fdt) +{ + int err; + + CHECK(fdt_create(fdt, 256)); + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + + return 0; +failed: + printf("Unable to create empty FDT: %s\n", fdt_strerror(err)); + return -EACCES; +} + +static int read_fdt_from_file(void) +{ + struct sandbox_state *state = state_get_current(); + void *blob; + int size; + int err; + + blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, 0); + if (!state->fdt_fname) { + err = make_empty_fdt(blob); + if (!err) + goto done; + return err; + } + err = fs_set_blk_dev("host", NULL, FS_TYPE_SANDBOX); + if (err) + return err; + size = fs_read(state->fdt_fname, CONFIG_SYS_FDT_LOAD_ADDR, 0, 0); + if (size < 0) + return -EIO; + +done: + gd->fdt_blob = blob; + + return 0; +} +#endif + #ifdef CONFIG_SANDBOX static int setup_ram_buf(void) { @@ -328,6 +378,11 @@ static int setup_fdt(void) # else gd->fdt_blob = (ulong *)&_end; # endif +#elif defined(CONFIG_OF_HOSTFILE) + if (read_fdt_from_file()) { + puts("Failed to read control FDT\n"); + return -1; + } #endif /* Allow the early environment to override the fdt address */ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, -- cgit v1.1 From d14da91307d8378ea9a99044165e83b79dec67a1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:42 +0000 Subject: fdt: Add a parameter to fdt_valid() At present this only checks working_fdt, but we want to check other FDTs also. So add the FDT to check as a parameter to fdt_valid(). Signed-off-by: Simon Glass --- common/cmd_fdt.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'common') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index ac77a08..07072f3 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -43,7 +43,7 @@ */ DECLARE_GLOBAL_DATA_PTR; -static int fdt_valid(void); +static int fdt_valid(struct fdt_header **blobp); static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); static int fdt_print(const char *pathp, char *prop, int depth); static int is_printable_string(const void *data, int len); @@ -104,9 +104,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * Set the address [and length] of the fdt. */ if (argc == 2) { - if (!fdt_valid()) { + if (!fdt_valid(&working_fdt)) return 1; - } printf("The address of the fdt is %p\n", working_fdt); return 0; } @@ -114,9 +113,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) addr = simple_strtoul(argv[2], NULL, 16); set_working_fdt_addr((void *)addr); - if (!fdt_valid()) { + if (!fdt_valid(&working_fdt)) return 1; - } if (argc >= 4) { int len; @@ -167,9 +165,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * Set the address and length of the fdt. */ working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); - if (!fdt_valid()) { + if (!fdt_valid(&working_fdt)) return 1; - } newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); @@ -592,16 +589,23 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /****************************************************************************/ -static int fdt_valid(void) +/** + * fdt_valid() - Check if an FDT is valid. If not, change it to NULL + * + * @blobp: Pointer to FDT pointer + * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL) + */ +static int fdt_valid(struct fdt_header **blobp) { - int err; + const void *blob = *blobp; + int err; - if (working_fdt == NULL) { + if (blob == NULL) { printf ("The address of the fdt is invalid (NULL).\n"); return 0; } - err = fdt_check_header(working_fdt); + err = fdt_check_header(blob); if (err == 0) return 1; /* valid */ @@ -611,23 +615,21 @@ static int fdt_valid(void) * Be more informative on bad version. */ if (err == -FDT_ERR_BADVERSION) { - if (fdt_version(working_fdt) < + if (fdt_version(blob) < FDT_FIRST_SUPPORTED_VERSION) { printf (" - too old, fdt %d < %d", - fdt_version(working_fdt), + fdt_version(blob), FDT_FIRST_SUPPORTED_VERSION); - working_fdt = NULL; } - if (fdt_last_comp_version(working_fdt) > + if (fdt_last_comp_version(blob) > FDT_LAST_SUPPORTED_VERSION) { printf (" - too new, fdt %d > %d", - fdt_version(working_fdt), + fdt_version(blob), FDT_LAST_SUPPORTED_VERSION); - working_fdt = NULL; } - return 0; } printf("\n"); + *blobp = NULL; return 0; } return 1; -- cgit v1.1 From 76b8f79c299ee8029c64c14a65cb0615bad77319 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:43 +0000 Subject: Add getenv_hex() to return an environment variable as hex This conversion is required in a number of places in U-Boot. Add a standard function to provide this feature, so we avoid all the different variations in the way it is coded. Signed-off-by: Simon Glass --- common/cmd_nvedit.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'common') diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 68b0f4f..d893aa1 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -315,6 +315,21 @@ int setenv_hex(const char *varname, ulong value) return setenv(varname, str); } +ulong getenv_hex(const char *varname, ulong default_val) +{ + const char *s; + ulong value; + char *endp; + + s = getenv(varname); + if (s) + value = simple_strtoul(s, &endp, 16); + if (!s || endp == s) + return default_val; + + return value; +} + #ifndef CONFIG_SPL_BUILD static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { -- cgit v1.1 From 4b5786550db2da6192f8d5f38eeccbb372f878a8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:44 +0000 Subject: fdt: Allow fdt command to check and update control FDT There is an existing fdt command to deal with the working FDT. Enhance this to support the control FDT also (CONFIG_OF_CONTROL). Signed-off-by: Simon Glass --- common/cmd_fdt.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'common') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 07072f3..e582961 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -100,38 +100,59 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) */ if (argv[1][0] == 'a') { unsigned long addr; + int control = 0; + struct fdt_header *blob; /* * Set the address [and length] of the fdt. */ - if (argc == 2) { - if (!fdt_valid(&working_fdt)) + argc -= 2; + argv += 2; +/* Temporary #ifdef - some archs don't have fdt_blob yet */ +#ifdef CONFIG_OF_CONTROL + if (argc && !strcmp(*argv, "-c")) { + control = 1; + argc--; + argv++; + } +#endif + if (argc == 0) { + if (control) + blob = (struct fdt_header *)gd->fdt_blob; + else + blob = working_fdt; + if (!blob || !fdt_valid(&blob)) return 1; - printf("The address of the fdt is %p\n", working_fdt); + printf("The address of the fdt is %#08lx\n", + control ? (ulong)blob : + getenv_hex("fdtaddr", 0)); return 0; } - addr = simple_strtoul(argv[2], NULL, 16); - set_working_fdt_addr((void *)addr); - - if (!fdt_valid(&working_fdt)) + addr = simple_strtoul(argv[0], NULL, 16); + blob = (struct fdt_header *)addr; + if (!fdt_valid(&blob)) return 1; + if (control) + gd->fdt_blob = blob; + else + set_working_fdt_addr((void *)addr); - if (argc >= 4) { + if (argc >= 2) { int len; int err; /* * Optional new length */ - len = simple_strtoul(argv[3], NULL, 16); - if (len < fdt_totalsize(working_fdt)) { + len = simple_strtoul(argv[1], NULL, 16); + if (len < fdt_totalsize(blob)) { printf ("New length %d < existing length %d, " "ignoring.\n", - len, fdt_totalsize(working_fdt)); + len, fdt_totalsize(blob)); } else { /* * Open in place with a new length. */ - err = fdt_open_into(working_fdt, working_fdt, len); + err = fdt_open_into(blob, blob, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); @@ -960,7 +981,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) /********************************************************************/ #ifdef CONFIG_SYS_LONGHELP static char fdt_help_text[] = - "addr [] - Set the fdt location to \n" + "addr [-c] [] - Set the [control] fdt location to \n" #ifdef CONFIG_OF_BOARD_SETUP "fdt boardsetup - Do board-specific set up\n" #endif -- cgit v1.1 From a92fd6577ea17751ead9b50243e3c562125cf581 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:45 +0000 Subject: sandbox: fdt: Support fdt command for sandbox By using map_sysmem() we can get the fdt command to work correctly with sandbox. Signed-off-by: Simon Glass --- common/cmd_fdt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index e582961..edefd77 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -31,6 +31,7 @@ #include #include #include +#include #define MAX_LEVEL 32 /* how deeply nested we will go */ #define SCRATCHPAD 1024 /* bytes of scratchpad memory */ @@ -55,7 +56,10 @@ struct fdt_header *working_fdt; void set_working_fdt_addr(void *addr) { - working_fdt = addr; + void *buf; + + buf = map_sysmem((ulong)addr, 0); + working_fdt = buf; setenv_addr("fdtaddr", addr); } @@ -129,13 +133,13 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } addr = simple_strtoul(argv[0], NULL, 16); - blob = (struct fdt_header *)addr; + blob = map_sysmem(addr, 0); if (!fdt_valid(&blob)) return 1; if (control) gd->fdt_blob = blob; else - set_working_fdt_addr((void *)addr); + set_working_fdt_addr(blob); if (argc >= 2) { int len; -- cgit v1.1 From 095686d3f5e0b46e76d40e3ad0b75982a215024d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:47 +0000 Subject: Revert "fdt- Tell the FDT library where the device tree is" This reverts commit 3b73459ea3421e9f8c6c8c62e1d3fe458ca5bc56. In practice it doesn't seem like a good idea to make the the working FDT point to the control FDT. Now that we can access the control FDT using the 'fdt' command, there is no need for this feature. Remove it. Signed-off-by: Simon Glass --- common/main.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'common') diff --git a/common/main.c b/common/main.c index a15f020..953ef29 100644 --- a/common/main.c +++ b/common/main.c @@ -45,10 +45,6 @@ #include #endif -#ifdef CONFIG_OF_LIBFDT -#include -#endif /* CONFIG_OF_LIBFDT */ - #include #include #include @@ -376,10 +372,6 @@ void main_loop (void) bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); -#if defined CONFIG_OF_CONTROL - set_working_fdt_addr((void *)gd->fdt_blob); -#endif /* CONFIG_OF_CONTROL */ - #ifdef CONFIG_BOOTCOUNT_LIMIT bootcount = bootcount_load(); bootcount++; -- cgit v1.1 From 4ca30d60248b42ac6f949b3e797fbec939387cb0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:49 +0000 Subject: sandbox: Support 'source' command Enhance the source command to work with sandbox, by using map_sysmem() to convert a ulong address into a pointer. Signed-off-by: Simon Glass --- common/cmd_source.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/cmd_source.c b/common/cmd_source.c index 02a862c..f0d7f52 100644 --- a/common/cmd_source.c +++ b/common/cmd_source.c @@ -36,6 +36,7 @@ #include #include #include +#include #if defined(CONFIG_8xx) #include #endif @@ -44,9 +45,10 @@ int source (ulong addr, const char *fit_uname) { ulong len; - image_header_t *hdr; + const image_header_t *hdr; ulong *data; int verify; + void *buf; #if defined(CONFIG_FIT) const void* fit_hdr; int noffset; @@ -56,9 +58,10 @@ source (ulong addr, const char *fit_uname) verify = getenv_yesno ("verify"); - switch (genimg_get_format ((void *)addr)) { + buf = map_sysmem(addr, 0); + switch (genimg_get_format(buf)) { case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; + hdr = buf; if (!image_check_magic (hdr)) { puts ("Bad magic number\n"); @@ -104,7 +107,7 @@ source (ulong addr, const char *fit_uname) return 1; } - fit_hdr = (const void *)addr; + fit_hdr = buf; if (!fit_check_format (fit_hdr)) { puts ("Bad FIT image format\n"); return 1; -- cgit v1.1 From 7eb2c8d573ad932bf67095f11c6b3beba41064f2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 20 Apr 2013 08:42:51 +0000 Subject: sandbox: fs: Add support for saving files to host filesystem This allows write of files from the host filesystem in sandbox. There is currently no concept of overwriting the file and removing its existing contents - all writing is done on top of what is there. This means that writing 10 bytes to the start of a 1KB file will only update those 10 bytes, not truncate the file to 10 byte slong. If the file does not exist it is created. Signed-off-by: Simon Glass --- common/cmd_sandbox.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/cmd_sandbox.c b/common/cmd_sandbox.c index 206a486..a28a844 100644 --- a/common/cmd_sandbox.c +++ b/common/cmd_sandbox.c @@ -32,9 +32,16 @@ static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc, return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); } +static int do_sandbox_save(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_save(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX, 16); +} + static cmd_tbl_t cmd_sandbox_sub[] = { - U_BOOT_CMD_MKENT(load, 3, 0, do_sandbox_load, "", ""), + U_BOOT_CMD_MKENT(load, 7, 0, do_sandbox_load, "", ""), U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""), + U_BOOT_CMD_MKENT(save, 6, 0, do_sandbox_save, "", ""), }; static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, @@ -56,8 +63,11 @@ static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, } U_BOOT_CMD( - sb, 6, 1, do_sandbox, + sb, 8, 1, do_sandbox, "Miscellaneous sandbox commands", - "load host [ ] - load a file from host\n" - "sb ls host - save a file to host" + "load host [ ] - " + "load a file from host\n" + "sb ls host - list files on host\n" + "sb save host [] - " + "save a file to host\n" ); -- cgit v1.1 From ea009d4743ab4b801703982086e053e74266ff4c Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:28 +0000 Subject: hashtable: preparations to use hexport_r() for "env grep" The output of "env grep" is unsorted, and printing is done by a private implementation to parse the hash table. We have all the needed code in place in hexport_r() alsready, so let's use this instead. Here we prepare the code for this, without any functional changes yet. Signed-off-by: Wolfgang Denk --- common/cmd_nvedit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index d893aa1..49b9d74 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2010 + * (C) Copyright 2000-2013 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH @@ -892,7 +892,9 @@ NXTARG: ; argv++; if (sep) { /* export as text file */ - len = hexport_r(&env_htab, sep, 0, &addr, size, argc, argv); + len = hexport_r(&env_htab, sep, + H_MATCH_KEY | H_MATCH_IDENT, + &addr, size, argc, argv); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; @@ -910,7 +912,9 @@ NXTARG: ; else /* export as raw binary data */ res = addr; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, argc, argv); + len = hexport_r(&env_htab, '\0', + H_MATCH_KEY | H_MATCH_IDENT, + &res, ENV_SIZE, argc, argv); if (len < 0) { error("Cannot export environment: errno = %d\n", errno); return 1; -- cgit v1.1 From 5a31ea04c9ee5544fbb70ad7597ea4b294840eab Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:29 +0000 Subject: "env grep" - reimplement command using hexport_r() Also drop hstrstr_r() which is not needed any more. The new code is way more flexible. Signed-off-by: Wolfgang Denk --- common/cmd_nvedit.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'common') diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 49b9d74..a4b71f8 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -164,31 +164,25 @@ static int do_env_print(cmd_tbl_t *cmdtp, int flag, int argc, static int do_env_grep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ENTRY *match; - unsigned char matched[env_htab.size / 8]; - int rcode = 1, arg = 1, idx; + char *res = NULL; + int len; if (argc < 2) return CMD_RET_USAGE; - memset(matched, 0, env_htab.size / 8); + len = hexport_r(&env_htab, '\n', + flag | H_MATCH_BOTH | H_MATCH_SUBSTR, + &res, 0, argc, argv); - while (arg <= argc) { - idx = 0; - while ((idx = hstrstr_r(argv[arg], idx, &match, &env_htab))) { - if (!(matched[idx / 8] & (1 << (idx & 7)))) { - puts(match->key); - puts("="); - puts(match->data); - puts("\n"); - } - matched[idx / 8] |= 1 << (idx & 7); - rcode = 0; - } - arg++; + if (len > 0) { + puts(res); + free(res); } - return rcode; + if (len < 2) + return 1; + + return 0; } #endif #endif /* CONFIG_SPL_BUILD */ -- cgit v1.1 From d87244d5af58cbc2d9cc3f5314648deb7810f10a Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:30 +0000 Subject: "env grep" - add options to grep in name, value, or both. Add options to "env grep" command: -n : search only the envrironment variable names -v : search only their values -b : search both names and values (= default) An option "--" will stop parsing options, so to print variables that contain the striing "- " please use: env grep -- "- " Or to print all environment varioables which have a '-' in their name, use: env grep -n -- - Signed-off-by: Wolfgang Denk --- common/cmd_nvedit.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'common') diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index a4b71f8..9158b96 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -165,13 +165,39 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *res = NULL; - int len; + int len, grep_flags; if (argc < 2) return CMD_RET_USAGE; + grep_flags = H_MATCH_BOTH; + + while (argc > 1 && **(argv + 1) == '-') { + char *arg = *++argv; + + --argc; + while (*++arg) { + switch (*arg) { + case 'n': /* grep for name */ + grep_flags = H_MATCH_KEY; + break; + case 'v': /* grep for value */ + grep_flags = H_MATCH_DATA; + break; + case 'b': /* grep for both */ + grep_flags = H_MATCH_BOTH; + break; + case '-': + goto DONE; + default: + return CMD_RET_USAGE; + } + } + } + +DONE: len = hexport_r(&env_htab, '\n', - flag | H_MATCH_BOTH | H_MATCH_SUBSTR, + flag | grep_flags | H_MATCH_SUBSTR, &res, 0, argc, argv); if (len > 0) { @@ -1127,7 +1153,7 @@ static char env_help_text[] = "env flags - print variables that have non-default flags\n" #endif #if defined(CONFIG_CMD_GREPENV) - "env grep string [...] - search environment\n" + "env grep [-n | -v | -b] string [...] - search environment\n" #endif #if defined(CONFIG_CMD_IMPORTENV) "env import [-d] [-t | -b | -c] addr [size] - import environment\n" @@ -1174,8 +1200,10 @@ U_BOOT_CMD_COMPLETE( U_BOOT_CMD_COMPLETE( grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep, "search environment variables", - "string ...\n" - " - list environment name=value pairs matching 'string'", + "[-n | -v | -b] string ...\n" + " - list environment name=value pairs matching 'string'\n" + " \"-n\": search variable names; \"-v\": search values;\n" + " \"-b\": search both names and values (default)", var_complete ); #endif -- cgit v1.1 From be29df6a1ac286e6c482828db28ca96e187c7e00 Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:32 +0000 Subject: "env grep" - add support for regular expression matches When CONFIG_REGEX is enabled, the new option "-e" becomes available which causes regular expression matches to be used. This allows for example things like these: - print all MAC addresses: => env grep -e eth.*addr eth1addr=00:10:ec:80:c5:15 ethaddr=00:10:ec:00:c5:15 - print all variables that have at least 2 colons in their value: => env grep -v -e :.*: addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1 eth1addr=00:10:ec:80:c5:15 ethaddr=00:10:ec:00:c5:15 ver=U-Boot 2013.04-rc1-00289-g497746b-dirty (Mar 22 2013 - 12:50:25) etc. Signed-off-by: Wolfgang Denk --- common/cmd_nvedit.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 9158b96..f8dc38e 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -165,12 +165,13 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *res = NULL; - int len, grep_flags; + int len, grep_how, grep_what; if (argc < 2) return CMD_RET_USAGE; - grep_flags = H_MATCH_BOTH; + grep_how = H_MATCH_SUBSTR; /* default: substring search */ + grep_what = H_MATCH_BOTH; /* default: grep names and values */ while (argc > 1 && **(argv + 1) == '-') { char *arg = *++argv; @@ -178,14 +179,19 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, --argc; while (*++arg) { switch (*arg) { +#ifdef CONFIG_REGEX + case 'e': /* use regex matching */ + grep_how = H_MATCH_REGEX; + break; +#endif case 'n': /* grep for name */ - grep_flags = H_MATCH_KEY; + grep_what = H_MATCH_KEY; break; case 'v': /* grep for value */ - grep_flags = H_MATCH_DATA; + grep_what = H_MATCH_DATA; break; case 'b': /* grep for both */ - grep_flags = H_MATCH_BOTH; + grep_what = H_MATCH_BOTH; break; case '-': goto DONE; @@ -197,7 +203,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag, DONE: len = hexport_r(&env_htab, '\n', - flag | grep_flags | H_MATCH_SUBSTR, + flag | grep_what | grep_how, &res, 0, argc, argv); if (len > 0) { @@ -1153,8 +1159,12 @@ static char env_help_text[] = "env flags - print variables that have non-default flags\n" #endif #if defined(CONFIG_CMD_GREPENV) +#ifdef CONFIG_REGEX + "env grep [-e] [-n | -v | -b] string [...] - search environment\n" +#else "env grep [-n | -v | -b] string [...] - search environment\n" #endif +#endif #if defined(CONFIG_CMD_IMPORTENV) "env import [-d] [-t | -b | -c] addr [size] - import environment\n" #endif @@ -1200,8 +1210,15 @@ U_BOOT_CMD_COMPLETE( U_BOOT_CMD_COMPLETE( grepenv, CONFIG_SYS_MAXARGS, 0, do_env_grep, "search environment variables", +#ifdef CONFIG_REGEX + "[-e] [-n | -v | -b] string ...\n" +#else "[-n | -v | -b] string ...\n" +#endif " - list environment name=value pairs matching 'string'\n" +#ifdef CONFIG_REGEX + " \"-e\": enable regular expressions;\n" +#endif " \"-n\": search variable names; \"-v\": search values;\n" " \"-b\": search both names and values (default)", var_complete -- cgit v1.1 From 103c94b10481cf8479c9d0356e5202bc9200a04f Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:33 +0000 Subject: setexpr: simplify code, improve help message Simplify the argument checking for the "setexpr" command. This is done mainly to make future extensions easier. Also improve the help message for the one argument version of the command - this does not "load an address", but a value, which in this context may be a plain number or a pointer dereference. Signed-off-by: Wolfgang Denk --- common/cmd_setexpr.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c index 7a38e94..ccd87f4 100644 --- a/common/cmd_setexpr.c +++ b/common/cmd_setexpr.c @@ -56,22 +56,26 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong value; int w; - /* Validate arguments */ - if (argc != 5 && argc != 3) - return CMD_RET_USAGE; - if (argc == 5 && strlen(argv[3]) != 1) + if (argc < 3) return CMD_RET_USAGE; w = cmd_get_data_size(argv[0], 4); a = get_arg(argv[2], w); + /* plain assignment: "setexpr name value" */ if (argc == 3) { setenv_hex(argv[1], a); - return 0; } + /* standard operators: "setexpr name val1 op val2" */ + if (argc != 5) + return CMD_RET_USAGE; + + if (strlen(argv[3]) != 1) + return CMD_RET_USAGE; + b = get_arg(argv[4], w); switch (argv[3][0]) { @@ -117,6 +121,6 @@ U_BOOT_CMD( " express specified by . can be &, |, ^, +, -, *, /, %\n" " size argument is only meaningful if value1 and/or value2 are\n" " memory addresses (*)\n" - "setexpr[.b, .w, .l] name *value\n" - " - load a memory address into a variable" + "setexpr[.b, .w, .l] name [*]value\n" + " - load a value into a variable" ); -- cgit v1.1 From 855f18ea0e6ff83ec9ed5af74e82bc4bff30867d Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Sat, 23 Mar 2013 23:50:34 +0000 Subject: setexpr: add regex substring matching and substitution Add "setexpr name gsub r s [t]" and "setexpr name sub r s [t]" commands which implement substring matching for the regular expression in the string , and substitution of the string . The result is assigned to the environment variable . If is not supplied, the previous value of is used instead. "gsub" performs global substitution, while "sub" will replace only the first substring. Both commands are closely modeled after the gawk functions with the same names. Examples: - Generate broadcast address by substituting the last two numbers of the IP address by "255.255": => print ipaddr ipaddr=192.168.1.104 => setexpr broadcast sub "(.*\\.).*\\..*" "\\1255.255" $ipaddr broadcast=192.168.255.255 - Depending on keyboard configuration (German vs. US keyboard) a barcode scanner may initialize the MAC address as C0:E5:4E:02:06:DC or as C0>E5>4E>02>06>DC. Make sure we always have a correct value: => print ethaddr ethaddr=C0>E5>4E>02>06>DC => setexpr ethaddr gsub > : ethaddr=C0:E5:4E:02:06:DC - Do the same, but substitute one step at a time in a loop until no futher matches: => setenv ethaddr C0>E5>4E>02>06>DC => while setexpr ethaddr sub > : > do > echo ----- > done ethaddr=C0:E5>4E>02>06>DC ----- ethaddr=C0:E5:4E>02>06>DC ----- ethaddr=C0:E5:4E:02>06>DC ----- ethaddr=C0:E5:4E:02:06>DC ----- ethaddr=C0:E5:4E:02:06:DC ----- C0:E5:4E:02:06:DC: No match => print ethaddr ethaddr=C0:E5:4E:02:06:DC etc. To enable this feature, the CONFIG_REGEX option has to be defined in the board config file. Signed-off-by: Wolfgang Denk --- common/cmd_setexpr.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 277 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c index ccd87f4..93cb255 100644 --- a/common/cmd_setexpr.c +++ b/common/cmd_setexpr.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Freescale Semiconductor, Inc. + * Copyright 2013 Wolfgang Denk * * See file CREDITS for list of people who contributed to this * project. @@ -50,13 +51,263 @@ static ulong get_arg(char *s, int w) } } +#ifdef CONFIG_REGEX + +#include + +#define SLRE_BUFSZ 16384 +#define SLRE_PATSZ 4096 + +/* + * memstr - Find the first substring in memory + * @s1: The string to be searched + * @s2: The string to search for + * + * Similar to and based on strstr(), + * but strings do not need to be NUL terminated. + */ +static char *memstr(const char *s1, int l1, const char *s2, int l2) +{ + if (!l2) + return (char *)s1; + + while (l1 >= l2) { + l1--; + if (!memcmp(s1, s2, l2)) + return (char *)s1; + s1++; + } + return NULL; +} + +static char *substitute(char *string, /* string buffer */ + int *slen, /* current string length */ + int ssize, /* string bufer size */ + const char *old,/* old (replaced) string */ + int olen, /* length of old string */ + const char *new,/* new (replacement) string */ + int nlen) /* length of new string */ +{ + char *p = memstr(string, *slen, old, olen); + + if (p == NULL) + return NULL; + + debug("## Match at pos %ld: match len %d, subst len %d\n", + (long)(p - string), olen, nlen); + + /* make sure replacement matches */ + if (*slen + nlen - olen > ssize) { + printf("## error: substitution buffer overflow\n"); + return NULL; + } + + /* move tail if needed */ + if (olen != nlen) { + int tail, len; + + len = (olen > nlen) ? olen : nlen; + + tail = ssize - (p + len - string); + + debug("## tail len %d\n", tail); + + memmove(p + nlen, p + olen, tail); + } + + /* insert substitue */ + memcpy(p, new, nlen); + + *slen += nlen - olen; + + return p + nlen; +} + +/* + * Perform regex operations on a environment variable + * + * Returns 0 if OK, 1 in case of errors. + */ +static int regex_sub(const char *name, + const char *r, const char *s, const char *t, + int global) +{ + struct slre slre; + char data[SLRE_BUFSZ]; + char *datap = data; + const char *value; + int res, len, nlen, loop; + + if (name == NULL) + return 1; + + if (slre_compile(&slre, r) == 0) { + printf("Error compiling regex: %s\n", slre.err_str); + return 1; + } + + if (t == NULL) { + value = getenv(name); + + if (value == NULL) { + printf("## Error: variable \"%s\" not defined\n", name); + return 1; + } + t = value; + } + + debug("REGEX on %s=%s\n", name, t); + debug("REGEX=\"%s\", SUBST=\"%s\", GLOBAL=%d\n", + r, s ? s : "", global); + + len = strlen(t); + if (len + 1 > SLRE_BUFSZ) { + printf("## error: subst buffer overflow: have %d, need %d\n", + SLRE_BUFSZ, len + 1); + return 1; + } + + strcpy(data, t); + + if (s == NULL) + nlen = 0; + else + nlen = strlen(s); + + for (loop = 0;; loop++) { + struct cap caps[slre.num_caps + 2]; + char nbuf[SLRE_PATSZ]; + const char *old; + char *np; + int i, olen; + + (void) memset(caps, 0, sizeof(caps)); + + res = slre_match(&slre, datap, len, caps); + + debug("Result: %d\n", res); + + for (i = 0; i < slre.num_caps; i++) { + if (caps[i].len > 0) { + debug("Substring %d: [%.*s]\n", i, + caps[i].len, caps[i].ptr); + } + } + + if (res == 0) { + if (loop == 0) { + printf("%s: No match\n", t); + return 1; + } else { + break; + } + } + + debug("## MATCH ## %s\n", data); + + if (s == NULL) { + printf("%s=%s\n", name, t); + return 1; + } + + old = caps[0].ptr; + olen = caps[0].len; + + if (nlen + 1 >= SLRE_PATSZ) { + printf("## error: pattern buffer overflow: have %d, need %d\n", + SLRE_BUFSZ, nlen + 1); + return 1; + } + strcpy(nbuf, s); + + debug("## SUBST(1) ## %s\n", nbuf); + + /* + * Handle back references + * + * Support for \0 ... \9, where \0 is the + * whole matched pattern (similar to &). + * + * Implementation is a bit simpleminded as + * backrefs are substituted sequentially, one + * by one. This will lead to somewhat + * unexpected results if the replacement + * strings contain any \N strings then then + * may get substitued, too. We accept this + * restriction for the sake of simplicity. + */ + for (i = 0; i < 10; ++i) { + char backref[2] = { + '\\', + '0', + }; + + if (caps[i].len == 0) + break; + + backref[1] += i; + + debug("## BACKREF %d: replace \"%.*s\" by \"%.*s\" in \"%s\"\n", + i, + 2, backref, + caps[i].len, caps[i].ptr, + nbuf); + + for (np = nbuf;;) { + char *p = memstr(np, nlen, backref, 2); + + if (p == NULL) + break; + + np = substitute(np, &nlen, + SLRE_PATSZ, + backref, 2, + caps[i].ptr, caps[i].len); + + if (np == NULL) + return 1; + } + } + debug("## SUBST(2) ## %s\n", nbuf); + + datap = substitute(datap, &len, SLRE_BUFSZ, + old, olen, + nbuf, nlen); + + if (datap == NULL) + return 1; + + debug("## REMAINDER: %s\n", datap); + + debug("## RESULT: %s\n", data); + + if (!global) + break; + } + debug("## FINAL (now setenv()) : %s\n", data); + + printf("%s=%s\n", name, data); + + return setenv(name, data); +} +#endif + static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong a, b; ulong value; int w; - if (argc < 3) + /* + * We take 3, 5, or 6 arguments: + * 3 : setexpr name value + * 5 : setexpr name val1 op val2 + * setexpr name [g]sub r s + * 6 : setexpr name [g]sub r s t + */ + + /* > 6 already tested by max command args */ + if ((argc < 3) || (argc == 4)) return CMD_RET_USAGE; w = cmd_get_data_size(argv[0], 4); @@ -69,6 +320,19 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } + /* 5 or 6 args (6 args only with [g]sub) */ +#ifdef CONFIG_REGEX + /* + * rexep handling: "setexpr name [g]sub r s [t]" + * with 5 args, "t" will be NULL + */ + if (strcmp(argv[2], "gsub") == 0) + return regex_sub(argv[1], argv[3], argv[4], argv[5], 1); + + if (strcmp(argv[2], "sub") == 0) + return regex_sub(argv[1], argv[3], argv[4], argv[5], 0); +#endif + /* standard operators: "setexpr name val1 op val2" */ if (argc != 5) return CMD_RET_USAGE; @@ -114,13 +378,23 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } U_BOOT_CMD( - setexpr, 5, 0, do_setexpr, + setexpr, 6, 0, do_setexpr, "set environment variable as the result of eval expression", "[.b, .w, .l] name [*]value1 [*]value2\n" " - set environment variable 'name' to the result of the evaluated\n" - " express specified by . can be &, |, ^, +, -, *, /, %\n" + " expression specified by . can be &, |, ^, +, -, *, /, %\n" " size argument is only meaningful if value1 and/or value2 are\n" " memory addresses (*)\n" "setexpr[.b, .w, .l] name [*]value\n" " - load a value into a variable" +#ifdef CONFIG_REGEX + "\n" + "setexpr name gsub r s [t]\n" + " - For each substring matching the regular expression in the\n" + " string , substitute the string . The result is\n" + " assigned to . If is not supplied, use the old\n" + " value of \n" + "setexpr name sub r s [t]\n" + " - Just like gsub(), but replace only the first matching substring" +#endif ); -- cgit v1.1 From 0472fbfd3250d1a33d3de78afdcbf24f78ac026b Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Tue, 9 Apr 2013 21:11:56 +0000 Subject: part/dev_desc: Add log2 of blocksize to block_dev_desc data struct log2 of the device block size serves as the shift value used to calculate the block number to read in file systems when implementing avaiable block sizes. It is needed quite often in file systems thus it is pre-calculated and stored in the block device descriptor. Signed-off-by: Egbert Eich --- common/cmd_ide.c | 5 +++++ common/cmd_sata.c | 1 + common/cmd_scsi.c | 4 ++++ common/usb_storage.c | 1 + 4 files changed, 11 insertions(+) (limited to 'common') diff --git a/common/cmd_ide.c b/common/cmd_ide.c index 0105bdb..78b4aa7 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -455,6 +455,8 @@ void ide_init(void) ide_dev_desc[i].dev = i; ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); ide_dev_desc[i].lba = 0; ide_dev_desc[i].block_read = ide_read; ide_dev_desc[i].block_write = ide_write; @@ -806,6 +808,7 @@ static void ide_ident(block_dev_desc_t *dev_desc) /* assuming HD */ dev_desc->type = DEV_TYPE_HARDDISK; dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); dev_desc->lun = 0; /* just to fill something in... */ #if 0 /* only used to test the powersaving mode, @@ -1448,6 +1451,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc) dev_desc->lun = 0; dev_desc->lba = 0; dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); dev_desc->type = iobuf[0] & 0x1f; if ((iobuf[1] & 0x80) == 0x80) @@ -1492,6 +1496,7 @@ static void atapi_inquiry(block_dev_desc_t *dev_desc) dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + ((unsigned long) iobuf[5] << 16) + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); #ifdef CONFIG_LBA48 /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ dev_desc->lba48 = 0; diff --git a/common/cmd_sata.c b/common/cmd_sata.c index 8d57285..5a57a37 100644 --- a/common/cmd_sata.c +++ b/common/cmd_sata.c @@ -44,6 +44,7 @@ int __sata_initialize(void) sata_dev_desc[i].type = DEV_TYPE_HARDDISK; sata_dev_desc[i].lba = 0; sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); sata_dev_desc[i].block_read = sata_read; sata_dev_desc[i].block_write = sata_write; diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 13b3d99..294d9f5 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -106,6 +106,8 @@ void scsi_scan(int mode) scsi_dev_desc[i].lun=0xff; scsi_dev_desc[i].lba=0; scsi_dev_desc[i].blksz=0; + scsi_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; scsi_dev_desc[i].vendor[0]=0; scsi_dev_desc[i].product[0]=0; @@ -166,6 +168,8 @@ void scsi_scan(int mode) } scsi_dev_desc[scsi_max_devs].lba=capacity; scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); scsi_dev_desc[scsi_max_devs].type=perq; init_part(&scsi_dev_desc[scsi_max_devs]); removable: diff --git a/common/usb_storage.c b/common/usb_storage.c index fb322b4..c5db044 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1430,6 +1430,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss, *capacity, *blksz); dev_desc->lba = *capacity; dev_desc->blksz = *blksz; + dev_desc->log2blksz = LOG2(dev_desc->blksz); dev_desc->type = perq; USB_STOR_PRINTF(" address %d\n", dev_desc->target); USB_STOR_PRINTF("partype: %d\n", dev_desc->part_type); -- cgit v1.1 From d2eae43ba803cff75b44a07d08d718ecdecdee94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Bie=C3=9Fmann?= Date: Thu, 18 Apr 2013 22:48:50 +0000 Subject: lib: consolidate hang() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete all occurrences of hang() and provide a generic function. Signed-off-by: Andreas Bießmann Acked-by: Albert ARIBAUD [trini: Modify check around puts() in hang.c slightly] Signed-off-by: Tom Rini --- common/board_f.c | 10 ---------- common/spl/spl.c | 7 ------- 2 files changed, 17 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 3a6638f..32e59fa 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -1087,13 +1087,3 @@ void board_init_f_r(void) hang(); } #endif /* CONFIG_X86 */ - -void hang(void) -{ - puts("### ERROR ### Please RESET the board ###\n"); -#ifdef CONFIG_SANDBOX - os_exit(0); -#else - for (;;); -#endif -} diff --git a/common/spl/spl.c b/common/spl/spl.c index 6715e0d..7ce2d5f 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -48,13 +48,6 @@ struct spl_image_info spl_image; /* Define board data structure */ static bd_t bdata __attribute__ ((section(".data"))); -inline void hang(void) -{ - puts("### ERROR ### Please RESET the board ###\n"); - for (;;) - ; -} - /* * Default function to determine if u-boot or the OS should * be started. This implementation always returns 1. -- cgit v1.1 From d196bd880347373237d73e0d115b4d51c68cf2ad Mon Sep 17 00:00:00 2001 From: Michael Heimpold Date: Wed, 10 Apr 2013 10:36:19 +0000 Subject: env_mmc: add support for redundant environment This patch add support for storing the environment redundant on mmc devices. Substantially it re-uses the logic from the NAND implementation, that means using an incremental counter for marking newer data. Signed-off-by: Michael Heimpold --- common/env_mmc.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/env_mmc.c b/common/env_mmc.c index 02bd5ae..9ca098f 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -32,6 +32,11 @@ #include #include +#if defined(CONFIG_ENV_SIZE_REDUND) && \ + (CONFIG_ENV_SIZE_REDUND != CONFIG_ENV_SIZE) +#error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE +#endif + char *env_name_spec = "MMC"; #ifdef ENV_IS_EMBEDDED @@ -46,9 +51,13 @@ DECLARE_GLOBAL_DATA_PTR; #define CONFIG_ENV_OFFSET 0 #endif -__weak int mmc_get_env_addr(struct mmc *mmc, u32 *env_addr) +__weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr) { *env_addr = CONFIG_ENV_OFFSET; +#ifdef CONFIG_ENV_OFFSET_REDUND + if (copy) + *env_addr = CONFIG_ENV_OFFSET_REDUND; +#endif return 0; } @@ -110,6 +119,10 @@ static inline int write_env(struct mmc *mmc, unsigned long size, return (n == blk_cnt) ? 0 : -1; } +#ifdef CONFIG_ENV_OFFSET_REDUND +static unsigned char env_flags; +#endif + int saveenv(void) { ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); @@ -117,16 +130,11 @@ int saveenv(void) char *res; struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); u32 offset; - int ret; + int ret, copy = 0; 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', 0, &res, ENV_SIZE, 0, NULL); if (len < 0) { @@ -136,7 +144,21 @@ int saveenv(void) } env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE); - printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV); + +#ifdef CONFIG_ENV_OFFSET_REDUND + env_new->flags = ++env_flags; /* increase the serial */ + + if (gd->env_valid == 1) + copy = 1; +#endif + + if (mmc_get_env_addr(mmc, copy, &offset)) { + ret = 1; + goto fini; + } + + printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", + CONFIG_SYS_MMC_ENV_DEV); if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) { puts("failed\n"); ret = 1; @@ -146,6 +168,10 @@ int saveenv(void) puts("done\n"); ret = 0; +#ifdef CONFIG_ENV_OFFSET_REDUND + gd->env_valid = gd->env_valid == 2 ? 1 : 2; +#endif + fini: fini_mmc_for_env(mmc); return ret; @@ -166,6 +192,93 @@ static inline int read_env(struct mmc *mmc, unsigned long size, return (n == blk_cnt) ? 0 : -1; } +#ifdef CONFIG_ENV_OFFSET_REDUND +void env_relocate_spec(void) +{ +#if !defined(ENV_IS_EMBEDDED) + struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); + u32 offset1, offset2; + int read1_fail = 0, read2_fail = 0; + int crc1_ok = 0, crc2_ok = 0; + env_t *ep, *tmp_env1, *tmp_env2; + int ret; + + tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); + tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); + if (tmp_env1 == NULL || tmp_env2 == NULL) { + puts("Can't allocate buffers for environment\n"); + ret = 1; + goto err; + } + + if (init_mmc_for_env(mmc)) { + ret = 1; + goto err; + } + + if (mmc_get_env_addr(mmc, 0, &offset1) || + mmc_get_env_addr(mmc, 1, &offset2)) { + ret = 1; + goto fini; + } + + read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1); + read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2); + + if (read1_fail && read2_fail) + puts("*** Error - No Valid Environment Area found\n"); + else if (read1_fail || read2_fail) + puts("*** Warning - some problems detected " + "reading environment; recovered successfully\n"); + + crc1_ok = !read1_fail && + (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); + crc2_ok = !read2_fail && + (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); + + if (!crc1_ok && !crc2_ok) { + ret = 1; + goto fini; + } else if (crc1_ok && !crc2_ok) { + gd->env_valid = 1; + } else if (!crc1_ok && crc2_ok) { + gd->env_valid = 2; + } else { + /* both ok - check serial */ + if (tmp_env1->flags == 255 && tmp_env2->flags == 0) + gd->env_valid = 2; + else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) + gd->env_valid = 1; + else if (tmp_env1->flags > tmp_env2->flags) + gd->env_valid = 1; + else if (tmp_env2->flags > tmp_env1->flags) + gd->env_valid = 2; + else /* flags are equal - almost impossible */ + gd->env_valid = 1; + } + + free(env_ptr); + + if (gd->env_valid == 1) + ep = tmp_env1; + else + ep = tmp_env2; + + env_flags = ep->flags; + env_import((char *)ep, 0); + ret = 0; + +fini: + fini_mmc_for_env(mmc); +err: + if (ret) + set_default_env(NULL); + + free(tmp_env1); + free(tmp_env2); +#endif +} +#else /* ! CONFIG_ENV_OFFSET_REDUND */ void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) @@ -179,7 +292,7 @@ void env_relocate_spec(void) goto err; } - if (mmc_get_env_addr(mmc, &offset)) { + if (mmc_get_env_addr(mmc, 0, &offset)) { ret = 1; goto fini; } @@ -199,3 +312,4 @@ err: set_default_env(NULL); #endif } +#endif /* CONFIG_ENV_OFFSET_REDUND */ -- cgit v1.1