From b97a2a0a21f279d66de8a9bdbfe21920968bcb1c Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 8 Jan 2008 18:14:09 +0100 Subject: [new uImage] Define a API for image handling operations - Add inline helper macros for basic header processing - Move common non inline code common/image.c - Replace direct header access with the API routines - Rename IH_CPU_* to IH_ARCH_* Signed-off-by: Marian Balakowicz --- common/image.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 common/image.c (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c new file mode 100644 index 0000000..7a0a3d2 --- /dev/null +++ b/common/image.c @@ -0,0 +1,91 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ +#ifndef USE_HOSTCC +# include +# include +#else +# include "mkimage.h" +#endif + +#include + +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); + +int image_check_hcrc (image_header_t *hdr) +{ + ulong hcrc; + ulong len = image_get_header_size (); + image_header_t header; + + /* Copy header so we can blank CRC field for re-calculation */ + memmove (&header, (char *)hdr, image_get_header_size ()); + image_set_hcrc (&header, 0); + + hcrc = crc32 (0, (unsigned char *)&header, len); + + return (hcrc == image_get_hcrc (hdr)); +} + +int image_check_dcrc (image_header_t *hdr) +{ + ulong data = image_get_data (hdr); + ulong len = image_get_data_size (hdr); + ulong dcrc = crc32 (0, (unsigned char *)data, len); + + return (dcrc == image_get_dcrc (hdr)); +} + +int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) +{ + ulong dcrc = 0; + ulong len = image_get_data_size (hdr); + ulong data = image_get_data (hdr); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + ulong cdata = data; + ulong edata = cdata + len; + + while (cdata < edata) { + ulong chunk = edata - cdata; + + if (chunk > chunksz) + chunk = chunksz; + dcrc = crc32 (dcrc, (unsigned char *)cdata, chunk); + cdata += chunk; + + WATCHDOG_RESET (); + } +#else + dcrc = crc32 (0, (unsigned char *)data, len); +#endif + + return (dcrc == image_get_dcrc (hdr)); +} + +int getenv_verify (void) +{ + char *s = getenv ("verify"); + return (s && (*s == 'n')) ? 0 : 1; +} -- cgit v1.1 From af13cdbc01eaf88880978bfb4f603e012818ba24 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Tue, 8 Jan 2008 18:11:45 +0100 Subject: [new uImage] Add memmove_wd() common routine Move common, watchdog sensible memmove code to a helper memmmove_wd() routine. Signed-off-by: Marian Balakowicz --- common/image.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 7a0a3d2..048b866 100644 --- a/common/image.c +++ b/common/image.c @@ -57,6 +57,7 @@ int image_check_dcrc (image_header_t *hdr) return (dcrc == image_get_dcrc (hdr)); } +#ifndef USE_HOSTCC int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) { ulong dcrc = 0; @@ -89,3 +90,20 @@ int getenv_verify (void) char *s = getenv ("verify"); return (s && (*s == 'n')) ? 0 : 1; } + +void memmove_wd (void *to, void *from, size_t len, ulong chunksz) +{ +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + while (len > 0) { + size_t tail = (len > chunksz) ? chunksz : len; + WATCHDOG_RESET (); + memmove (to, from, tail); + to += tail; + from += tail; + len -= tail; + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove (to, from, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} +#endif /* USE_HOSTCC */ -- cgit v1.1 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/image.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'common/image.c') 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 From 42b73e8ee00d48004791dea64b8093fb974c57e1 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 31 Jan 2008 13:20:07 +0100 Subject: [new uImage] Factor out common routines for getting os/arch/type/comp names Move numeric-id to name translation for image os/arch/type/comp header fields to a helper routines: image_get_os_name(), image_get_arch_name(), image_get_type_name(), image_get_comp_name(). Signed-off-by: Marian Balakowicz --- common/image.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 6eee83d..6726f03 100644 --- a/common/image.c +++ b/common/image.c @@ -193,3 +193,91 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, *data = 0; } } + +#ifndef USE_HOSTCC +const char* image_get_os_name (uint8_t os) +{ + const char *name; + + switch (os) { + case IH_OS_INVALID: name = "Invalid OS"; break; + case IH_OS_NETBSD: name = "NetBSD"; break; + case IH_OS_LINUX: name = "Linux"; break; + case IH_OS_VXWORKS: name = "VxWorks"; break; + case IH_OS_QNX: name = "QNX"; break; + case IH_OS_U_BOOT: name = "U-Boot"; break; + case IH_OS_RTEMS: name = "RTEMS"; break; +#ifdef CONFIG_ARTOS + case IH_OS_ARTOS: name = "ARTOS"; break; +#endif +#ifdef CONFIG_LYNXKDI + case IH_OS_LYNXOS: name = "LynxOS"; break; +#endif + default: name = "Unknown OS"; break; + } + + return name; +} + +const char* image_get_arch_name (uint8_t arch) +{ + const char *name; + + switch (arch) { + case IH_ARCH_INVALID: name = "Invalid Architecture"; break; + case IH_ARCH_ALPHA: name = "Alpha"; break; + case IH_ARCH_ARM: name = "ARM"; break; + case IH_ARCH_AVR32: name = "AVR32"; break; + case IH_ARCH_BLACKFIN: name = "Blackfin"; break; + case IH_ARCH_I386: name = "Intel x86"; break; + case IH_ARCH_IA64: name = "IA64"; break; + case IH_ARCH_M68K: name = "M68K"; break; + case IH_ARCH_MICROBLAZE:name = "Microblaze"; break; + case IH_ARCH_MIPS64: name = "MIPS 64 Bit"; break; + case IH_ARCH_MIPS: name = "MIPS"; break; + case IH_ARCH_NIOS2: name = "Nios-II"; break; + case IH_ARCH_NIOS: name = "Nios"; break; + case IH_ARCH_PPC: name = "PowerPC"; break; + case IH_ARCH_S390: name = "IBM S390"; break; + case IH_ARCH_SH: name = "SuperH"; break; + case IH_ARCH_SPARC64: name = "SPARC 64 Bit"; break; + case IH_ARCH_SPARC: name = "SPARC"; break; + default: name = "Unknown Architecture"; break; + } + + return name; +} + +const char* image_get_type_name (uint8_t type) +{ + const char *name; + + switch (type) { + case IH_TYPE_INVALID: name = "Invalid Image"; break; + case IH_TYPE_STANDALONE:name = "Standalone Program"; break; + case IH_TYPE_KERNEL: name = "Kernel Image"; break; + case IH_TYPE_RAMDISK: name = "RAMDisk Image"; break; + case IH_TYPE_MULTI: name = "Multi-File Image"; break; + case IH_TYPE_FIRMWARE: name = "Firmware"; break; + case IH_TYPE_SCRIPT: name = "Script"; break; + case IH_TYPE_FLATDT: name = "Flat Device Tree"; break; + default: name = "Unknown Image"; break; + } + + return name; +} + +const char* image_get_comp_name (uint8_t comp) +{ + const char *name; + + switch (comp) { + case IH_COMP_NONE: name = "uncompressed"; break; + case IH_COMP_GZIP: name = "gzip compressed"; break; + case IH_COMP_BZIP2: name = "bzip2 compressed"; break; + default: name = "unknown compression"; break; + } + + return name; +} +#endif -- cgit v1.1 From 5ad03eb3854c162684222a718b44c0716ea0db03 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 31 Jan 2008 13:55:39 +0100 Subject: [new uImage] Factor out common image_get_ramdisk() routine Architecture specific do_bootm_linux() routines share common ramdisk image processing code. Move this code to a common helper routine. Signed-off-by: Marian Balakowicz --- common/image.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 6726f03..e4be4ca 100644 --- a/common/image.c +++ b/common/image.c @@ -23,10 +23,20 @@ * MA 02111-1307 USA */ #ifndef USE_HOSTCC -# include -# include +#include +#include + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +#include +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#include +#endif + +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #else -# include "mkimage.h" +#include "mkimage.h" #endif #include @@ -280,4 +290,191 @@ const char* image_get_comp_name (uint8_t comp) return name; } + +/** + * image_get_ramdisk - get and verify ramdisk image + * @cmdtp: command table pointer + * @flag: command flag + * @argc: command argument count + * @argv: command argument list + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * If dataflash support is enabled routine checks for dataflash addresses + * and handles required dataflash reads. + * + * returns: + * pointer to a ramdisk image header, if image was found and valid + * otherwise, board is reset + */ +image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong rd_addr, uint8_t arch, int verify) +{ + image_header_t *rd_hdr; + + show_boot_progress (9); + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (rd_addr)) { + rd_hdr = (image_header_t *)CFG_LOAD_ADDR; + debug (" Reading Ramdisk image header from dataflash address " + "%08lx to %08lx\n", rd_addr, (ulong)rd_hdr); + read_dataflash (rd_addr, image_get_header_size (), + (char *)rd_hdr); + } else +#endif + rd_hdr = (image_header_t *)rd_addr; + + if (!image_check_magic (rd_hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-10); + do_reset (cmdtp, flag, argc, argv); + } + + if (!image_check_hcrc (rd_hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-11); + do_reset (cmdtp, flag, argc, argv); + } + + show_boot_progress (10); + print_image_hdr (rd_hdr); + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (rd_addr)) { + debug (" Reading Ramdisk image data from dataflash address " + "%08lx to %08lx\n", rd_addr + image_get_header_size, + (ulong)image_get_data (rd_hdr)); + + read_dataflash (rd_addr + image_get_header_size (), + image_get_data_size (rd_hdr), + (char *)image_get_data (rd_hdr)); + } #endif + + if (verify) { + puts(" Verifying Checksum ... "); + if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { + puts ("Bad Data CRC\n"); + show_boot_progress (-12); + do_reset (cmdtp, flag, argc, argv); + } + puts("OK\n"); + } + + show_boot_progress (11); + + if (!image_check_os (rd_hdr, IH_OS_LINUX) || + !image_check_arch (rd_hdr, arch) || + !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + image_get_arch_name(arch)); + show_boot_progress (-13); + do_reset (cmdtp, flag, argc, argv); + } + + return rd_hdr; +} + +/** + * get_ramdisk - main ramdisk handling routine + * @cmdtp: command table pointer + * @flag: command flag + * @argc: command argument count + * @argv: command argument list + * @hdr: pointer to the posiibly multi componet kernel image + * @verify: checksum verification flag + * @arch: expected ramdisk architecture + * @rd_start: pointer to a ulong variable, will hold ramdisk start address + * @rd_end: pointer to a ulong variable, will hold ramdisk end + * + * get_ramdisk() is responsible for finding a valid ramdisk image. + * Curently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * rd_start and rd_end are set to ramdisk start/end addresses if + * ramdisk image is found and valid + * rd_start and rd_end are set to 0 if no ramdisk exists + * board is reset if ramdisk image is found but corrupted + */ +void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, uint8_t arch, + ulong *rd_start, ulong *rd_end) +{ + ulong rd_addr; + ulong rd_data, rd_len; + image_header_t *rd_hdr; + + if (argc >= 3) { + /* + * Look for a '-' which indicates to ignore the + * ramdisk argument + */ + if (strcmp(argv[2], "-") == 0) { + debug ("## Skipping init Ramdisk\n"); + rd_len = rd_data = 0; + } else { + /* + * Check if there is an initrd image at the + * address provided in the second bootm argument + */ + rd_addr = simple_strtoul (argv[2], NULL, 16); + printf ("## Loading init Ramdisk Image at %08lx ...\n", + rd_addr); + + rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, + rd_addr, arch, verify); + + rd_data = image_get_data (rd_hdr); + rd_len = image_get_data_size (rd_hdr); + +#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) + /* + *we need to copy the ramdisk to SRAM to let Linux boot + */ + memmove ((void *)image_get_load (rd_hdr), + (uchar *)rd_data, rd_len); + + rd_data = image_get_load (rd_hdr); +#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ + } + + } else if (image_check_type (hdr, IH_TYPE_MULTI)) { + /* + * Now check if we have a multifile image + * Get second entry data start address and len + */ + show_boot_progress (13); + printf ("## Loading init Ramdisk from multi component " + "Image at %08lx ...\n", (ulong)hdr); + image_multi_getimg (hdr, 1, &rd_data, &rd_len); + } else { + /* + * no initrd image + */ + show_boot_progress (14); + rd_len = rd_data = 0; + } + + if (!rd_data) { + debug ("## No init Ramdisk\n"); + *rd_start = 0; + *rd_end = 0; + } else { + *rd_start = rd_data; + *rd_end = rd_data + rd_len; + } + debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", + *rd_start, *rd_end); +} +#endif /* USE_HOSTCC */ + -- cgit v1.1 From ceaed2b1e54ebf14d600e02fef016c8df5cc4d40 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 31 Jan 2008 13:57:17 +0100 Subject: [new uImage] Move ramdisk loading to a common routine Ramdisk loading code, including initrd_high variable handling, was duplicated for PPC and M68K platforms. This patch creates common helper routine that is being called from both platform do_bootm_linux() routines. Signed-off-by: Marian Balakowicz --- common/image.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index e4be4ca..56d6b52 100644 --- a/common/image.c +++ b/common/image.c @@ -22,6 +22,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ + +#define DEBUG + #ifndef USE_HOSTCC #include #include @@ -34,6 +37,10 @@ #include #endif +#ifdef CONFIG_LOGBUFFER +#include +#endif + extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #else #include "mkimage.h" @@ -476,5 +483,111 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", *rd_start, *rd_end); } + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * ramdisk_high - relocate init ramdisk + * @rd_data: ramdisk data start address + * @rd_len: ramdisk data length + * @kbd: kernel board info copy (within BOOTMAPSZ boundary) + * @sp_limit: stack pointer limit (including BOOTMAPSZ) + * @sp: current stack pointer + * @initrd_start: pointer to a ulong variable, will hold final init ramdisk + * start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + * end address (after possible relocation) + * + * ramdisk_high() takes a relocation hint from "initrd_high" environement + * variable and if requested ramdisk data is moved to a specified location. + * + * returns: + * initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided + * otherwise set initrd_start and initrd_end to zeros + * + */ +void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, + ulong sp, ulong *initrd_start, ulong *initrd_end) +{ + char *s; + ulong initrd_high; + int initrd_copy_to_ram = 1; + + if ((s = getenv ("initrd_high")) != NULL) { + /* a value of "no" or a similar string will act like 0, + * turning the "load high" feature off. This is intentional. + */ + initrd_high = simple_strtoul (s, NULL, 16); + if (initrd_high == ~0) + initrd_copy_to_ram = 0; + } else { + /* not set, no restrictions to load high */ + initrd_high = ~0; + } + +#ifdef CONFIG_LOGBUFFER + /* Prevent initrd from overwriting logbuffer */ + if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) + initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; + debug ("## Logbuffer at 0x%08lx ", kbd->bi_memsize - LOGBUFF_LEN); +#endif + debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", + initrd_high, initrd_copy_to_ram); + + if (rd_data) { + if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ + debug (" in-place initrd\n"); + *initrd_start = rd_data; + *initrd_end = rd_data + rd_len; + } else { + *initrd_start = (ulong)kbd - rd_len; + *initrd_start &= ~(4096 - 1); /* align on page */ + + if (initrd_high) { + ulong nsp; + + /* + * the inital ramdisk does not need to be within + * CFG_BOOTMAPSZ as it is not accessed until after + * the mm system is initialised. + * + * do the stack bottom calculation again and see if + * the initrd will fit just below the monitor stack + * bottom without overwriting the area allocated + * for command line args and board info. + */ + nsp = sp; + nsp -= 2048; /* just to be sure */ + nsp &= ~0xF; + + if (nsp > initrd_high) /* limit as specified */ + nsp = initrd_high; + + nsp -= rd_len; + nsp &= ~(4096 - 1); /* align on page */ + + if (nsp >= sp_limit) + *initrd_start = nsp; + } + + show_boot_progress (12); + + *initrd_end = *initrd_start + rd_len; + printf (" Loading Ramdisk to %08lx, end %08lx ... ", + *initrd_start, *initrd_end); + + memmove_wd((void *)*initrd_start, + (void *)rd_data, rd_len, CHUNKSZ); + + puts ("OK\n"); + } + } else { + *initrd_start = 0; + *initrd_end = 0; + } + debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", + *initrd_start, *initrd_end); +} +#endif /* CONFIG_PPC || CONFIG_M68K */ #endif /* USE_HOSTCC */ -- cgit v1.1 From b6b0fe6460b7063ac60b9a3531ef210aedb31451 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 31 Jan 2008 13:58:13 +0100 Subject: [new uImage] Cleanup do_botm_linux() boot allocations This patch moves common pre-boot allocation steps shared between PPC and M68K to a helper routines: common: - get_boot_sp_limit() - get_boot_cmline() - get_boot_kbd() platform: - set_clocks_in_mhz() Signed-off-by: Marian Balakowicz --- common/image.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 9 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 56d6b52..39e5f23 100644 --- a/common/image.c +++ b/common/image.c @@ -42,9 +42,15 @@ #endif extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#ifdef CONFIG_CMD_BDI +extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif + +DECLARE_GLOBAL_DATA_PTR; #else #include "mkimage.h" -#endif +#endif /* USE_HOSTCC*/ #include @@ -501,17 +507,19 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * variable and if requested ramdisk data is moved to a specified location. * * returns: - * initrd_start and initrd_end are set to final (after relocation) ramdisk + * - initrd_start and initrd_end are set to final (after relocation) ramdisk * start/end addresses if ramdisk image start and len were provided - * otherwise set initrd_start and initrd_end to zeros - * + * otherwise set initrd_start and initrd_end set to zeros + * - returns new allc_current, next free address below BOOTMAPSZ */ -void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, - ulong sp, ulong *initrd_start, ulong *initrd_end) +ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, + bd_t *kbd, ulong sp_limit, ulong sp, + ulong *initrd_start, ulong *initrd_end) { char *s; ulong initrd_high; int initrd_copy_to_ram = 1; + ulong new_alloc_current = alloc_current; if ((s = getenv ("initrd_high")) != NULL) { /* a value of "no" or a similar string will act like 0, @@ -540,7 +548,8 @@ void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, *initrd_start = rd_data; *initrd_end = rd_data + rd_len; } else { - *initrd_start = (ulong)kbd - rd_len; + new_alloc_current = alloc_current - rd_len; + *initrd_start = new_alloc_current; *initrd_start &= ~(4096 - 1); /* align on page */ if (initrd_high) { @@ -566,8 +575,10 @@ void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, nsp -= rd_len; nsp &= ~(4096 - 1); /* align on page */ - if (nsp >= sp_limit) + if (nsp >= sp_limit) { *initrd_start = nsp; + new_alloc_current = alloc_current; + } } show_boot_progress (12); @@ -587,7 +598,96 @@ void ramdisk_high (ulong rd_data, ulong rd_len, bd_t *kbd, ulong sp_limit, } debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", *initrd_start, *initrd_end); + + return new_alloc_current; +} + +/** + * get_boot_sp_limit - calculate stack pointer limit + * @sp: current stack pointer + * + * get_boot_sp_limit() takes current stack pointer adrress and calculates + * stack pointer limit, below which kernel boot data (cmdline, board info, + * etc.) will be allocated. + * + * returns: + * stack pointer limit + */ +ulong get_boot_sp_limit(ulong sp) +{ + ulong sp_limit = sp; + + sp_limit -= 2048; /* just to be sure */ + + /* make sure sp_limit is within kernel mapped space */ + if (sp_limit > CFG_BOOTMAPSZ) + sp_limit = CFG_BOOTMAPSZ; + sp_limit &= ~0xF; + + return sp_limit; +} + +/** + * get_boot_cmdline - allocate and initialize kernel cmdline + * @alloc_current: current boot allocation address (counting down + * from sp_limit) + * @cmd_start: pointer to a ulong variable, will hold cmdline start + * @cmd_end: pointer to a ulong variable, will hold cmdline end + * + * get_boot_cmdline() allocates space for kernel command line below + * provided alloc_current address. If "bootargs" U-boot environemnt + * variable is present its contents is copied to allocated kernel + * command line. + * + * returns: + * alloc_current after cmdline allocation + */ +ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) +{ + char *cmdline; + char *s; + + cmdline = (char *)((alloc_current - CFG_BARGSIZE) & ~0xF); + + if ((s = getenv("bootargs")) == NULL) + s = ""; + + strcpy(cmdline, s); + + *cmd_start = (ulong) & cmdline[0]; + *cmd_end = *cmd_start + strlen(cmdline); + + debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); + + return (ulong)cmdline; +} + +/** + * get_boot_kbd - allocate and initialize kernel copy of board info + * @alloc_current: current boot allocation address (counting down + * from sp_limit) + * @kbd: double pointer to board info data + * + * get_boot_kbd() - allocates space for kernel copy of board info data. + * Space is allocated below provided alloc_current address and kernel + * board info is initialized with the current u-boot board info data. + * + * returns: + * alloc_current after kbd allocation + */ +ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) +{ + *kbd = (bd_t *) (((ulong)alloc_current - sizeof(bd_t)) & ~0xF); + **kbd = *(gd->bd); + + debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); + +#if defined(DEBUG) && defined(CONFIG_CMD_BDI) + do_bdinfo(NULL, 0, 0, NULL); +#endif + + return (ulong)*kbd; } #endif /* CONFIG_PPC || CONFIG_M68K */ -#endif /* USE_HOSTCC */ +#endif /* USE_HOSTCC */ -- cgit v1.1 From fff888a1997ff7de9b29e24050fc4a0fd403ba16 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 21 Feb 2008 17:20:19 +0100 Subject: [new uImage] Add gen_get_image() routine This routine assures that image (whether legacy or FIT) is not in a special dataflash storage. If image address is a dataflash address image is moved to system RAM. Signed-off-by: Marian Balakowicz --- common/image.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 21 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 39e5f23..ab6b8e6 100644 --- a/common/image.c +++ b/common/image.c @@ -41,6 +41,12 @@ #include #endif +#if defined(CONFIG_FIT) +#include +#include +#include +#endif + extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #ifdef CONFIG_CMD_BDI @@ -305,6 +311,103 @@ const char* image_get_comp_name (uint8_t comp) } /** + * gen_image_get_format - get image format type + * @img_addr: image start address + * + * gen_image_get_format() checks whether provided address points to a valid + * legacy or FIT image. + * + * returns: + * image format type or IMAGE_FORMAT_INVALID if no image is present + */ +int gen_image_get_format (void *img_addr) +{ + ulong format = IMAGE_FORMAT_INVALID; + image_header_t *hdr; +#if defined(CONFIG_FIT) + char *fit_hdr; +#endif + + hdr = (image_header_t *)img_addr; + if (image_check_magic(hdr)) + format = IMAGE_FORMAT_LEGACY; +#if defined(CONFIG_FIT) + else { + fit_hdr = (char *)img_addr; + if (fdt_check_header (fit_hdr) == 0) + format = IMAGE_FORMAT_FIT; + } +#endif + + return format; +} + +/** + * gen_get_image - get image from special storage (if necessary) + * @img_addr: image start address + * + * gen_get_image() checks if provided image start adddress is located + * in a dataflash storage. If so, image is moved to a system RAM memory. + * + * returns: + * image start address after possible relocation from special storage + */ +ulong gen_get_image (ulong img_addr) +{ + ulong ram_addr, h_size, d_size; + + h_size = image_get_header_size (); +#if defined(CONFIG_FIT) + if (sizeof(struct fdt_header) > h_size) + h_size = sizeof(struct fdt_header); +#endif + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (img_addr)){ + ram_addr = CFG_LOAD_ADDR; + debug (" Reading image header from dataflash address " + "%08lx to RAM address %08lx\n", img_addr, ram_addr); + read_dataflash (img_addr, h_size, (char *)ram_addr); + } else +#endif + return img_addr; + + ram_addr = img_addr; + + switch (gen_image_get_format ((void *)ram_addr)) { + case IMAGE_FORMAT_LEGACY: + d_size = image_get_data_size ((image_header_t *)ram_addr); + debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + d_size = fdt_totalsize((void *)ram_addr) - h_size; + debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + + break; +#endif + default: + printf (" No valid image found at 0x%08lx\n", img_addr); + return ram_addr; + } + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (img_addr)) { + debug (" Reading image remaining data from dataflash address " + "%08lx to RAM address %08lx\n", img_addr + h_size, + ram_addr + h_size); + + read_dataflash (img_addr + h_size, d_size, + (char *)(ram_addr + h_size)); + } +#endif + + return ram_addr; +} + +/** * image_get_ramdisk - get and verify ramdisk image * @cmdtp: command table pointer * @flag: command flag @@ -334,15 +437,8 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, show_boot_progress (9); -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (rd_addr)) { - rd_hdr = (image_header_t *)CFG_LOAD_ADDR; - debug (" Reading Ramdisk image header from dataflash address " - "%08lx to %08lx\n", rd_addr, (ulong)rd_hdr); - read_dataflash (rd_addr, image_get_header_size (), - (char *)rd_hdr); - } else -#endif + /* copy from dataflash if needed */ + rd_addr = gen_get_image (rd_addr); rd_hdr = (image_header_t *)rd_addr; if (!image_check_magic (rd_hdr)) { @@ -360,18 +456,6 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, show_boot_progress (10); print_image_hdr (rd_hdr); -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (rd_addr)) { - debug (" Reading Ramdisk image data from dataflash address " - "%08lx to %08lx\n", rd_addr + image_get_header_size, - (ulong)image_get_data (rd_hdr)); - - read_dataflash (rd_addr + image_get_header_size (), - image_get_data_size (rd_hdr), - (char *)image_get_data (rd_hdr)); - } -#endif - if (verify) { puts(" Verifying Checksum ... "); if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { -- cgit v1.1 From f50433d670ec2ee9e96abac67cdc6e5e061a810d Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 21 Feb 2008 17:20:20 +0100 Subject: [new uImage] Add fit_parse_conf() and fit_parse_subimage() routines Introducing routines for parsing new uImage format bootm arguments: []# - configuration specification []: - subimage specification New format images can contain multiple subimages of the same type. For example a single new format image file can contain three kernels, two ramdisks and a couple of FDT blobs. Subimage and configuration specifications are extensions to bootm (and other image-related commands) arguments' syntax that allow to specify which particular subimage should be operated on. Subimage specification is used to denote a particular subimage. Configurations are a bit more complex -- they are used to define a particualr booting setup, for example a (kernel, fdt blob) pair, or a (kernel, ramdisk, fdt blob) tuple, etc. Signed-off-by: Marian Balakowicz --- common/image.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index ab6b8e6..7362328 100644 --- a/common/image.c +++ b/common/image.c @@ -774,4 +774,82 @@ ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) } #endif /* CONFIG_PPC || CONFIG_M68K */ +#if defined(CONFIG_FIT) +/*****************************************************************************/ +/* New uImage format routines */ +/*****************************************************************************/ +static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, + ulong *addr, const char **name) +{ + const char *sep; + + *addr = addr_curr; + *name = NULL; + + sep = strchr (spec, sepc); + if (sep) { + if (sep - spec > 0) + *addr = simple_strtoul (spec, NULL, 16); + + *name = sep + 1; + return 1; + } + + return 0; +} + +/** + * fit_parse_conf - parse FIT configuration spec + * @spec: input string, containing configuration spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * configuration + * @conf_name double pointer to a char, will hold pointer to a configuration + * unit name + * + * fit_parse_conf() expects configuration spec in the for of []#, + * where is a FIT image address that contains configuration + * with a unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + * 1 if spec is a valid configuration string, + * addr and conf_name are set accordingly + * 0 otherwise + */ +inline int fit_parse_conf (const char *spec, ulong addr_curr, + ulong *addr, const char **conf_name) +{ + return fit_parse_spec (spec, '#', addr_curr, addr, conf_name); +} + +/** + * fit_parse_subimage - parse FIT subimage spec + * @spec: input string, containing subimage spec + * @add_curr: current image address (to be used as a possible default) + * @addr: pointer to a ulong variable, will hold FIT image address of a given + * subimage + * @image_name: double pointer to a char, will hold pointer to a subimage name + * + * fit_parse_subimage() expects subimage spec in the for of + * []:, where is a FIT image address that contains + * subimage with a unit name. + * + * Address part is optional, and if omitted default add_curr will + * be used instead. + * + * returns: + * 1 if spec is a valid subimage string, + * addr and image_name are set accordingly + * 0 otherwise + */ +inline int fit_parse_subimage (const char *spec, ulong addr_curr, + ulong *addr, const char **image_name) +{ + return fit_parse_spec (spec, ':', addr_curr, addr, image_name); +} +#endif /* CONFIG_FIT */ + #endif /* USE_HOSTCC */ -- cgit v1.1 From 2242f5369822bc7780db95c47985bb408ea9157b Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Thu, 21 Feb 2008 17:27:41 +0100 Subject: [new uImage] Rename and move print_image_hdr() routine Signed-off-by: Marian Balakowicz --- common/image.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 7362328..690e0af 100644 --- a/common/image.c +++ b/common/image.c @@ -41,6 +41,10 @@ #include #endif +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) +#include +#endif + #if defined(CONFIG_FIT) #include #include @@ -310,6 +314,56 @@ const char* image_get_comp_name (uint8_t comp) return name; } +static void image_print_type (image_header_t *hdr) +{ + const char *os, *arch, *type, *comp; + + os = image_get_os_name (image_get_os (hdr)); + arch = image_get_arch_name (image_get_arch (hdr)); + type = image_get_type_name (image_get_type (hdr)); + comp = image_get_comp_name (image_get_comp (hdr)); + + printf ("%s %s %s (%s)", arch, os, type, comp); +} + +void image_print_contents (image_header_t *hdr) +{ +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) + time_t timestamp = (time_t)image_get_time (hdr); + struct rtc_time tm; +#endif + + printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) + to_tm (timestamp, &tm); + printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +#endif + puts (" Image Type: "); + image_print_type (hdr); + + printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); + print_size (image_get_data_size (hdr), "\n"); + printf (" Load Address: %08x\n" + " Entry Point: %08x\n", + image_get_load (hdr), image_get_ep (hdr)); + + if (image_check_type (hdr, IH_TYPE_MULTI)) { + int i; + ulong data, len; + ulong count = image_multi_count (hdr); + + puts (" Contents:\n"); + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); + printf (" Image %d: %8ld Bytes = ", i, len); + print_size (len, "\n"); + } + } +} + /** * gen_image_get_format - get image format type * @img_addr: image start address @@ -454,7 +508,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, } show_boot_progress (10); - print_image_hdr (rd_hdr); + image_print_contents (rd_hdr); if (verify) { puts(" Verifying Checksum ... "); -- cgit v1.1 From d5934ad7756f038a393a9cfab76a4fe306d9d930 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Mon, 4 Feb 2008 08:28:09 +0100 Subject: [new uImage] Add dual format uImage support framework This patch adds framework for dual format images. Format detection is added and the bootm controll flow is updated to include cases for new FIT format uImages. When the legacy (image_header based) format is detected appropriate legacy specific handling is invoked. For the new (FIT based) format uImages dual boot framework has a minial support, that will only print out a corresponding debug messages. Implementation of the FIT specific handling will be added in following patches. Signed-off-by: Marian Balakowicz --- common/image.c | 117 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 32 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 690e0af..ea27b0b 100644 --- a/common/image.c +++ b/common/image.c @@ -490,9 +490,6 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, image_header_t *rd_hdr; show_boot_progress (9); - - /* copy from dataflash if needed */ - rd_addr = gen_get_image (rd_addr); rd_hdr = (image_header_t *)rd_addr; if (!image_check_magic (rd_hdr)) { @@ -540,7 +537,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * @flag: command flag * @argc: command argument count * @argv: command argument list - * @hdr: pointer to the posiibly multi componet kernel image + * @images: pointer to the bootm images strcture * @verify: checksum verification flag * @arch: expected ramdisk architecture * @rd_start: pointer to a ulong variable, will hold ramdisk start address @@ -558,56 +555,111 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * board is reset if ramdisk image is found but corrupted */ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - image_header_t *hdr, int verify, uint8_t arch, + bootm_headers_t *images, int verify, uint8_t arch, ulong *rd_start, ulong *rd_end) { - ulong rd_addr; + ulong rd_addr, rd_load; ulong rd_data, rd_len; image_header_t *rd_hdr; +#if defined(CONFIG_FIT) + void *fit_hdr; + const char *fit_uname_config = NULL; + const char *fit_uname_ramdisk = NULL; + ulong default_addr; +#endif - if (argc >= 3) { + /* + * Look for a '-' which indicates to ignore the + * ramdisk argument + */ + if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { + debug ("## Skipping init Ramdisk\n"); + rd_len = rd_data = 0; + } else if (argc >= 3) { +#if defined(CONFIG_FIT) /* - * Look for a '-' which indicates to ignore the - * ramdisk argument + * If the init ramdisk comes from the FIT image and the FIT image + * address is omitted in the command line argument, try to use + * os FIT image address or default load address. */ - if (strcmp(argv[2], "-") == 0) { - debug ("## Skipping init Ramdisk\n"); - rd_len = rd_data = 0; - } else { - /* - * Check if there is an initrd image at the - * address provided in the second bootm argument - */ - rd_addr = simple_strtoul (argv[2], NULL, 16); - printf ("## Loading init Ramdisk Image at %08lx ...\n", + if (images->fit_uname_os) + default_addr = (ulong)images->fit_hdr_os; + else + default_addr = load_addr; + + if (fit_parse_conf (argv[2], default_addr, + &rd_addr, &fit_uname_config)) { + debug ("* ramdisk: config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + } else if (fit_parse_subimage (argv[2], default_addr, + &rd_addr, &fit_uname_ramdisk)) { + debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", + fit_uname_ramdisk, rd_addr); + } else +#endif + { + rd_addr = simple_strtoul(argv[2], NULL, 16); + debug ("* ramdisk: cmdline image address = 0x%08lx\n", rd_addr); + } + + /* copy from dataflash if needed */ + printf ("## Loading init Ramdisk Image at %08lx ...\n", + rd_addr); + rd_addr = gen_get_image (rd_addr); + + /* + * Check if there is an initrd image at the + * address provided in the second bootm argument + * check image type, for FIT images get FIT node. + */ + switch (gen_image_get_format ((void *)rd_addr)) { + case IMAGE_FORMAT_LEGACY: + + debug ("* ramdisk: legacy format image\n"); rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, rd_addr, arch, verify); rd_data = image_get_data (rd_hdr); rd_len = image_get_data_size (rd_hdr); + rd_load = image_get_load (rd_hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (void *)rd_addr; + debug ("* ramdisk: FIT format image\n"); + fit_unsupported_reset ("ramdisk"); + do_reset (cmdtp, flag, argc, argv); +#endif + default: + printf ("Wrong Image Format for %s command\n", + cmdtp->name); + rd_data = rd_len = 0; + } #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) - /* - *we need to copy the ramdisk to SRAM to let Linux boot - */ - memmove ((void *)image_get_load (rd_hdr), - (uchar *)rd_data, rd_len); - - rd_data = image_get_load (rd_hdr); -#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ + /* + * We need to copy the ramdisk to SRAM to let Linux boot + */ + if (rd_data) { + memmove ((void *)rd_load, (uchar *)rd_data, rd_len); + rd_data = rd_load; } +#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ - } else if (image_check_type (hdr, IH_TYPE_MULTI)) { + } else if (images->legacy_hdr_valid && + image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { /* - * Now check if we have a multifile image - * Get second entry data start address and len + * Now check if we have a legacy mult-component image, + * get second entry data start address and len. */ show_boot_progress (13); printf ("## Loading init Ramdisk from multi component " - "Image at %08lx ...\n", (ulong)hdr); - image_multi_getimg (hdr, 1, &rd_data, &rd_len); + "Image at %08lx ...\n", + (ulong)images->legacy_hdr_os); + + image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); } else { /* * no initrd image @@ -904,6 +956,7 @@ inline int fit_parse_subimage (const char *spec, ulong addr_curr, { return fit_parse_spec (spec, ':', addr_curr, addr, image_name); } + #endif /* CONFIG_FIT */ #endif /* USE_HOSTCC */ -- cgit v1.1 From 6f0f9dfc4ee880fbf400a2ebe14238181a6c3f91 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 27 Feb 2008 11:00:47 +0100 Subject: [new uImage] Optimize gen_get_image() flow control When CONFIG_HAS_DATAFLASH is not defined gen_get_image() routine has nothing to do, update its control flow to better reflect that simple case. Signed-off-by: Marian Balakowicz Acked-by: Kumar Gala --- common/image.c | 64 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index ea27b0b..dd55264 100644 --- a/common/image.c +++ b/common/image.c @@ -408,55 +408,57 @@ int gen_image_get_format (void *img_addr) */ ulong gen_get_image (ulong img_addr) { - ulong ram_addr, h_size, d_size; - - h_size = image_get_header_size (); -#if defined(CONFIG_FIT) - if (sizeof(struct fdt_header) > h_size) - h_size = sizeof(struct fdt_header); -#endif + ulong ram_addr = img_addr; #ifdef CONFIG_HAS_DATAFLASH + ulong h_size, d_size; + if (addr_dataflash (img_addr)){ + /* ger RAM address */ ram_addr = CFG_LOAD_ADDR; + + /* get header size */ + h_size = image_get_header_size (); +#if defined(CONFIG_FIT) + if (sizeof(struct fdt_header) > h_size) + h_size = sizeof(struct fdt_header); +#endif + + /* read in header */ debug (" Reading image header from dataflash address " "%08lx to RAM address %08lx\n", img_addr, ram_addr); - read_dataflash (img_addr, h_size, (char *)ram_addr); - } else -#endif - return img_addr; - ram_addr = img_addr; + read_dataflash (img_addr, h_size, (char *)ram_addr); - switch (gen_image_get_format ((void *)ram_addr)) { - case IMAGE_FORMAT_LEGACY: - d_size = image_get_data_size ((image_header_t *)ram_addr); - debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", - ram_addr, d_size); - break; + /* get data size */ + switch (gen_image_get_format ((void *)ram_addr)) { + case IMAGE_FORMAT_LEGACY: + d_size = image_get_data_size ((image_header_t *)ram_addr); + debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + break; #if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - d_size = fdt_totalsize((void *)ram_addr) - h_size; - debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", - ram_addr, d_size); - - break; + case IMAGE_FORMAT_FIT: + d_size = fdt_totalsize((void *)ram_addr) - h_size; + debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", + ram_addr, d_size); + break; #endif - default: - printf (" No valid image found at 0x%08lx\n", img_addr); - return ram_addr; - } + default: + printf (" No valid image found at 0x%08lx\n", img_addr); + return ram_addr; + } -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (img_addr)) { + /* read in image data */ debug (" Reading image remaining data from dataflash address " "%08lx to RAM address %08lx\n", img_addr + h_size, ram_addr + h_size); read_dataflash (img_addr + h_size, d_size, (char *)(ram_addr + h_size)); + } -#endif +#endif /* CONFIG_HAS_DATAFLASH */ return ram_addr; } -- cgit v1.1 From 8a5ea3e6168fe6a2780eeaf257a3b19f30dec658 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 27 Feb 2008 11:01:04 +0100 Subject: [new uImage] Move image verify flag to bootm_headers structure Do not pass image verification flag directly to related routines. Simplify argument passing and move it to the bootm_header structure which contains curently processed image specific data and is already being passed on the argument list. Signed-off-by: Marian Balakowicz Acked-by: Kumar Gala --- common/image.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index dd55264..5ca77b9 100644 --- a/common/image.c +++ b/common/image.c @@ -58,6 +58,10 @@ extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif DECLARE_GLOBAL_DATA_PTR; + +static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong rd_addr, uint8_t arch, int verify); #else #include "mkimage.h" #endif /* USE_HOSTCC*/ @@ -485,7 +489,7 @@ ulong gen_get_image (ulong img_addr) * pointer to a ramdisk image header, if image was found and valid * otherwise, board is reset */ -image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, +static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], ulong rd_addr, uint8_t arch, int verify) { @@ -539,8 +543,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * @flag: command flag * @argc: command argument count * @argv: command argument list - * @images: pointer to the bootm images strcture - * @verify: checksum verification flag + * @images: pointer to the bootm images structure * @arch: expected ramdisk architecture * @rd_start: pointer to a ulong variable, will hold ramdisk start address * @rd_end: pointer to a ulong variable, will hold ramdisk end @@ -557,7 +560,7 @@ image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * board is reset if ramdisk image is found but corrupted */ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - bootm_headers_t *images, int verify, uint8_t arch, + bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end) { ulong rd_addr, rd_load; @@ -621,7 +624,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], debug ("* ramdisk: legacy format image\n"); rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, - rd_addr, arch, verify); + rd_addr, arch, images->verify); rd_data = image_get_data (rd_hdr); rd_len = image_get_data_size (rd_hdr); -- cgit v1.1 From 4efbe9dbb129f857f27856936112c8c02f016be6 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 27 Feb 2008 11:02:26 +0100 Subject: [new uImage] Correct raw FDT blob handlig when CONFIG_FIT is disabled Dual format image code must properly handle all three FDT passing methods: - raw FDT blob passed - FDT blob embedded in the legacy uImage - FDT blob embedded in the new uImage This patch enables proper raw FDT handling when no FIT imaeg support is compiled in. This is a bit tricky as we must dected FIT format even when FIT uImage handling is not enabled as both FIT uImages and raw FDT blobs use tha same low level format (libfdt). Signed-off-by: Marian Balakowicz --- common/image.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 5ca77b9..c689b0e 100644 --- a/common/image.c +++ b/common/image.c @@ -375,6 +375,10 @@ void image_print_contents (image_header_t *hdr) * gen_image_get_format() checks whether provided address points to a valid * legacy or FIT image. * + * New uImage format and FDT blob are based on a libfdt. FDT blob + * may be passed directly or embedded in a FIT image. In both situations + * gen_image_get_format() must be able to dectect libfdt header. + * * returns: * image format type or IMAGE_FORMAT_INVALID if no image is present */ @@ -382,14 +386,14 @@ int gen_image_get_format (void *img_addr) { ulong format = IMAGE_FORMAT_INVALID; image_header_t *hdr; -#if defined(CONFIG_FIT) +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) char *fit_hdr; #endif hdr = (image_header_t *)img_addr; if (image_check_magic(hdr)) format = IMAGE_FORMAT_LEGACY; -#if defined(CONFIG_FIT) +#if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) else { fit_hdr = (char *)img_addr; if (fdt_check_header (fit_hdr) == 0) -- cgit v1.1 From a6612bdfe7ef37b9787b66800cf02aaded05fbeb Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 27 Feb 2008 21:51:43 -0600 Subject: [new uImage] Don't pass kdb to ramdisk_high since we may not have one We don't actually need the kdb param as we are just using it to get bd->bi_memsize which we can get from gd->bd->bi_memsize. Also, if we boot via OF we might not actually fill out a kdb. Signed-off-by: Kumar Gala Acked-by: Marian Balakowicz --- common/image.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index c689b0e..92c067f 100644 --- a/common/image.c +++ b/common/image.c @@ -694,7 +694,6 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * ramdisk_high - relocate init ramdisk * @rd_data: ramdisk data start address * @rd_len: ramdisk data length - * @kbd: kernel board info copy (within BOOTMAPSZ boundary) * @sp_limit: stack pointer limit (including BOOTMAPSZ) * @sp: current stack pointer * @initrd_start: pointer to a ulong variable, will hold final init ramdisk @@ -712,7 +711,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * - returns new allc_current, next free address below BOOTMAPSZ */ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - bd_t *kbd, ulong sp_limit, ulong sp, + ulong sp_limit, ulong sp, ulong *initrd_start, ulong *initrd_end) { char *s; @@ -734,9 +733,9 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, #ifdef CONFIG_LOGBUFFER /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug ("## Logbuffer at 0x%08lx ", kbd->bi_memsize - LOGBUFF_LEN); + if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) + initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; + debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN); #endif debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); -- cgit v1.1 From 274cea2bddbca10cdad7daa518951b75c44ef6bc Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 27 Feb 2008 21:51:46 -0600 Subject: [new uImage] rework error handling so common functions don't reset Changed image_get_ramdisk() to just return NULL on error and have get_ramdisk() propogate that error to the caller. It's left to the caller to call do_reset() if it wants to. Also moved calling do_reset() in get_fdt() and fdt_relocate() on ppc to a common location. In the future we will change get_fdt() and fdt_relocate() to return success/failure and not call do_reset() at all. Signed-off-by: Kumar Gala Acked-by: Marian Balakowicz --- common/image.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 92c067f..d4acb6b 100644 --- a/common/image.c +++ b/common/image.c @@ -51,8 +51,6 @@ #include #endif -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - #ifdef CONFIG_CMD_BDI extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif @@ -491,7 +489,7 @@ ulong gen_get_image (ulong img_addr) * * returns: * pointer to a ramdisk image header, if image was found and valid - * otherwise, board is reset + * otherwise, return NULL */ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], @@ -505,13 +503,13 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, if (!image_check_magic (rd_hdr)) { puts ("Bad Magic Number\n"); show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); + return NULL; } if (!image_check_hcrc (rd_hdr)) { puts ("Bad Header Checksum\n"); show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); + return NULL; } show_boot_progress (10); @@ -522,7 +520,7 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { puts ("Bad Data CRC\n"); show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); + return NULL; } puts("OK\n"); } @@ -535,7 +533,7 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, printf ("No Linux %s Ramdisk Image\n", image_get_arch_name(arch)); show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); + return NULL; } return rd_hdr; @@ -561,9 +559,9 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * rd_start and rd_end are set to ramdisk start/end addresses if * ramdisk image is found and valid * rd_start and rd_end are set to 0 if no ramdisk exists - * board is reset if ramdisk image is found but corrupted + * return 1 if ramdisk image is found but corrupted */ -void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end) { @@ -630,6 +628,12 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, rd_addr, arch, images->verify); + if (rd_hdr == NULL) { + *rd_start = 0; + *rd_end = 0; + return 1; + } + rd_data = image_get_data (rd_hdr); rd_len = image_get_data_size (rd_hdr); rd_load = image_get_load (rd_hdr); @@ -639,7 +643,7 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], fit_hdr = (void *)rd_addr; debug ("* ramdisk: FIT format image\n"); fit_unsupported_reset ("ramdisk"); - do_reset (cmdtp, flag, argc, argv); + return 1; #endif default: printf ("Wrong Image Format for %s command\n", @@ -687,6 +691,8 @@ void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", *rd_start, *rd_end); + + return 0; } #if defined(CONFIG_PPC) || defined(CONFIG_M68K) -- cgit v1.1 From f5614e7926863bf0225ec860d9b319741a9c4004 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 27 Feb 2008 21:51:48 -0600 Subject: [new uImage] Add autostart flag to bootm_headers structure The autostart env variable was dropped as part of the initial new uImage cleanup. Add it back here so the arch specific code can decide if it wants to really boot or not. Signed-off-by: Kumar Gala Acked-by: Marian Balakowicz --- common/image.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index d4acb6b..4f2ff9c 100644 --- a/common/image.c +++ b/common/image.c @@ -126,6 +126,12 @@ int getenv_verify (void) return (s && (*s == 'n')) ? 0 : 1; } +int getenv_autostart (void) +{ + char *s = getenv ("autostart"); + return (s && (*s == 'n')) ? 0 : 1; +} + void memmove_wd (void *to, void *from, size_t len, ulong chunksz) { #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -- cgit v1.1 From e822d7fc4dd4755d4d0a22f05e33f33d1a0481da Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 27 Feb 2008 21:51:49 -0600 Subject: [new uImage] Use lmb for bootm allocations Convert generic ramdisk_high(), get_boot_cmdline(), get_boot_kbd() functions over to using lmb for allocation of the ramdisk, command line and kernel bd info. Convert PPC specific fdt_relocate() to use lmb for allocation of the device tree. Provided a weak function that board code can call to do additional lmb reserves if needed. Also introduce the concept of bootmap_base to specify the offset in physical memory that the bootmap is located at. This is used for allocations of the cmdline, kernel bd, and device tree as they should be contained within bootmap_base and bootmap_base + CFG_BOOTMAPSZ. Signed-off-by: Kumar Gala --- common/image.c | 134 ++++++++++++++++++++------------------------------------- 1 file changed, 47 insertions(+), 87 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 4f2ff9c..0b71811 100644 --- a/common/image.c +++ b/common/image.c @@ -704,10 +704,9 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #if defined(CONFIG_PPC) || defined(CONFIG_M68K) /** * ramdisk_high - relocate init ramdisk + * @lmb: pointer to lmb handle, will be used for memory mgmt * @rd_data: ramdisk data start address * @rd_len: ramdisk data length - * @sp_limit: stack pointer limit (including BOOTMAPSZ) - * @sp: current stack pointer * @initrd_start: pointer to a ulong variable, will hold final init ramdisk * start address (after possible relocation) * @initrd_end: pointer to a ulong variable, will hold final init ramdisk @@ -720,16 +719,16 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * - initrd_start and initrd_end are set to final (after relocation) ramdisk * start/end addresses if ramdisk image start and len were provided * otherwise set initrd_start and initrd_end set to zeros - * - returns new allc_current, next free address below BOOTMAPSZ + * - returns: + * 0 - success + * -1 - failure */ -ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, - ulong sp_limit, ulong sp, - ulong *initrd_start, ulong *initrd_end) +int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, + ulong *initrd_start, ulong *initrd_end) { char *s; ulong initrd_high; int initrd_copy_to_ram = 1; - ulong new_alloc_current = alloc_current; if ((s = getenv ("initrd_high")) != NULL) { /* a value of "no" or a similar string will act like 0, @@ -743,12 +742,6 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, initrd_high = ~0; } -#ifdef CONFIG_LOGBUFFER - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = gd->bd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug ("## Logbuffer at 0x%08lx ", gd->bd->bi_memsize - LOGBUFF_LEN); -#endif debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); @@ -757,40 +750,17 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, debug (" in-place initrd\n"); *initrd_start = rd_data; *initrd_end = rd_data + rd_len; + lmb_reserve(lmb, rd_data, rd_len); } else { - new_alloc_current = alloc_current - rd_len; - *initrd_start = new_alloc_current; - *initrd_start &= ~(4096 - 1); /* align on page */ - - if (initrd_high) { - ulong nsp; - - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * for command line args and board info. - */ - nsp = sp; - nsp -= 2048; /* just to be sure */ - nsp &= ~0xF; - - if (nsp > initrd_high) /* limit as specified */ - nsp = initrd_high; - - nsp -= rd_len; - nsp &= ~(4096 - 1); /* align on page */ - - if (nsp >= sp_limit) { - *initrd_start = nsp; - new_alloc_current = alloc_current; - } + if (initrd_high) + *initrd_start = lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); + else + *initrd_start = lmb_alloc(lmb, rd_len, 0x1000); + + if (*initrd_start == 0) { + puts("ramdisk - allocation error\n"); + goto error; } - show_boot_progress (12); *initrd_end = *initrd_start + rd_len; @@ -808,56 +778,40 @@ ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, } debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", *initrd_start, *initrd_end); + return 0; - return new_alloc_current; -} - -/** - * get_boot_sp_limit - calculate stack pointer limit - * @sp: current stack pointer - * - * get_boot_sp_limit() takes current stack pointer adrress and calculates - * stack pointer limit, below which kernel boot data (cmdline, board info, - * etc.) will be allocated. - * - * returns: - * stack pointer limit - */ -ulong get_boot_sp_limit(ulong sp) -{ - ulong sp_limit = sp; - - sp_limit -= 2048; /* just to be sure */ - - /* make sure sp_limit is within kernel mapped space */ - if (sp_limit > CFG_BOOTMAPSZ) - sp_limit = CFG_BOOTMAPSZ; - sp_limit &= ~0xF; - - return sp_limit; +error: + return -1; } /** * get_boot_cmdline - allocate and initialize kernel cmdline - * @alloc_current: current boot allocation address (counting down - * from sp_limit) + * @lmb: pointer to lmb handle, will be used for memory mgmt * @cmd_start: pointer to a ulong variable, will hold cmdline start * @cmd_end: pointer to a ulong variable, will hold cmdline end + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap * * get_boot_cmdline() allocates space for kernel command line below - * provided alloc_current address. If "bootargs" U-boot environemnt + * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt * variable is present its contents is copied to allocated kernel * command line. * * returns: - * alloc_current after cmdline allocation + * 0 - success + * -1 - failure */ -ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) +int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base) { char *cmdline; char *s; - cmdline = (char *)((alloc_current - CFG_BARGSIZE) & ~0xF); + cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, + CFG_BOOTMAPSZ + bootmap_base); + + if (cmdline == NULL) + return -1; if ((s = getenv("bootargs")) == NULL) s = ""; @@ -869,25 +823,31 @@ ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); - return (ulong)cmdline; + return 0; } /** * get_boot_kbd - allocate and initialize kernel copy of board info - * @alloc_current: current boot allocation address (counting down - * from sp_limit) + * @lmb: pointer to lmb handle, will be used for memory mgmt * @kbd: double pointer to board info data + * @bootmap_base: ulong variable, holds offset in physical memory to + * base of bootmap * - * get_boot_kbd() - allocates space for kernel copy of board info data. - * Space is allocated below provided alloc_current address and kernel - * board info is initialized with the current u-boot board info data. + * get_boot_kbd() allocates space for kernel copy of board info data below + * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with + * the current u-boot board info data. * * returns: - * alloc_current after kbd allocation + * 0 - success + * -1 - failure */ -ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) +int get_boot_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) { - *kbd = (bd_t *) (((ulong)alloc_current - sizeof(bd_t)) & ~0xF); + *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, + CFG_BOOTMAPSZ + bootmap_base); + if (*kbd == NULL) + return -1; + **kbd = *(gd->bd); debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); @@ -896,7 +856,7 @@ ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) do_bdinfo(NULL, 0, 0, NULL); #endif - return (ulong)*kbd; + return 0; } #endif /* CONFIG_PPC || CONFIG_M68K */ -- cgit v1.1 From d3f2fa0d278467b2232e4eb2372f905c3febfbeb Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Wed, 27 Feb 2008 21:51:50 -0600 Subject: [new uImage] Provide ability to restrict region used for boot images Allow the user to set 'bootm_low' and 'bootm_size' env vars as a way to restrict what memory range is used for bootm. Signed-off-by: Kumar Gala Acked-by: Marian Balakowicz --- common/image.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 0b71811..9e446fa 100644 --- a/common/image.c +++ b/common/image.c @@ -132,6 +132,32 @@ int getenv_autostart (void) return (s && (*s == 'n')) ? 0 : 1; } +ulong getenv_bootm_low(void) +{ + char *s = getenv ("bootm_low"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + +#ifdef CFG_SDRAM_BASE + return CFG_SDRAM_BASE; +#else + return 0; +#endif +} + +ulong getenv_bootm_size(void) +{ + char *s = getenv ("bootm_size"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + + return gd->bd->bi_memsize; +} + void memmove_wd (void *to, void *from, size_t len, ulong chunksz) { #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -- cgit v1.1 From 9a4daad0a35eb5143037eea9f786a3e9d672bdd6 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 29 Feb 2008 14:58:34 +0100 Subject: [new uImage] Update naming convention for bootm/uImage related code This patch introduces the following prefix convention for the image format handling and bootm related code: genimg_ - dual format shared code image_ - legacy uImage format specific code fit_ - new uImage format specific code boot_ - booting process related code Related routines are renamed and a few pieces of code are moved around and re-grouped. Signed-off-by: Marian Balakowicz --- common/image.c | 429 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 218 insertions(+), 211 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 9e446fa..99ed3b8 100644 --- a/common/image.c +++ b/common/image.c @@ -68,6 +68,9 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); +/*****************************************************************************/ +/* Legacy format routines */ +/*****************************************************************************/ int image_check_hcrc (image_header_t *hdr) { ulong hcrc; @@ -120,61 +123,6 @@ int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) return (dcrc == image_get_dcrc (hdr)); } -int getenv_verify (void) -{ - char *s = getenv ("verify"); - return (s && (*s == 'n')) ? 0 : 1; -} - -int getenv_autostart (void) -{ - char *s = getenv ("autostart"); - return (s && (*s == 'n')) ? 0 : 1; -} - -ulong getenv_bootm_low(void) -{ - char *s = getenv ("bootm_low"); - if (s) { - ulong tmp = simple_strtoul (s, NULL, 16); - return tmp; - } - -#ifdef CFG_SDRAM_BASE - return CFG_SDRAM_BASE; -#else - return 0; -#endif -} - -ulong getenv_bootm_size(void) -{ - char *s = getenv ("bootm_size"); - if (s) { - ulong tmp = simple_strtoul (s, NULL, 16); - return tmp; - } - - return gd->bd->bi_memsize; -} - -void memmove_wd (void *to, void *from, size_t len, ulong chunksz) -{ -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - while (len > 0) { - size_t tail = (len > chunksz) ? chunksz : len; - WATCHDOG_RESET (); - memmove (to, from, tail); - to += tail; - from += tail; - len -= tail; - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove (to, from, len); -#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 @@ -262,7 +210,185 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, } #ifndef USE_HOSTCC -const char* image_get_os_name (uint8_t os) +static void image_print_type (image_header_t *hdr) +{ + const char *os, *arch, *type, *comp; + + os = genimg_get_os_name (image_get_os (hdr)); + arch = genimg_get_arch_name (image_get_arch (hdr)); + type = genimg_get_type_name (image_get_type (hdr)); + comp = genimg_get_comp_name (image_get_comp (hdr)); + + printf ("%s %s %s (%s)", arch, os, type, comp); +} + +void image_print_contents (image_header_t *hdr) +{ +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) + time_t timestamp = (time_t)image_get_time (hdr); + struct rtc_time tm; +#endif + + printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) + to_tm (timestamp, &tm); + printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +#endif + puts (" Image Type: "); + image_print_type (hdr); + + printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); + print_size (image_get_data_size (hdr), "\n"); + printf (" Load Address: %08x\n" + " Entry Point: %08x\n", + image_get_load (hdr), image_get_ep (hdr)); + + if (image_check_type (hdr, IH_TYPE_MULTI)) { + int i; + ulong data, len; + ulong count = image_multi_count (hdr); + + puts (" Contents:\n"); + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); + printf (" Image %d: %8ld Bytes = ", i, len); + print_size (len, "\n"); + } + } +} + +/** + * image_get_ramdisk - get and verify ramdisk image + * @cmdtp: command table pointer + * @flag: command flag + * @argc: command argument count + * @argv: command argument list + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * If dataflash support is enabled routine checks for dataflash addresses + * and handles required dataflash reads. + * + * returns: + * pointer to a ramdisk image header, if image was found and valid + * otherwise, return NULL + */ +static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong rd_addr, uint8_t arch, int verify) +{ + image_header_t *rd_hdr; + + show_boot_progress (9); + rd_hdr = (image_header_t *)rd_addr; + + if (!image_check_magic (rd_hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-10); + return NULL; + } + + if (!image_check_hcrc (rd_hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-11); + return NULL; + } + + show_boot_progress (10); + image_print_contents (rd_hdr); + + if (verify) { + puts(" Verifying Checksum ... "); + if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { + puts ("Bad Data CRC\n"); + show_boot_progress (-12); + return NULL; + } + puts("OK\n"); + } + + show_boot_progress (11); + + if (!image_check_os (rd_hdr, IH_OS_LINUX) || + !image_check_arch (rd_hdr, arch) || + !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + genimg_get_arch_name(arch)); + show_boot_progress (-13); + return NULL; + } + + return rd_hdr; +} + +/*****************************************************************************/ +/* Shared dual-format routines */ +/*****************************************************************************/ +int getenv_verify (void) +{ + char *s = getenv ("verify"); + return (s && (*s == 'n')) ? 0 : 1; +} + +int getenv_autostart (void) +{ + char *s = getenv ("autostart"); + return (s && (*s == 'n')) ? 0 : 1; +} + +ulong getenv_bootm_low(void) +{ + char *s = getenv ("bootm_low"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + +#ifdef CFG_SDRAM_BASE + return CFG_SDRAM_BASE; +#else + return 0; +#endif +} + +ulong getenv_bootm_size(void) +{ + char *s = getenv ("bootm_size"); + if (s) { + ulong tmp = simple_strtoul (s, NULL, 16); + return tmp; + } + + return gd->bd->bi_memsize; +} + +void memmove_wd (void *to, void *from, size_t len, ulong chunksz) +{ +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + while (len > 0) { + size_t tail = (len > chunksz) ? chunksz : len; + WATCHDOG_RESET (); + memmove (to, from, tail); + to += tail; + from += tail; + len -= tail; + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove (to, from, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} +#endif /* USE_HOSTCC */ + +const char* genimg_get_os_name (uint8_t os) { const char *name; @@ -286,7 +412,7 @@ const char* image_get_os_name (uint8_t os) return name; } -const char* image_get_arch_name (uint8_t arch) +const char* genimg_get_arch_name (uint8_t arch) { const char *name; @@ -315,7 +441,7 @@ const char* image_get_arch_name (uint8_t arch) return name; } -const char* image_get_type_name (uint8_t type) +const char* genimg_get_type_name (uint8_t type) { const char *name; @@ -334,7 +460,7 @@ const char* image_get_type_name (uint8_t type) return name; } -const char* image_get_comp_name (uint8_t comp) +const char* genimg_get_comp_name (uint8_t comp) { const char *name; @@ -348,71 +474,21 @@ const char* image_get_comp_name (uint8_t comp) return name; } -static void image_print_type (image_header_t *hdr) -{ - const char *os, *arch, *type, *comp; - - os = image_get_os_name (image_get_os (hdr)); - arch = image_get_arch_name (image_get_arch (hdr)); - type = image_get_type_name (image_get_type (hdr)); - comp = image_get_comp_name (image_get_comp (hdr)); - - printf ("%s %s %s (%s)", arch, os, type, comp); -} - -void image_print_contents (image_header_t *hdr) -{ -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - time_t timestamp = (time_t)image_get_time (hdr); - struct rtc_time tm; -#endif - - printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); - -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - to_tm (timestamp, &tm); - printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); -#endif - puts (" Image Type: "); - image_print_type (hdr); - - printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); - print_size (image_get_data_size (hdr), "\n"); - printf (" Load Address: %08x\n" - " Entry Point: %08x\n", - image_get_load (hdr), image_get_ep (hdr)); - - if (image_check_type (hdr, IH_TYPE_MULTI)) { - int i; - ulong data, len; - ulong count = image_multi_count (hdr); - - puts (" Contents:\n"); - for (i = 0; i < count; i++) { - image_multi_getimg (hdr, i, &data, &len); - printf (" Image %d: %8ld Bytes = ", i, len); - print_size (len, "\n"); - } - } -} - /** - * gen_image_get_format - get image format type + * genimg_get_format - get image format type * @img_addr: image start address * - * gen_image_get_format() checks whether provided address points to a valid + * genimg_get_format() checks whether provided address points to a valid * legacy or FIT image. * * New uImage format and FDT blob are based on a libfdt. FDT blob * may be passed directly or embedded in a FIT image. In both situations - * gen_image_get_format() must be able to dectect libfdt header. + * genimg_get_format() must be able to dectect libfdt header. * * returns: * image format type or IMAGE_FORMAT_INVALID if no image is present */ -int gen_image_get_format (void *img_addr) +int genimg_get_format (void *img_addr) { ulong format = IMAGE_FORMAT_INVALID; image_header_t *hdr; @@ -435,16 +511,16 @@ int gen_image_get_format (void *img_addr) } /** - * gen_get_image - get image from special storage (if necessary) + * genimg_get_image - get image from special storage (if necessary) * @img_addr: image start address * - * gen_get_image() checks if provided image start adddress is located + * genimg_get_image() checks if provided image start adddress is located * in a dataflash storage. If so, image is moved to a system RAM memory. * * returns: * image start address after possible relocation from special storage */ -ulong gen_get_image (ulong img_addr) +ulong genimg_get_image (ulong img_addr) { ulong ram_addr = img_addr; @@ -469,7 +545,7 @@ ulong gen_get_image (ulong img_addr) read_dataflash (img_addr, h_size, (char *)ram_addr); /* get data size */ - switch (gen_image_get_format ((void *)ram_addr)) { + switch (genimg_get_format ((void *)ram_addr)) { case IMAGE_FORMAT_LEGACY: d_size = image_get_data_size ((image_header_t *)ram_addr); debug (" Legacy format image found at 0x%08lx, size 0x%08lx\n", @@ -502,77 +578,7 @@ ulong gen_get_image (ulong img_addr) } /** - * image_get_ramdisk - get and verify ramdisk image - * @cmdtp: command table pointer - * @flag: command flag - * @argc: command argument count - * @argv: command argument list - * @rd_addr: ramdisk image start address - * @arch: expected ramdisk architecture - * @verify: checksum verification flag - * - * image_get_ramdisk() returns a pointer to the verified ramdisk image - * header. Routine receives image start address and expected architecture - * flag. Verification done covers data and header integrity and os/type/arch - * fields checking. - * - * If dataflash support is enabled routine checks for dataflash addresses - * and handles required dataflash reads. - * - * returns: - * pointer to a ramdisk image header, if image was found and valid - * otherwise, return NULL - */ -static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong rd_addr, uint8_t arch, int verify) -{ - image_header_t *rd_hdr; - - show_boot_progress (9); - rd_hdr = (image_header_t *)rd_addr; - - if (!image_check_magic (rd_hdr)) { - puts ("Bad Magic Number\n"); - show_boot_progress (-10); - return NULL; - } - - if (!image_check_hcrc (rd_hdr)) { - puts ("Bad Header Checksum\n"); - show_boot_progress (-11); - return NULL; - } - - show_boot_progress (10); - image_print_contents (rd_hdr); - - if (verify) { - puts(" Verifying Checksum ... "); - if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { - puts ("Bad Data CRC\n"); - show_boot_progress (-12); - return NULL; - } - puts("OK\n"); - } - - show_boot_progress (11); - - if (!image_check_os (rd_hdr, IH_OS_LINUX) || - !image_check_arch (rd_hdr, arch) || - !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { - printf ("No Linux %s Ramdisk Image\n", - image_get_arch_name(arch)); - show_boot_progress (-13); - return NULL; - } - - return rd_hdr; -} - -/** - * get_ramdisk - main ramdisk handling routine + * boot_get_ramdisk - main ramdisk handling routine * @cmdtp: command table pointer * @flag: command flag * @argc: command argument count @@ -582,7 +588,7 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * @rd_start: pointer to a ulong variable, will hold ramdisk start address * @rd_end: pointer to a ulong variable, will hold ramdisk end * - * get_ramdisk() is responsible for finding a valid ramdisk image. + * boot_get_ramdisk() is responsible for finding a valid ramdisk image. * Curently supported are the following ramdisk sources: * - multicomponent kernel/ramdisk image, * - commandline provided address of decicated ramdisk image. @@ -593,7 +599,7 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, * rd_start and rd_end are set to 0 if no ramdisk exists * return 1 if ramdisk image is found but corrupted */ -int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], +int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], bootm_headers_t *images, uint8_t arch, ulong *rd_start, ulong *rd_end) { @@ -645,14 +651,14 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], /* copy from dataflash if needed */ printf ("## Loading init Ramdisk Image at %08lx ...\n", rd_addr); - rd_addr = gen_get_image (rd_addr); + rd_addr = genimg_get_image (rd_addr); /* * Check if there is an initrd image at the * address provided in the second bootm argument * check image type, for FIT images get FIT node. */ - switch (gen_image_get_format ((void *)rd_addr)) { + switch (genimg_get_format ((void *)rd_addr)) { case IMAGE_FORMAT_LEGACY: debug ("* ramdisk: legacy format image\n"); @@ -729,7 +735,7 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #if defined(CONFIG_PPC) || defined(CONFIG_M68K) /** - * ramdisk_high - relocate init ramdisk + * boot_ramdisk_high - relocate init ramdisk * @lmb: pointer to lmb handle, will be used for memory mgmt * @rd_data: ramdisk data start address * @rd_len: ramdisk data length @@ -738,18 +744,18 @@ int get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * @initrd_end: pointer to a ulong variable, will hold final init ramdisk * end address (after possible relocation) * - * ramdisk_high() takes a relocation hint from "initrd_high" environement + * boot_ramdisk_high() takes a relocation hint from "initrd_high" environement * variable and if requested ramdisk data is moved to a specified location. * + * Initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided, + * otherwise set initrd_start and initrd_end set to zeros. + * * returns: - * - initrd_start and initrd_end are set to final (after relocation) ramdisk - * start/end addresses if ramdisk image start and len were provided - * otherwise set initrd_start and initrd_end set to zeros - * - returns: - * 0 - success - * -1 - failure + * 0 - success + * -1 - failure */ -int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, +int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, ulong *initrd_start, ulong *initrd_end) { char *s; @@ -779,12 +785,12 @@ int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, lmb_reserve(lmb, rd_data, rd_len); } else { if (initrd_high) - *initrd_start = lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); + *initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high); else - *initrd_start = lmb_alloc(lmb, rd_len, 0x1000); + *initrd_start = lmb_alloc (lmb, rd_len, 0x1000); if (*initrd_start == 0) { - puts("ramdisk - allocation error\n"); + puts ("ramdisk - allocation error\n"); goto error; } show_boot_progress (12); @@ -793,7 +799,7 @@ int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, printf (" Loading Ramdisk to %08lx, end %08lx ... ", *initrd_start, *initrd_end); - memmove_wd((void *)*initrd_start, + memmove_wd ((void *)*initrd_start, (void *)rd_data, rd_len, CHUNKSZ); puts ("OK\n"); @@ -804,6 +810,7 @@ int ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, } debug (" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", *initrd_start, *initrd_end); + return 0; error: @@ -811,14 +818,14 @@ error: } /** - * get_boot_cmdline - allocate and initialize kernel cmdline + * boot_get_cmdline - allocate and initialize kernel cmdline * @lmb: pointer to lmb handle, will be used for memory mgmt * @cmd_start: pointer to a ulong variable, will hold cmdline start * @cmd_end: pointer to a ulong variable, will hold cmdline end * @bootmap_base: ulong variable, holds offset in physical memory to * base of bootmap * - * get_boot_cmdline() allocates space for kernel command line below + * boot_get_cmdline() allocates space for kernel command line below * BOOTMAPSZ + bootmap_base address. If "bootargs" U-boot environemnt * variable is present its contents is copied to allocated kernel * command line. @@ -827,7 +834,7 @@ error: * 0 - success * -1 - failure */ -int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, +int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, ulong bootmap_base) { char *cmdline; @@ -853,13 +860,13 @@ int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, } /** - * get_boot_kbd - allocate and initialize kernel copy of board info + * boot_get_kbd - allocate and initialize kernel copy of board info * @lmb: pointer to lmb handle, will be used for memory mgmt * @kbd: double pointer to board info data * @bootmap_base: ulong variable, holds offset in physical memory to * base of bootmap * - * get_boot_kbd() allocates space for kernel copy of board info data below + * boot_get_kbd() allocates space for kernel copy of board info data below * BOOTMAPSZ + bootmap_base address and kernel board info is initialized with * the current u-boot board info data. * @@ -867,7 +874,7 @@ int get_boot_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, * 0 - success * -1 - failure */ -int get_boot_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) +int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) { *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, CFG_BOOTMAPSZ + bootmap_base); -- cgit v1.1 From 570abb0ad120f6002bcaa3cf6f32bd4ca2e1b248 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 29 Feb 2008 15:59:59 +0100 Subject: [new uImage] Share common uImage code between mkimage and U-boot This patch adds the following common routines: 1) Dedicated mkimage print_header() is replaced with common image_print_contents() image_print_contents_noindent() 2) Common os/arch/type/comp fields name <--> id translation routines genimg_get_os_name() genimg_get_arch_name() genimg_get_type_name() genimg_get_comp_name() genimg_get_os_id() genimg_get_arch_id() genimg_get_type_id() genimg_get_comp_id() Signed-off-by: Marian Balakowicz --- common/image.c | 341 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 244 insertions(+), 97 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 99ed3b8..421a474 100644 --- a/common/image.c +++ b/common/image.c @@ -62,11 +62,95 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, ulong rd_addr, uint8_t arch, int verify); #else #include "mkimage.h" -#endif /* USE_HOSTCC*/ +#endif /* !USE_HOSTCC*/ #include +typedef struct table_entry { + int id; /* as defined in image.h */ + char *sname; /* short (input) name */ + char *lname; /* long (output) name */ +} table_entry_t; + +static table_entry_t uimage_arch[] = { + { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, + { IH_ARCH_ALPHA, "alpha", "Alpha", }, + { IH_ARCH_ARM, "arm", "ARM", }, + { IH_ARCH_I386, "x86", "Intel x86", }, + { IH_ARCH_IA64, "ia64", "IA64", }, + { IH_ARCH_M68K, "m68k", "M68K", }, + { IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", }, + { IH_ARCH_MIPS, "mips", "MIPS", }, + { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", }, + { IH_ARCH_NIOS, "nios", "NIOS", }, + { IH_ARCH_NIOS2, "nios2", "NIOS II", }, + { IH_ARCH_PPC, "ppc", "PowerPC", }, + { IH_ARCH_S390, "s390", "IBM S390", }, + { IH_ARCH_SH, "sh", "SuperH", }, + { IH_ARCH_SPARC, "sparc", "SPARC", }, + { IH_ARCH_SPARC64, "sparc64", "SPARC 64 Bit", }, + { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, + { IH_ARCH_AVR32, "avr32", "AVR32", }, + { -1, "", "", }, +}; + +static table_entry_t uimage_os[] = { + { IH_OS_INVALID, NULL, "Invalid OS", }, +#if defined(CONFIG_ARTOS) || defined(USE_HOSTCC) + { IH_OS_ARTOS, "artos", "ARTOS", }, +#endif + { IH_OS_LINUX, "linux", "Linux", }, +#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) + { IH_OS_LYNXOS, "lynxos", "LynxOS", }, +#endif + { IH_OS_NETBSD, "netbsd", "NetBSD", }, + { IH_OS_RTEMS, "rtems", "RTEMS", }, + { IH_OS_U_BOOT, "u-boot", "U-Boot", }, +#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) + { IH_OS_QNX, "qnx", "QNX", }, + { IH_OS_VXWORKS, "vxworks", "VxWorks", }, +#endif +#ifdef USE_HOSTCC + { IH_OS_4_4BSD, "4_4bsd", "4_4BSD", }, + { IH_OS_DELL, "dell", "Dell", }, + { IH_OS_ESIX, "esix", "Esix", }, + { IH_OS_FREEBSD, "freebsd", "FreeBSD", }, + { IH_OS_IRIX, "irix", "Irix", }, + { IH_OS_NCR, "ncr", "NCR", }, + { IH_OS_OPENBSD, "openbsd", "OpenBSD", }, + { IH_OS_PSOS, "psos", "pSOS", }, + { IH_OS_SCO, "sco", "SCO", }, + { IH_OS_SOLARIS, "solaris", "Solaris", }, + { IH_OS_SVR4, "svr4", "SVR4", }, +#endif + { -1, "", "", }, +}; + +static table_entry_t uimage_type[] = { + { IH_TYPE_INVALID, NULL, "Invalid Image", }, + { IH_TYPE_FILESYSTEM, "filesystem", "Filesystem Image", }, + { IH_TYPE_FIRMWARE, "firmware", "Firmware", }, + { IH_TYPE_KERNEL, "kernel", "Kernel Image", }, + { IH_TYPE_MULTI, "multi", "Multi-File Image", }, + { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, + { IH_TYPE_SCRIPT, "script", "Script", }, + { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, + { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, + { -1, "", "", }, +}; + +static table_entry_t uimage_comp[] = { + { IH_COMP_NONE, "none", "uncompressed", }, + { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, + { IH_COMP_GZIP, "gzip", "gzip compressed", }, + { -1, "", "", }, +}; + unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); +static void genimg_print_size (uint32_t size); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp); +#endif /*****************************************************************************/ /* Legacy format routines */ @@ -122,6 +206,7 @@ int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) return (dcrc == image_get_dcrc (hdr)); } +#endif /* !USE_HOSTCC */ /** * image_multi_count - get component (sub-image) count @@ -209,7 +294,6 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, } } -#ifndef USE_HOSTCC static void image_print_type (image_header_t *hdr) { const char *os, *arch, *type, *comp; @@ -219,47 +303,59 @@ static void image_print_type (image_header_t *hdr) type = genimg_get_type_name (image_get_type (hdr)); comp = genimg_get_comp_name (image_get_comp (hdr)); - printf ("%s %s %s (%s)", arch, os, type, comp); + printf ("%s %s %s (%s)\n", arch, os, type, comp); } -void image_print_contents (image_header_t *hdr) +static void __image_print_contents (image_header_t *hdr, const char *p) { -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - time_t timestamp = (time_t)image_get_time (hdr); - struct rtc_time tm; -#endif - - printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); - -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - to_tm (timestamp, &tm); - printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", - tm.tm_year, tm.tm_mon, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr)); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + printf ("%sCreated: ", p); + genimg_print_time ((time_t)image_get_time (hdr)); #endif - puts (" Image Type: "); + printf ("%sImage Type: ", p); image_print_type (hdr); + printf ("%sData Size: ", p); + genimg_print_size (image_get_data_size (hdr)); + printf ("%sLoad Address: %08x\n", p, image_get_load (hdr)); + printf ("%sEntry Point: %08x\n", p, image_get_ep (hdr)); - printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); - print_size (image_get_data_size (hdr), "\n"); - printf (" Load Address: %08x\n" - " Entry Point: %08x\n", - image_get_load (hdr), image_get_ep (hdr)); - - if (image_check_type (hdr, IH_TYPE_MULTI)) { + if (image_check_type (hdr, IH_TYPE_MULTI) || + image_check_type (hdr, IH_TYPE_SCRIPT)) { int i; ulong data, len; ulong count = image_multi_count (hdr); - puts (" Contents:\n"); + printf ("%sContents:\n", p); for (i = 0; i < count; i++) { image_multi_getimg (hdr, i, &data, &len); - printf (" Image %d: %8ld Bytes = ", i, len); - print_size (len, "\n"); + + printf ("%s Image %d: ", p, i); + genimg_print_size (len); + + if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { + /* + * the user may need to know offsets + * if planning to do something with + * multiple files + */ + printf ("%s Offset = 0x%08lx\n", p, data); + } } } } +inline void image_print_contents (image_header_t *hdr) +{ + __image_print_contents (hdr, " "); +} + +inline void image_print_contents_noindent (image_header_t *hdr) +{ + __image_print_contents (hdr, ""); +} + +#ifndef USE_HOSTCC /** * image_get_ramdisk - get and verify ramdisk image * @cmdtp: command table pointer @@ -329,10 +425,12 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, return rd_hdr; } +#endif /* !USE_HOSTCC */ /*****************************************************************************/ /* Shared dual-format routines */ /*****************************************************************************/ +#ifndef USE_HOSTCC int getenv_verify (void) { char *s = getenv ("verify"); @@ -386,94 +484,144 @@ void memmove_wd (void *to, void *from, size_t len, ulong chunksz) memmove (to, from, len); #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ } -#endif /* USE_HOSTCC */ +#endif /* !USE_HOSTCC */ -const char* genimg_get_os_name (uint8_t os) +static void genimg_print_size (uint32_t size) { - const char *name; - - switch (os) { - case IH_OS_INVALID: name = "Invalid OS"; break; - case IH_OS_NETBSD: name = "NetBSD"; break; - case IH_OS_LINUX: name = "Linux"; break; - case IH_OS_VXWORKS: name = "VxWorks"; break; - case IH_OS_QNX: name = "QNX"; break; - case IH_OS_U_BOOT: name = "U-Boot"; break; - case IH_OS_RTEMS: name = "RTEMS"; break; -#ifdef CONFIG_ARTOS - case IH_OS_ARTOS: name = "ARTOS"; break; +#ifndef USE_HOSTCC + printf ("%d Bytes = ", size); + print_size (size, "\n"); +#else + printf ("%d Bytes = %.2f kB = %.2f MB\n", + size, (double)size / 1.024e3, + (double)size / 1.048576e6); #endif -#ifdef CONFIG_LYNXKDI - case IH_OS_LYNXOS: name = "LynxOS"; break; +} + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) +static void genimg_print_time (time_t timestamp) +{ +#ifndef USE_HOSTCC + struct rtc_time tm; + + to_tm (timestamp, &tm); + printf ("%4d-%02d-%02d %2d:%02d:%02d UTC\n", + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +#else + printf ("%s", ctime(×tamp)); #endif - default: name = "Unknown OS"; break; - } +} +#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */ - return name; -} - -const char* genimg_get_arch_name (uint8_t arch) -{ - const char *name; - - switch (arch) { - case IH_ARCH_INVALID: name = "Invalid Architecture"; break; - case IH_ARCH_ALPHA: name = "Alpha"; break; - case IH_ARCH_ARM: name = "ARM"; break; - case IH_ARCH_AVR32: name = "AVR32"; break; - case IH_ARCH_BLACKFIN: name = "Blackfin"; break; - case IH_ARCH_I386: name = "Intel x86"; break; - case IH_ARCH_IA64: name = "IA64"; break; - case IH_ARCH_M68K: name = "M68K"; break; - case IH_ARCH_MICROBLAZE:name = "Microblaze"; break; - case IH_ARCH_MIPS64: name = "MIPS 64 Bit"; break; - case IH_ARCH_MIPS: name = "MIPS"; break; - case IH_ARCH_NIOS2: name = "Nios-II"; break; - case IH_ARCH_NIOS: name = "Nios"; break; - case IH_ARCH_PPC: name = "PowerPC"; break; - case IH_ARCH_S390: name = "IBM S390"; break; - case IH_ARCH_SH: name = "SuperH"; break; - case IH_ARCH_SPARC64: name = "SPARC 64 Bit"; break; - case IH_ARCH_SPARC: name = "SPARC"; break; - default: name = "Unknown Architecture"; break; +/** + * get_table_entry_name - translate entry id to long name + * @table: pointer to a translation table for entries of a specific type + * @msg: message to be returned when translation fails + * @id: entry id to be translated + * + * get_table_entry_name() will go over translation table trying to find + * entry that matches given id. If matching entry is found, its long + * name is returned to the caller. + * + * returns: + * long entry name if translation succeeds + * msg otherwise + */ +static char *get_table_entry_name (table_entry_t *table, char *msg, int id) +{ + for (; table->id >= 0; ++table) { + if (table->id == id) + return (table->lname); } + return (msg); +} - return name; +const char *genimg_get_os_name (uint8_t os) +{ + return (get_table_entry_name (uimage_os, "Unknown OS", os)); } -const char* genimg_get_type_name (uint8_t type) +const char *genimg_get_arch_name (uint8_t arch) { - const char *name; + return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch)); +} - switch (type) { - case IH_TYPE_INVALID: name = "Invalid Image"; break; - case IH_TYPE_STANDALONE:name = "Standalone Program"; break; - case IH_TYPE_KERNEL: name = "Kernel Image"; break; - case IH_TYPE_RAMDISK: name = "RAMDisk Image"; break; - case IH_TYPE_MULTI: name = "Multi-File Image"; break; - case IH_TYPE_FIRMWARE: name = "Firmware"; break; - case IH_TYPE_SCRIPT: name = "Script"; break; - case IH_TYPE_FLATDT: name = "Flat Device Tree"; break; - default: name = "Unknown Image"; break; - } +const char *genimg_get_type_name (uint8_t type) +{ + return (get_table_entry_name (uimage_type, "Unknown Image", type)); +} - return name; +const char *genimg_get_comp_name (uint8_t comp) +{ + return (get_table_entry_name (uimage_comp, "Unknown Compression", comp)); } -const char* genimg_get_comp_name (uint8_t comp) +/** + * get_table_entry_id - translate short entry name to id + * @table: pointer to a translation table for entries of a specific type + * @table_name: to be used in case of error + * @name: entry short name to be translated + * + * get_table_entry_id() will go over translation table trying to find + * entry that matches given short name. If matching entry is found, + * its id returned to the caller. + * + * returns: + * entry id if translation succeeds + * -1 otherwise + */ +static int get_table_entry_id (table_entry_t *table, + const char *table_name, const char *name) { - const char *name; + table_entry_t *t; +#ifdef USE_HOSTCC + int first = 1; - switch (comp) { - case IH_COMP_NONE: name = "uncompressed"; break; - case IH_COMP_GZIP: name = "gzip compressed"; break; - case IH_COMP_BZIP2: name = "bzip2 compressed"; break; - default: name = "unknown compression"; break; + for (t = table; t->id >= 0; ++t) { + if (t->sname && strcasecmp(t->sname, name) == 0) + return (t->id); } - return name; + fprintf (stderr, "\nInvalid %s Type - valid names are", table_name); + for (t = table; t->id >= 0; ++t) { + if (t->sname == NULL) + continue; + fprintf (stderr, "%c %s", (first) ? ':' : ',', t->sname); + first = 0; + } + fprintf (stderr, "\n"); +#else + for (t = table; t->id >= 0; ++t) { + if (t->sname && strcmp(t->sname, name) == 0) + return (t->id); + } + debug ("Invalid %s Type: %s\n", table_name, name); +#endif /* USE_HOSTCC */ + return (-1); +} + +int genimg_get_os_id (const char *name) +{ + return (get_table_entry_id (uimage_os, "OS", name)); +} + +int genimg_get_arch_id (const char *name) +{ + return (get_table_entry_id (uimage_arch, "CPU", name)); } +int genimg_get_type_id (const char *name) +{ + return (get_table_entry_id (uimage_type, "Image", name)); +} + +int genimg_get_comp_id (const char *name) +{ + return (get_table_entry_id (uimage_comp, "Compression", name)); +} + +#ifndef USE_HOSTCC /** * genimg_get_format - get image format type * @img_addr: image start address @@ -971,5 +1119,4 @@ inline int fit_parse_subimage (const char *spec, ulong addr_curr, } #endif /* CONFIG_FIT */ - -#endif /* USE_HOSTCC */ +#endif /* !USE_HOSTCC */ -- cgit v1.1 From df6f1b895c997978f03afe04502ee76b7ba34ab9 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 29 Feb 2008 16:00:06 +0100 Subject: [new uImage] Fix component handling for legacy multi component images Use uint32_t when accessing size table in image_multi_count() and image_multi_getimg() for multi component images. Add missing uimage_to_cpu() endianness conversion. Signed-off-by: Marian Balakowicz --- common/image.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 421a474..3911b2f 100644 --- a/common/image.c +++ b/common/image.c @@ -224,11 +224,11 @@ int image_check_dcrc_wd (image_header_t *hdr, ulong chunksz) ulong image_multi_count (image_header_t *hdr) { ulong i, count = 0; - ulong *size; + uint32_t *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); + size = (uint32_t *)image_get_data (hdr); /* count non empty slots */ for (i = 0; size[i]; ++i) @@ -258,7 +258,7 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, ulong *data, ulong *len) { int i; - ulong *size; + uint32_t *size; ulong offset, tail, count, img_data; /* get number of component */ @@ -266,24 +266,24 @@ void image_multi_getimg (image_header_t *hdr, ulong idx, /* 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); + size = (uint32_t *)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); + img_data = image_get_data (hdr) + (count + 1) * sizeof (uint32_t); if (idx < count) { - *len = size[idx]; + *len = uimage_to_cpu (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]; + offset += uimage_to_cpu (size[i]); /* add up alignment for i-th component */ - tail += (4 - size[i] % 4); + tail += (4 - uimage_to_cpu (size[i]) % 4); } /* calculate idx-th component data address */ -- cgit v1.1 From 5dfb52138688ccbf0146f62683fe6217b3ce1b05 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 29 Feb 2008 21:24:06 +0100 Subject: [new uImage] New uImage low-level API Add FDT-based functions for handling new format component images, configurations, node operations, property get/set, etc. fit_ - routines handling global new format uImage operations like get/set top level property, process all nodes, etc. fit_image_ - routines handling component images subnodes fit_conf_ - routines handling configurations node Signed-off-by: Bartlomiej Sieka Signed-off-by: Marian Balakowicz --- common/image.c | 1265 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1261 insertions(+), 4 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 3911b2f..9278ea9 100644 --- a/common/image.c +++ b/common/image.c @@ -45,10 +45,13 @@ #include #endif +#include + #if defined(CONFIG_FIT) #include #include #include +#include #endif #ifdef CONFIG_CMD_BDI @@ -62,9 +65,9 @@ static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, ulong rd_addr, uint8_t arch, int verify); #else #include "mkimage.h" -#endif /* !USE_HOSTCC*/ - +#include #include +#endif /* !USE_HOSTCC*/ typedef struct table_entry { int id; /* as defined in image.h */ @@ -306,6 +309,18 @@ static void image_print_type (image_header_t *hdr) printf ("%s %s %s (%s)\n", arch, os, type, comp); } +/** + * __image_print_contents - prints out the contents of the legacy format image + * @hdr: pointer to the legacy format image header + * @p: pointer to prefix string + * + * __image_print_contents() formats a multi line legacy image contents description. + * The routine prints out all header fields followed by the size/offset data + * for MULTI/SCRIPT images. + * + * returns: + * no returned results + */ static void __image_print_contents (image_header_t *hdr, const char *p) { printf ("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name (hdr)); @@ -701,7 +716,7 @@ ulong genimg_get_image (ulong img_addr) break; #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: - d_size = fdt_totalsize((void *)ram_addr) - h_size; + d_size = fit_get_size ((const void *)ram_addr) - h_size; debug (" FIT/FDT format image found at 0x%08lx, size 0x%08lx\n", ram_addr, d_size); break; @@ -1040,11 +1055,13 @@ int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) return 0; } #endif /* CONFIG_PPC || CONFIG_M68K */ +#endif /* !USE_HOSTCC */ #if defined(CONFIG_FIT) /*****************************************************************************/ /* New uImage format routines */ /*****************************************************************************/ +#ifndef USE_HOSTCC static int fit_parse_spec (const char *spec, char sepc, ulong addr_curr, ulong *addr, const char **name) { @@ -1117,6 +1134,1246 @@ inline int fit_parse_subimage (const char *spec, ulong addr_curr, { return fit_parse_spec (spec, ':', addr_curr, addr, image_name); } +#endif /* !USE_HOSTCC */ + +static void fit_get_debug (const void *fit, int noffset, + char *prop_name, int err) +{ + debug ("Can't get '%s' property from FIT 0x%08lx, " + "node: offset %d, name %s (%s)\n", + prop_name, (ulong)fit, noffset, + fit_get_name (fit, noffset, NULL), + fdt_strerror (err)); +} + +/** + * __fit_print_contents - prints out the contents of the FIT format image + * @fit: pointer to the FIT format image header + * @p: pointer to prefix string + * + * __fit_print_contents() formats a multi line FIT image contents description. + * The routine prints out FIT image properties (root node level) follwed by + * the details of each component image. + * + * returns: + * no returned results + */ +static void __fit_print_contents (const void *fit, const char *p) +{ + char *desc; + char *uname; + int images_noffset; + int confs_noffset; + int noffset; + int ndepth; + int count = 0; + int ret; +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + time_t timestamp; +#endif + + /* Root node properties */ + ret = fit_get_desc (fit, 0, &desc); + printf ("%sFIT description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + ret = fit_get_timestamp (fit, 0, ×tamp); + printf ("%sCreated: ", p); + if (ret) + printf ("unavailable\n"); + else + genimg_print_time (timestamp); +#endif + + /* Find images parent node offset */ + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return; + } + + /* Process its subnodes, print out component images details */ + for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + printf ("%s Image %u (%s)\n", p, count++, + fit_get_name(fit, noffset, NULL)); + + fit_image_print (fit, noffset, p); + } + } + + /* Find configurations parent node offset */ + confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); + if (confs_noffset < 0) { + debug ("Can't get configurations parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror (confs_noffset)); + return; + } + + /* get default configuration unit name from default property */ + uname = (char *)fdt_getprop (fit, noffset, FIT_DEFAULT_PROP, NULL); + if (uname) + printf ("%s Default Configuration: '%s'\n", p, uname); + + /* Process its subnodes, print out configurations details */ + for (ndepth = 0, count = 0, noffset = fdt_next_node (fit, confs_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the configurations parent node, + * i.e. configuration node. + */ + printf ("%s Configuration %u (%s)\n", p, count++, + fit_get_name(fit, noffset, NULL)); + + fit_conf_print (fit, noffset, p); + } + } +} + +inline void fit_print_contents (const void *fit) +{ + __fit_print_contents (fit, " "); +} + +inline void fit_print_contents_noindent (const void *fit) +{ + __fit_print_contents (fit, ""); +} + +/** + * fit_image_print - prints out the FIT component image details + * @fit: pointer to the FIT format image header + * @image_noffset: offset of the component image node + * @p: pointer to prefix string + * + * fit_image_print() lists all mandatory properies for the processed component + * image. If present, hash nodes are printed out as well. + * + * returns: + * no returned results + */ +void fit_image_print (const void *fit, int image_noffset, const char *p) +{ + char *desc; + uint8_t type, arch, os, comp; + size_t size; + ulong load, entry; + const void *data; + int noffset; + int ndepth; + int ret; + + /* Mandatory properties */ + ret = fit_get_desc (fit, image_noffset, &desc); + printf ("%s Description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + + fit_image_get_type (fit, image_noffset, &type); + printf ("%s Type: %s\n", p, genimg_get_type_name (type)); + + fit_image_get_comp (fit, image_noffset, &comp); + printf ("%s Compression: %s\n", p, genimg_get_comp_name (comp)); + + ret = fit_image_get_data (fit, image_noffset, &data, &size); + +#ifndef USE_HOSTCC + printf ("%s Data Start: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", (ulong)data); +#endif + + printf ("%s Data Size: ", p); + if (ret) + printf ("unavailable\n"); + else + genimg_print_size (size); + + /* Remaining, type dependent properties */ + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || + (type == IH_TYPE_FLATDT)) { + fit_image_get_arch (fit, image_noffset, &arch); + printf ("%s Architecture: %s\n", p, genimg_get_arch_name (arch)); + } + + if (type == IH_TYPE_KERNEL) { + 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)) { + ret = fit_image_get_load (fit, image_noffset, &load); + printf ("%s Load Address: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", load); + + fit_image_get_entry (fit, image_noffset, &entry); + printf ("%s Entry Point: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("0x%08lx\n", entry); + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + fit_image_print_hash (fit, noffset, p); + } + } +} + +/** + * fit_image_print_hash - prints out the hash node details + * @fit: pointer to the FIT format image header + * @noffset: offset of the hash node + * @p: pointer to prefix string + * + * fit_image_print_hash() lists properies for the processed hash node + * + * returns: + * no returned results + */ +void fit_image_print_hash (const void *fit, int noffset, const char *p) +{ + char *algo; + uint8_t *value; + int value_len; + int i, ret; + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) + return; + + debug ("%s Hash node: '%s'\n", p, + fit_get_name (fit, noffset, NULL)); + + printf ("%s Hash algo: ", p); + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + printf ("invalid/unsupported\n"); + return; + } + printf ("%s\n", algo); + + ret = fit_image_hash_get_value (fit, noffset, &value, + &value_len); + printf ("%s Hash value: ", p); + if (ret) { + printf ("unavailable\n"); + } else { + for (i = 0; i < value_len; i++) + printf ("%02x", value[i]); + printf ("\n"); + } + + debug ("%s Hash len: %d\n", p, value_len); +} + +/** + * fit_get_desc - get node description property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @desc: double pointer to the char, will hold pointer to the descrption + * + * fit_get_desc() reads description property from a given node, if + * description is found pointer to it is returened in third call argument. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_get_desc (const void *fit, int noffset, char **desc) +{ + int len; + + *desc = (char *)fdt_getprop (fit, noffset, FIT_DESC_PROP, &len); + if (*desc == NULL) { + fit_get_debug (fit, noffset, FIT_DESC_PROP, len); + return -1; + } + + return 0; +} + +/** + * fit_get_timestamp - get node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: pointer to the time_t, will hold read timestamp + * + * fit_get_timestamp() reads timestamp poperty from given node, if timestamp + * is found and has a correct size its value is retured in third call + * argument. + * + * returns: + * 0, on success + * -1, on property read failure + * -2, on wrong timestamp size + */ +int fit_get_timestamp (const void *fit, int noffset, time_t *timestamp) +{ + int len; + const void *data; + + data = fdt_getprop (fit, noffset, FIT_TIMESTAMP_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_TIMESTAMP_PROP, len); + return -1; + } + if (len != sizeof (uint32_t)) { + debug ("FIT timestamp with incorrect size of (%u)\n", len); + return -2; + } + + *timestamp = uimage_to_cpu (*((uint32_t *)data)); + return 0; +} + +/** + * fit_image_get_node - get node offset for component image of a given unit name + * @fit: pointer to the FIT format image header + * @image_uname: component image node unit name + * + * fit_image_get_node() finds a component image (withing the '/images' + * node) of a provided unit name. If image is found its node offset is + * returned to the caller. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_image_get_node (const void *fit, const char *image_uname) +{ + int noffset, images_noffset; + + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + debug ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return images_noffset; + } + + noffset = fdt_subnode_offset (fit, images_noffset, image_uname); + if (noffset < 0) { + debug ("Can't get node offset for image unit name: '%s' (%s)\n", + image_uname, fdt_strerror (noffset)); + } + + return noffset; +} + +/** + * fit_image_get_os - get os id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: pointer to the uint8_t, will hold os numeric id + * + * fit_image_get_os() finds os property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_os (const void *fit, int noffset, uint8_t *os) +{ + int len; + const void *data; + + /* Get OS name from property data */ + data = fdt_getprop (fit, noffset, FIT_OS_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_OS_PROP, len); + *os = -1; + return -1; + } + + /* Translate OS name to id */ + *os = genimg_get_os_id (data); + return 0; +} + +/** + * fit_image_get_arch - get arch id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: pointer to the uint8_t, will hold arch numeric id + * + * fit_image_get_arch() finds arch property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_arch (const void *fit, int noffset, uint8_t *arch) +{ + int len; + const void *data; + + /* Get architecture name from property data */ + data = fdt_getprop (fit, noffset, FIT_ARCH_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_ARCH_PROP, len); + *arch = -1; + return -1; + } + + /* Translate architecture name to id */ + *arch = genimg_get_arch_id (data); + return 0; +} + +/** + * fit_image_get_type - get type id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: pointer to the uint8_t, will hold type numeric id + * + * fit_image_get_type() finds type property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_type (const void *fit, int noffset, uint8_t *type) +{ + int len; + const void *data; + + /* Get image type name from property data */ + data = fdt_getprop (fit, noffset, FIT_TYPE_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_TYPE_PROP, len); + *type = -1; + return -1; + } + + /* Translate image type name to id */ + *type = genimg_get_type_id (data); + return 0; +} + +/** + * fit_image_get_comp - get comp id for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: pointer to the uint8_t, will hold comp numeric id + * + * fit_image_get_comp() finds comp property in a given component image node. + * If the property is found, its (string) value is translated to the numeric + * id which is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_comp (const void *fit, int noffset, uint8_t *comp) +{ + int len; + const void *data; + + /* Get compression name from property data */ + data = fdt_getprop (fit, noffset, FIT_COMP_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_COMP_PROP, len); + *comp = -1; + return -1; + } + + /* Translate compression name to id */ + *comp = genimg_get_comp_id (data); + return 0; +} + +/** + * fit_image_get_load - get load address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @load: pointer to the uint32_t, will hold load address + * + * fit_image_get_load() finds load address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_load (const void *fit, int noffset, ulong *load) +{ + int len; + const uint32_t *data; + + data = fdt_getprop (fit, noffset, FIT_LOAD_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_LOAD_PROP, len); + return -1; + } + + *load = uimage_to_cpu (*data); + return 0; +} + +/** + * fit_image_get_entry - get entry point address property for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @entry: pointer to the uint32_t, will hold entry point address + * + * fit_image_get_entry() finds entry point address property in a given component image node. + * If the property is found, its value is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_entry (const void *fit, int noffset, ulong *entry) +{ + int len; + const uint32_t *data; + + data = fdt_getprop (fit, noffset, FIT_ENTRY_PROP, &len); + if (data == NULL) { + fit_get_debug (fit, noffset, FIT_ENTRY_PROP, len); + return -1; + } + + *entry = uimage_to_cpu (*data); + return 0; +} + +/** + * fit_image_get_data - get data property and its size for a given component image node + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @data: double pointer to void, will hold data property's data address + * @size: pointer to size_t, will hold data property's data size + * + * fit_image_get_data() finds data property in a given component image node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_get_data (const void *fit, int noffset, + const void **data, size_t *size) +{ + int len; + + *data = fdt_getprop (fit, noffset, FIT_DATA_PROP, &len); + if (*data == NULL) { + fit_get_debug (fit, noffset, FIT_DATA_PROP, len); + *size = 0; + return -1; + } + + *size = len; + return 0; +} + +/** + * fit_image_hash_get_algo - get hash algorithm name + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @algo: double pointer to char, will hold pointer to the algorithm name + * + * fit_image_hash_get_algo() finds hash algorithm property in a given hash node. + * If the property is found its data start address is returned to the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_hash_get_algo (const void *fit, int noffset, char **algo) +{ + int len; + + *algo = (char *)fdt_getprop (fit, noffset, FIT_ALGO_PROP, &len); + if (*algo == NULL) { + fit_get_debug (fit, noffset, FIT_ALGO_PROP, len); + return -1; + } + + return 0; +} + +/** + * fit_image_hash_get_value - get hash value and length + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: double pointer to uint8_t, will hold address of a hash value data + * @value_len: pointer to an int, will hold hash data length + * + * fit_image_hash_get_value() finds hash value property in a given hash node. + * If the property is found its data start address and size are returned to + * the caller. + * + * returns: + * 0, on success + * -1, on failure + */ +int fit_image_hash_get_value (const void *fit, int noffset, uint8_t **value, + int *value_len) +{ + int len; + + *value = (uint8_t *)fdt_getprop (fit, noffset, FIT_VALUE_PROP, &len); + if (*value == NULL) { + fit_get_debug (fit, noffset, FIT_VALUE_PROP, len); + *value_len = 0; + return -1; + } + + *value_len = len; + return 0; +} + +/** + * fit_set_timestamp - set node timestamp property + * @fit: pointer to the FIT format image header + * @noffset: node offset + * @timestamp: timestamp value to be set + * + * fit_set_timestamp() attempts to set timestamp property in the requested + * node and returns operation status to the caller. + * + * returns: + * 0, on success + * -1, on property read failure + */ +int fit_set_timestamp (void *fit, int noffset, time_t timestamp) +{ + uint32_t t; + int ret; + + t = cpu_to_uimage (timestamp); + ret = fdt_setprop (fit, noffset, FIT_TIMESTAMP_PROP, &t, + sizeof (uint32_t)); + if (ret) { + printf ("Can't set '%s' property for '%s' node (%s)\n", + FIT_TIMESTAMP_PROP, fit_get_name (fit, noffset, NULL), + fdt_strerror (ret)); + return -1; + } + + return 0; +} + +/** + * calculate_hash - calculate and return hash for provided input data + * @data: pointer to the input data + * @data_len: data length + * @algo: requested hash algorithm + * @value: pointer to the char, will hold hash value data (caller must + * allocate enough free space) + * value_len: length of the calculated hash + * + * calculate_hash() computes input data hash according to the requested algorithm. + * Resulting hash value is placed in caller provided 'value' buffer, length + * of the calculated hash is returned via value_len pointer argument. + * + * returns: + * 0, on success + * -1, when algo is unsupported + */ +static int calculate_hash (const void *data, int data_len, const char *algo, + uint8_t *value, int *value_len) +{ + if (strcmp (algo, "crc32") == 0 ) { + *((uint32_t *)value) = crc32 (0, data, data_len); + *((uint32_t *)value) = cpu_to_uimage (*((uint32_t *)value)); + *value_len = 4; + } else if (strcmp (algo, "sha1") == 0 ) { + sha1_csum ((unsigned char *) data, data_len, + (unsigned char *) value); + *value_len = 20; + } else if (strcmp (algo, "md5") == 0 ) { + printf ("MD5 not supported\n"); + *value_len = 0; + } else { + debug ("Unsupported hash alogrithm\n"); + return -1; + } + return 0; +} + +#ifdef USE_HOSTCC +/** + * fit_set_hashes - process FIT component image nodes and calculate hashes + * @fit: pointer to the FIT format image header + * + * fit_set_hashes() adds hash values for all component images in the FIT blob. + * Hashes are calculated for all component images which have hash subnodes + * with algorithm property set to one of the supported hash algorithms. + * + * returns + * 0, on success + * libfdt error code, on failure + */ +int fit_set_hashes (void *fit) +{ + int images_noffset; + int noffset; + int ndepth; + int ret; + + /* Find images parent node offset */ + images_noffset = fdt_path_offset (fit, FIT_IMAGES_PATH); + if (images_noffset < 0) { + printf ("Can't find images parent node '%s' (%s)\n", + FIT_IMAGES_PATH, fdt_strerror (images_noffset)); + return images_noffset; + } + + /* Process its subnodes, print out component images details */ + for (ndepth = 0, noffset = fdt_next_node (fit, images_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* + * Direct child node of the images parent node, + * i.e. component image node. + */ + ret = fit_image_set_hashes (fit, noffset); + if (ret) + return ret; + } + } + + return 0; +} + +/** + * fit_image_set_hashes - calculate/set hashes for given component image node + * @fit: pointer to the FIT format image header + * @image_noffset: requested component image node + * + * fit_image_set_hashes() adds hash values for an component image node. All + * existing hash subnodes are checked, if algorithm property is set to one of + * the supported hash algorithms, hash value is computed and corresponding + * hash node property is set, for example: + * + * Input component image node structure: + * + * o image@1 (at image_noffset) + * | - data = [binary data] + * o hash@1 + * |- algo = "sha1" + * + * Output component image node structure: + * + * o image@1 (at image_noffset) + * | - data = [binary data] + * o hash@1 + * |- algo = "sha1" + * |- value = sha1(data) + * + * returns: + * 0 on sucess + * <0 on failure + */ +int fit_image_set_hashes (void *fit, int image_noffset) +{ + const void *data; + size_t size; + char *algo; + uint8_t value[FIT_MAX_HASH_LEN]; + int value_len; + int noffset; + int ndepth; + + /* Get image data and data length */ + if (fit_image_get_data (fit, image_noffset, &data, &size)) { + printf ("Can't get image data/size\n"); + return -1; + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) { + /* Not a hash subnode, skip it */ + continue; + } + + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + printf ("Can't get hash algo property for " + "'%s' hash node in '%s' image node\n", + fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + + if (calculate_hash (data, size, algo, value, &value_len)) { + printf ("Unsupported hash algorithm (%s) for " + "'%s' hash node in '%s' image node\n", + algo, fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + + if (fit_image_hash_set_value (fit, noffset, value, + value_len)) { + printf ("Can't set hash value for " + "'%s' hash node in '%s' image node\n", + fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return -1; + } + } + } + + return 0; +} + +/** + * fit_image_hash_set_value - set hash value in requested has node + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: hash value to be set + * @value_len: hash value length + * + * fit_image_hash_set_value() attempts to set hash value in a node at offset + * given and returns operation status to the caller. + * + * returns + * 0, on success + * -1, on failure + */ +int fit_image_hash_set_value (void *fit, int noffset, uint8_t *value, + int value_len) +{ + int ret; + + ret = fdt_setprop (fit, noffset, FIT_VALUE_PROP, value, value_len); + if (ret) { + printf ("Can't set hash '%s' property for '%s' node (%s)\n", + FIT_VALUE_PROP, fit_get_name (fit, noffset, NULL), + fdt_strerror (ret)); + return -1; + } + + return 0; +} +#endif /* USE_HOSTCC */ + +/** + * fit_image_check_hashes - verify data intergity + * @fit: pointer to the FIT format image header + * @image_noffset: component image node offset + * + * fit_image_check_hashes() goes over component image hash nodes, + * re-calculates each data hash and compares with the value stored in hash + * node. + * + * returns: + * 1, if all hashes are valid + * 0, otherwise (or on error) + */ +int fit_image_check_hashes (const void *fit, int image_noffset) +{ + const void *data; + size_t size; + char *algo; + uint8_t *fit_value; + int fit_value_len; + uint8_t value[FIT_MAX_HASH_LEN]; + int value_len; + int noffset; + int ndepth; + char *err_msg = ""; + + /* Get image data and data length */ + if (fit_image_get_data (fit, image_noffset, &data, &size)) { + printf ("Can't get image data/size\n"); + return 0; + } + + /* Process all hash subnodes of the component image node */ + for (ndepth = 0, noffset = fdt_next_node (fit, image_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node (fit, noffset, &ndepth)) { + if (ndepth == 1) { + /* Direct child node of the component image node */ + + /* + * Check subnode name, must be equal to "hash". + * Multiple hash nodes require unique unit node + * names, e.g. hash@1, hash@2, etc. + */ + if (strncmp (fit_get_name(fit, noffset, NULL), + FIT_HASH_NODENAME, + strlen(FIT_HASH_NODENAME)) != 0) + continue; + + if (fit_image_hash_get_algo (fit, noffset, &algo)) { + err_msg = "Can't get hash algo property"; + goto error; + } + printf ("%s", algo); + + if (fit_image_hash_get_value (fit, noffset, &fit_value, + &fit_value_len)) { + err_msg = "Can't get hash value property"; + goto error; + } + + if (calculate_hash (data, size, algo, value, &value_len)) { + err_msg = "Unsupported hash algorithm"; + goto error; + } + + if (value_len != fit_value_len) { + err_msg = "Bad hash value len"; + goto error; + } else if (memcmp (value, fit_value, value_len) != 0) { + err_msg = "Bad hash value"; + goto error; + } + printf ("+ "); + } + } + + return 1; + +error: + printf ("%s for '%s' hash node in '%s' image node\n", + err_msg, fit_get_name (fit, noffset, NULL), + fit_get_name (fit, image_noffset, NULL)); + return 0; +} + +/** + * fit_image_check_os - check whether image node is of a given os type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @os: requested image os + * + * fit_image_check_os() reads image os property and compares its numeric + * id with the requested os. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given os type + * 0 otherwise (or on error) + */ +int fit_image_check_os (const void *fit, int noffset, uint8_t os) +{ + uint8_t image_os; + + if (fit_image_get_os (fit, noffset, &image_os)) + return 0; + return (os == image_os); +} + +/** + * fit_image_check_arch - check whether image node is of a given arch + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @arch: requested imagearch + * + * fit_image_check_arch() reads image arch property and compares its numeric + * id with the requested arch. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given arch + * 0 otherwise (or on error) + */ +int fit_image_check_arch (const void *fit, int noffset, uint8_t arch) +{ + uint8_t image_arch; + + if (fit_image_get_arch (fit, noffset, &image_arch)) + return 0; + return (arch == image_arch); +} + +/** + * fit_image_check_type - check whether image node is of a given type + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @type: requested image type + * + * fit_image_check_type() reads image type property and compares its numeric + * id with the requested type. Comparison result is returned to the caller. + * + * returns: + * 1 if image is of given type + * 0 otherwise (or on error) + */ +int fit_image_check_type (const void *fit, int noffset, uint8_t type) +{ + uint8_t image_type; + + if (fit_image_get_type (fit, noffset, &image_type)) + return 0; + return (type == image_type); +} + +/** + * fit_image_check_comp - check whether image node uses given compression + * @fit: pointer to the FIT format image header + * @noffset: component image node offset + * @comp: requested image compression type + * + * fit_image_check_comp() reads image compression property and compares its + * numeric id with the requested compression type. Comparison result is + * returned to the caller. + * + * returns: + * 1 if image uses requested compression + * 0 otherwise (or on error) + */ +int fit_image_check_comp (const void *fit, int noffset, uint8_t comp) +{ + uint8_t image_comp; + + if (fit_image_get_comp (fit, noffset, &image_comp)) + return 0; + return (comp == image_comp); +} + +/** + * fit_check_format - sanity check FIT image format + * @fit: pointer to the FIT format image header + * + * fit_check_format() runs a basic sanity FIT image verification. + * Routine checks for mandatory properties, nodes, etc. + * + * returns: + * 1, on success + * 0, on failure + */ +int fit_check_format (const void *fit) +{ + /* mandatory / node 'description' property */ + if (fdt_getprop (fit, 0, FIT_DESC_PROP, NULL) == NULL) { + debug ("Wrong FIT format: no description\n"); + return 0; + } + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + /* mandatory / node 'timestamp' property */ + if (fdt_getprop (fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) { + debug ("Wrong FIT format: no description\n"); + return 0; + } +#endif + + /* mandatory subimages parent '/images' node */ + if (fdt_path_offset (fit, FIT_IMAGES_PATH) < 0) { + debug ("Wrong FIT format: no images parent node\n"); + return 0; + } + + return 1; +} + +/** + * fit_conf_get_node - get node offset for configuration of a given unit name + * @fit: pointer to the FIT format image header + * @conf_uname: configuration node unit name + * + * fit_conf_get_node() finds a configuration (withing the '/configurations' + * parant node) of a provided unit name. If configuration is found its node offset + * is returned to the caller. + * + * When NULL is provided in second argument fit_conf_get_node() will search + * for a default configuration node instead. Default configuration node unit name + * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node. + * + * returns: + * configuration node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_node (const void *fit, const char *conf_uname) +{ + int noffset, confs_noffset; + int len; + + confs_noffset = fdt_path_offset (fit, FIT_CONFS_PATH); + if (confs_noffset < 0) { + debug ("Can't find configurations parent node '%s' (%s)\n", + FIT_CONFS_PATH, fdt_strerror (confs_noffset)); + return confs_noffset; + } + + if (conf_uname == NULL) { + /* get configuration unit name from the default property */ + debug ("No configuration specified, trying default...\n"); + conf_uname = (char *)fdt_getprop (fit, confs_noffset, FIT_DEFAULT_PROP, &len); + if (conf_uname == NULL) { + fit_get_debug (fit, confs_noffset, FIT_DEFAULT_PROP, len); + return len; + } + debug ("Found default configuration: '%s'\n", conf_uname); + } + + noffset = fdt_subnode_offset (fit, confs_noffset, conf_uname); + if (noffset < 0) { + debug ("Can't get node offset for configuration unit name: '%s' (%s)\n", + conf_uname, fdt_strerror (noffset)); + } + + return noffset; +} + +static int __fit_conf_get_prop_node (const void *fit, int noffset, + const char *prop_name) +{ + char *uname; + int len; + + /* get kernel image unit name from configuration kernel property */ + uname = (char *)fdt_getprop (fit, noffset, prop_name, &len); + if (uname == NULL) + return len; + + return fit_image_get_node (fit, uname); +} + +/** + * fit_conf_get_kernel_node - get kernel image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_kernel_node() retrives kernel image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_kernel_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_KERNEL_PROP); +} + +/** + * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_ramdisk_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_RAMDISK_PROP); +} + +/** + * fit_conf_get_fdt_node - get fdt image node offset that corresponds to + * a given configuration + * @fit: pointer to the FIT format image header + * @noffset: configuration node offset + * + * fit_conf_get_fdt_node() retrives fdt image node unit name from + * configuration FIT_KERNEL_PROP property and translates it to the node + * offset. + * + * returns: + * image node offset when found (>=0) + * negative number on failure (FDT_ERR_* code) + */ +int fit_conf_get_fdt_node (const void *fit, int noffset) +{ + return __fit_conf_get_prop_node (fit, noffset, FIT_FDT_PROP); +} +/** + * fit_conf_print - prints out the FIT configuration details + * @fit: pointer to the FIT format image header + * @conf_noffset: offset of the configuration node + * @p: pointer to prefix string + * + * fit_conf_print() lists all mandatory properies for the processed + * configuration node. + * + * returns: + * no returned results + */ +void fit_conf_print (const void *fit, int noffset, const char *p) +{ + char *desc; + char *uname; + int ret; + + /* Mandatory properties */ + ret = fit_get_desc (fit, noffset, &desc); + printf ("%s Description: ", p); + if (ret) + printf ("unavailable\n"); + else + printf ("%s\n", desc); + + uname = (char *)fdt_getprop (fit, noffset, FIT_KERNEL_PROP, NULL); + printf ("%s Kernel: ", p); + if (uname == NULL) + printf ("unavailable\n"); + else + printf ("%s\n", uname); + + /* Optional properties */ + uname = (char *)fdt_getprop (fit, noffset, FIT_RAMDISK_PROP, NULL); + if (uname) + printf ("%s Init Ramdisk: %s\n", p, uname); + + uname = (char *)fdt_getprop (fit, noffset, FIT_FDT_PROP, NULL); + if (uname) + printf ("%s FDT: %s\n", p, uname); +} #endif /* CONFIG_FIT */ -#endif /* !USE_HOSTCC */ -- cgit v1.1 From c87796483bc7c2900470dc747c367f602577608d Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 10:12:37 +0100 Subject: [new uImage] Add new uImage format support for ramdisk handling This patch updates boot_get_ramdisk() routine adding format verification and handling for new (FIT) uImages. Signed-off-by: Marian Balakowicz --- common/image.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 16 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 9278ea9..3b15853 100644 --- a/common/image.c +++ b/common/image.c @@ -47,11 +47,17 @@ #include -#if defined(CONFIG_FIT) +#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT) #include #include #include +#endif + +#if defined(CONFIG_FIT) #include + +static int fit_check_ramdisk (const void *fit, int os_noffset, + uint8_t arch, int verify); #endif #ifdef CONFIG_CMD_BDI @@ -774,8 +780,15 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], const char *fit_uname_config = NULL; const char *fit_uname_ramdisk = NULL; ulong default_addr; + int rd_noffset; + int conf_noffset; + const void *data; + size_t size; #endif + *rd_start = 0; + *rd_end = 0; + /* * Look for a '-' which indicates to ignore the * ramdisk argument @@ -812,8 +825,6 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], } /* copy from dataflash if needed */ - printf ("## Loading init Ramdisk Image at %08lx ...\n", - rd_addr); rd_addr = genimg_get_image (rd_addr); /* @@ -823,17 +834,14 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], */ switch (genimg_get_format ((void *)rd_addr)) { case IMAGE_FORMAT_LEGACY: - - debug ("* ramdisk: legacy format image\n"); + printf ("## Loading init Ramdisk from Legacy " + "Image at %08lx ...\n", rd_addr); rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, rd_addr, arch, images->verify); - if (rd_hdr == NULL) { - *rd_start = 0; - *rd_end = 0; + if (rd_hdr == NULL) return 1; - } rd_data = image_get_data (rd_hdr); rd_len = image_get_data_size (rd_hdr); @@ -842,14 +850,60 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (void *)rd_addr; - debug ("* ramdisk: FIT format image\n"); - fit_unsupported_reset ("ramdisk"); - return 1; + printf ("## Loading init Ramdisk from FIT " + "Image at %08lx ...\n", rd_addr); + + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT ramdisk image format!\n"); + return 0; + } + + if (!fit_uname_ramdisk) { + /* + * no ramdisk image node unit name, try to get config + * node first. If config unit node name is NULL + * fit_conf_get_node() will try to find default config node + */ + conf_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (conf_noffset < 0) + return 0; + + rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, conf_noffset); + fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL); + } else { + /* get ramdisk component image node offset */ + rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk); + } + if (rd_noffset < 0) + return 0; + + printf (" Trying '%s' ramdisk subimage\n", fit_uname_ramdisk); + + if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify)) + return 0; + + /* get ramdisk image data address and length */ + if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) { + puts ("Could not find ramdisk subimage data!\n"); + return 0; + } + + rd_data = (ulong)data; + rd_len = size; + + if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) { + puts ("Can't get ramdisk subimage load address!\n"); + return 0; + } + + images->fit_hdr_rd = fit_hdr; + images->fit_uname_rd = fit_uname_ramdisk; + break; #endif default: printf ("Wrong Image Format for %s command\n", cmdtp->name); - rd_data = rd_len = 0; + rd_data = rd_len = rd_load = 0; } #if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) @@ -870,7 +924,7 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], */ show_boot_progress (13); printf ("## Loading init Ramdisk from multi component " - "Image at %08lx ...\n", + "Legacy Image at %08lx ...\n", (ulong)images->legacy_hdr_os); image_multi_getimg (images->legacy_hdr_os, 1, &rd_data, &rd_len); @@ -884,8 +938,6 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], if (!rd_data) { debug ("## No init Ramdisk\n"); - *rd_start = 0; - *rd_end = 0; } else { *rd_start = rd_data; *rd_end = rd_data + rd_len; @@ -2376,4 +2428,44 @@ void fit_conf_print (const void *fit, int noffset, const char *p) if (uname) printf ("%s FDT: %s\n", p, uname); } + +/** + * fit_check_ramdisk - verify FIT format ramdisk subimage + * @fit_hdr: pointer to the FIT ramdisk header + * @rd_noffset: ramdisk subimage node offset within FIT image + * @arch: requested ramdisk image architecture type + * @verify: data CRC verification flag + * + * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#ifndef USE_HOSTCC +static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int verify) +{ + fit_image_print (fit, rd_noffset, " "); + + if (verify) { + puts (" Verifying Hash Integrity ... "); + if (!fit_image_check_hashes (fit, rd_noffset)) { + puts ("Bad Data Hash\n"); + return 0; + } + puts ("OK\n"); + } + + if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) || + !fit_image_check_arch (fit, rd_noffset, arch) || + !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + genimg_get_arch_name(arch)); + return 0; + } + + return 1; +} +#endif /* USE_HOSTCC */ #endif /* CONFIG_FIT */ -- cgit v1.1 From d985c8498c4e47095820da97aa722381d39172c5 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 10:14:38 +0100 Subject: [new uImage] Remove unnecessary arguments passed to ramdisk routines boot_get_ramdisk() and image_get_ramdisk() do not need all cmdtp, flag, argc and argv arguments. Simplify routines definition. Signed-off-by: Marian Balakowicz --- common/image.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 3b15853..6458fb1 100644 --- a/common/image.c +++ b/common/image.c @@ -66,9 +66,8 @@ extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); DECLARE_GLOBAL_DATA_PTR; -static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong rd_addr, uint8_t arch, int verify); +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, + int verify); #else #include "mkimage.h" #include @@ -379,10 +378,6 @@ inline void image_print_contents_noindent (image_header_t *hdr) #ifndef USE_HOSTCC /** * image_get_ramdisk - get and verify ramdisk image - * @cmdtp: command table pointer - * @flag: command flag - * @argc: command argument count - * @argv: command argument list * @rd_addr: ramdisk image start address * @arch: expected ramdisk architecture * @verify: checksum verification flag @@ -399,9 +394,8 @@ inline void image_print_contents_noindent (image_header_t *hdr) * pointer to a ramdisk image header, if image was found and valid * otherwise, return NULL */ -static image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong rd_addr, uint8_t arch, int verify) +static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, + int verify) { image_header_t *rd_hdr; @@ -748,8 +742,6 @@ ulong genimg_get_image (ulong img_addr) /** * boot_get_ramdisk - main ramdisk handling routine - * @cmdtp: command table pointer - * @flag: command flag * @argc: command argument count * @argv: command argument list * @images: pointer to the bootm images structure @@ -763,14 +755,15 @@ ulong genimg_get_image (ulong img_addr) * - commandline provided address of decicated ramdisk image. * * returns: + * 0, if ramdisk image was found and valid, or skiped * rd_start and rd_end are set to ramdisk start/end addresses if * ramdisk image is found and valid + * + * 1, if ramdisk image is found but corrupted * rd_start and rd_end are set to 0 if no ramdisk exists - * return 1 if ramdisk image is found but corrupted */ -int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - bootm_headers_t *images, uint8_t arch, - ulong *rd_start, ulong *rd_end) +int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, + uint8_t arch, ulong *rd_start, ulong *rd_end) { ulong rd_addr, rd_load; ulong rd_data, rd_len; @@ -837,8 +830,8 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], printf ("## Loading init Ramdisk from Legacy " "Image at %08lx ...\n", rd_addr); - rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, - rd_addr, arch, images->verify); + rd_hdr = image_get_ramdisk (rd_addr, arch, + images->verify); if (rd_hdr == NULL) return 1; @@ -901,8 +894,7 @@ int boot_get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], break; #endif default: - printf ("Wrong Image Format for %s command\n", - cmdtp->name); + puts ("Wrong Ramdisk Image Format\n"); rd_data = rd_len = rd_load = 0; } -- cgit v1.1 From 3dfe110149311425919e6d6a14b561b4207498f1 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 10:32:59 +0100 Subject: [new uImage] Add node offsets for FIT images listed in struct bootm_headers This patch adds new node offset fields to struct bootm_headers and updates bootm_headers processing code to make use of them. Saved node offsets allow to avoid repeating fit_image_get_node() calls. Signed-off-by: Marian Balakowicz --- common/image.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 6458fb1..e838f65 100644 --- a/common/image.c +++ b/common/image.c @@ -891,6 +891,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, images->fit_hdr_rd = fit_hdr; images->fit_uname_rd = fit_uname_ramdisk; + images->fit_noffset_rd = rd_noffset; break; #endif default: -- cgit v1.1 From 1372cce2b9040fb640e5032b84e3a033a22d6ff0 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 10:33:01 +0100 Subject: [new uImage] Use show_boot_progress() for new uImage format This patch allocates a set of show_boot_progress() IDs for new uImage format and adds show_boot_progress() calls in new uImage format handling code. Signed-off-by: Marian Balakowicz --- common/image.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index e838f65..f29614b 100644 --- a/common/image.c +++ b/common/image.c @@ -397,10 +397,7 @@ inline void image_print_contents_noindent (image_header_t *hdr) static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify) { - image_header_t *rd_hdr; - - show_boot_progress (9); - rd_hdr = (image_header_t *)rd_addr; + image_header_t *rd_hdr = (image_header_t *)rd_addr; if (!image_check_magic (rd_hdr)) { puts ("Bad Magic Number\n"); @@ -830,6 +827,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, printf ("## Loading init Ramdisk from Legacy " "Image at %08lx ...\n", rd_addr); + show_boot_progress (9); rd_hdr = image_get_ramdisk (rd_addr, arch, images->verify); @@ -846,10 +844,13 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, printf ("## Loading init Ramdisk from FIT " "Image at %08lx ...\n", rd_addr); + show_boot_progress (120); if (!fit_check_format (fit_hdr)) { puts ("Bad FIT ramdisk image format!\n"); + show_boot_progress (-120); return 0; } + show_boot_progress (121); if (!fit_uname_ramdisk) { /* @@ -857,37 +858,48 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, * node first. If config unit node name is NULL * fit_conf_get_node() will try to find default config node */ + show_boot_progress (122); conf_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); - if (conf_noffset < 0) + if (conf_noffset < 0) { + show_boot_progress (-122); return 0; + } rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, conf_noffset); fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL); } else { /* get ramdisk component image node offset */ + show_boot_progress (123); rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk); } - if (rd_noffset < 0) + if (rd_noffset < 0) { + show_boot_progress (-124); return 0; + } printf (" Trying '%s' ramdisk subimage\n", fit_uname_ramdisk); + show_boot_progress (125); if (!fit_check_ramdisk (fit_hdr, rd_noffset, arch, images->verify)) return 0; /* get ramdisk image data address and length */ if (fit_image_get_data (fit_hdr, rd_noffset, &data, &size)) { puts ("Could not find ramdisk subimage data!\n"); + show_boot_progress (-127); return 0; } + show_boot_progress (128); rd_data = (ulong)data; rd_len = size; if (fit_image_get_load (fit_hdr, rd_noffset, &rd_load)) { puts ("Can't get ramdisk subimage load address!\n"); + show_boot_progress (-129); return 0; } + show_boot_progress (129); images->fit_hdr_rd = fit_hdr; images->fit_uname_rd = fit_uname_ramdisk; @@ -2445,19 +2457,23 @@ static int fit_check_ramdisk (const void *fit, int rd_noffset, uint8_t arch, int puts (" Verifying Hash Integrity ... "); if (!fit_image_check_hashes (fit, rd_noffset)) { puts ("Bad Data Hash\n"); + show_boot_progress (-125); return 0; } puts ("OK\n"); } + show_boot_progress (126); if (!fit_image_check_os (fit, rd_noffset, IH_OS_LINUX) || !fit_image_check_arch (fit, rd_noffset, arch) || !fit_image_check_type (fit, rd_noffset, IH_TYPE_RAMDISK)) { printf ("No Linux %s Ramdisk Image\n", genimg_get_arch_name(arch)); + show_boot_progress (-126); return 0; } + show_boot_progress (127); return 1; } #endif /* USE_HOSTCC */ -- cgit v1.1 From f773bea8e11f4a11c388dcee956b2444203e6b65 Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 10:35:46 +0100 Subject: [new uImage] Add proper ramdisk/FDT handling when FIT configuration is used Save FIT configuration provied in the first bootm argument and use it when to get ramdisk/FDT subimages when second and third (ramdisk/FDT) arguments are not specified. Signed-off-by: Marian Balakowicz --- common/image.c | 112 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 29 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index f29614b..bb57d6d 100644 --- a/common/image.c +++ b/common/image.c @@ -738,6 +738,26 @@ ulong genimg_get_image (ulong img_addr) } /** + * fit_has_config - check if there is a valid FIT configuration + * @images: pointer to the bootm command headers structure + * + * fit_has_config() checks if there is a FIT configuration in use + * (if FTI support is present). + * + * returns: + * 0, no FIT support or no configuration found + * 1, configuration found + */ +int genimg_has_config (bootm_headers_t *images) +{ +#if defined(CONFIG_FIT) + if (images->fit_uname_cfg) + return 1; +#endif + return 0; +} + +/** * boot_get_ramdisk - main ramdisk handling routine * @argc: command argument count * @argv: command argument list @@ -771,7 +791,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, const char *fit_uname_ramdisk = NULL; ulong default_addr; int rd_noffset; - int conf_noffset; + int cfg_noffset; const void *data; size_t size; #endif @@ -786,33 +806,63 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, if ((argc >= 3) && (strcmp(argv[2], "-") == 0)) { debug ("## Skipping init Ramdisk\n"); rd_len = rd_data = 0; - } else if (argc >= 3) { + } else if (argc >= 3 || genimg_has_config (images)) { #if defined(CONFIG_FIT) - /* - * If the init ramdisk comes from the FIT image and the FIT image - * address is omitted in the command line argument, try to use - * os FIT image address or default load address. - */ - if (images->fit_uname_os) - default_addr = (ulong)images->fit_hdr_os; - else - default_addr = load_addr; - - if (fit_parse_conf (argv[2], default_addr, - &rd_addr, &fit_uname_config)) { - debug ("* ramdisk: config '%s' from image at 0x%08lx\n", - fit_uname_config, rd_addr); - } else if (fit_parse_subimage (argv[2], default_addr, - &rd_addr, &fit_uname_ramdisk)) { - debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", - fit_uname_ramdisk, rd_addr); - } else + if (argc >= 3) { + /* + * If the init ramdisk comes from the FIT image and + * the FIT image address is omitted in the command + * line argument, try to use os FIT image address or + * default load address. + */ + if (images->fit_uname_os) + default_addr = (ulong)images->fit_hdr_os; + else + default_addr = load_addr; + + if (fit_parse_conf (argv[2], default_addr, + &rd_addr, &fit_uname_config)) { + debug ("* ramdisk: config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + } else if (fit_parse_subimage (argv[2], default_addr, + &rd_addr, &fit_uname_ramdisk)) { + debug ("* ramdisk: subimage '%s' from image at 0x%08lx\n", + fit_uname_ramdisk, rd_addr); + } else #endif - { - rd_addr = simple_strtoul(argv[2], NULL, 16); - debug ("* ramdisk: cmdline image address = 0x%08lx\n", - rd_addr); + { + rd_addr = simple_strtoul(argv[2], NULL, 16); + debug ("* ramdisk: cmdline image address = 0x%08lx\n", + rd_addr); + } +#if defined(CONFIG_FIT) + } else { + /* use FIT configuration provided in first bootm + * command argument + */ + rd_addr = (ulong)images->fit_hdr_os; + fit_uname_config = images->fit_uname_cfg; + debug ("* ramdisk: using config '%s' from image at 0x%08lx\n", + fit_uname_config, rd_addr); + + /* + * Check whether configuration has ramdisk defined, + * if not, don't try to use it, quit silently. + */ + fit_hdr = (void *)rd_addr; + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + debug ("* ramdisk: no such config\n"); + return 0; + } + + rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); + if (rd_noffset < 0) { + debug ("* ramdisk: no ramdisk in config\n"); + return 0; + } } +#endif /* copy from dataflash if needed */ rd_addr = genimg_get_image (rd_addr); @@ -859,13 +909,16 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, * fit_conf_get_node() will try to find default config node */ show_boot_progress (122); - conf_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); - if (conf_noffset < 0) { + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + puts ("Could not find configuration node\n"); show_boot_progress (-122); return 0; } + fit_uname_config = fdt_get_name (fit_hdr, cfg_noffset, NULL); + printf (" Using '%s' configuration\n", fit_uname_config); - rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, conf_noffset); + rd_noffset = fit_conf_get_ramdisk_node (fit_hdr, cfg_noffset); fit_uname_ramdisk = fit_get_name (fit_hdr, rd_noffset, NULL); } else { /* get ramdisk component image node offset */ @@ -873,6 +926,7 @@ int boot_get_ramdisk (int argc, char *argv[], bootm_headers_t *images, rd_noffset = fit_image_get_node (fit_hdr, fit_uname_ramdisk); } if (rd_noffset < 0) { + puts ("Could not find subimage node\n"); show_boot_progress (-124); return 0; } @@ -2394,7 +2448,7 @@ int fit_conf_get_fdt_node (const void *fit, int noffset) /** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header - * @conf_noffset: offset of the configuration node + * @noffset: offset of the configuration node * @p: pointer to prefix string * * fit_conf_print() lists all mandatory properies for the processed -- cgit v1.1 From afe45c87e3c5d77bad76b1a57dccd20764d45b5d Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Wed, 12 Mar 2008 12:14:15 +0100 Subject: [new uImage] Fix build issue on ARM ARM platforms don't have a bd->bi_memsize so use bd->bi_dram[0].size instead. Signed-off-by: Kumar Gala --- common/image.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index bb57d6d..a2a739e 100644 --- a/common/image.c +++ b/common/image.c @@ -463,8 +463,10 @@ ulong getenv_bootm_low(void) return tmp; } -#ifdef CFG_SDRAM_BASE +#if defined(CFG_SDRAM_BASE) return CFG_SDRAM_BASE; +#elif defined(CONFIG_ARM) + return gd->bd->bi_dram[0].start; #else return 0; #endif @@ -478,7 +480,11 @@ ulong getenv_bootm_size(void) return tmp; } +#if defined(CONFIG_ARM) + return gd->bd->bi_dram[0].size; +#else return gd->bd->bi_memsize; +#endif } void memmove_wd (void *to, void *from, size_t len, ulong chunksz) -- cgit v1.1 From 766529fccc860ecb9e955b4239dff69cd9e4ea09 Mon Sep 17 00:00:00 2001 From: Bartlomiej Sieka Date: Fri, 14 Mar 2008 16:22:34 +0100 Subject: Add MD5 support to the new uImage format Signed-off-by: Bartlomiej Sieka --- common/image.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index a2a739e..6508df9 100644 --- a/common/image.c +++ b/common/image.c @@ -54,6 +54,7 @@ #endif #if defined(CONFIG_FIT) +#include #include static int fit_check_ramdisk (const void *fit, int os_noffset, @@ -70,6 +71,7 @@ static image_header_t* image_get_ramdisk (ulong rd_addr, uint8_t arch, int verify); #else #include "mkimage.h" +#include #include #include #endif /* !USE_HOSTCC*/ @@ -1940,8 +1942,8 @@ static int calculate_hash (const void *data, int data_len, const char *algo, (unsigned char *) value); *value_len = 20; } else if (strcmp (algo, "md5") == 0 ) { - printf ("MD5 not supported\n"); - *value_len = 0; + md5 ((unsigned char *)data, data_len, value); + *value_len = 16; } else { debug ("Unsupported hash alogrithm\n"); return -1; -- cgit v1.1 From dafaede8a46c7159310239e036c93e31c6374487 Mon Sep 17 00:00:00 2001 From: Bartlomiej Sieka Date: Thu, 20 Mar 2008 23:20:31 +0100 Subject: [new uImage] Disable debuging output in preparation for merge with master Signed-off-by: Bartlomiej Sieka --- common/image.c | 1 - 1 file changed, 1 deletion(-) (limited to 'common/image.c') diff --git a/common/image.c b/common/image.c index 6508df9..f04826a 100644 --- a/common/image.c +++ b/common/image.c @@ -23,7 +23,6 @@ * MA 02111-1307 USA */ -#define DEBUG #ifndef USE_HOSTCC #include -- cgit v1.1