diff options
author | Gerald Van Baren <vanbaren@cideas.com> | 2008-03-29 18:08:02 -0400 |
---|---|---|
committer | Gerald Van Baren <vanbaren@cideas.com> | 2008-03-29 18:08:02 -0400 |
commit | 3596d55eb22703d3f4f1b839fe4b000fabe081b3 (patch) | |
tree | 96d1ce693dc72c2fbc63da37928afd4761e82fd2 /common | |
parent | 493a2b1dc97367e904bf83869501f6290f3b374e (diff) | |
parent | 74d1e66d22dac91388bc538b2fe19f735edc5b82 (diff) | |
download | u-boot-imx-3596d55eb22703d3f4f1b839fe4b000fabe081b3.zip u-boot-imx-3596d55eb22703d3f4f1b839fe4b000fabe081b3.tar.gz u-boot-imx-3596d55eb22703d3f4f1b839fe4b000fabe081b3.tar.bz2 |
Merge git://www.denx.de/git/u-boot into uboot
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 7 | ||||
-rw-r--r-- | common/cmd_autoscript.c | 153 | ||||
-rw-r--r-- | common/cmd_bootm.c | 1983 | ||||
-rw-r--r-- | common/cmd_doc.c | 38 | ||||
-rw-r--r-- | common/cmd_fdc.c | 59 | ||||
-rw-r--r-- | common/cmd_fdt.c | 17 | ||||
-rw-r--r-- | common/cmd_fpga.c | 109 | ||||
-rw-r--r-- | common/cmd_ide.c | 58 | ||||
-rw-r--r-- | common/cmd_load.c | 11 | ||||
-rw-r--r-- | common/cmd_mp.c | 93 | ||||
-rw-r--r-- | common/cmd_nand.c | 80 | ||||
-rw-r--r-- | common/cmd_net.c | 11 | ||||
-rw-r--r-- | common/cmd_sata.c | 767 | ||||
-rw-r--r-- | common/cmd_scsi.c | 47 | ||||
-rw-r--r-- | common/cmd_setexpr.c | 70 | ||||
-rw-r--r-- | common/cmd_usb.c | 53 | ||||
-rw-r--r-- | common/cmd_ximg.c | 168 | ||||
-rw-r--r-- | common/fdt_support.c | 218 | ||||
-rw-r--r-- | common/gunzip.c | 113 | ||||
-rw-r--r-- | common/image.c | 2541 | ||||
-rw-r--r-- | common/lynxkdi.c | 46 | ||||
-rw-r--r-- | common/usb_storage.c | 11 |
22 files changed, 4301 insertions, 2352 deletions
diff --git a/common/Makefile b/common/Makefile index 56d0581..0d67337 100644 --- a/common/Makefile +++ b/common/Makefile @@ -36,6 +36,8 @@ COBJS-y += cmd_autoscript.o COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o COBJS-$(CONFIG_CMD_BEDBUG) += cmd_bedbug.o COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o +COBJS-y += image.o +COBJS-y += gunzip.o COBJS-y += cmd_boot.o COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o COBJS-y += cmd_bootm.o @@ -86,13 +88,15 @@ COBJS-y += cmd_pcmcia.o COBJS-$(CONFIG_CMD_PORTIO) += cmd_portio.o COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o -COBJS-y += cmd_sata.o +COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o +COBJS-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o COBJS-$(CONFIG_CMD_SPI) += cmd_spi.o COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o COBJS-$(CONFIG_CMD_USB) += cmd_usb.o +COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o COBJS-y += cmd_vfd.o COBJS-y += command.o COBJS-y += console.o @@ -136,6 +140,7 @@ COBJS-y += crc16.o COBJS-y += xyzModem.o COBJS-y += cmd_mac.o COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o +COBJS-$(CONFIG_MP) += cmd_mp.o COBJS := $(COBJS-y) SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/common/cmd_autoscript.c b/common/cmd_autoscript.c index a6038a6..1a37b90 100644 --- a/common/cmd_autoscript.c +++ b/common/cmd_autoscript.c @@ -49,57 +49,110 @@ #if defined(CONFIG_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT) -extern image_header_t header; /* from cmd_bootm.c */ int -autoscript (ulong addr) +autoscript (ulong addr, const char *fit_uname) { - ulong crc, data, len; - image_header_t *hdr = &header; - ulong *len_ptr; - char *cmd; - int rcode = 0; - int verify; + ulong len; + image_header_t *hdr; + ulong *data; + char *cmd; + int rcode = 0; + int verify; +#if defined(CONFIG_FIT) + const void* fit_hdr; + int noffset; + const void *fit_data; + size_t fit_len; +#endif - cmd = getenv ("verify"); - verify = (cmd && (*cmd == 'n')) ? 0 : 1; + verify = getenv_verify (); + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - memmove (hdr, (char *)addr, sizeof(image_header_t)); + if (!image_check_magic (hdr)) { + puts ("Bad magic number\n"); + return 1; + } - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad magic number\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("Bad header crc\n"); + return 1; + } - crc = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - len = sizeof (image_header_t); - data = (ulong)hdr; - if (crc32(0, (uchar *)data, len) != crc) { - puts ("Bad header crc\n"); - return 1; - } + if (verify) { + if (!image_check_dcrc (hdr)) { + puts ("Bad data crc\n"); + return 1; + } + } - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { + puts ("Bad image type\n"); + return 1; + } + + /* get length of script */ + data = (ulong *)image_get_data (hdr); - if (verify) { - if (crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts ("Bad data crc\n"); + if ((len = uimage_to_cpu (*data)) == 0) { + puts ("Empty Script\n"); return 1; } - } - if (hdr->ih_type != IH_TYPE_SCRIPT) { - puts ("Bad image type\n"); - return 1; - } + /* + * scripts are just multi-image files with one component, seek + * past the zero-terminated sequence of image lengths to get + * to the actual image data + */ + while (*data++); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (fit_uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } - /* get length of script */ - len_ptr = (ulong *)data; + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get script component image node offset */ + noffset = fit_image_get_node (fit_hdr, fit_uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", fit_uname); + return 1; + } + + if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { + puts ("Not a image image\n"); + return 1; + } + + /* verify integrity */ + if (verify) { + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; + } + } - if ((len = ntohl(*len_ptr)) == 0) { - puts ("Empty Script\n"); + /* get script subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { + puts ("Could not find script subimage data\n"); + return 1; + } + + data = (ulong *)fit_data; + len = (ulong)fit_len; + break; +#endif + default: + puts ("Wrong image format for autoscript\n"); return 1; } @@ -109,10 +162,8 @@ autoscript (ulong addr) return 1; } - while (*len_ptr++); - /* make sure cmd is null terminated */ - memmove (cmd, (char *)len_ptr, len); + memmove (cmd, (char *)data, len); *(cmd + len) = 0; #ifdef CFG_HUSH_PARSER /*?? */ @@ -158,25 +209,35 @@ do_autoscript (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { ulong addr; int rcode; + const char *fit_uname = NULL; + /* Find script image */ if (argc < 2) { addr = CFG_LOAD_ADDR; + debug ("* autoscr: default load address = 0x%08lx\n", addr); +#if defined(CONFIG_FIT) + } else if (fit_parse_subimage (argv[1], load_addr, &addr, &fit_uname)) { + debug ("* autoscr: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, addr); +#endif } else { - addr = simple_strtoul (argv[1],0,16); + addr = simple_strtoul(argv[1], NULL, 16); + debug ("* autoscr: cmdline image address = 0x%08lx\n", addr); } - printf ("## Executing script at %08lx\n",addr); - rcode = autoscript (addr); + printf ("## Executing script at %08lx\n", addr); + rcode = autoscript (addr, fit_uname); return rcode; } -#if defined(CONFIG_CMD_AUTOSCRIPT) U_BOOT_CMD( autoscr, 2, 0, do_autoscript, "autoscr - run script from memory\n", "[addr] - run script starting at addr" " - A valid autoscr header must be present\n" -); +#if defined(CONFIG_FIT) + "For FIT format uImage addr must include subimage\n" + "unit name in the form of addr:<subimg_uname>\n" #endif - +); #endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9deb781..9e5ce4b 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,6 +21,7 @@ * MA 02111-1307 USA */ + /* * Boot support */ @@ -32,56 +33,24 @@ #include <zlib.h> #include <bzlib.h> #include <environment.h> +#include <lmb.h> #include <asm/byteorder.h> -#if defined(CONFIG_OF_LIBFDT) -#include <fdt.h> -#include <libfdt.h> -#include <fdt_support.h> -#endif -#if defined(CONFIG_OF_FLAT_TREE) -#include <ft_build.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) -#include <rtc.h> -#endif - #ifdef CFG_HUSH_PARSER #include <hush.h> #endif -#ifdef CFG_INIT_RAM_LOCK -#include <asm/cache.h> -#endif - -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif +DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_HAS_DATAFLASH -#include <dataflash.h> +extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp); +#ifndef CFG_BOOTM_LEN +#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ #endif -/* - * Some systems (for example LWMON) have very short watchdog periods; - * we must make sure to split long operations like memmove() or - * crc32() into reasonable chunks. - */ -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -# define CHUNKSZ (64 * 1024) +#ifdef CONFIG_BZIP2 +extern void bz_internal_error(int); #endif -int gunzip (void *, int, unsigned char *, unsigned long *); - -static void *zalloc(void *, unsigned, unsigned); -static void zfree(void *, void *, unsigned); - #if defined(CONFIG_CMD_IMI) static int image_info (unsigned long addr); #endif @@ -92,12 +61,19 @@ extern flash_info_t flash_info[]; /* info for FLASH chips */ static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif -static void print_type (image_header_t *hdr); +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux (void); +#endif -#ifdef __I386__ -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +static image_header_t *image_get_kernel (ulong img_addr, int verify); +#if defined(CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify); #endif +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], + bootm_headers_t *images, ulong *os_data, ulong *os_len); +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + /* * Continue booting an OS image; caller already has: * - copied image header to global variable `header' @@ -106,203 +82,135 @@ image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); * - loaded (first part of) image to header load address, * - disabled interrupts. */ -typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, /* of image to boot */ - ulong *len_ptr, /* multi-file image length table */ - int verify); /* getenv("verify")[0] != 'n' */ - -#ifdef DEBUG -extern int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); -#endif - -#ifdef CONFIG_PPC -static boot_os_Fcn do_bootm_linux; -#else -extern boot_os_Fcn do_bootm_linux; +typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images); /* pointers to os/initrd/fdt */ + +extern boot_os_fn do_bootm_linux; +static boot_os_fn do_bootm_netbsd; +#if defined(CONFIG_LYNXKDI) +static boot_os_fn do_bootm_lynxkdi; +extern void lynxkdi_boot (image_header_t *); #endif -#ifdef CONFIG_SILENT_CONSOLE -static void fixup_silent_linux (void); -#endif -static boot_os_Fcn do_bootm_netbsd; -static boot_os_Fcn do_bootm_rtems; +static boot_os_fn do_bootm_rtems; #if defined(CONFIG_CMD_ELF) -static boot_os_Fcn do_bootm_vxworks; -static boot_os_Fcn do_bootm_qnxelf; -int do_bootvx ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); -int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] ); +static boot_os_fn do_bootm_vxworks; +static boot_os_fn do_bootm_qnxelf; +int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #endif #if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) -static boot_os_Fcn do_bootm_artos; -#endif -#ifdef CONFIG_LYNXKDI -static boot_os_Fcn do_bootm_lynxkdi; -extern void lynxkdi_boot( image_header_t * ); +extern uchar (*env_get_char)(int); /* Returns a character from the environment */ +static boot_os_fn do_bootm_artos; #endif -#ifndef CFG_BOOTM_LEN -#define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ -#endif +ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ +static bootm_headers_t images; /* pointers to os/initrd/fdt images */ -image_header_t header; +void __board_lmb_reserve(struct lmb *lmb) +{ + /* please define platform specific board_lmb_reserve() */ +} +void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); -ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ +/*******************************************************************/ +/* bootm - boot application image from image in memory */ +/*******************************************************************/ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - ulong iflag; - ulong addr; - ulong data, len, checksum; - ulong *len_ptr; - uint unc_len = CFG_BOOTM_LEN; - int i, verify; - char *name, *s; - int (*appl)(int, char *[]); - image_header_t *hdr = &header; + ulong iflag; + const char *type_name; + uint unc_len = CFG_BOOTM_LEN; + uint8_t comp, type, os; - s = getenv ("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + void *os_hdr; + ulong os_data, os_len; + ulong image_start, image_end; + ulong load_start, load_end; + ulong mem_start, mem_size; - if (argc < 2) { - addr = load_addr; - } else { - addr = simple_strtoul(argv[1], NULL, 16); - } + struct lmb lmb; - show_boot_progress (1); - printf ("## Booting image at %08lx ...\n", addr); + memset ((void *)&images, 0, sizeof (images)); + images.verify = getenv_verify(); + images.autostart = getenv_autostart(); + images.lmb = &lmb; - /* Copy header so we can blank CRC field for re-calculation */ -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - read_dataflash(addr, sizeof(image_header_t), (char *)&header); - } else -#endif - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { -#ifdef __I386__ /* correct image format not implemented yet - fake it */ - if (fake_header(hdr, (void*)addr, -1) != NULL) { - /* to compensate for the addition below */ - addr -= sizeof(image_header_t); - /* turnof verify, - * fake_header() does not fake the data crc - */ - verify = 0; - } else -#endif /* __I386__ */ - { - puts ("Bad Magic Number\n"); - show_boot_progress (-1); - return 1; - } - } - show_boot_progress (2); + lmb_init(&lmb); - data = (ulong)&header; - len = sizeof(image_header_t); + mem_start = getenv_bootm_low(); + mem_size = getenv_bootm_size(); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + lmb_add(&lmb, mem_start, mem_size); - if (crc32 (0, (uchar *)data, len) != checksum) { - puts ("Bad Header Checksum\n"); - show_boot_progress (-2); - return 1; - } - show_boot_progress (3); + board_lmb_reserve(&lmb); -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash(addr)){ - len = ntohl(hdr->ih_size) + sizeof(image_header_t); - read_dataflash(addr, len, (char *)CFG_LOAD_ADDR); - addr = CFG_LOAD_ADDR; + /* get kernel image header, start address and length */ + os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, + &images, &os_data, &os_len); + if (os_len == 0) { + puts ("ERROR: can't get kernel image!\n"); + return 1; } -#endif + /* get image parameters */ + switch (genimg_get_format (os_hdr)) { + case IMAGE_FORMAT_LEGACY: + type = image_get_type (os_hdr); + comp = image_get_comp (os_hdr); + os = image_get_os (os_hdr); - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); + image_end = image_get_image_end (os_hdr); + load_start = image_get_load (os_hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (fit_image_get_type (images.fit_hdr_os, + images.fit_noffset_os, &type)) { + puts ("Can't get image type!\n"); + show_boot_progress (-109); + return 1; + } - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + if (fit_image_get_comp (images.fit_hdr_os, + images.fit_noffset_os, &comp)) { + puts ("Can't get image compression!\n"); + show_boot_progress (-110); + return 1; + } - if (verify) { - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-3); + if (fit_image_get_os (images.fit_hdr_os, + images.fit_noffset_os, &os)) { + puts ("Can't get image OS!\n"); + show_boot_progress (-111); return 1; } - puts ("OK\n"); - } - show_boot_progress (4); - len_ptr = (ulong *)data; - -#if defined(__ARM__) - if (hdr->ih_arch != IH_CPU_ARM) -#elif defined(__avr32__) - if (hdr->ih_arch != IH_CPU_AVR32) -#elif defined(__bfin__) - if (hdr->ih_arch != IH_CPU_BLACKFIN) -#elif defined(__I386__) - if (hdr->ih_arch != IH_CPU_I386) -#elif defined(__M68K__) - if (hdr->ih_arch != IH_CPU_M68K) -#elif defined(__microblaze__) - if (hdr->ih_arch != IH_CPU_MICROBLAZE) -#elif defined(__mips__) - if (hdr->ih_arch != IH_CPU_MIPS) -#elif defined(__nios__) - if (hdr->ih_arch != IH_CPU_NIOS) -#elif defined(__nios2__) - if (hdr->ih_arch != IH_CPU_NIOS2) -#elif defined(__PPC__) - if (hdr->ih_arch != IH_CPU_PPC) -#elif defined(__sh__) - if (hdr->ih_arch != IH_CPU_SH) -#else -# error Unknown CPU type -#endif - { - printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch); - show_boot_progress (-4); - return 1; - } - show_boot_progress (5); - - switch (hdr->ih_type) { - case IH_TYPE_STANDALONE: - name = "Standalone Application"; - /* A second argument overwrites the load address */ - if (argc > 2) { - hdr->ih_load = htonl(simple_strtoul(argv[2], NULL, 16)); + image_end = fit_get_end (images.fit_hdr_os); + + if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, + &load_start)) { + puts ("Can't get image load address!\n"); + show_boot_progress (-112); + return 1; } break; - case IH_TYPE_KERNEL: - name = "Kernel Image"; - break; - case IH_TYPE_MULTI: - name = "Multi-File Image"; - len = ntohl(len_ptr[0]); - /* OS kernel is always the first image */ - data += 8; /* kernel_len + terminator */ - for (i=1; len_ptr[i]; ++i) - data += 4; - break; - default: printf ("Wrong Image Type for %s command\n", cmdtp->name); - show_boot_progress (-5); +#endif + default: + puts ("ERROR: unknown image format type!\n"); return 1; } - show_boot_progress (6); + + image_start = (ulong)os_hdr; + load_end = 0; + type_name = genimg_get_type_name (type); /* * We have reached the point of no return: we are going to * overwrite all exception vector code, so we cannot easily * recover from any failures any more... */ - iflag = disable_interrupts(); #ifdef CONFIG_AMIGAONEG3SE @@ -316,138 +224,113 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dcache_disable(); #endif - switch (hdr->ih_comp) { + switch (comp) { case IH_COMP_NONE: - if(ntohl(hdr->ih_load) == addr) { - printf (" XIP %s ... ", name); + if (load_start == (ulong)os_hdr) { + printf (" XIP %s ... ", type_name); } else { -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - size_t l = len; - void *to = (void *)ntohl(hdr->ih_load); - void *from = (void *)data; - - printf (" Loading %s ... ", name); - - while (l > 0) { - size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; - WATCHDOG_RESET(); - memmove (to, from, tail); - to += tail; - from += tail; - l -= tail; - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + printf (" Loading %s ... ", type_name); + + memmove_wd ((void *)load_start, + (void *)os_data, os_len, CHUNKSZ); + + load_end = load_start + os_len; + puts("OK\n"); } break; case IH_COMP_GZIP: - printf (" Uncompressing %s ... ", name); - if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, - (uchar *)data, &len) != 0) { - puts ("GUNZIP ERROR - must RESET board to recover\n"); + printf (" Uncompressing %s ... ", type_name); + if (gunzip ((void *)load_start, unc_len, + (uchar *)os_data, &os_len) != 0) { + puts ("GUNZIP: uncompress or overwrite error " + "- must RESET board to recover\n"); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } + + load_end = load_start + os_len; break; #ifdef CONFIG_BZIP2 case IH_COMP_BZIP2: - printf (" Uncompressing %s ... ", name); + printf (" Uncompressing %s ... ", type_name); /* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */ - i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), - &unc_len, (char *)data, len, - CFG_MALLOC_LEN < (4096 * 1024), 0); + int i = BZ2_bzBuffToBuffDecompress ((char*)load_start, + &unc_len, (char *)os_data, os_len, + CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { - printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); + printf ("BUNZIP2: uncompress or overwrite error %d " + "- must RESET board to recover\n", i); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } + + load_end = load_start + unc_len; break; #endif /* CONFIG_BZIP2 */ default: if (iflag) enable_interrupts(); - printf ("Unimplemented compression type %d\n", hdr->ih_comp); + printf ("Unimplemented compression type %d\n", comp); show_boot_progress (-7); return 1; } puts ("OK\n"); + debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load_start, load_end); show_boot_progress (7); - switch (hdr->ih_type) { - case IH_TYPE_STANDALONE: - if (iflag) - enable_interrupts(); + if ((load_start < image_end) && (load_end > image_start)) { + debug ("image_start = 0x%lX, image_end = 0x%lx\n", image_start, image_end); + debug ("load_start = 0x%lx, load_end = 0x%lx\n", load_start, load_end); - /* load (and uncompress), but don't start if "autostart" - * is set to "no" - */ - if (((s = getenv("autostart")) != NULL) && (strcmp(s,"no") == 0)) { - char buf[32]; - sprintf(buf, "%lX", len); - setenv("filesize", buf); - return 0; - } - appl = (int (*)(int, char *[]))ntohl(hdr->ih_ep); - (*appl)(argc-1, &argv[1]); - return 0; - case IH_TYPE_KERNEL: - case IH_TYPE_MULTI: - /* handled below */ - break; - default: - if (iflag) - enable_interrupts(); - printf ("Can't boot image type %d\n", hdr->ih_type); - show_boot_progress (-8); - return 1; + puts ("ERROR: image overwritten - must RESET the board to recover.\n"); + show_boot_progress (-113); + do_reset (cmdtp, flag, argc, argv); } + show_boot_progress (8); - switch (hdr->ih_os) { + lmb_reserve(&lmb, load_start, (load_end - load_start)); + + switch (os) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: #ifdef CONFIG_SILENT_CONSOLE fixup_silent_linux(); #endif - do_bootm_linux (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_linux (cmdtp, flag, argc, argv, &images); break; + case IH_OS_NETBSD: - do_bootm_netbsd (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_netbsd (cmdtp, flag, argc, argv, &images); break; #ifdef CONFIG_LYNXKDI case IH_OS_LYNXOS: - do_bootm_lynxkdi (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_lynxkdi (cmdtp, flag, argc, argv, &images); break; #endif case IH_OS_RTEMS: - do_bootm_rtems (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_rtems (cmdtp, flag, argc, argv, &images); break; #if defined(CONFIG_CMD_ELF) case IH_OS_VXWORKS: - do_bootm_vxworks (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_vxworks (cmdtp, flag, argc, argv, &images); break; + case IH_OS_QNX: - do_bootm_qnxelf (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_qnxelf (cmdtp, flag, argc, argv, &images); break; #endif + #ifdef CONFIG_ARTOS case IH_OS_ARTOS: - do_bootm_artos (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_artos (cmdtp, flag, argc, argv, &images); break; #endif } @@ -455,94 +338,94 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) show_boot_progress (-9); #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); - do_reset (cmdtp, flag, argc, argv); + if (images.autostart) + do_reset (cmdtp, flag, argc, argv); #endif + if (!images.autostart && iflag) + enable_interrupts(); + return 1; } -U_BOOT_CMD( - bootm, CFG_MAXARGS, 1, do_bootm, - "bootm - boot application image from memory\n", - "[addr [arg ...]]\n - boot application image stored in memory\n" - "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" - "\t'arg' can be the address of an initrd image\n" -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - "\tWhen booting a Linux kernel which requires a flat device-tree\n" - "\ta third argument is required which is the address of the\n" - "\tdevice-tree blob. To boot that kernel without an initrd image,\n" - "\tuse a '-' for the second argument. If you do not pass a third\n" - "\ta bd_info struct will be passed instead\n" -#endif -); - -#ifdef CONFIG_SILENT_CONSOLE -static void -fixup_silent_linux () +/** + * image_get_kernel - verify legacy format kernel image + * @img_addr: in RAM address of the legacy format image to be verified + * @verify: data CRC verification flag + * + * image_get_kernel() verifies legacy image integrity and returns pointer to + * legacy image header if image verification was completed successfully. + * + * returns: + * pointer to a legacy image header if valid image was found + * otherwise return NULL + */ +static image_header_t *image_get_kernel (ulong img_addr, int verify) { - char buf[256], *start, *end; - char *cmdline = getenv ("bootargs"); + image_header_t *hdr = (image_header_t *)img_addr; - /* Only fix cmdline when requested */ - if (!(gd->flags & GD_FLG_SILENT)) - return; + if (!image_check_magic(hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-1); + return NULL; + } + show_boot_progress (2); - debug ("before silent fix-up: %s\n", cmdline); - if (cmdline) { - if ((start = strstr (cmdline, "console=")) != NULL) { - end = strchr (start, ' '); - strncpy (buf, cmdline, (start - cmdline + 8)); - if (end) - strcpy (buf + (start - cmdline + 8), end); - else - buf[start - cmdline + 8] = '\0'; - } else { - strcpy (buf, cmdline); - strcat (buf, " console="); + if (!image_check_hcrc (hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-2); + return NULL; + } + + show_boot_progress (3); + image_print_contents (hdr); + + if (verify) { + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + printf ("Bad Data CRC\n"); + show_boot_progress (-3); + return NULL; } - } else { - strcpy (buf, "console="); + puts ("OK\n"); } + show_boot_progress (4); - setenv ("bootargs", buf); - debug ("after silent fix-up: %s\n", buf); + if (!image_check_target_arch (hdr)) { + printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr)); + show_boot_progress (-4); + return NULL; + } + return hdr; } -#endif /* CONFIG_SILENT_CONSOLE */ -#ifdef CONFIG_PPC -static void __attribute__((noinline)) -do_bootm_linux (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) +/** + * fit_check_kernel - verify FIT format kernel subimage + * @fit_hdr: pointer to the FIT image header + * os_noffset: kernel subimage node offset within FIT image + * @verify: data CRC verification flag + * + * fit_check_kernel() verifies integrity of the kernel subimage and from + * specified FIT image. + * + * returns: + * 1, on success + * 0, on failure + */ +#if defined (CONFIG_FIT) +static int fit_check_kernel (const void *fit, int os_noffset, int verify) { - ulong sp; - ulong len, checksum; - ulong initrd_start, initrd_end; - ulong cmd_start, cmd_end; - ulong initrd_high; - ulong data; - int initrd_copy_to_ram = 1; - char *cmdline; - char *s; - bd_t *kbd; - void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); - image_header_t *hdr = &header; -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - char *of_flat_tree = NULL; - ulong of_data = 0; -#endif + fit_image_print (fit, os_noffset, " "); - 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; + if (verify) { + puts (" Verifying Hash Integrity ... "); + if (!fit_image_check_hashes (fit, os_noffset)) { + puts ("Bad Data Hash\n"); + show_boot_progress (-104); + return 0; + } + puts ("OK\n"); } + show_boot_progress (105); #ifdef CONFIG_LOGBUFFER #ifndef CONFIG_ALT_LB_ADDR @@ -555,539 +438,445 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, debug ("## Logbuffer at 0x%08lX ", CONFIG_ALT_LB_ADDR); #endif #endif + if (!fit_image_check_target_arch (fit, os_noffset)) { + puts ("Unsupported Architecture\n"); + show_boot_progress (-105); + return 0; + } - /* - * Booting a (Linux) kernel image - * - * Allocate space for command line and board info - the - * address should be as high as possible within the reach of - * the kernel (see CFG_BOOTMAPSZ settings), but in unused - * memory, which means far enough below the current stack - * pointer. - */ - - asm( "mr %0,1": "=r"(sp) : ); - - debug ("## Current stack ends at 0x%08lX ", sp); - - sp -= 2048; /* just to be sure */ - if (sp > CFG_BOOTMAPSZ) - sp = CFG_BOOTMAPSZ; - sp &= ~0xF; - - debug ("=> set upper limit to 0x%08lX\n", sp); - - cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); - kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); - - if ((s = getenv("bootargs")) == NULL) - s = ""; - - strcpy (cmdline, s); - - cmd_start = (ulong)&cmdline[0]; - cmd_end = cmd_start + strlen(cmdline); - - *kbd = *(gd->bd); + show_boot_progress (106); + if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { + puts ("Not a kernel image\n"); + show_boot_progress (-106); + return 0; + } -#ifdef DEBUG - printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); + show_boot_progress (107); + return 1; +} +#endif /* CONFIG_FIT */ - do_bdinfo (NULL, 0, 0, NULL); +/** + * boot_get_kernel - find kernel image + * @os_data: pointer to a ulong variable, will hold os data start address + * @os_len: pointer to a ulong variable, will hold os data length + * + * boot_get_kernel() tries to find a kernel image, verifies its integrity + * and locates kernel data. + * + * returns: + * pointer to image header if valid image was found, plus kernel start + * address and length, otherwise NULL + */ +static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + bootm_headers_t *images, ulong *os_data, ulong *os_len) +{ + image_header_t *hdr; + ulong img_addr; +#if defined(CONFIG_FIT) + void *fit_hdr; + const char *fit_uname_config = NULL; + const char *fit_uname_kernel = NULL; + const void *data; + size_t len; + int cfg_noffset; + int os_noffset; #endif - if ((s = getenv ("clocks_in_mhz")) != NULL) { - /* convert all clock information to MHz */ - kbd->bi_intfreq /= 1000000L; - kbd->bi_busfreq /= 1000000L; -#if defined(CONFIG_MPC8220) - kbd->bi_inpfreq /= 1000000L; - kbd->bi_pcifreq /= 1000000L; - kbd->bi_pevfreq /= 1000000L; - kbd->bi_flbfreq /= 1000000L; - kbd->bi_vcofreq /= 1000000L; -#endif -#if defined(CONFIG_CPM2) - kbd->bi_cpmfreq /= 1000000L; - kbd->bi_brgfreq /= 1000000L; - kbd->bi_sccfreq /= 1000000L; - kbd->bi_vco /= 1000000L; + /* find out kernel image address */ + if (argc < 2) { + img_addr = load_addr; + debug ("* kernel: default image load address = 0x%08lx\n", + load_addr); +#if defined(CONFIG_FIT) + } else if (fit_parse_conf (argv[1], load_addr, &img_addr, + &fit_uname_config)) { + debug ("* kernel: config '%s' from image at 0x%08lx\n", + fit_uname_config, img_addr); + } else if (fit_parse_subimage (argv[1], load_addr, &img_addr, + &fit_uname_kernel)) { + debug ("* kernel: subimage '%s' from image at 0x%08lx\n", + fit_uname_kernel, img_addr); #endif -#if defined(CONFIG_MPC5xxx) - kbd->bi_ipbfreq /= 1000000L; - kbd->bi_pcifreq /= 1000000L; -#endif /* CONFIG_MPC5xxx */ + } else { + img_addr = simple_strtoul(argv[1], NULL, 16); + debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr); } - kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong)) ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ + show_boot_progress (1); -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - /* Look for a '-' which indicates to ignore the ramdisk argument */ - if (argc >= 3 && strcmp(argv[2], "-") == 0) { - debug ("Skipping initrd\n"); - len = data = 0; + /* copy from dataflash if needed */ + img_addr = genimg_get_image (img_addr); + + /* check image type, for FIT images get FIT kernel node */ + *os_data = *os_len = 0; + switch (genimg_get_format ((void *)img_addr)) { + case IMAGE_FORMAT_LEGACY: + printf ("## Booting kernel from Legacy Image at %08lx ...\n", + img_addr); + hdr = image_get_kernel (img_addr, images->verify); + if (!hdr) + return NULL; + show_boot_progress (5); + + /* get os_data and os_len */ + switch (image_get_type (hdr)) { + case IH_TYPE_KERNEL: + *os_data = image_get_data (hdr); + *os_len = image_get_data_size (hdr); + break; + case IH_TYPE_MULTI: + image_multi_getimg (hdr, 0, os_data, os_len); + break; + default: + printf ("Wrong Image Type for %s command\n", cmdtp->name); + show_boot_progress (-5); + return NULL; } - else -#endif - if (argc >= 3) { - debug ("Not skipping initrd\n"); - show_boot_progress (9); - - addr = simple_strtoul(argv[2], NULL, 16); + images->legacy_hdr_os = hdr; + images->legacy_hdr_valid = 1; - printf ("## Loading RAMDisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); + show_boot_progress (6); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (void *)img_addr; + printf ("## Booting kernel from FIT Image at %08lx ...\n", + img_addr); + + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT kernel image format!\n"); + show_boot_progress (-100); + return NULL; } + show_boot_progress (100); - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + if (!fit_uname_kernel) { + /* + * no kernel 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 + */ + show_boot_progress (101); + cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); + if (cfg_noffset < 0) { + show_boot_progress (-101); + return NULL; + } + /* save configuration uname provided in the first + * bootm argument + */ + images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); + printf (" Using '%s' configuration\n", images->fit_uname_cfg); + show_boot_progress (103); - if (crc32 (0, (uchar *)data, len) != checksum) { - puts ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); + os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); + fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); + } else { + /* get kernel component image node offset */ + show_boot_progress (102); + os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); + } + if (os_noffset < 0) { + show_boot_progress (-103); + return NULL; } - show_boot_progress (10); + printf (" Trying '%s' kernel subimage\n", fit_uname_kernel); - print_image_hdr (hdr); + show_boot_progress (104); + if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) + return NULL; - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); + /* get kernel image data address and length */ + if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { + puts ("Could not find kernel subimage data!\n"); + show_boot_progress (-107); + return NULL; + } + show_boot_progress (108); - if (verify) { - ulong csum = 0; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - ulong cdata = data, edata = cdata + len; -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + *os_len = len; + *os_data = (ulong)data; + images->fit_hdr_os = fit_hdr; + images->fit_uname_os = fit_uname_kernel; + images->fit_noffset_os = os_noffset; + break; +#endif + default: + printf ("Wrong Image Format for %s command\n", cmdtp->name); + show_boot_progress (-108); + return NULL; + } - puts (" Verifying Checksum ... "); + debug (" kernel data at 0x%08lx, len = 0x%08lx (%d)\n", + *os_data, *os_len, *os_len); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + return (void *)img_addr; +} - while (cdata < edata) { - ulong chunk = edata - cdata; +U_BOOT_CMD( + bootm, CFG_MAXARGS, 1, do_bootm, + "bootm - boot application image from memory\n", + "[addr [arg ...]]\n - boot application image stored in memory\n" + "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" + "\t'arg' can be the address of an initrd image\n" +#if defined(CONFIG_OF_LIBFDT) + "\tWhen booting a Linux kernel which requires a flat device-tree\n" + "\ta third argument is required which is the address of the\n" + "\tdevice-tree blob. To boot that kernel without an initrd image,\n" + "\tuse a '-' for the second argument. If you do not pass a third\n" + "\ta bd_info struct will be passed instead\n" +#endif +#if defined(CONFIG_FIT) + "\t\nFor the new multi component uImage format (FIT) addresses\n" + "\tmust be extened to include component or configuration unit name:\n" + "\taddr:<subimg_uname> - direct component image specification\n" + "\taddr#<conf_uname> - configuration specification\n" + "\tUse iminfo command to get the list of existing component\n" + "\timages and configurations.\n" +#endif +); - if (chunk > CHUNKSZ) - chunk = CHUNKSZ; - csum = crc32 (csum, (uchar *)cdata, chunk); - cdata += chunk; +/*******************************************************************/ +/* bootd - boot default image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_BOOTD) +int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; - WATCHDOG_RESET(); - } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - csum = crc32 (0, (uchar *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - - if (csum != ntohl(hdr->ih_dcrc)) { - puts ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); - } +#ifndef CFG_HUSH_PARSER + if (run_command (getenv ("bootcmd"), flag) < 0) + rcode = 1; +#else + if (parse_string_outer (getenv ("bootcmd"), + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) + rcode = 1; +#endif + return rcode; +} - show_boot_progress (11); +U_BOOT_CMD( + boot, 1, 1, do_bootd, + "boot - boot default, i.e., run 'bootcmd'\n", + NULL +); - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_PPC) || - (hdr->ih_type != IH_TYPE_RAMDISK) ) { - puts ("No Linux PPC Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } +/* keep old command name "bootd" for backward compatibility */ +U_BOOT_CMD( + bootd, 1, 1, do_bootd, + "bootd - boot default, i.e., run 'bootcmd'\n", + NULL +); - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - u_long tail = ntohl(len_ptr[0]) % 4; - int i; - - show_boot_progress (13); - - /* skip kernel length and terminator */ - data = (ulong)(&len_ptr[2]); - /* skip any additional image length fields */ - for (i=1; len_ptr[i]; ++i) - data += 4; - /* add kernel length, and align */ - data += ntohl(len_ptr[0]); - if (tail) { - data += 4 - tail; - } +#endif - len = ntohl(len_ptr[1]); - } else { - /* - * no initrd image - */ - show_boot_progress (14); +/*******************************************************************/ +/* iminfo - print header info for a requested image */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMI) +int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int arg; + ulong addr; + int rcode = 0; - len = data = 0; + if (argc < 2) { + return image_info (load_addr); } -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - if(argc > 3) { - of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16); - hdr = (image_header_t *)of_flat_tree; -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else - if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { -#endif -#ifndef CFG_NO_FLASH - if (addr2info((ulong)of_flat_tree) != NULL) - of_data = (ulong)of_flat_tree; -#endif - } else if (ntohl(hdr->ih_magic) == IH_MAGIC) { - printf("## Flat Device Tree at %08lX\n", hdr); - print_image_hdr(hdr); - - if ((ntohl(hdr->ih_load) < ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) && - ((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) { - puts ("ERROR: fdt overwritten - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + for (arg = 1; arg < argc; ++arg) { + addr = simple_strtoul (argv[arg], NULL, 16); + if (image_info (addr) != 0) + rcode = 1; + } + return rcode; +} - puts (" Verifying Checksum ... "); - memmove (&header, (char *)hdr, sizeof(image_header_t)); - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; +static int image_info (ulong addr) +{ + void *hdr = (void *)addr; - if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) { - puts ("ERROR: fdt header checksum invalid - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + printf ("\n## Checking Image at %08lx ...\n", addr); - checksum = ntohl(hdr->ih_dcrc); - addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t)); + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + puts (" Legacy image found\n"); + if (!image_check_magic (hdr)) { + puts (" Bad Magic Number\n"); + return 1; + } - if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) { - puts ("ERROR: fdt checksum invalid - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); + if (!image_check_hcrc (hdr)) { + puts (" Bad Header Checksum\n"); + return 1; + } - if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) { - puts ("ERROR: uImage is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - if (ntohl(hdr->ih_comp) != IH_COMP_NONE) { - puts ("ERROR: uImage is compressed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { -#else - if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) { -#endif - puts ("ERROR: uImage data is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } + image_print_contents (hdr); - memmove((void *)ntohl(hdr->ih_load), - (void *)(of_flat_tree + sizeof(image_header_t)), - ntohl(hdr->ih_size)); - of_flat_tree = (char *)ntohl(hdr->ih_load); - } else { - puts ("Did not find a flat Flat Device Tree.\n" - "Must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - printf (" Booting using the fdt at 0x%x\n", - of_flat_tree); - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) { - u_long tail = ntohl(len_ptr[0]) % 4; - int i; - - /* skip kernel length, initrd length, and terminator */ - of_flat_tree = (char *)(&len_ptr[3]); - /* skip any additional image length fields */ - for (i=2; len_ptr[i]; ++i) - of_flat_tree += 4; - /* add kernel length, and align */ - of_flat_tree += ntohl(len_ptr[0]); - if (tail) { - of_flat_tree += 4 - tail; + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts (" Bad Data CRC\n"); + return 1; } + puts ("OK\n"); + return 0; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + puts (" FIT image found\n"); - /* add initrd length, and align */ - tail = ntohl(len_ptr[1]) % 4; - of_flat_tree += ntohl(len_ptr[1]); - if (tail) { - of_flat_tree += 4 - tail; + if (!fit_check_format (hdr)) { + puts ("Bad FIT image format!\n"); + return 1; } -#ifndef CFG_NO_FLASH - /* move the blob if it is in flash (set of_data to !null) */ - if (addr2info ((ulong)of_flat_tree) != NULL) - of_data = (ulong)of_flat_tree; + fit_print_contents (hdr); + return 0; #endif + default: + puts ("Unknown image format!\n"); + break; + } + return 1; +} -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) { -#else - if (fdt_check_header (of_flat_tree) != 0) { +U_BOOT_CMD( + iminfo, CFG_MAXARGS, 1, do_iminfo, + "iminfo - print header information for application image\n", + "addr [addr ...]\n" + " - print header information for application image starting at\n" + " address 'addr' in memory; this includes verification of the\n" + " image contents (magic number, header and payload checksums)\n" +); #endif - puts ("ERROR: image is not a fdt - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#if defined(CONFIG_OF_FLAT_TREE) - if (((struct boot_param_header *)of_flat_tree)->totalsize != - ntohl (len_ptr[2])) { -#else - if (be32_to_cpu (fdt_totalsize (of_flat_tree)) != - ntohl(len_ptr[2])) { -#endif - puts ("ERROR: fdt size != image size - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - } -#endif - if (!data) { - debug ("No initrd\n"); - } - if (data) { - if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = (ulong)kbd - len; - initrd_start &= ~(4096 - 1); /* align on page */ +/*******************************************************************/ +/* imls - list all images found in flash */ +/*******************************************************************/ +#if defined(CONFIG_CMD_IMLS) +int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + flash_info_t *info; + int i, j; + void *hdr; + + for (i = 0, info = &flash_info[0]; + i < CFG_MAX_FLASH_BANKS; ++i, ++info) { - if (initrd_high) { - ulong nsp; + if (info->flash_id == FLASH_UNKNOWN) + goto next_bank; + for (j = 0; j < info->sector_count; ++j) { - /* - * 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 - * above for command line args and board info. - */ - asm( "mr %0,1": "=r"(nsp) : ); - nsp -= 2048; /* just to be sure */ - nsp &= ~0xF; - if (nsp > initrd_high) /* limit as specified */ - nsp = initrd_high; - nsp -= len; - nsp &= ~(4096 - 1); /* align on page */ - if (nsp >= sp) - initrd_start = nsp; - } + hdr = (void *)info->start[j]; + if (!hdr) + goto next_sector; - show_boot_progress (12); - - debug ("## initrd at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - data, data + len - 1, len, len); - - initrd_end = initrd_start + len; - printf (" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - { - size_t l = len; - void *to = (void *)initrd_start; - void *from = (void *)data; - - while (l > 0) { - size_t tail = (l > CHUNKSZ) ? CHUNKSZ : l; - WATCHDOG_RESET(); - memmove (to, from, tail); - to += tail; - from += tail; - l -= tail; + switch (genimg_get_format (hdr)) { + case IMAGE_FORMAT_LEGACY: + if (!image_check_hcrc (hdr)) + goto next_sector; + + printf ("Legacy Image at %08lX:\n", (ulong)hdr); + image_print_contents (hdr); + + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + puts ("Bad Data CRC\n"); + } else { + puts ("OK\n"); + } + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (!fit_check_format (hdr)) + goto next_sector; + + printf ("FIT Image at %08lX:\n", (ulong)hdr); + fit_print_contents (hdr); + break; +#endif + default: + goto next_sector; } + +next_sector: ; } -#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ - memmove ((void *)initrd_start, (void *)data, len); -#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ - puts ("OK\n"); - } - } else { - initrd_start = 0; - initrd_end = 0; +next_bank: ; } -#if defined(CONFIG_OF_LIBFDT) + return (0); +} -#ifdef CFG_BOOTMAPSZ - /* - * The blob must be within CFG_BOOTMAPSZ, - * so we flag it to be copied if it is not. - */ - if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) - of_data = (ulong)of_flat_tree; +U_BOOT_CMD( + imls, 1, 1, do_imls, + "imls - list all images found in flash\n", + "\n" + " - Prints information about all images found at sector\n" + " boundaries in flash.\n" +); #endif - /* move of_flat_tree if needed */ - if (of_data) { - int err; - ulong of_start, of_len; - - of_len = be32_to_cpu(fdt_totalsize(of_data)); - - /* position on a 4K boundary before the kbd */ - of_start = (ulong)kbd - of_len; - of_start &= ~(4096 - 1); /* align on page */ - debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - of_data, of_data + of_len - 1, of_len, of_len); - - of_flat_tree = (char *)of_start; - printf (" Loading Device Tree to %08lx, end %08lx ... ", - of_start, of_start + of_len - 1); - err = fdt_open_into((void *)of_data, (void *)of_start, of_len); - if (err != 0) { - puts ("ERROR: fdt move failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } - puts ("OK\n"); - } - /* - * Add the chosen node if it doesn't exist, add the env and bd_t - * if the user wants it (the logic is in the subroutines). - */ - if (of_flat_tree) { - if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { - puts ("ERROR: /chosen node create failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#ifdef CONFIG_OF_HAS_UBOOT_ENV - if (fdt_env(of_flat_tree) < 0) { - puts ("ERROR: /u-boot-env node create failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); - } -#endif -#ifdef CONFIG_OF_HAS_BD_T - if (fdt_bd_t(of_flat_tree) < 0) { - puts ("ERROR: /bd_t node create failed - " - "must RESET the board to recover.\n"); - do_reset (cmdtp, flag, argc, argv); +/*******************************************************************/ +/* helper routines */ +/*******************************************************************/ +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux () +{ + char buf[256], *start, *end; + char *cmdline = getenv ("bootargs"); + + /* Only fix cmdline when requested */ + if (!(gd->flags & GD_FLG_SILENT)) + return; + + debug ("before silent fix-up: %s\n", cmdline); + if (cmdline) { + if ((start = strstr (cmdline, "console=")) != NULL) { + end = strchr (start, ' '); + strncpy (buf, cmdline, (start - cmdline + 8)); + if (end) + strcpy (buf + (start - cmdline + 8), end); + else + buf[start - cmdline + 8] = '\0'; + } else { + strcpy (buf, cmdline); + strcat (buf, " console="); } -#endif -#ifdef CONFIG_OF_BOARD_SETUP - /* Call the board-specific fixup routine */ - ft_board_setup(of_flat_tree, gd->bd); -#endif + } else { + strcpy (buf, "console="); } -#endif /* CONFIG_OF_LIBFDT */ -#if defined(CONFIG_OF_FLAT_TREE) -#ifdef CFG_BOOTMAPSZ - /* - * The blob must be within CFG_BOOTMAPSZ, - * so we flag it to be copied if it is not. - */ - if (of_flat_tree >= (char *)CFG_BOOTMAPSZ) - of_data = (ulong)of_flat_tree; -#endif - /* move of_flat_tree if needed */ - if (of_data) { - ulong of_start, of_len; - of_len = ((struct boot_param_header *)of_data)->totalsize; - - /* provide extra 8k pad */ - of_start = (ulong)kbd - of_len - 8192; - of_start &= ~(4096 - 1); /* align on page */ - debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", - of_data, of_data + of_len - 1, of_len, of_len); - - of_flat_tree = (char *)of_start; - printf (" Loading Device Tree to %08lx, end %08lx ... ", - of_start, of_start + of_len - 1); - memmove ((void *)of_start, (void *)of_data, of_len); - puts ("OK\n"); - } - /* - * Create the /chosen node and modify the blob with board specific - * values as needed. - */ - ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); - /* ft_dump_blob(of_flat_tree); */ -#endif - debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong)kernel); + setenv ("bootargs", buf); + debug ("after silent fix-up: %s\n", buf); +} +#endif /* CONFIG_SILENT_CONSOLE */ - show_boot_progress (15); -#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) - unlock_ram_in_cache(); -#endif +/*******************************************************************/ +/* OS booting routines */ +/*******************************************************************/ -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) - if (of_flat_tree) { /* device tree; boot new style */ - /* - * Linux Kernel Parameters (passing device tree): - * r3: pointer to the fdt, followed by the board info data - * r4: physical pointer to the kernel itself - * r5: NULL - * r6: NULL - * r7: NULL - */ - (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); - /* does not return */ +static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + void (*loader)(bd_t *, image_header_t *, char *, char *); + image_header_t *os_hdr, *hdr; + ulong kernel_data, kernel_len; + char *consdev; + char *cmdline; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("NetBSD"); + do_reset (cmdtp, flag, argc, argv); } #endif - /* - * Linux Kernel Parameters (passing board info data): - * r3: ptr to board info data - * r4: initrd_start or 0 if no initrd - * r5: initrd_end - unused if r4 is 0 - * r6: Start of command line string - * r7: End of command line string - */ - (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); - /* does not return */ -} -#endif /* CONFIG_PPC */ - -static void -do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) -{ - image_header_t *hdr = &header; - - void (*loader)(bd_t *, image_header_t *, char *, char *); - image_header_t *img_addr; - char *consdev; - char *cmdline; - + hdr = images->legacy_hdr_os; /* * Booting a (NetBSD) kernel image @@ -1100,11 +889,12 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, * line, the name of the console device, and (optionally) the * address of the original image header. */ - - img_addr = 0; - if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) - img_addr = (image_header_t *) addr; - + os_hdr = NULL; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); + if (kernel_len) + os_hdr = hdr; + } consdev = ""; #if defined (CONFIG_8xx_CONS_SMC1) @@ -1121,21 +911,21 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, ulong len; int i; - for (i=2, len=0 ; i<argc ; i+=1) + for (i = 2, len = 0; i < argc; i += 1) len += strlen (argv[i]) + 1; cmdline = malloc (len); - for (i=2, len=0 ; i<argc ; i+=1) { + for (i = 2, len = 0; i < argc; i += 1) { if (i > 2) cmdline[len++] = ' '; strcpy (&cmdline[len], argv[i]); len += strlen (argv[i]); } - } else if ((cmdline = getenv("bootargs")) == NULL) { + } else if ((cmdline = getenv ("bootargs")) == NULL) { cmdline = ""; } - loader = (void (*)(bd_t *, image_header_t *, char *, char *)) ntohl(hdr->ih_ep); + loader = (void (*)(bd_t *, image_header_t *, char *, char *))image_get_ep (hdr); printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", (ulong)loader); @@ -1149,20 +939,101 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, * r5: console device * r6: boot args string */ - (*loader) (gd->bd, img_addr, consdev, cmdline); + (*loader) (gd->bd, os_hdr, consdev, cmdline); } -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +#ifdef CONFIG_LYNXKDI +static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + image_header_t *hdr = images->legacy_hdr_os; -/* Function that returns a character from the environment */ -extern uchar (*env_get_char)(int); +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("Lynx"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + lynxkdi_boot ((image_header_t *)hdr); +} +#endif /* CONFIG_LYNXKDI */ + +static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + image_header_t *hdr = images->legacy_hdr_os; + void (*entry_point)(bd_t *); + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("RTEMS"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + entry_point = (void (*)(bd_t *))image_get_ep (hdr); + + printf ("## Transferring control to RTEMS (at address %08lx) ...\n", + (ulong)entry_point); + + show_boot_progress (15); + + /* + * RTEMS Parameters: + * r3: ptr to board info data + */ + (*entry_point)(gd->bd); +} -static void -do_bootm_artos (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) +#if defined(CONFIG_CMD_ELF) +static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + char str[80]; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (hdr == NULL) { + fit_unsupported_reset ("VxWorks"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ + setenv("loadaddr", str); + do_bootvx(cmdtp, 0, 0, NULL); +} + +static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) +{ + char *local_args[2]; + char str[16]; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("QNX"); + do_reset (cmdtp, flag, argc, argv); + } +#endif + + sprintf(str, "%x", image_get_ep (hdr)); /* write entry-point into string */ + local_args[0] = argv[0]; + local_args[1] = str; /* and provide it via the arguments */ + do_bootelf(cmdtp, 0, 2, local_args); +} +#endif + +#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + bootm_headers_t *images) { ulong top; char *s, *cmdline; @@ -1170,7 +1041,14 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, int i, j, nxt, len, envno, envsz; bd_t *kbd; void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); - image_header_t *hdr = &header; + image_header_t *hdr = images->legacy_hdr_os; + +#if defined(CONFIG_FIT) + if (!images->legacy_hdr_valid) { + fit_unsupported_reset ("ARTOS"); + do_reset (cmdtp, flag, argc, argv); + } +#endif /* * Booting an ARTOS kernel image + application @@ -1191,27 +1069,27 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, debug ("=> set upper limit to 0x%08lX\n", top); /* first check the artos specific boot args, then the linux args*/ - if ((s = getenv("abootargs")) == NULL && (s = getenv("bootargs")) == NULL) + if ((s = getenv( "abootargs")) == NULL && (s = getenv ("bootargs")) == NULL) s = ""; /* get length of cmdline, and place it */ - len = strlen(s); + len = strlen (s); top = (top - (len + 1)) & ~0xF; cmdline = (char *)top; debug ("## cmdline at 0x%08lX ", top); - strcpy(cmdline, s); + strcpy (cmdline, s); /* copy bdinfo */ - top = (top - sizeof(bd_t)) & ~0xF; + top = (top - sizeof (bd_t)) & ~0xF; debug ("## bd at 0x%08lX ", top); kbd = (bd_t *)top; - memcpy(kbd, gd->bd, sizeof(bd_t)); + memcpy (kbd, gd->bd, sizeof (bd_t)); /* first find number of env entries, and their size */ envno = 0; envsz = 0; - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) + for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { + for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) ; envno++; envsz += (nxt - i) + 1; /* plus trailing zero */ @@ -1219,7 +1097,7 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, envno++; /* plus the terminating zero */ debug ("## %u envvars total size %u ", envno, envsz); - top = (top - sizeof(char **)*envno) & ~0xF; + top = (top - sizeof (char **) * envno) & ~0xF; fwenv = (char **)top; debug ("## fwenv at 0x%08lX ", top); @@ -1228,428 +1106,17 @@ do_bootm_artos (cmd_tbl_t *cmdtp, int flag, ss = fwenv; /* now copy them */ - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) + for (i = 0; env_get_char (i) != '\0'; i = nxt + 1) { + for (nxt = i; env_get_char (nxt) != '\0'; ++nxt) ; *ss++ = s; for (j = i; j < nxt; ++j) - *s++ = env_get_char(j); + *s++ = env_get_char (j); *s++ = '\0'; } *ss++ = NULL; /* terminate */ - entry = (void (*)(bd_t *, char *, char **, ulong))ntohl(hdr->ih_ep); - (*entry)(kbd, cmdline, fwenv, top); + entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr); + (*entry) (kbd, cmdline, fwenv, top); } #endif - - -#if defined(CONFIG_CMD_BOOTD) -int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int rcode = 0; -#ifndef CFG_HUSH_PARSER - if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1; -#else - if (parse_string_outer(getenv("bootcmd"), - FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0 ) rcode = 1; -#endif - return rcode; -} - -U_BOOT_CMD( - boot, 1, 1, do_bootd, - "boot - boot default, i.e., run 'bootcmd'\n", - NULL -); - -/* keep old command name "bootd" for backward compatibility */ -U_BOOT_CMD( - bootd, 1, 1, do_bootd, - "bootd - boot default, i.e., run 'bootcmd'\n", - NULL -); - -#endif - -#if defined(CONFIG_CMD_IMI) -int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int arg; - ulong addr; - int rcode=0; - - if (argc < 2) { - return image_info (load_addr); - } - - for (arg=1; arg <argc; ++arg) { - addr = simple_strtoul(argv[arg], NULL, 16); - if (image_info (addr) != 0) rcode = 1; - } - return rcode; -} - -static int image_info (ulong addr) -{ - ulong data, len, checksum; - image_header_t *hdr = &header; - - printf ("\n## Checking Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts (" Bad Magic Number\n"); - return 1; - } - - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)data, len) != checksum) { - puts (" Bad Header Checksum\n"); - return 1; - } - - /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts (" Bad Data CRC\n"); - return 1; - } - puts ("OK\n"); - return 0; -} - -U_BOOT_CMD( - iminfo, CFG_MAXARGS, 1, do_iminfo, - "iminfo - print header information for application image\n", - "addr [addr ...]\n" - " - print header information for application image starting at\n" - " address 'addr' in memory; this includes verification of the\n" - " image contents (magic number, header and payload checksums)\n" -); - -#endif - -#if defined(CONFIG_CMD_IMLS) -/*----------------------------------------------------------------------- - * List all images found in flash. - */ -int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - flash_info_t *info; - int i, j; - image_header_t *hdr; - ulong data, len, checksum; - - for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) { - if (info->flash_id == FLASH_UNKNOWN) - goto next_bank; - for (j=0; j<info->sector_count; ++j) { - - if (!(hdr=(image_header_t *)info->start[j]) || - (ntohl(hdr->ih_magic) != IH_MAGIC)) - goto next_sector; - - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)hdr, sizeof(image_header_t)); - - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; - - if (crc32 (0, (uchar *)&header, sizeof(image_header_t)) - != checksum) - goto next_sector; - - printf ("Image at %08lX:\n", (ulong)hdr); - print_image_hdr( hdr ); - - data = (ulong)hdr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts (" Bad Data CRC\n"); - } - puts ("OK\n"); -next_sector: ; - } -next_bank: ; - } - - return (0); -} - -U_BOOT_CMD( - imls, 1, 1, do_imls, - "imls - list all images found in flash\n", - "\n" - " - Prints information about all images found at sector\n" - " boundaries in flash.\n" -); -#endif - -void -print_image_hdr (image_header_t *hdr) -{ -#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) - time_t timestamp = (time_t)ntohl(hdr->ih_time); - struct rtc_time tm; -#endif - - printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); -#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: "); print_type(hdr); - printf ("\n Data Size: %d Bytes = ", ntohl(hdr->ih_size)); - print_size (ntohl(hdr->ih_size), "\n"); - printf (" Load Address: %08x\n" - " Entry Point: %08x\n", - ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); - - if (hdr->ih_type == IH_TYPE_MULTI) { - int i; - ulong len; - ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); - - puts (" Contents:\n"); - for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { - printf (" Image %d: %8ld Bytes = ", i, len); - print_size (len, "\n"); - } - } -} - - -static void -print_type (image_header_t *hdr) -{ - char *os, *arch, *type, *comp; - - switch (hdr->ih_os) { - case IH_OS_INVALID: os = "Invalid OS"; break; - case IH_OS_NETBSD: os = "NetBSD"; break; - case IH_OS_LINUX: os = "Linux"; break; - case IH_OS_VXWORKS: os = "VxWorks"; break; - case IH_OS_QNX: os = "QNX"; break; - case IH_OS_U_BOOT: os = "U-Boot"; break; - case IH_OS_RTEMS: os = "RTEMS"; break; -#ifdef CONFIG_ARTOS - case IH_OS_ARTOS: os = "ARTOS"; break; -#endif -#ifdef CONFIG_LYNXKDI - case IH_OS_LYNXOS: os = "LynxOS"; break; -#endif - default: os = "Unknown OS"; break; - } - - switch (hdr->ih_arch) { - case IH_CPU_INVALID: arch = "Invalid CPU"; break; - case IH_CPU_ALPHA: arch = "Alpha"; break; - case IH_CPU_ARM: arch = "ARM"; break; - case IH_CPU_AVR32: arch = "AVR32"; break; - case IH_CPU_BLACKFIN: arch = "Blackfin"; break; - case IH_CPU_I386: arch = "Intel x86"; break; - case IH_CPU_IA64: arch = "IA64"; break; - case IH_CPU_M68K: arch = "M68K"; break; - case IH_CPU_MICROBLAZE: arch = "Microblaze"; break; - case IH_CPU_MIPS64: arch = "MIPS 64 Bit"; break; - case IH_CPU_MIPS: arch = "MIPS"; break; - case IH_CPU_NIOS2: arch = "Nios-II"; break; - case IH_CPU_NIOS: arch = "Nios"; break; - case IH_CPU_PPC: arch = "PowerPC"; break; - case IH_CPU_S390: arch = "IBM S390"; break; - case IH_CPU_SH: arch = "SuperH"; break; - case IH_CPU_SPARC64: arch = "SPARC 64 Bit"; break; - case IH_CPU_SPARC: arch = "SPARC"; break; - default: arch = "Unknown Architecture"; break; - } - - switch (hdr->ih_type) { - case IH_TYPE_INVALID: type = "Invalid Image"; break; - case IH_TYPE_STANDALONE:type = "Standalone Program"; break; - case IH_TYPE_KERNEL: type = "Kernel Image"; break; - case IH_TYPE_RAMDISK: type = "RAMDisk Image"; break; - case IH_TYPE_MULTI: type = "Multi-File Image"; break; - case IH_TYPE_FIRMWARE: type = "Firmware"; break; - case IH_TYPE_SCRIPT: type = "Script"; break; - case IH_TYPE_FLATDT: type = "Flat Device Tree"; break; - default: type = "Unknown Image"; break; - } - - switch (hdr->ih_comp) { - case IH_COMP_NONE: comp = "uncompressed"; break; - case IH_COMP_GZIP: comp = "gzip compressed"; break; - case IH_COMP_BZIP2: comp = "bzip2 compressed"; break; - default: comp = "unknown compression"; break; - } - - printf ("%s %s %s (%s)", arch, os, type, comp); -} - -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc(void *x, unsigned items, unsigned size) -{ - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); - - p = malloc (size); - - return (p); -} - -static void zfree(void *x, void *addr, unsigned nb) -{ - free (addr); -} - -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 - -#define DEFLATED 8 - -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) -{ - z_stream s; - int r, i, flags; - - /* skip header */ - i = 10; - flags = src[3]; - if (src[2] != DEFLATED || (flags & RESERVED) != 0) { - puts ("Error: Bad gzipped data\n"); - return (-1); - } - if ((flags & EXTRA_FIELD) != 0) - i = 12 + src[10] + (src[11] << 8); - if ((flags & ORIG_NAME) != 0) - while (src[i++] != 0) - ; - if ((flags & COMMENT) != 0) - while (src[i++] != 0) - ; - if ((flags & HEAD_CRC) != 0) - i += 2; - if (i >= *lenp) { - puts ("Error: gunzip out of data in header\n"); - return (-1); - } - - s.zalloc = zalloc; - s.zfree = zfree; -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - s.outcb = (cb_func)WATCHDOG_RESET; -#else - s.outcb = Z_NULL; -#endif /* CONFIG_HW_WATCHDOG */ - - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf ("Error: inflateInit2() returned %d\n", r); - return (-1); - } - s.next_in = src + i; - s.avail_in = *lenp - i; - s.next_out = dst; - s.avail_out = dstlen; - r = inflate(&s, Z_FINISH); - if (r != Z_OK && r != Z_STREAM_END) { - printf ("Error: inflate() returned %d\n", r); - return (-1); - } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); - - return (0); -} - -#ifdef CONFIG_BZIP2 -void bz_internal_error(int errcode) -{ - printf ("BZIP2 internal error %d\n", errcode); -} -#endif /* CONFIG_BZIP2 */ - -static void -do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - void (*entry_point)(bd_t *); - - entry_point = (void (*)(bd_t *)) ntohl(hdr->ih_ep); - - printf ("## Transferring control to RTEMS (at address %08lx) ...\n", - (ulong)entry_point); - - show_boot_progress (15); - - /* - * RTEMS Parameters: - * r3: ptr to board info data - */ - - (*entry_point ) ( gd->bd ); -} - -#if defined(CONFIG_CMD_ELF) -static void -do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - char str[80]; - - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ - setenv("loadaddr", str); - do_bootvx(cmdtp, 0, 0, NULL); -} - -static void -do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - image_header_t *hdr = &header; - char *local_args[2]; - char str[16]; - - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ - local_args[0] = argv[0]; - local_args[1] = str; /* and provide it via the arguments */ - do_bootelf(cmdtp, 0, 2, local_args); -} -#endif - -#ifdef CONFIG_LYNXKDI -static void -do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) -{ - lynxkdi_boot( &header ); -} - -#endif /* CONFIG_LYNXKDI */ diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 3d717c0..83aba37 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -205,6 +205,9 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif show_boot_progress (34); switch (argc) { @@ -261,21 +264,36 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (38); - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (hdr->ih_magic == IH_MAGIC) { + image_print_contents (hdr); - print_image_hdr (hdr); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-130); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (131); + puts ("Fit image detected...\n"); - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); - cnt -= SECTORSIZE; - } else { - puts ("\n** Bad Magic Number **\n"); + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-39); + puts ("** Unknown image type\n"); return 1; } show_boot_progress (39); + cnt -= SECTORSIZE; if (doc_rw (doc_dev_desc + dev, 1, offset + SECTORSIZE, cnt, NULL, (u_char *)(addr+SECTORSIZE))) { printf ("** Read error on %d\n", dev); @@ -284,6 +302,12 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (40); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 7349412..bf28370 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -788,6 +788,9 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int i,nrofblk; char *ep; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -835,14 +838,31 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf("result%d: 0x%02X\n",i,pCMD->result[i]); return 1; } - hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); + + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + image_print_contents (hdr); + + imsize = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); + + imsize = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - print_image_hdr(hdr); - imsize= ntohl(hdr->ih_size)+sizeof(image_header_t); nrofblk=imsize/512; if((imsize%512)>0) nrofblk++; @@ -858,23 +878,28 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf("OK %ld Bytes loaded.\n",imsize); flush_cache (addr, imsize); - /* Loading ok, update default load address */ +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + + /* Loading ok, update default load address */ load_addr = addr; - if(hdr->ih_type == IH_TYPE_KERNEL) { - /* Check if we should attempt an auto-start */ - if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { - char *local_args[2]; - extern int do_bootm (cmd_tbl_t *, int, int, char *[]); - local_args[0] = argv[0]; - local_args[1] = NULL; + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); - printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + local_args[0] = argv[0]; + local_args[1] = NULL; - do_bootm (cmdtp, 0, 1, local_args); - rcode ++; - } + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode ++; } return rcode; } diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 14c3fa0..a52284e 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -410,17 +410,6 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* Create a chosen node */ else if (argv[1][0] == 'c') fdt_chosen(fdt, 0, 0, 1); - -#ifdef CONFIG_OF_HAS_UBOOT_ENV - /* Create a u-boot-env node */ - else if (argv[1][0] == 'e') - fdt_env(fdt); -#endif -#ifdef CONFIG_OF_HAS_BD_T - /* Create a bd_t node */ - else if (argv[1][0] == 'b') - fdt_bd_t(fdt); -#endif else { /* Unrecognized command */ printf ("Usage:\n%s\n", cmdtp->usage); @@ -801,12 +790,6 @@ U_BOOT_CMD( "fdt rsvmem add <addr> <size> - Add a mem reserve\n" "fdt rsvmem delete <index> - Delete a mem reserves\n" "fdt chosen - Add/update the /chosen branch in the tree\n" -#ifdef CONFIG_OF_HAS_UBOOT_ENV - "fdt env - Add/replace the /u-boot-env branch in the tree\n" -#endif -#ifdef CONFIG_OF_HAS_BD_T - "fdt bd_t - Add/replace the /bd_t branch in the tree\n" -#endif "NOTE: If the path or property you are setting/printing has a '#' character\n" " or spaces, you MUST escape it with a \\ character or quote it with \".\n" ); diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index f55447a..9141dcc 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -164,6 +164,10 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) char *devstr = getenv ("fpga"); char *datastr = getenv ("fpgadata"); int rc = FPGA_FAIL; +#if defined (CONFIG_FIT) + const char *fit_uname = NULL; + ulong fit_addr; +#endif if (devstr) dev = (int) simple_strtoul (devstr, NULL, 16); @@ -173,9 +177,22 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) switch (argc) { case 5: /* fpga <op> <dev> <data> <datasize> */ data_size = simple_strtoul (argv[4], NULL, 16); + case 4: /* fpga <op> <dev> <data> */ - fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); +#if defined(CONFIG_FIT) + if (fit_parse_subimage (argv[3], (ulong)fpga_data, + &fit_addr, &fit_uname)) { + fpga_data = (void *)fit_addr; + debug ("* fpga: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, fit_addr); + } else +#endif + { + fpga_data = (void *) simple_strtoul (argv[3], NULL, 16); + debug ("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); + } PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data); + case 3: /* fpga <op> <dev | data addr> */ dev = (int) simple_strtoul (argv[2], NULL, 16); PRINTF ("%s: device = %d\n", __FUNCTION__, dev); @@ -183,14 +200,29 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) if ((argc == 3) && (dev > fpga_count ())) { /* must be buffer ptr */ PRINTF ("%s: Assuming buffer pointer in arg 3\n", __FUNCTION__); - fpga_data = (void *) dev; + +#if defined(CONFIG_FIT) + if (fit_parse_subimage (argv[2], (ulong)fpga_data, + &fit_addr, &fit_uname)) { + fpga_data = (void *)fit_addr; + debug ("* fpga: subimage '%s' from FIT image at 0x%08lx\n", + fit_uname, fit_addr); + } else +#endif + { + fpga_data = (void *) dev; + debug ("* fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data); + } + PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data); dev = FPGA_INVALID_DEVICE; /* reset device num */ } + case 2: /* fpga <op> */ op = (int) fpga_get_op (argv[1]); break; + default: PRINTF ("%s: Too many or too few args (%d)\n", __FUNCTION__, argc); @@ -216,19 +248,61 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) break; case FPGA_LOADMK: - { - image_header_t header; - image_header_t *hdr = &header; - ulong data; - - memmove (&header, (char *)fpga_data, sizeof(image_header_t)); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts ("Bad Magic Number\n"); - return 1; + switch (genimg_get_format (fpga_data)) { + case IMAGE_FORMAT_LEGACY: + { + image_header_t *hdr = (image_header_t *)fpga_data; + ulong data; + + data = (ulong)image_get_data (hdr); + data_size = image_get_data_size (hdr); + rc = fpga_load (dev, (void *)data, data_size); + } + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + { + const void *fit_hdr = (const void *)fpga_data; + int noffset; + void *fit_data; + + if (fit_uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } + + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get fpga component image node offset */ + noffset = fit_image_get_node (fit_hdr, fit_uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", fit_uname); + return 1; + } + + /* verify integrity */ + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; + } + + /* get fpga subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) { + puts ("Could not find fpga subimage data\n"); + return 1; + } + + rc = fpga_load (dev, fit_data, data_size); } - data = ((ulong)fpga_data + sizeof(image_header_t)); - data_size = ntohl(hdr->ih_size); - rc = fpga_load (dev, (void *)data, data_size); + break; +#endif + default: + puts ("** Unknown image type\n"); + rc = FPGA_FAIL; + break; } break; @@ -283,4 +357,9 @@ U_BOOT_CMD (fpga, 6, 1, do_fpga, "\tload\tLoad device from memory buffer\n" "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n" "\tloadmk\tLoad device generated with mkimage\n" - "\tdump\tLoad device to memory buffer\n"); + "\tdump\tLoad device to memory buffer\n" +#if defined(CONFIG_FIT) + "\tFor loadmk operating on FIT format uImage address must include\n" + "\tsubimage unit name in the form of addr:<subimg_uname>\n" +#endif +); diff --git a/common/cmd_ide.c b/common/cmd_ide.c index c38be4f..8ace970 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -366,10 +366,13 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part = 0; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif show_boot_progress (41); switch (argc) { @@ -446,29 +449,43 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (48); - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - show_boot_progress (-49); - return 1; - } - show_boot_progress (49); + show_boot_progress (49); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + show_boot_progress (-50); + return 1; + } + show_boot_progress (50); + + image_print_contents (hdr); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); - show_boot_progress (-50); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-140); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (141); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + show_boot_progress (-49); + puts ("** Unknown image type\n"); return 1; } - show_boot_progress (50); - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -481,6 +498,11 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (51); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif /* Loading ok, update default load address */ diff --git a/common/cmd_load.c b/common/cmd_load.c index 204c3eb..1b75a7b 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -521,8 +521,15 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *s; if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { - printf("Running autoscript at addr 0x%08lX ...\n", load_addr); - rcode = autoscript (load_addr); + printf ("Running autoscript at addr 0x%08lX", load_addr); + + s = getenv ("autoscript_uname"); + if (s) + printf (":%s ...\n", s); + else + puts (" ...\n"); + + rcode = autoscript (load_addr, s); } } #endif diff --git a/common/cmd_mp.c b/common/cmd_mp.c new file mode 100644 index 0000000..26a57c5 --- /dev/null +++ b/common/cmd_mp.c @@ -0,0 +1,93 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * 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 + */ + +#include <common.h> +#include <command.h> + +int +cpu_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unsigned long cpuid; + + if (argc < 3) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + cpuid = simple_strtoul(argv[1], NULL, 10); + if (cpuid >= CONFIG_NR_CPUS) { + printf ("Core num: %d is out of range[0..%d]\n", + cpuid, CONFIG_NR_CPUS - 1); + return 1; + } + + + if (argc == 3) { + if (strncmp(argv[2], "reset", 5) == 0) { + cpu_reset(cpuid); + } else if (strncmp(argv[2], "status", 6) == 0) { + cpu_status(cpuid); + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + return 0; + } + + /* 4 or greater, make sure its release */ + if (strncmp(argv[2], "release", 7) != 0) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if (cpu_release(cpuid, argc - 3, argv + 3)) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return 0; +} + +#ifdef CONFIG_PPC +#define CPU_ARCH_HELP \ + " [args] : <pir> <r3> <r6>\n" \ + " pir - processor id (if writeable)\n" \ + " r3 - value for gpr 3\n" \ + " r6 - value for gpr 6\n" \ + "\n" \ + " Use '-' for any arg if you want the default value.\n" \ + " Default for r3 is <num> and r6 is 0\n" \ + "\n" \ + " When cpu <num> is released r4 and r5 = 0.\n" \ + " r7 will contain the size of the initial mapped area\n" +#endif + +U_BOOT_CMD( + cpu, CFG_MAXARGS, 1, cpu_cmd, + "cpu - Multiprocessor CPU boot manipulation and release\n", + "<num> reset - Reset cpu <num>\n" + "cpu <num> status - Status of cpu <num>\n" + "cpu <num> release <addr> [args] - Release cpu <num> at <addr> with [args]\n" +#ifdef CPU_ARCH_HELP + CPU_ARCH_HELP +#endif + ); diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 8d6c959..7b1f830 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -484,6 +484,9 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, ulong cnt; image_header_t *hdr; int jffs2 = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif s = strchr(cmd, '.'); if (s != NULL && @@ -512,18 +515,35 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } show_boot_progress (56); - hdr = (image_header_t *) addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + + show_boot_progress (57); + image_print_contents (hdr); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-57); + puts ("** Unknown image type\n"); return 1; } - show_boot_progress (57); - - print_image_hdr(hdr); - cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t)); if (jffs2) { nand_read_options_t opts; memset(&opts, 0, sizeof(opts)); @@ -543,6 +563,12 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, } show_boot_progress (58); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; @@ -925,6 +951,10 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif + show_boot_progress (52); switch (argc) { case 1: @@ -980,17 +1010,31 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (56); - hdr = (image_header_t *)addr; - - if (ntohl(hdr->ih_magic) == IH_MAGIC) { + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; + image_print_contents (hdr); - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt = image_get_image_size (hdr); cnt -= SECTORSIZE; - } else { - printf ("\n** Bad Magic Number 0x%x **\n", ntohl(hdr->ih_magic)); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + puts ("Fit image detected...\n"); + + cnt = fit_get_size (fit_hdr); + break; +#endif + default: show_boot_progress (-57); + puts ("** Unknown image type\n"); return 1; } show_boot_progress (57); @@ -1004,6 +1048,12 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } show_boot_progress (58); +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_net.c b/common/cmd_net.c index dbf6b86..79e910c 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -220,9 +220,16 @@ netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[]) #ifdef CONFIG_AUTOSCRIPT if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { - printf("Running autoscript at addr 0x%08lX ...\n", load_addr); + printf ("Running autoscript at addr 0x%08lX", load_addr); + + s = getenv ("autoscript_uname"); + if (s) + printf (":%s ...\n", s); + else + puts (" ...\n"); + show_boot_progress (83); - rcode = autoscript (load_addr); + rcode = autoscript (load_addr, s); } #endif if (rcode < 0) diff --git a/common/cmd_sata.c b/common/cmd_sata.c index bd4c11f..79c2495 100644 --- a/common/cmd_sata.c +++ b/common/cmd_sata.c @@ -1,8 +1,11 @@ /* + * Copyright (C) 2000-2005, DENX Software Engineering + * Wolfgang Denk <wd@denx.de> * Copyright (C) Procsys. All rights reserved. - * Author: Mushtaq Khan <mushtaq_k@procsys.com> + * Mushtaq Khan <mushtaq_k@procsys.com> * <mushtaqk_921@yahoo.co.in> - * + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * Dave Liu <daveliu@freescale.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -11,702 +14,180 @@ * * 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 + * 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 - * - * with the reference to libata in kernel 2.4.32 - * */ -/* - * File contains SATA read-write and other utility functions. - */ #include <common.h> -#include <asm/io.h> -#include <pci.h> #include <command.h> -#include <config.h> -#include <ide.h> -#include <ata.h> - -#ifdef CFG_SATA_SUPPORTED -/*For debug prints set macro DEBUG_SATA to 1 */ -#define DEBUG_SATA 0 -/*Macro for SATA library specific declarations */ -#define SATA_DECL +#include <part.h> #include <sata.h> -#undef SATA_DECL - -static u8 __inline__ -sata_inb (unsigned long ioaddr) -{ - return inb (ioaddr); -} - -static void __inline__ -sata_outb (unsigned char val, unsigned long ioaddr) -{ - outb (val, ioaddr); -} - -static void -output_data (struct sata_ioports *ioaddr, ulong * sect_buf, int words) -{ - outsw (ioaddr->data_addr, sect_buf, words << 1); -} - -static int -input_data (struct sata_ioports *ioaddr, ulong * sect_buf, int words) -{ - insw (ioaddr->data_addr, sect_buf, words << 1); - return 0; -} - -static void -sata_cpy (unsigned char *dst, unsigned char *src, unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } - OUT: - *last = '\0'; -} - -int -sata_bus_softreset (int num) -{ - u8 dev = 0, status = 0, i; - - port[num].dev_mask = 0; - - for (i = 0; i < CFG_SATA_DEVS_PER_BUS; i++) { - if (!(sata_devchk (&port[num].ioaddr, i))) { - PRINTF ("dev_chk failed for dev#%d\n", i); - } else { - port[num].dev_mask |= (1 << i); - PRINTF ("dev_chk passed for dev#%d\n", i); - } - } - - if (!(port[num].dev_mask)) { - printf ("no devices on port%d\n", num); - return 1; - } - - dev_select (&port[num].ioaddr, dev); - - port[num].ctl_reg = 0x08; /*Default value of control reg */ - sata_outb (port[num].ctl_reg, port[num].ioaddr.ctl_addr); - udelay (10); - sata_outb (port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr); - udelay (10); - sata_outb (port[num].ctl_reg, port[num].ioaddr.ctl_addr); - - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - msleep (150); - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 300); - while ((status & ATA_BUSY)) { - msleep (100); - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 3); - } - - if (status & ATA_BUSY) - printf ("ata%u is slow to respond,plz be patient\n", port); - - while ((status & ATA_BUSY)) { - msleep (100); - status = sata_chk_status (&port[num].ioaddr); - } - - if (status & ATA_BUSY) { - printf ("ata%u failed to respond : ", port); - printf ("bus reset failed\n"); - return 1; - } - return 0; -} - -void -sata_identify (int num, int dev) -{ - u8 cmd = 0, status = 0, devno = num * CFG_SATA_DEVS_PER_BUS + dev; - u16 iobuf[ATA_SECT_SIZE]; - u64 n_sectors = 0; - u8 mask = 0; - - memset (iobuf, 0, sizeof (iobuf)); - hd_driveid_t *iop = (hd_driveid_t *) iobuf; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - printf ("dev%d is not present on port#%d\n", dev, num); - return; - } - - printf ("port=%d dev=%d\n", num, dev); - - dev_select (&port[num].ioaddr, dev); - - status = 0; - cmd = ATA_CMD_IDENT; /*Device Identify Command */ - sata_outb (cmd, port[num].ioaddr.command_addr); - sata_inb (port[num].ioaddr.altstatus_addr); - udelay (10); - - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 1000); - if (status & ATA_ERR) { - printf ("\ndevice not responding\n"); - port[num].dev_mask &= ~mask; - return; - } - - input_data (&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS); - - PRINTF ("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x" - "86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49], - iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86], - iobuf[87], iobuf[88]); - - /* we require LBA and DMA support (bits 8 & 9 of word 49) */ - if (!ata_id_has_dma (iobuf) || !ata_id_has_lba (iobuf)) { - PRINTF ("ata%u: no dma/lba\n", num); - } - ata_dump_id (iobuf); - - if (ata_id_has_lba48 (iobuf)) { - n_sectors = ata_id_u64 (iobuf, 100); - } else { - n_sectors = ata_id_u32 (iobuf, 60); - } - PRINTF ("no. of sectors %u\n", ata_id_u64 (iobuf, 100)); - PRINTF ("no. of sectors %u\n", ata_id_u32 (iobuf, 60)); - - if (n_sectors == 0) { - port[num].dev_mask &= ~mask; - return; - } - - sata_cpy (sata_dev_desc[devno].revision, iop->fw_rev, - sizeof (sata_dev_desc[devno].revision)); - sata_cpy (sata_dev_desc[devno].vendor, iop->model, - sizeof (sata_dev_desc[devno].vendor)); - sata_cpy (sata_dev_desc[devno].product, iop->serial_no, - sizeof (sata_dev_desc[devno].product)); - strswab (sata_dev_desc[devno].revision); - strswab (sata_dev_desc[devno].vendor); - - if ((iop->config & 0x0080) == 0x0080) { - sata_dev_desc[devno].removable = 1; - } else { - sata_dev_desc[devno].removable = 0; - } - sata_dev_desc[devno].lba = iop->lba_capacity; - PRINTF ("lba=0x%x", sata_dev_desc[devno].lba); +int curr_device = -1; +block_dev_desc_t sata_dev_desc[CFG_SATA_MAX_DEVICE]; -#ifdef CONFIG_LBA48 - if (iop->command_set_2 & 0x0400) { - sata_dev_desc[devno].lba48 = 1; - lba = (unsigned long long) iop->lba48_capacity[0] | - ((unsigned long long) iop->lba48_capacity[1] << 16) | - ((unsigned long long) iop->lba48_capacity[2] << 32) | - ((unsigned long long) iop->lba48_capacity[3] << 48); - } else { - sata_dev_desc[devno].lba48 = 0; - } -#endif - - /* assuming HD */ - sata_dev_desc[devno].type = DEV_TYPE_HARDDISK; - sata_dev_desc[devno].blksz = ATA_BLOCKSIZE; - sata_dev_desc[devno].lun = 0; /* just to fill something in... */ -} - -void -set_Feature_cmd (int num, int dev) -{ - u8 mask = 0x00, status = 0; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - PRINTF ("dev%d is not present on port#%d\n", dev, num); - return; - } - - dev_select (&port[num].ioaddr, dev); - - sata_outb (SETFEATURES_XFER, port[num].ioaddr.feature_addr); - sata_outb (XFER_PIO_4, port[num].ioaddr.nsect_addr); - sata_outb (0, port[num].ioaddr.lbal_addr); - sata_outb (0, port[num].ioaddr.lbam_addr); - sata_outb (0, port[num].ioaddr.lbah_addr); - - sata_outb (ATA_DEVICE_OBS, port[num].ioaddr.device_addr); - sata_outb (ATA_CMD_SETF, port[num].ioaddr.command_addr); - - udelay (50); - msleep (150); - - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 5000); - if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) { - printf ("Error : status 0x%02x\n", status); - port[num].dev_mask &= ~mask; - } -} - -void -sata_port (struct sata_ioports *ioport) -{ - ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA; - ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR; - ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE; - ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT; - ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL; - ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM; - ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH; - ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE; - ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS; - ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD; -} - -int -sata_devchk (struct sata_ioports *ioaddr, int dev) -{ - u8 nsect, lbal; - - dev_select (ioaddr, dev); - - sata_outb (0x55, ioaddr->nsect_addr); - sata_outb (0xaa, ioaddr->lbal_addr); - - sata_outb (0xaa, ioaddr->nsect_addr); - sata_outb (0x55, ioaddr->lbal_addr); - - sata_outb (0x55, ioaddr->nsect_addr); - sata_outb (0xaa, ioaddr->lbal_addr); - - nsect = sata_inb (ioaddr->nsect_addr); - lbal = sata_inb (ioaddr->lbal_addr); - - if ((nsect == 0x55) && (lbal == 0xaa)) - return 1; /* we found a device */ - else - return 0; /* nothing found */ -} - -void -dev_select (struct sata_ioports *ioaddr, int dev) -{ - u8 tmp = 0; - - if (dev == 0) - tmp = ATA_DEVICE_OBS; - else - tmp = ATA_DEVICE_OBS | ATA_DEV1; - - sata_outb (tmp, ioaddr->device_addr); - sata_inb (ioaddr->altstatus_addr); - udelay (5); -} - -u8 -sata_busy_wait (struct sata_ioports *ioaddr, int bits, unsigned int max) -{ - u8 status; - - do { - udelay (1000); - status = sata_chk_status (ioaddr); - max--; - } while ((status & bits) && (max > 0)); - - return status; -} - -u8 -sata_chk_status (struct sata_ioports * ioaddr) -{ - return sata_inb (ioaddr->status_addr); -} - -void -msleep (int count) +int sata_initialize(void) { + int rc; int i; - for (i = 0; i < count; i++) - udelay (1000); -} - -ulong -sata_read (int device, ulong blknr,lbaint_t blkcnt, void * buff) -{ - ulong n = 0, *buffer = (ulong *)buff; - u8 dev = 0, num = 0, mask = 0, status = 0; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000) { - if (!sata_dev_desc[devno].lba48) { - printf ("Drive doesn't support 48-bit addressing\n"); - return 0; - } - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - /*Port Number */ - num = device / CFG_SATA_DEVS_PER_BUS; - /*dev on the port */ - if (device >= CFG_SATA_DEVS_PER_BUS) - dev = device - CFG_SATA_DEVS_PER_BUS; - else - dev = device; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - if (!(port[num].dev_mask & mask)) { - printf ("dev%d is not present on port#%d\n", dev, num); - return 0; - } + for (i = 0; i < CFG_SATA_MAX_DEVICE; i++) { + memset(&sata_dev_desc[i], 0, sizeof(struct block_dev_desc)); + sata_dev_desc[i].if_type = IF_TYPE_SATA; + sata_dev_desc[i].dev = i; + sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + sata_dev_desc[i].type = DEV_TYPE_HARDDISK; + sata_dev_desc[i].lba = 0; + sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].block_read = sata_read; + sata_dev_desc[i].block_write = sata_write; - /* Select device */ - dev_select (&port[num].ioaddr, dev); - - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf ("ata%u failed to respond\n", port[num].port_no); - return n; + rc = init_sata(i); + rc = scan_sata(i); + if ((sata_dev_desc[i].lba > 0) && (sata_dev_desc[i].blksz > 0)) + init_part(&sata_dev_desc[i]); } - while (blkcnt-- > 0) { - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf ("ata%u failed to respond\n", 0); - return n; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - sata_outb (0, port[num].ioaddr.nsect_addr); - sata_outb ((blknr >> 24) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb ((blknr >> 32) & 0xFF, - port[num].ioaddr.lbam_addr); - sata_outb ((blknr >> 40) & 0xFF, - port[num].ioaddr.lbah_addr); - } -#endif - sata_outb (1, port[num].ioaddr.nsect_addr); - sata_outb (((blknr) >> 0) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb ((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr); - sata_outb ((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr); - -#ifdef CONFIG_LBA48 - if (lba48) { - sata_outb (ATA_LBA, port[num].ioaddr.device_addr); - sata_outb (ATA_CMD_READ_EXT, - port[num].ioaddr.command_addr); - } else -#endif - { - sata_outb (ATA_LBA | ((blknr >> 24) & 0xF), - port[num].ioaddr.device_addr); - sata_outb (ATA_CMD_READ, - port[num].ioaddr.command_addr); - } - - msleep (50); - /*may take up to 4 sec */ - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 4000); - - if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) - != ATA_STAT_DRQ) { - u8 err = 0; - - printf ("Error no DRQ dev %d blk %ld: sts 0x%02x\n", - device, (ulong) blknr, status); - err = sata_inb (port[num].ioaddr.error_addr); - printf ("Error reg = 0x%x\n", err); - return (n); - } - input_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS); - sata_inb (port[num].ioaddr.altstatus_addr); - udelay (50); - - ++n; - ++blknr; - buffer += ATA_SECTORWORDS; - } - return n; + curr_device = 0; + return rc; } -ulong -sata_write (int device, ulong blknr,lbaint_t blkcnt, void * buff) +block_dev_desc_t *sata_get_dev(int dev) { - ulong n = 0, *buffer = (ulong *)buff; - unsigned char status = 0, num = 0, dev = 0, mask = 0; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000) { - if (!sata_dev_desc[devno].lba48) { - printf ("Drive doesn't support 48-bit addressing\n"); - return 0; - } - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - /*Port Number */ - num = device / CFG_SATA_DEVS_PER_BUS; - /*dev on the Port */ - if (device >= CFG_SATA_DEVS_PER_BUS) - dev = device - CFG_SATA_DEVS_PER_BUS; - else - dev = device; - - if (dev == 0) - mask = 0x01; - else - mask = 0x02; - - /* Select device */ - dev_select (&port[num].ioaddr, dev); - - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf ("ata%u failed to respond\n", port[num].port_no); - return n; - } - - while (blkcnt-- > 0) { - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 500); - if (status & ATA_BUSY) { - printf ("ata%u failed to respond\n", - port[num].port_no); - return n; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - sata_outb (0, port[num].ioaddr.nsect_addr); - sata_outb ((blknr >> 24) & 0xFF, - port[num].ioaddr.lbal_addr); - sata_outb ((blknr >> 32) & 0xFF, - port[num].ioaddr.lbam_addr); - sata_outb ((blknr >> 40) & 0xFF, - port[num].ioaddr.lbah_addr); - } -#endif - sata_outb (1, port[num].ioaddr.nsect_addr); - sata_outb ((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr); - sata_outb ((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr); - sata_outb ((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr); -#ifdef CONFIG_LBA48 - if (lba48) { - sata_outb (ATA_LBA, port[num].ioaddr.device_addr); - sata_outb (ATA_CMD_WRITE_EXT, - port[num].ioaddr.command_addr); - } else -#endif - { - sata_outb (ATA_LBA | ((blknr >> 24) & 0xF), - port[num].ioaddr.device_addr); - sata_outb (ATA_CMD_WRITE, - port[num].ioaddr.command_addr); - } - - msleep (50); - /*may take up to 4 sec */ - status = sata_busy_wait (&port[num].ioaddr, ATA_BUSY, 4000); - if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) - != ATA_STAT_DRQ) { - printf ("Error no DRQ dev %d blk %ld: sts 0x%02x\n", - device, (ulong) blknr, status); - return (n); - } - - output_data (&port[num].ioaddr, buffer, ATA_SECTORWORDS); - sata_inb (port[num].ioaddr.altstatus_addr); - udelay (50); - - ++n; - ++blknr; - buffer += ATA_SECTORWORDS; - } - return n; + return (dev < CFG_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; } -block_dev_desc_t *sata_get_dev (int dev); - -block_dev_desc_t * -sata_get_dev (int dev) -{ - return ((block_dev_desc_t *) & sata_dev_desc[dev]); -} - -int -do_sata (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { + int rc = 0; switch (argc) { case 0: case 1: - printf ("Usage:\n%s\n", cmdtp->usage); + printf("Usage:\n%s\n", cmdtp->usage); return 1; case 2: - if (strncmp (argv[1], "init", 4) == 0) { - int rcode = 0; - - rcode = init_sata (); - if (rcode) - printf ("Sata initialization Failed\n"); - return rcode; - } else if (strncmp (argv[1], "inf", 3) == 0) { + if (strncmp(argv[1],"inf", 3) == 0) { int i; - - putc ('\n'); - for (i = 0; i < CFG_SATA_MAXDEVICES; ++i) { - /*List only known devices */ - if (sata_dev_desc[i].type == - DEV_TYPE_UNKNOWN) + putc('\n'); + for (i = 0; i < CFG_SATA_MAX_DEVICE; ++i) { + if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) continue; - printf ("sata dev %d: ", i); - dev_print (&sata_dev_desc[i]); + printf ("SATA device %d: ", i); + dev_print(&sata_dev_desc[i]); } return 0; + } else if (strncmp(argv[1],"dev", 3) == 0) { + if ((curr_device < 0) || (curr_device >= CFG_SATA_MAX_DEVICE)) { + puts("\nno SATA devices available\n"); + return 1; + } + printf("\nSATA device %d: ", curr_device); + dev_print(&sata_dev_desc[curr_device]); + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev, ok; + + for (ok = 0, dev = 0; dev < CFG_SATA_MAX_DEVICE; ++dev) { + if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc ('\n'); + print_part(&sata_dev_desc[dev]); + } + } + if (!ok) { + puts("\nno SATA devices available\n"); + rc ++; + } + return rc; } - printf ("Usage:\n%s\n", cmdtp->usage); + printf("Usage:\n%s\n", cmdtp->usage); return 1; case 3: - if (strcmp (argv[1], "dev") == 0) { - int dev = (int) simple_strtoul (argv[2], NULL, 10); + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (dev >= CFG_SATA_MAXDEVICES) { - printf ("\nSata dev %d not available\n", - dev); + printf("\nSATA device %d: ", dev); + if (dev >= CFG_SATA_MAX_DEVICE) { + puts ("unknown device\n"); return 1; } - printf ("\nSATA dev %d: ", dev); - dev_print (&sata_dev_desc[dev]); + dev_print(&sata_dev_desc[dev]); + if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) return 1; - curr_dev = dev; + + curr_device = dev; + + puts("... is now current device\n"); + return 0; - } else if (strcmp (argv[1], "part") == 0) { - int dev = (int) simple_strtoul (argv[2], NULL, 10); + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (dev >= CFG_SATA_MAXDEVICES) { - printf ("\nSata dev %d not available\n", - dev); - return 1; - } - PRINTF ("\nSATA dev %d: ", dev); - if (sata_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - print_part (&sata_dev_desc[dev]); + if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + print_part(&sata_dev_desc[dev]); } else { - printf ("\nSata dev %d partition type " - "unknown\n", dev); - return 1; + printf("\nSATA device %d not available\n", dev); + rc = 1; } - return 0; + return rc; } printf ("Usage:\n%s\n", cmdtp->usage); return 1; - default: - if (argc < 5) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; - } - if (strcmp (argv[1], "read") == 0) { - ulong addr = simple_strtoul (argv[2], NULL, 16); - ulong cnt = simple_strtoul (argv[4], NULL, 16); + + default: /* at least 4 args */ + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; - lbaint_t blk = simple_strtoul (argv[3], NULL, 16); + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nSATA read: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); + + n = sata_read(curr_device, blk, cnt, (u32 *)addr); - memset ((int *) addr, 0, cnt * 512); - printf ("\nSATA read: dev %d blk # %ld," - "count %ld ... ", curr_dev, blk, cnt); - n = sata_read (curr_dev, blk, cnt, (ulong *) addr); /* flush cache after read */ - flush_cache (addr, cnt * 512); - printf ("%ld blocks read: %s\n", n, - (n == cnt) ? "OK" : "ERR"); - if (n == cnt) - return 1; - else - return 0; - } else if (strcmp (argv[1], "write") == 0) { - ulong addr = simple_strtoul (argv[2], NULL, 16); - ulong cnt = simple_strtoul (argv[4], NULL, 16); + flush_cache(addr, cnt * sata_dev_desc[curr_device].blksz); + + printf("%ld blocks read: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + return (n == cnt) ? 0 : 1; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; - lbaint_t blk = simple_strtoul (argv[3], NULL, 16); - printf ("\nSata write: dev %d blk # %ld," - "count %ld ... ", curr_dev, blk, cnt); - n = sata_write (curr_dev, blk, cnt, (ulong *) addr); - printf ("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERR"); - if (n == cnt) - return 1; - else - return 0; + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nSATA write: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); + + n = sata_write(curr_device, blk, cnt, (u32 *)addr); + + printf("%ld blocks written: %s\n", + n, (n == cnt) ? "OK" : "ERROR"); + return (n == cnt) ? 0 : 1; } else { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; + printf("Usage:\n%s\n", cmdtp->usage); + rc = 1; } - } /*End OF SWITCH */ -} -U_BOOT_CMD (sata, 5, 1, do_sata, - "sata init\n" - "sata info\n" - "sata part device\n" - "sata dev device\n" - "sata read addr blk# cnt\n" - "sata write addr blk# cnt\n", "cmd for init,rw and dev-info\n"); + return rc; + } +} -#endif +U_BOOT_CMD( + sata, 5, 1, do_sata, + "sata - SATA sub system\n", + "sata info - show available SATA devices\n" + "sata device [dev] - show or set current device\n" + "sata part [dev] - print partition table\n" + "sata read addr blk# cnt\n" + "sata write addr blk# cnt\n"); diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 1cdec15..f49531e 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -207,10 +207,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part = 0; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; int rcode = 0; +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -273,24 +276,35 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) == IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + return 1; + } - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + image_print_contents (hdr); + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -300,6 +314,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf ("** Read error on %d:%d\n", dev, part); return 1; } + +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c new file mode 100644 index 0000000..2e49b6d --- /dev/null +++ b/common/cmd_setexpr.c @@ -0,0 +1,70 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * 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 + */ + +/* + * This file provides a shell like 'expr' function to return. + */ + +#include <common.h> +#include <config.h> +#include <command.h> + +int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong a, b; + char buf[16]; + + /* Validate arguments */ + if ((argc != 5) || (strlen(argv[3]) != 1)) { + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + a = simple_strtoul(argv[2], NULL, 16); + b = simple_strtoul(argv[4], NULL, 16); + + switch (argv[3][0]) { + case '|': sprintf(buf, "%lx", (a | b)); break; + case '&': sprintf(buf, "%lx", (a & b)); break; + case '+': sprintf(buf, "%lx", (a + b)); break; + case '^': sprintf(buf, "%lx", (a ^ b)); break; + case '-': sprintf(buf, "%lx", (a - b)); break; + case '*': sprintf(buf, "%lx", (a * b)); break; + case '/': sprintf(buf, "%lx", (a / b)); break; + case '%': sprintf(buf, "%lx", (a % b)); break; + default: + printf("invalid op\n"); + return 1; + } + + setenv(argv[1], buf); + + return 0; +} + +U_BOOT_CMD( + setexpr, 5, 0, do_setexpr, + "setexpr - set environment variable as the result of eval expression\n", + "name value1 <op> value2\n" + " - set environment variable 'name' to the result of the evaluated\n" + " express specified by <op>. <op> can be &, |, ^, +, -, *, /, %\n" +); diff --git a/common/cmd_usb.c b/common/cmd_usb.c index c6b17c2..23413b5 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -311,11 +311,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *boot_device = NULL; char *ep; int dev, part=1, rcode; - ulong addr, cnt, checksum; + ulong addr, cnt; disk_partition_t info; image_header_t *hdr; block_dev_desc_t *stor_dev; - +#if defined(CONFIG_FIT) + const void *fit_hdr; +#endif switch (argc) { case 1: @@ -386,25 +388,36 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - hdr = (image_header_t *)addr; + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: + hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number **\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + puts ("\n** Bad Header Checksum **\n"); + return 1; + } + + image_print_contents (hdr); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; + cnt = image_get_image_size (hdr); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + puts ("Fit image detected...\n"); - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { - puts ("\n** Bad Header Checksum **\n"); + cnt = fit_get_size (fit_hdr); + break; +#endif + default: + puts ("** Unknown image type\n"); return 1; } - hdr->ih_hcrc = htonl(checksum); /* restore checksum for later use */ - print_image_hdr (hdr); - - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; @@ -414,6 +427,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf ("\n** Read error on %d:%d\n", dev, part); return 1; } + +#if defined(CONFIG_FIT) + /* This cannot be done earlier, we need complete FIT image in RAM first */ + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) + fit_print_contents ((const void *)addr); +#endif + /* Loading ok, update default load address */ load_addr = addr; @@ -529,8 +549,7 @@ int do_usb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } if (strncmp(argv[1], "stor", 4) == 0) { - usb_stor_info(); - return 0; + return usb_stor_info(); } if (strncmp(argv[1],"part",4) == 0) { diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 52e0614..7916fc1 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -24,7 +24,6 @@ * MA 02111-1307 USA */ -#if defined(CONFIG_CMD_XIMG) /* * Multi Image extract @@ -37,92 +36,136 @@ int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { - ulong addr = load_addr, dest = 0; - ulong data, len, checksum; - ulong *len_ptr; - int i, verify, part = 0; - char pbuf[10], *s; - image_header_t header; + ulong addr = load_addr; + ulong dest = 0; + ulong data, len, count; + int verify; + int part = 0; + char pbuf[10]; + image_header_t *hdr; +#if defined(CONFIG_FIT) + const char *uname = NULL; + const void* fit_hdr; + int noffset; + const void *fit_data; + size_t fit_len; +#endif - s = getenv("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + verify = getenv_verify (); if (argc > 1) { addr = simple_strtoul(argv[1], NULL, 16); } if (argc > 2) { part = simple_strtoul(argv[2], NULL, 16); +#if defined(CONFIG_FIT) + uname = argv[2]; +#endif } if (argc > 3) { dest = simple_strtoul(argv[3], NULL, 16); } - printf("## Copying from image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memmove(&header, (char *) addr, sizeof (image_header_t)); - - if (ntohl(header.ih_magic) != IH_MAGIC) { - printf("Bad Magic Number\n"); - return 1; - } + switch (genimg_get_format ((void *)addr)) { + case IMAGE_FORMAT_LEGACY: - data = (ulong) & header; - len = sizeof (image_header_t); + printf("## Copying part %d from legacy image " + "at %08lx ...\n", part, addr); - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; + hdr = (image_header_t *)addr; + if (!image_check_magic (hdr)) { + printf("Bad Magic Number\n"); + return 1; + } - if (crc32(0, (char *) data, len) != checksum) { - printf("Bad Header Checksum\n"); - return 1; - } + if (!image_check_hcrc (hdr)) { + printf("Bad Header Checksum\n"); + return 1; + } #ifdef DEBUG - print_image_hdr((image_header_t *) addr); + image_print_contents (hdr); #endif - data = addr + sizeof (image_header_t); - len = ntohl(header.ih_size); + if (!image_check_type (hdr, IH_TYPE_MULTI)) { + printf("Wrong Image Type for %s command\n", + cmdtp->name); + return 1; + } - if (header.ih_type != IH_TYPE_MULTI) { - printf("Wrong Image Type for %s command\n", cmdtp->name); - return 1; - } + if (image_get_comp (hdr) != IH_COMP_NONE) { + printf("Wrong Compression Type for %s command\n", + cmdtp->name); + return 1; + } - if (header.ih_comp != IH_COMP_NONE) { - printf("Wrong Compression Type for %s command\n", cmdtp->name); - return 1; - } + if (verify) { + printf(" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + printf("Bad Data CRC\n"); + return 1; + } + printf("OK\n"); + } - if (verify) { - printf(" Verifying Checksum ... "); - if (crc32(0, (char *) data, len) != ntohl(header.ih_dcrc)) { - printf("Bad Data CRC\n"); + count = image_multi_count (hdr); + if (part >= count) { + printf("Bad Image Part\n"); + return 1; + } + + image_multi_getimg (hdr, part, &data, &len); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + if (uname == NULL) { + puts ("No FIT subimage unit name\n"); + return 1; + } + + printf("## Copying '%s' subimage from FIT image " + "at %08lx ...\n", uname, addr); + + fit_hdr = (const void *)addr; + if (!fit_check_format (fit_hdr)) { + puts ("Bad FIT image format\n"); + return 1; + } + + /* get subimage node offset */ + noffset = fit_image_get_node (fit_hdr, uname); + if (noffset < 0) { + printf ("Can't find '%s' FIT subimage\n", uname); return 1; } - printf("OK\n"); - } - len_ptr = (ulong *) data; - - data += 4; /* terminator */ - for (i = 0; len_ptr[i]; ++i) { - data += 4; - if (argc > 2 && part > i) { - u_long tail; - len = ntohl(len_ptr[i]); - tail = len % 4; - data += len; - if (tail) { - data += 4 - tail; + if (fit_image_check_comp (fit_hdr, noffset, IH_COMP_NONE)) { + printf("Wrong Compression Type for %s command\n", + cmdtp->name); + return 1; + } + + /* verify integrity */ + if (verify) { + if (!fit_image_check_hashes (fit_hdr, noffset)) { + puts ("Bad Data Hash\n"); + return 1; } } - } - if (argc > 2 && part >= i) { - printf("Bad Image Part\n"); + + /* get subimage data address and length */ + if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) { + puts ("Could not find script subimage data\n"); + return 1; + } + + data = (ulong)fit_data; + len = (ulong)fit_len; + break; +#endif + default: + puts ("Invalid image type for imxtract\n"); return 1; } - len = ntohl(len_ptr[part]); if (argc > 3) { memcpy((char *) dest, (char *) data, len); @@ -139,6 +182,9 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) U_BOOT_CMD(imxtract, 4, 1, do_imgextract, "imxtract- extract a part of a multi-image\n", "addr part [dest]\n" - " - extract <part> from image at <addr> and copy to <dest>\n"); - + " - extract <part> from legacy image at <addr> and copy to <dest>\n" +#if defined(CONFIG_FIT) + "addr uname [dest]\n" + " - extract <uname> subimage from FIT image at <addr> and copy to <dest>\n" #endif +); diff --git a/common/fdt_support.c b/common/fdt_support.c index 69eb667..7507744 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -40,7 +40,6 @@ DECLARE_GLOBAL_DATA_PTR; */ struct fdt_header *fdt; -/********************************************************************/ /** * fdt_find_and_setprop: Find a node and set it's property @@ -218,198 +217,6 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force) return err; } -/********************************************************************/ - -#ifdef CONFIG_OF_HAS_UBOOT_ENV - -/* Function that returns a character from the environment */ -extern uchar(*env_get_char) (int); - - -int fdt_env(void *fdt) -{ - int nodeoffset; - int err; - int k, nxt; - int i; - static char tmpenv[256]; - - err = fdt_check_header(fdt); - if (err < 0) { - printf("fdt_env: %s\n", fdt_strerror(err)); - return err; - } - - /* - * See if we already have a "u-boot-env" node, delete it if so. - * Then create a new empty node. - */ - nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); - if (nodeoffset >= 0) { - err = fdt_del_node(fdt, nodeoffset); - if (err < 0) { - printf("fdt_env: %s\n", fdt_strerror(err)); - return err; - } - } - /* - * Create a new node "/u-boot-env" (offset 0 is root level) - */ - nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); - if (nodeoffset < 0) { - printf("WARNING: could not create /u-boot-env %s.\n", - fdt_strerror(nodeoffset)); - return nodeoffset; - } - - for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { - char *s, *lval, *rval; - - /* - * Find the end of the name=definition - */ - for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) - ; - s = tmpenv; - for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) - *s++ = env_get_char(k); - *s++ = '\0'; - lval = tmpenv; - /* - * Find the first '=': it separates the name from the value - */ - s = strchr(tmpenv, '='); - if (s != NULL) { - *s++ = '\0'; - rval = s; - } else - continue; - err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); - if (err < 0) { - printf("WARNING: could not set %s %s.\n", - lval, fdt_strerror(err)); - return err; - } - } - return 0; -} -#endif /* ifdef CONFIG_OF_HAS_UBOOT_ENV */ - -/********************************************************************/ - -#ifdef CONFIG_OF_HAS_BD_T - -#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) } - -static const struct { - const char *name; - int offset; -} bd_map[] = { - BDM(memstart), - BDM(memsize), - BDM(flashstart), - BDM(flashsize), - BDM(flashoffset), - BDM(sramstart), - BDM(sramsize), -#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \ - || defined(CONFIG_E500) - BDM(immr_base), -#endif -#if defined(CONFIG_MPC5xxx) - BDM(mbar_base), -#endif -#if defined(CONFIG_MPC83XX) - BDM(immrbar), -#endif -#if defined(CONFIG_MPC8220) - BDM(mbar_base), - BDM(inpfreq), - BDM(pcifreq), - BDM(pevfreq), - BDM(flbfreq), - BDM(vcofreq), -#endif - BDM(bootflags), - BDM(ip_addr), - BDM(intfreq), - BDM(busfreq), -#ifdef CONFIG_CPM2 - BDM(cpmfreq), - BDM(brgfreq), - BDM(sccfreq), - BDM(vco), -#endif -#if defined(CONFIG_MPC5xxx) - BDM(ipbfreq), - BDM(pcifreq), -#endif - BDM(baudrate), -}; - - -int fdt_bd_t(void *fdt) -{ - bd_t *bd = gd->bd; - int nodeoffset; - int err; - u32 tmp; /* used to set 32 bit integer properties */ - int i; - - err = fdt_check_header(fdt); - if (err < 0) { - printf("fdt_bd_t: %s\n", fdt_strerror(err)); - return err; - } - - /* - * See if we already have a "bd_t" node, delete it if so. - * Then create a new empty node. - */ - nodeoffset = fdt_path_offset (fdt, "/bd_t"); - if (nodeoffset >= 0) { - err = fdt_del_node(fdt, nodeoffset); - if (err < 0) { - printf("fdt_bd_t: %s\n", fdt_strerror(err)); - return err; - } - } - /* - * Create a new node "/bd_t" (offset 0 is root level) - */ - nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); - if (nodeoffset < 0) { - printf("WARNING: could not create /bd_t %s.\n", - fdt_strerror(nodeoffset)); - printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset)); - return nodeoffset; - } - /* - * Use the string/pointer structure to create the entries... - */ - for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { - tmp = cpu_to_be32(getenv("bootargs")); - err = fdt_setprop(fdt, nodeoffset, - bd_map[i].name, &tmp, sizeof(tmp)); - if (err < 0) - printf("WARNING: could not set %s %s.\n", - bd_map[i].name, fdt_strerror(err)); - } - /* - * Add a couple of oddball entries... - */ - err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); - if (err < 0) - printf("WARNING: could not set enetaddr %s.\n", - fdt_strerror(err)); - err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); - if (err < 0) - printf("WARNING: could not set ethspeed %s.\n", - fdt_strerror(err)); - return 0; -} -#endif /* ifdef CONFIG_OF_HAS_BD_T */ - void do_fixup_by_path(void *fdt, const char *path, const char *prop, const void *val, int len, int create) { @@ -615,3 +422,28 @@ void fdt_fixup_ethernet(void *fdt, bd_t *bd) } } #endif + +#ifdef CONFIG_HAS_FSL_DR_USB +void fdt_fixup_dr_usb(void *blob, bd_t *bd) +{ + char *mode; + const char *compat = "fsl-usb2-dr"; + const char *prop = "dr_mode"; + int node_offset; + int err; + + mode = getenv("usb_dr_mode"); + if (!mode) + return; + + node_offset = fdt_node_offset_by_compatible(blob, 0, compat); + if (node_offset < 0) + printf("WARNING: could not find compatible node %s: %s.\n", + compat, fdt_strerror(node_offset)); + + err = fdt_setprop(blob, node_offset, prop, mode, strlen(mode) + 1); + if (err < 0) + printf("WARNING: could not set %s for %s: %s.\n", + prop, compat, fdt_strerror(err)); +} +#endif /* CONFIG_HAS_FSL_DR_USB */ diff --git a/common/gunzip.c b/common/gunzip.c new file mode 100644 index 0000000..74f0bf9 --- /dev/null +++ b/common/gunzip.c @@ -0,0 +1,113 @@ +/* + * (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 + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <malloc.h> +#include <zlib.h> + +#define ZALLOC_ALIGNMENT 16 +#define HEAD_CRC 2 +#define EXTRA_FIELD 4 +#define ORIG_NAME 8 +#define COMMENT 0x10 +#define RESERVED 0xe0 +#define DEFLATED 8 + +int gunzip(void *, int, unsigned char *, unsigned long *); +void *zalloc(void *, unsigned, unsigned); +void zfree(void *, void *, unsigned); + +void *zalloc(void *x, unsigned items, unsigned size) +{ + void *p; + + size *= items; + size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); + + p = malloc (size); + + return (p); +} + +void zfree(void *x, void *addr, unsigned nb) +{ + free (addr); +} + +int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +{ + z_stream s; + int r, i, flags; + + /* skip header */ + i = 10; + flags = src[3]; + if (src[2] != DEFLATED || (flags & RESERVED) != 0) { + puts ("Error: Bad gzipped data\n"); + return (-1); + } + if ((flags & EXTRA_FIELD) != 0) + i = 12 + src[10] + (src[11] << 8); + if ((flags & ORIG_NAME) != 0) + while (src[i++] != 0) + ; + if ((flags & COMMENT) != 0) + while (src[i++] != 0) + ; + if ((flags & HEAD_CRC) != 0) + i += 2; + if (i >= *lenp) { + puts ("Error: gunzip out of data in header\n"); + return (-1); + } + + s.zalloc = zalloc; + s.zfree = zfree; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + s.outcb = (cb_func)WATCHDOG_RESET; +#else + s.outcb = Z_NULL; +#endif /* CONFIG_HW_WATCHDOG */ + + r = inflateInit2(&s, -MAX_WBITS); + if (r != Z_OK) { + printf ("Error: inflateInit2() returned %d\n", r); + return (-1); + } + s.next_in = src + i; + s.avail_in = *lenp - i; + s.next_out = dst; + s.avail_out = dstlen; + r = inflate(&s, Z_FINISH); + if (r != Z_OK && r != Z_STREAM_END) { + printf ("Error: inflate() returned %d\n", r); + return (-1); + } + *lenp = s.next_out - (unsigned char *) dst; + inflateEnd(&s); + + return (0); +} diff --git a/common/image.c b/common/image.c new file mode 100644 index 0000000..f04826a --- /dev/null +++ b/common/image.c @@ -0,0 +1,2541 @@ +/* + * (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 <common.h> +#include <watchdog.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +#include <status_led.h> +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#include <dataflash.h> +#endif + +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) +#include <rtc.h> +#endif + +#include <image.h> + +#if defined(CONFIG_FIT) || defined (CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> +#endif + +#if defined(CONFIG_FIT) +#include <md5.h> +#include <sha1.h> + +static int fit_check_ramdisk (const void *fit, int os_noffset, + uint8_t arch, int verify); +#endif + +#ifdef CONFIG_CMD_BDI +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 (ulong rd_addr, uint8_t arch, + int verify); +#else +#include "mkimage.h" +#include <md5.h> +#include <time.h> +#include <image.h> +#endif /* !USE_HOSTCC*/ + +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 */ +/*****************************************************************************/ +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)); +} + +#ifndef USE_HOSTCC +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)); +} +#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; + 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 = (uint32_t *)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; + uint32_t *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 = (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 (uint32_t); + + if (idx < count) { + *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 += uimage_to_cpu (size[i]); + + /* add up alignment for i-th component */ + tail += (4 - uimage_to_cpu (size[i]) % 4); + } + + /* calculate idx-th component data address */ + *data = img_data + offset + tail; + } else { + *len = 0; + *data = 0; + } +} + +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)\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)); +#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) + printf ("%sCreated: ", p); + genimg_print_time ((time_t)image_get_time (hdr)); +#endif + 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)); + + 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); + + printf ("%sContents:\n", p); + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); + + 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 + * @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 (ulong rd_addr, uint8_t arch, + int verify) +{ + image_header_t *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; +} +#endif /* !USE_HOSTCC */ + +/*****************************************************************************/ +/* Shared dual-format routines */ +/*****************************************************************************/ +#ifndef USE_HOSTCC +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; + } + +#if defined(CFG_SDRAM_BASE) + return CFG_SDRAM_BASE; +#elif defined(CONFIG_ARM) + return gd->bd->bi_dram[0].start; +#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; + } + +#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) +{ +#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 */ + +static void genimg_print_size (uint32_t size) +{ +#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 +} + +#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 +} +#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */ + +/** + * 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); +} + +const char *genimg_get_os_name (uint8_t os) +{ + return (get_table_entry_name (uimage_os, "Unknown OS", os)); +} + +const char *genimg_get_arch_name (uint8_t arch) +{ + return (get_table_entry_name (uimage_arch, "Unknown Architecture", arch)); +} + +const char *genimg_get_type_name (uint8_t type) +{ + return (get_table_entry_name (uimage_type, "Unknown Image", type)); +} + +const char *genimg_get_comp_name (uint8_t comp) +{ + return (get_table_entry_name (uimage_comp, "Unknown Compression", 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) +{ + table_entry_t *t; +#ifdef USE_HOSTCC + int first = 1; + + for (t = table; t->id >= 0; ++t) { + if (t->sname && strcasecmp(t->sname, name) == 0) + return (t->id); + } + + 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 + * + * 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 + * genimg_get_format() must be able to dectect libfdt header. + * + * returns: + * image format type or IMAGE_FORMAT_INVALID if no image is present + */ +int genimg_get_format (void *img_addr) +{ + ulong format = IMAGE_FORMAT_INVALID; + image_header_t *hdr; +#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) || defined(CONFIG_OF_LIBFDT) + else { + fit_hdr = (char *)img_addr; + if (fdt_check_header (fit_hdr) == 0) + format = IMAGE_FORMAT_FIT; + } +#endif + + return format; +} + +/** + * genimg_get_image - get image from special storage (if necessary) + * @img_addr: image start address + * + * 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 genimg_get_image (ulong img_addr) +{ + 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); + + /* get data size */ + 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", + ram_addr, d_size); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + 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; +#endif + default: + printf (" No valid image found at 0x%08lx\n", img_addr); + return ram_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 /* CONFIG_HAS_DATAFLASH */ + + return ram_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 + * @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 + * + * 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. + * + * 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 + */ +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; + 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; + int rd_noffset; + int cfg_noffset; + const void *data; + size_t size; +#endif + + *rd_start = 0; + *rd_end = 0; + + /* + * 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 || genimg_has_config (images)) { +#if defined(CONFIG_FIT) + 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); + } +#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); + + /* + * 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 (genimg_get_format ((void *)rd_addr)) { + case IMAGE_FORMAT_LEGACY: + 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); + + if (rd_hdr == NULL) + return 1; + + 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; + 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) { + /* + * 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 + */ + show_boot_progress (122); + 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, cfg_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) { + puts ("Could not find subimage node\n"); + 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; + images->fit_noffset_rd = rd_noffset; + break; +#endif + default: + puts ("Wrong Ramdisk Image Format\n"); + rd_data = rd_len = rd_load = 0; + } + +#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(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 (images->legacy_hdr_valid && + image_check_type (images->legacy_hdr_os, IH_TYPE_MULTI)) { + /* + * 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 " + "Legacy 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 + */ + show_boot_progress (14); + rd_len = rd_data = 0; + } + + if (!rd_data) { + debug ("## No init Ramdisk\n"); + } 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); + + return 0; +} + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * 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 + * @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) + * + * 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: + * 0 - success + * -1 - failure + */ +int boot_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; + + 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; + } + + 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; + lmb_reserve(lmb, rd_data, rd_len); + } else { + 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; + 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); + + return 0; + +error: + return -1; +} + +/** + * 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 + * + * 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. + * + * returns: + * 0 - success + * -1 - failure + */ +int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, + ulong bootmap_base) +{ + char *cmdline; + char *s; + + cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, + CFG_BOOTMAPSZ + bootmap_base); + + if (cmdline == NULL) + return -1; + + 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 0; +} + +/** + * 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 + * + * 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. + * + * returns: + * 0 - success + * -1 - failure + */ +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); + if (*kbd == NULL) + return -1; + + **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 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) +{ + 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 [<addr>]#<conf>, + * where <addr> is a FIT image address that contains configuration + * with a <conf> 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 + * [<addr>]:<subimage>, where <addr> is a FIT image address that contains + * subimage with a <subimg> 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 /* !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 ) { + md5 ((unsigned char *)data, data_len, value); + *value_len = 16; + } 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 + * @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); +} + +/** + * 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"); + 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 */ +#endif /* CONFIG_FIT */ diff --git a/common/lynxkdi.c b/common/lynxkdi.c index 76a271b..a5dc887 100644 --- a/common/lynxkdi.c +++ b/common/lynxkdi.c @@ -23,45 +23,45 @@ DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_MPC8260) || defined(CONFIG_440EP) || defined(CONFIG_440GR) -void lynxkdi_boot ( image_header_t *hdr ) +void lynxkdi_boot (image_header_t *hdr) { - void (*lynxkdi)(void) = (void(*)(void)) ntohl(hdr->ih_ep); + void (*lynxkdi)(void) = (void(*)(void))image_get_ep (hdr); lynxos_bootparms_t *parms = (lynxos_bootparms_t *)0x0020; bd_t *kbd; - u32 *psz = (u32 *)(ntohl(hdr->ih_load) + 0x0204); + u32 *psz = (u32 *)(image_get_load (hdr) + 0x0204); - memset( parms, 0, sizeof(*parms)); + memset (parms, 0, sizeof(*parms)); kbd = gd->bd; parms->clock_ref = kbd->bi_busfreq; parms->dramsz = kbd->bi_memsize; - memcpy(parms->ethaddr, kbd->bi_enetaddr, 6); - mtspr(SPRN_SPRG2, 0x0020); + memcpy (parms->ethaddr, kbd->bi_enetaddr, 6); + mtspr (SPRN_SPRG2, 0x0020); /* Do a simple check for Bluecat so we can pass the * kernel command line parameters. */ - if( le32_to_cpu(*psz) == ntohl(hdr->ih_size) ){ /* FIXME: NOT SURE HERE ! */ - char *args; - char *cmdline = (char *)(ntohl(hdr->ih_load) + 0x020c); - int len; + if (le32_to_cpu (*psz) == image_get_data_size (hdr)) { /* FIXME: NOT SURE HERE ! */ + char *args; + char *cmdline = (char *)(image_get_load (hdr) + 0x020c); + int len; - printf("Booting Bluecat KDI ...\n"); - udelay(200*1000); /* Allow serial port to flush */ - if ((args = getenv("bootargs")) == NULL) - args = ""; - /* Prepend the cmdline */ - len = strlen(args); - if( len && (len + strlen(cmdline) + 2 < (0x0400 - 0x020c))) { - memmove( cmdline + strlen(args) + 1, cmdline, strlen(cmdline) ); - strcpy( cmdline, args ); - cmdline[len] = ' '; - } + printf ("Booting Bluecat KDI ...\n"); + udelay (200*1000); /* Allow serial port to flush */ + if ((args = getenv ("bootargs")) == NULL) + args = ""; + /* Prepend the cmdline */ + len = strlen (args); + if (len && (len + strlen (cmdline) + 2 < (0x0400 - 0x020c))) { + memmove (cmdline + strlen (args) + 1, cmdline, strlen (cmdline)); + strcpy (cmdline, args); + cmdline[len] = ' '; + } } else { - printf("Booting LynxOS KDI ...\n"); + printf ("Booting LynxOS KDI ...\n"); } - lynxkdi(); + lynxkdi (); } #else #error "Lynx KDI support not implemented for configured CPU" diff --git a/common/usb_storage.c b/common/usb_storage.c index 443d785..d263b6c 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -188,17 +188,20 @@ void usb_show_progress(void) * show info on storage devices; 'usb start/init' must be invoked earlier * as we only retrieve structures populated during devices initialization */ -void usb_stor_info(void) +int usb_stor_info(void) { int i; - if (usb_max_devs > 0) + if (usb_max_devs > 0) { for (i = 0; i < usb_max_devs; i++) { printf (" Device %d: ", i); dev_print(&usb_dev_desc[i]); } - else - printf("No storage devices, perhaps not 'usb start'ed..?\n"); + return 0; + } + + printf("No storage devices, perhaps not 'usb start'ed..?\n"); + return 1; } /********************************************************************************* |