From f13e7b2e993c61fed1f607962501e051940d6e80 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 8 Jan 2008 18:12:17 +0100 Subject: [new uImage] Cleanup image header pointer use in bootm code - use single image header pointer instead of a set of auxilliary variables. - add multi component image helper routines: get component size/data address Signed-off-by: Marian Balakowicz --- common/cmd_autoscript.c | 10 ++-- common/cmd_bootm.c | 153 ++++++++++++++++++++---------------------------- common/image.c | 86 +++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 94 deletions(-) (limited to 'common') diff --git a/common/cmd_autoscript.c b/common/cmd_autoscript.c index 3e68ced..53f8e83 100644 --- a/common/cmd_autoscript.c +++ b/common/cmd_autoscript.c @@ -54,7 +54,7 @@ autoscript (ulong addr) { ulong len; image_header_t *hdr = (image_header_t *)addr; - ulong *len_ptr; + ulong *data; char *cmd; int rcode = 0; int verify; @@ -84,9 +84,9 @@ autoscript (ulong addr) } /* get length of script */ - len_ptr = (ulong *)image_get_data (hdr); + data = (ulong *)image_get_data (hdr); - if ((len = image_to_cpu (*len_ptr)) == 0) { + if ((len = image_to_cpu (*data)) == 0) { puts ("Empty Script\n"); return 1; } @@ -97,10 +97,10 @@ autoscript (ulong addr) return 1; } - while (*len_ptr++); + while (*data++); /* make sure cmd is null terminated */ - memmove (cmd, (char *)len_ptr, len); + memmove (cmd, (char *)data, len); *(cmd + len) = 0; #ifdef CFG_HUSH_PARSER /*?? */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 2de1329..2d17bdd 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -93,14 +93,13 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); * - disabled interrupts. */ typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, /* of image to boot */ - ulong *len_ptr, /* multi-file image length table */ - int verify); /* getenv("verify")[0] != 'n' */ + int argc, char *argv[], + image_header_t *hdr, /* of image to boot */ + int verify); /* getenv("verify")[0] != 'n' */ extern boot_os_fn do_bootm_linux; static boot_os_fn do_bootm_netbsd; -#ifdef CONFIG_LYNXKDI +#if defined(CONFIG_LYNXKDI) static boot_os_fn do_bootm_lynxkdi; extern void lynxkdi_boot (image_header_t *); #endif @@ -116,8 +115,6 @@ extern uchar (*env_get_char)(int); /* Returns a character from the environment * static boot_os_fn do_bootm_artos; #endif -image_header_t header; - ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ @@ -126,34 +123,32 @@ ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ /*******************************************************************/ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - ulong iflag; - ulong addr; - ulong data, len; - ulong *len_ptr; - uint unc_len = CFG_BOOTM_LEN; - int i, verify; - char *name, *s; - int (*appl)(int, char *[]); - image_header_t *hdr = &header; + ulong iflag; + char *name, *s; + int (*appl)(int, char *[]); + uint unc_len = CFG_BOOTM_LEN; + int verify = getenv_verify(); - verify = getenv_verify (); + image_header_t *hdr; + ulong img_addr; + ulong os_data, os_len; if (argc < 2) { - addr = load_addr; + img_addr = load_addr; } else { - addr = simple_strtoul(argv[1], NULL, 16); + img_addr = simple_strtoul(argv[1], NULL, 16); } show_boot_progress (1); - printf ("## Booting image at %08lx ...\n", addr); + printf ("## Booting image at %08lx ...\n", img_addr); - /* Copy header so we can blank CRC field for re-calculation */ #ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - read_dataflash (addr, image_get_header_size (), (char *)&header); + if (addr_dataflash (img_addr)){ + hdr = (image_header_t *)CFG_LOAD_ADDR; + read_dataflash (img_addr, image_get_header_size (), (char *)hdr); } else #endif - memmove (&header, (char *)addr, image_get_header_size ()); + hdr = (image_header_t *)img_addr; if (!image_check_magic(hdr)) { puts ("Bad Magic Number\n"); @@ -170,23 +165,18 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) show_boot_progress (3); #ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - len = image_get_image_size (hdr); - read_dataflash(addr, len, (char *)CFG_LOAD_ADDR); - addr = CFG_LOAD_ADDR; - } + if (addr_dataflash (img_addr)) + read_dataflash (img_addr + image_get_header_size (), + image_get_data_size (hdr), + (char *)image_get_data (hdr)); #endif - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); - - len = image_get_data_size (hdr); - data = addr + image_get_header_size (); - len_ptr = (ulong *)data; + /* uImage is in a system RAM, pointed to by hdr */ + print_image_hdr (hdr); if (verify) { puts (" Verifying Checksum ... "); - if (!image_check_dcrc ((image_header_t *)addr)) { + if (!image_check_dcrc (hdr)) { printf ("Bad Data CRC\n"); show_boot_progress (-3); return 1; @@ -212,14 +202,12 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; case IH_TYPE_KERNEL: name = "Kernel Image"; + os_data = image_get_data (hdr); + os_len = image_get_data_size (hdr); break; case IH_TYPE_MULTI: name = "Multi-File Image"; - len = image_to_cpu (len_ptr[0]); - /* OS kernel is always the first image */ - data += 8; /* kernel_len + terminator */ - for (i=1; len_ptr[i]; ++i) - data += 4; + image_multi_getimg (hdr, 0, &os_data, &os_len); break; default: printf ("Wrong Image Type for %s command\n", cmdtp->name); @@ -248,13 +236,13 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) switch (image_get_comp (hdr)) { case IH_COMP_NONE: - if (image_get_load (hdr) == addr) { + if (image_get_load (hdr) == img_addr) { printf (" XIP %s ... ", name); } else { printf (" Loading %s ... ", name); memmove_wd ((void *)image_get_load (hdr), - (void *)data, len, CHUNKSZ); + (void *)os_data, os_len, CHUNKSZ); puts("OK\n"); } @@ -262,7 +250,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) case IH_COMP_GZIP: printf (" Uncompressing %s ... ", name); if (gunzip ((void *)image_get_load (hdr), unc_len, - (uchar *)data, &len) != 0) { + (uchar *)os_data, &os_len) != 0) { puts ("GUNZIP ERROR - must RESET board to recover\n"); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); @@ -276,9 +264,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - i = BZ2_bzBuffToBuffDecompress ((char*)image_get_load (hdr), - &unc_len, (char *)data, len, - CFG_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress ((char*)image_get_load (hdr), + &unc_len, (char *)os_data, os_len, + CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); show_boot_progress (-6); @@ -306,7 +294,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) */ if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) { char buf[32]; - sprintf(buf, "%lX", len); + sprintf(buf, "%lX", image_get_data_size(hdr)); setenv("filesize", buf); return 0; } @@ -332,42 +320,36 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif - do_bootm_linux (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_linux (cmdtp, flag, argc, argv, hdr, verify); break; case IH_OS_NETBSD: - do_bootm_netbsd (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_netbsd (cmdtp, flag, argc, argv, hdr, verify); break; #ifdef CONFIG_LYNXKDI case IH_OS_LYNXOS: - do_bootm_lynxkdi (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_lynxkdi (cmdtp, flag, argc, argv, hdr, verify); break; #endif case IH_OS_RTEMS: - do_bootm_rtems (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_rtems (cmdtp, flag, argc, argv, hdr, verify); break; #if defined(CONFIG_CMD_ELF) case IH_OS_VXWORKS: - do_bootm_vxworks (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_vxworks (cmdtp, flag, argc, argv, hdr, verify); break; + case IH_OS_QNX: - do_bootm_qnxelf (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_qnxelf (cmdtp, flag, argc, argv, hdr, verify); break; #endif #ifdef CONFIG_ARTOS case IH_OS_ARTOS: - do_bootm_artos (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_artos (cmdtp, flag, argc, argv, hdr, verify); break; #endif } @@ -570,11 +552,12 @@ void print_image_hdr (image_header_t *hdr) if (image_check_type (hdr, IH_TYPE_MULTI)) { int i; - ulong len; - ulong *len_ptr = (ulong *)((ulong)hdr + image_get_header_size ()); + ulong data, len; + ulong count = image_multi_count (hdr); puts (" Contents:\n"); - for (i = 0; (len = image_to_cpu (*len_ptr)); ++i, ++len_ptr) { + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); printf (" Image %d: %8ld Bytes = ", i, len); print_size (len, "\n"); } @@ -684,14 +667,12 @@ static void fixup_silent_linux () /*******************************************************************/ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) + int argc, char *argv[], + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; - void (*loader)(bd_t *, image_header_t *, char *, char *); image_header_t *img_addr; + ulong kernel_data, kernel_len; char *consdev; char *cmdline; @@ -708,8 +689,11 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, */ img_addr = 0; - if ((image_check_type (hdr, IH_TYPE_MULTI)) && (len_ptr[1])) - img_addr = (image_header_t *)addr; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); + if (kernel_len) + img_addr = hdr; + } consdev = ""; #if defined (CONFIG_8xx_CONS_SMC1) @@ -760,19 +744,16 @@ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, #ifdef CONFIG_LYNXKDI static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) + image_header_t *hdr, int verify) { - lynxkdi_boot (&header); + lynxkdi_boot (hdr); } #endif /* CONFIG_LYNXKDI */ static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; void (*entry_point)(bd_t *); entry_point = (void (*)(bd_t *))image_get_ep (hdr); @@ -792,10 +773,8 @@ static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, #if defined(CONFIG_CMD_ELF) static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; char str[80]; sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ @@ -803,12 +782,10 @@ static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, do_bootvx(cmdtp, 0, 0, NULL); } -static void do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) +static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; char *local_args[2]; char str[16]; @@ -822,8 +799,7 @@ static void do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, - int verify) + image_header_t *hdr, int verify) { ulong top; char *s, *cmdline; @@ -831,7 +807,6 @@ static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int i, j, nxt, len, envno, envsz; bd_t *kbd; void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); - image_header_t *hdr = &header; /* * Booting an ARTOS kernel image + application diff --git a/common/image.c b/common/image.c index 048b866..6eee83d 100644 --- a/common/image.c +++ b/common/image.c @@ -107,3 +107,89 @@ void memmove_wd (void *to, void *from, size_t len, ulong chunksz) #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ } #endif /* USE_HOSTCC */ + +/** + * image_multi_count - get component (sub-image) count + * @hdr: pointer to the header of the multi component image + * + * image_multi_count() returns number of components in a multi + * component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * number of components + */ +ulong image_multi_count (image_header_t *hdr) +{ + ulong i, count = 0; + ulong *size; + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (ulong *)image_get_data (hdr); + + /* count non empty slots */ + for (i = 0; size[i]; ++i) + count++; + + return count; +} + +/** + * image_multi_getimg - get component data address and size + * @hdr: pointer to the header of the multi component image + * @idx: index of the requested component + * @data: pointer to a ulong variable, will hold component data address + * @len: pointer to a ulong variable, will hold component size + * + * image_multi_getimg() returns size and data address for the requested + * component in a multi component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * data address and size of the component, if idx is valid + * 0 in data and len, if idx is out of range + */ +void image_multi_getimg (image_header_t *hdr, ulong idx, + ulong *data, ulong *len) +{ + int i; + ulong *size; + ulong offset, tail, count, img_data; + + /* get number of component */ + count = image_multi_count (hdr); + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (ulong *)image_get_data (hdr); + + /* get address of the proper component data start, which means + * skipping sizes table (add 1 for last, null entry) */ + img_data = image_get_data (hdr) + (count + 1) * sizeof (ulong); + + if (idx < count) { + *len = size[idx]; + offset = 0; + tail = 0; + + /* go over all indices preceding requested component idx */ + for (i = 0; i < idx; i++) { + /* add up i-th component size */ + offset += size[i]; + + /* add up alignment for i-th component */ + tail += (4 - size[i] % 4); + } + + /* calculate idx-th component data address */ + *data = img_data + offset + tail; + } else { + *len = 0; + *data = 0; + } +} -- cgit v1.1