diff options
55 files changed, 2496 insertions, 2813 deletions
@@ -2921,7 +2921,8 @@ clobber: clean @rm -f $(OBJS) $(obj)*.bak $(obj)ctags $(obj)etags $(obj)TAGS @rm -fr $(obj)*.*~ @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL) - @rm -f $(obj)tools/crc32.c $(obj)tools/environment.c $(obj)tools/env/crc32.c $(obj)tools/sha1.c + @rm -f $(obj)tools/crc32.c $(obj)tools/environment.c $(obj)tools/env/crc32.c + @rm -f $(obj)tools/sha1.c $(obj)tools/image.c @rm -f $(obj)tools/inca-swap-bytes $(obj)cpu/mpc824x/bedbug_603e.c @rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm @[ ! -d $(obj)nand_spl ] || find $(obj)nand_spl -lname "*" -print | xargs rm -f diff --git a/board/cray/L1/L1.c b/board/cray/L1/L1.c index a0fac7f..8e6d74e 100644 --- a/board/cray/L1/L1.c +++ b/board/cray/L1/L1.c @@ -139,8 +139,8 @@ int misc_init_r (void) struct rtc_time tm; char bootcmd[32]; - hdr = (image_header_t *) (CFG_MONITOR_BASE - sizeof (image_header_t)); - timestamp = (time_t) hdr->ih_time; + hdr = (image_header_t *) (CFG_MONITOR_BASE - image_get_header_size ()); + timestamp = (time_t)image_get_time (hdr); to_tm (timestamp, &tm); printf ("Welcome to U-Boot on Cray L1. Compiled %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); diff --git a/board/esd/common/auto_update.c b/board/esd/common/auto_update.c index a76b00f..cb8087b 100644 --- a/board/esd/common/auto_update.c +++ b/board/esd/common/auto_update.c @@ -89,24 +89,22 @@ extern block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; int au_check_cksum_valid(int i, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; - if ((au_image[i].type == AU_FIRMWARE) && (au_image[i].size != ntohl(hdr->ih_size))) { + if ((au_image[i].type == AU_FIRMWARE) && + (au_image[i].size != image_get_data_size (hdr))) { printf ("Image %s has wrong size\n", au_image[i].name); return -1; } - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) { + if (nbytes != (image_get_image_size (hdr))) { printf ("Image %s bad total SIZE\n", au_image[i].name); return -1; } - /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) - != checksum) { + /* check the data CRC */ + if (!image_check_dcrc (hdr)) { printf ("Image %s bad data checksum\n", au_image[i].name); return -1; } @@ -123,48 +121,43 @@ int au_check_header_valid(int i, long nbytes) /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_PPC); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_PPC); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", au_image[i].name); return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_PPC) + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) { printf ("Image %s bad MAGIC or ARCH\n", au_image[i].name); return -1; } - /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", au_image[i].name); return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((au_image[i].type == AU_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((au_image[i].type == AU_FIRMWARE) && !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", au_image[i].name); return -1; } - if ((au_image[i].type == AU_SCRIPT) && (hdr->ih_type != IH_TYPE_SCRIPT)) { + if ((au_image[i].type == AU_SCRIPT) && !image_check_type (hdr, IH_TYPE_SCRIPT)) { printf ("Image %s wrong type\n", au_image[i].name); return -1; } /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); #if 0 /* test-only */ /* for kernel and app the image header must also fit into flash */ if (idx != IDX_DISK) - checksum += sizeof(*hdr); + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ /* all have ausize[] set to 0 */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -196,11 +189,11 @@ int au_do_update(int i, long sz) printf("Executing script %s\n", au_image[i].name); /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; /* @@ -231,8 +224,8 @@ int au_do_update(int i, long sz) */ if (au_image[i].type == AU_FIRMWARE) { char *orig = (char*)start; - char *new = (char *)((char *)hdr + sizeof(*hdr)); - nbytes = ntohl(hdr->ih_size); + char *new = (char *)((char *)hdr + image_get_header_size ()); + nbytes = image_get_data_size (hdr); while(--nbytes) { if (*orig++ != *new++) { @@ -272,12 +265,12 @@ int au_do_update(int i, long sz) /* strip the header - except for the kernel and ramdisk */ if (au_image[i].type != AU_FIRMWARE) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* @@ -305,15 +298,15 @@ int au_do_update(int i, long sz) * check the dcrc of the copy */ if (au_image[i].type != AU_NAND) { - rc = crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)); + rc = crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)); } else { #if defined(CONFIG_CMD_NAND) && defined(CFG_NAND_LEGACY) rc = nand_legacy_rw(nand_dev_desc, NANDRW_READ | NANDRW_JFFS2 | NANDRW_JFFS2_SKIP, start, nbytes, (size_t *)&total, (uchar *)addr); - rc = crc32 (0, (uchar *)(addr + off), ntohl(hdr->ih_size)); + rc = crc32 (0, (uchar *)(addr + off), image_get_data_size (hdr)); #endif } - if (rc != ntohl(hdr->ih_dcrc)) { + if (rc != image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum After COPY\n", au_image[i].name); return -1; } @@ -497,10 +490,10 @@ int do_auto_update(void) printf("Reading %s ...", au_image[i].name); /* just read the header */ - sz = do_fat_read(au_image[i].name, LOAD_ADDR, sizeof(image_header_t), LS_NO); + sz = do_fat_read(au_image[i].name, LOAD_ADDR, image_get_header_size (), LS_NO); debug ("read %s sz %ld hdr %d\n", - au_image[i].name, sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + au_image[i].name, sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { puts(" not found\n"); continue; } @@ -510,8 +503,8 @@ int do_auto_update(void) } sz = do_fat_read(au_image[i].name, LOAD_ADDR, MAX_LOADSZ, LS_NO); debug ("read %s sz %ld hdr %d\n", - au_image[i].name, sz, sizeof(image_header_t)); - if (sz <= 0 || sz <= sizeof(image_header_t)) { + au_image[i].name, sz, image_get_header_size ()); + if (sz <= 0 || sz <= image_get_header_size ()) { puts(" not found\n"); continue; } diff --git a/board/mcc200/auto_update.c b/board/mcc200/auto_update.c index 28e4c87..8b520c8 100644 --- a/board/mcc200/auto_update.c +++ b/board/mcc200/auto_update.c @@ -141,18 +141,15 @@ extern void lcd_enable(void); int au_check_cksum_valid(int idx, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) { + if (nbytes != image_get_image_size (hdr)) { printf ("Image %s bad total SIZE\n", aufile[idx]); return -1; } /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) != checksum) { + if (!image_check_dcrc (hdr)) { printf ("Image %s bad data checksum\n", aufile[idx]); return -1; } @@ -168,56 +165,52 @@ int au_check_header_valid(int idx, long nbytes) /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_ARM); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) { + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", aufile[idx]); ausize[idx] = 0; return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_PPC) { + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) { printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]); ausize[idx] = 0; return -1; } /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", aufile[idx]); ausize[idx] = 0; return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((idx == IDX_FIRMWARE) && !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } - if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) { + if ((idx == IDX_KERNEL) && !image_check_type (hdr, IH_TYPE_KERNEL)) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } if ((idx == IDX_ROOTFS) && - ( (hdr->ih_type != IH_TYPE_RAMDISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM) ) - ) { + (!image_check_type (hdr, IH_TYPE_RAMDISK) && + !image_check_type (hdr, IH_TYPE_FILESYSTEM))) { printf ("Image %s wrong type\n", aufile[idx]); ausize[idx] = 0; return -1; } /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); - fsize = checksum + sizeof(*hdr); + fsize = checksum + image_get_header_size (); /* for kernel and ramdisk the image header must also fit into flash */ - if (idx == IDX_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) - checksum += sizeof(*hdr); + if (idx == IDX_KERNEL || image_check_type (hdr, IH_TYPE_RAMDISK)) + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -242,11 +235,11 @@ int au_do_update(int idx, long sz) hdr = (image_header_t *)LOAD_ADDR; /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; parse_string_outer(addr, FLAG_PARSE_SEMICOLON); return 0; @@ -278,19 +271,20 @@ int au_do_update(int idx, long sz) #endif /* strip the header - except for the kernel and ramdisk */ - if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) { + if (image_check_type (hdr, IH_TYPE_KERNEL) || + image_check_type (hdr, IH_TYPE_RAMDISK)) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); #ifdef AU_UPDATE_TEST /* copy it to where Linux goes */ if (idx == IDX_FIRMWARE) start = aufl_layout[1].start; #endif off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* copy the data from RAM to FLASH */ @@ -306,7 +300,8 @@ int au_do_update(int idx, long sz) #endif /* check the data CRC of the copy */ - if (crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) { + if (crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)) != + image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum after COPY\n", aufile[idx]); return -1; } @@ -442,10 +437,10 @@ int do_auto_update(void) for (i = 0; i < AU_MAXFILES; i++) { ulong imsize; /* just read the header */ - sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t)); + sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ()); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { debug ("%s not found\n", aufile[i]); ausize[i] = 0; continue; @@ -474,14 +469,14 @@ int do_auto_update(void) sz = file_fat_read(aufile[i], LOAD_ADDR, ausize[i]); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); + aufile[i], sz, image_get_header_size ()); if (sz != ausize[i]) { printf ("%s: size %d read %d?\n", aufile[i], ausize[i], sz); continue; } - if (sz <= 0 || sz <= sizeof(image_header_t)) { + if (sz <= 0 || sz <= image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c index 8d4cbe8..30c6ca9 100644 --- a/board/mpl/common/common_util.c +++ b/board/mpl/common/common_util.c @@ -57,9 +57,6 @@ extern int mem_test(ulong start, ulong ramsize, int quiet); extern flash_info_t flash_info[]; /* info for FLASH chips */ -static image_header_t header; - - static int mpl_prg(uchar *src, ulong size) { @@ -77,7 +74,7 @@ mpl_prg(uchar *src, ulong size) info = &flash_info[0]; #if defined(CONFIG_PIP405) || defined(CONFIG_MIP405) || defined(CONFIG_PATI) - if (ntohl(magic[0]) != IH_MAGIC) { + if (image_to_cpu (magic[0]) != IH_MAGIC) { puts("Bad Magic number\n"); return -1; } @@ -179,44 +176,39 @@ mpl_prg(uchar *src, ulong size) static int mpl_prg_image(uchar *ld_addr) { - unsigned long len, checksum; + unsigned long len; uchar *data; - image_header_t *hdr = &header; + image_header_t *hdr = (image_header_t *)ld_addr; int rc; - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)ld_addr, sizeof(image_header_t)); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_check_magic (hdr)) { puts("Bad Magic Number\n"); return 1; } print_image_hdr(hdr); - if (hdr->ih_os != IH_OS_U_BOOT) { + if (!image_check_os (hdr, IH_OS_U_BOOT)) { puts("No U-Boot Image\n"); return 1; } - if (hdr->ih_type != IH_TYPE_FIRMWARE) { + if (!image_check_type (hdr, IH_TYPE_FIRMWARE)) { puts("No Firmware Image\n"); return 1; } - data = (uchar *)&header; - len = sizeof(image_header_t); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - if (crc32 (0, (uchar *)data, len) != checksum) { + if (!image_check_hcrc (hdr)) { puts("Bad Header Checksum\n"); return 1; } - data = ld_addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); puts("Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { + if (!image_check_dcrc (hdr)) { puts("Bad Data CRC\n"); return 1; } puts("OK\n"); - if (hdr->ih_comp != IH_COMP_NONE) { + data = (uchar *)image_get_data (hdr); + len = image_get_data_size (hdr); + + if (image_get_comp (hdr) != IH_COMP_NONE) { uchar *buf; /* reserve space for uncompressed image */ if ((buf = malloc(IMAGE_SIZE)) == NULL) { @@ -224,7 +216,7 @@ mpl_prg_image(uchar *ld_addr) return 1; } - switch (hdr->ih_comp) { + switch (image_get_comp (hdr)) { case IH_COMP_GZIP: puts("Uncompressing (GZIP) ... "); rc = gunzip ((void *)(buf), IMAGE_SIZE, data, &len); @@ -253,7 +245,8 @@ mpl_prg_image(uchar *ld_addr) break; #endif default: - printf ("Unimplemented compression type %d\n", hdr->ih_comp); + printf ("Unimplemented compression type %d\n", + image_get_comp (hdr)); free(buf); return 1; } diff --git a/board/siemens/common/fpga.c b/board/siemens/common/fpga.c index f022ed6..9d71946 100644 --- a/board/siemens/common/fpga.c +++ b/board/siemens/common/fpga.c @@ -131,45 +131,37 @@ static int fpga_reset (fpga_t* fpga) static int fpga_load (fpga_t* fpga, ulong addr, int checkall) { volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base; - image_header_t hdr; - ulong len, checksum; - uchar *data = (uchar *)&hdr; - char *s, msg[32]; + image_header_t *hdr = (image_header_t *)addr; + ulong len; + uchar *data; + char msg[32]; int verify, i; /* * Check the image header and data of the net-list */ - memcpy (&hdr, (char *)addr, sizeof(image_header_t)); - - if (hdr.ih_magic != IH_MAGIC) { + if (!image_check_magic (hdr)) { strcpy (msg, "Bad Image Magic Number"); goto failure; } - len = sizeof(image_header_t); - - checksum = hdr.ih_hcrc; - hdr.ih_hcrc = 0; - - if (crc32 (0, data, len) != checksum) { + if (!image_check_hcrc (hdr)) { strcpy (msg, "Bad Image Header CRC"); goto failure; } - data = (uchar*)(addr + sizeof(image_header_t)); - len = hdr.ih_size; + data = (uchar*)image_get_data (hdr); + len = image_get_data_size (hdr); - s = getenv ("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + verify = getenv_verify (); if (verify) { - if (crc32 (0, data, len) != hdr.ih_dcrc) { + if (!image_check_dcrc (hdr)) { strcpy (msg, "Bad Image Data CRC"); goto failure; } } - if (checkall && fpga_get_version(fpga, (char *)(hdr.ih_name)) < 0) + if (checkall && fpga_get_version(fpga, image_get_name (hdr)) < 0) return 1; /* align length */ @@ -184,7 +176,7 @@ static int fpga_load (fpga_t* fpga, ulong addr, int checkall) goto failure; } - printf ("(%s)... ", hdr.ih_name); + printf ("(%s)... ", image_get_name (hdr)); /* * Copy data to FPGA */ @@ -341,7 +333,7 @@ int fpga_init (void) } hdr = (image_header_t *)addr; - if ((new_id = fpga_get_version(fpga, (char *)(hdr->ih_name))) == -1) + if ((new_id = fpga_get_version(fpga, image_get_name (hdr))) == -1) return 1; do_load = 1; diff --git a/board/trab/auto_update.c b/board/trab/auto_update.c index 54d3645..bd9ee0c 100644 --- a/board/trab/auto_update.c +++ b/board/trab/auto_update.c @@ -209,20 +209,16 @@ int au_check_cksum_valid(int idx, long nbytes) { image_header_t *hdr; - unsigned long checksum; hdr = (image_header_t *)LOAD_ADDR; - if (nbytes != (sizeof(*hdr) + ntohl(hdr->ih_size))) + if (nbytes != image_get_image_size (hdr)) { printf ("Image %s bad total SIZE\n", aufile[idx]); return -1; } /* check the data CRC */ - checksum = ntohl(hdr->ih_dcrc); - - if (crc32 (0, (uchar *)(LOAD_ADDR + sizeof(*hdr)), ntohl(hdr->ih_size)) - != checksum) + if (!image_check_dcrc (hdr)) { { printf ("Image %s bad data checksum\n", aufile[idx]); return -1; @@ -241,50 +237,46 @@ au_check_header_valid(int idx, long nbytes) /* check the easy ones first */ #undef CHECK_VALID_DEBUG #ifdef CHECK_VALID_DEBUG - printf("magic %#x %#x ", ntohl(hdr->ih_magic), IH_MAGIC); - printf("arch %#x %#x ", hdr->ih_arch, IH_CPU_ARM); - printf("size %#x %#lx ", ntohl(hdr->ih_size), nbytes); - printf("type %#x %#x ", hdr->ih_type, IH_TYPE_KERNEL); + printf("magic %#x %#x ", image_get_magic (hdr), IH_MAGIC); + printf("arch %#x %#x ", image_get_arch (hdr), IH_ARCH_ARM); + printf("size %#x %#lx ", image_get_data_size (hdr), nbytes); + printf("type %#x %#x ", image_get_type (hdr), IH_TYPE_KERNEL); #endif - if (nbytes < sizeof(*hdr)) + if (nbytes < image_get_header_size ()) { printf ("Image %s bad header SIZE\n", aufile[idx]); return -1; } - if (ntohl(hdr->ih_magic) != IH_MAGIC || hdr->ih_arch != IH_CPU_ARM) + if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_ARM)) { printf ("Image %s bad MAGIC or ARCH\n", aufile[idx]); return -1; } /* check the hdr CRC */ - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(*hdr)) != checksum) { + if (!image_check_hcrc (hdr)) { printf ("Image %s bad header checksum\n", aufile[idx]); return -1; } - hdr->ih_hcrc = htonl(checksum); /* check the type - could do this all in one gigantic if() */ - if ((idx == IDX_FIRMWARE) && (hdr->ih_type != IH_TYPE_FIRMWARE)) { + if ((idx == IDX_FIRMWARE) && !image_check_type (hdr, IH_TYPE_FIRMWARE)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_KERNEL) && (hdr->ih_type != IH_TYPE_KERNEL)) { + if ((idx == IDX_KERNEL) && !image_check_type (hdr, IH_TYPE_KERNEL)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_DISK) && (hdr->ih_type != IH_TYPE_FILESYSTEM)) { + if ((idx == IDX_DISK) && !image_check_type (hdr, IH_TYPE_FILESYSTEM)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } - if ((idx == IDX_APP) && (hdr->ih_type != IH_TYPE_RAMDISK) - && (hdr->ih_type != IH_TYPE_FILESYSTEM)) { + if ((idx == IDX_APP) && !image_check_type (hdr, IH_TYPE_RAMDISK) + && !image_check_type (hdr, FILESYSTEM)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; } if ((idx == IDX_PREPARE || idx == IDX_PREINST || idx == IDX_POSTINST) - && (hdr->ih_type != IH_TYPE_SCRIPT)) + && !image_check_type (hdr, IH_TYPE_SCRIPT)) { printf ("Image %s wrong type\n", aufile[idx]); return -1; @@ -293,10 +285,10 @@ au_check_header_valid(int idx, long nbytes) if (idx == IDX_PREPARE) return 0; /* recycle checksum */ - checksum = ntohl(hdr->ih_size); + checksum = image_get_data_size (hdr); /* for kernel and app the image header must also fit into flash */ if ((idx != IDX_DISK) && (idx != IDX_FIRMWARE)) - checksum += sizeof(*hdr); + checksum += image_get_header_size (); /* check the size does not exceed space in flash. HUSH scripts */ /* all have ausize[] set to 0 */ if ((ausize[idx] != 0) && (ausize[idx] < checksum)) { @@ -310,10 +302,10 @@ au_check_header_valid(int idx, long nbytes) printf ("buf[0] %#x buf[1] %#x buf[2] %#x buf[3] %#x " "as int %#x time %#x\n", buf[0], buf[1], buf[2], buf[3], - *((unsigned int *)buf), ntohl(hdr->ih_time)); + *((unsigned int *)buf), image_get_time (hdr)); #endif /* check it */ - if (*((unsigned int *)buf) >= ntohl(hdr->ih_time)) { + if (*((unsigned int *)buf) >= image_get_time (hdr)) { printf ("Image %s is too old\n", aufile[idx]); return -1; } @@ -340,11 +332,11 @@ au_do_update(int idx, long sz) *CPLD_VFD_BK |= POWER_OFF; /* execute a script */ - if (hdr->ih_type == IH_TYPE_SCRIPT) { - addr = (char *)((char *)hdr + sizeof(*hdr)); + if (image_check_type (hdr, IH_TYPE_SCRIPT)) { + addr = (char *)((char *)hdr + image_get_header_size ()); /* stick a NULL at the end of the script, otherwise */ /* parse_string_outer() runs off the end. */ - addr[ntohl(hdr->ih_size)] = 0; + addr[image_get_data_size (hdr)] = 0; addr += 8; parse_string_outer(addr, FLAG_PARSE_SEMICOLON); return 0; @@ -372,19 +364,20 @@ au_do_update(int idx, long sz) flash_sect_erase(start, end); wait_ms(100); /* strip the header - except for the kernel and ramdisk */ - if (hdr->ih_type == IH_TYPE_KERNEL || hdr->ih_type == IH_TYPE_RAMDISK) { + if (image_check_type (hdr, IH_TYPE_KERNEL) || + image_check_type (hdr, IH_TYPE_RAMDISK)) { addr = (char *)hdr; - off = sizeof(*hdr); - nbytes = sizeof(*hdr) + ntohl(hdr->ih_size); + off = image_get_header_size (); + nbytes = image_get_image_size (hdr); } else { - addr = (char *)((char *)hdr + sizeof(*hdr)); + addr = (char *)((char *)hdr + image_get_header_size ()); #ifdef AU_UPDATE_TEST /* copy it to where Linux goes */ if (idx == IDX_FIRMWARE) start = aufl_layout[1].start; #endif off = 0; - nbytes = ntohl(hdr->ih_size); + nbytes = image_get_data_size (hdr); } /* copy the data from RAM to FLASH */ @@ -396,7 +389,8 @@ au_do_update(int idx, long sz) } /* check the dcrc of the copy */ - if (crc32 (0, (uchar *)(start + off), ntohl(hdr->ih_size)) != ntohl(hdr->ih_dcrc)) { + if (crc32 (0, (uchar *)(start + off), image_get_data_size (hdr)) != + image_get_dcrc (hdr)) { printf ("Image %s Bad Data Checksum After COPY\n", aufile[idx]); return -1; } @@ -425,15 +419,15 @@ au_update_eeprom(int idx) hdr = (image_header_t *)LOAD_ADDR; /* write the time field into EEPROM */ off = auee_off[idx].time; - val = ntohl(hdr->ih_time); + val = image_get_time (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* write the size field into EEPROM */ off = auee_off[idx].size; - val = ntohl(hdr->ih_size); + val = image_get_data_size (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* write the dcrc field into EEPROM */ off = auee_off[idx].dcrc; - val = ntohl(hdr->ih_dcrc); + val = image_get_dcrc (hdr); i2c_write_multiple(0x54, off, 1, &val, sizeof(val)); /* enable the power switch */ *CPLD_VFD_BK &= ~POWER_OFF; @@ -577,10 +571,10 @@ do_auto_update(void) /* just loop thru all the possible files */ for (i = 0; i < AU_MAXFILES; i++) { /* just read the header */ - sz = file_fat_read(aufile[i], LOAD_ADDR, sizeof(image_header_t)); + sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ()); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz < sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz < image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } @@ -590,8 +584,8 @@ do_auto_update(void) } sz = file_fat_read(aufile[i], LOAD_ADDR, MAX_LOADSZ); debug ("read %s sz %ld hdr %d\n", - aufile[i], sz, sizeof(image_header_t)); - if (sz <= 0 || sz <= sizeof(image_header_t)) { + aufile[i], sz, image_get_header_size ()); + if (sz <= 0 || sz <= image_get_header_size ()) { debug ("%s not found\n", aufile[i]); continue; } diff --git a/common/Makefile b/common/Makefile index a88d1ef..fc84222 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-y += cmd_bootm.o COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o @@ -91,6 +93,7 @@ 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 diff --git a/common/cmd_autoscript.c b/common/cmd_autoscript.c index a6038a6..53f8e83 100644 --- a/common/cmd_autoscript.c +++ b/common/cmd_autoscript.c @@ -49,56 +49,44 @@ #if defined(CONFIG_AUTOSCRIPT) || defined(CONFIG_CMD_AUTOSCRIPT) -extern image_header_t header; /* from cmd_bootm.c */ int autoscript (ulong addr) { - ulong crc, data, len; - image_header_t *hdr = &header; - ulong *len_ptr; + ulong len; + image_header_t *hdr = (image_header_t *)addr; + ulong *data; char *cmd; int rcode = 0; int verify; - cmd = getenv ("verify"); - verify = (cmd && (*cmd == 'n')) ? 0 : 1; + verify = getenv_verify (); - - memmove (hdr, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_check_magic (hdr)) { puts ("Bad magic number\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) { + if (!image_check_hcrc (hdr)) { puts ("Bad header crc\n"); return 1; } - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - if (verify) { - if (crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { + if (!image_check_dcrc (hdr)) { puts ("Bad data crc\n"); return 1; } } - if (hdr->ih_type != IH_TYPE_SCRIPT) { + if (!image_check_type (hdr, IH_TYPE_SCRIPT)) { puts ("Bad image type\n"); return 1; } /* get length of script */ - len_ptr = (ulong *)data; + data = (ulong *)image_get_data (hdr); - if ((len = ntohl(*len_ptr)) == 0) { + if ((len = image_to_cpu (*data)) == 0) { puts ("Empty Script\n"); return 1; } @@ -109,10 +97,10 @@ autoscript (ulong addr) return 1; } - while (*len_ptr++); + while (*data++); /* make sure cmd is null terminated */ - memmove (cmd, (char *)len_ptr, len); + memmove (cmd, (char *)data, len); *(cmd + len) = 0; #ifdef CFG_HUSH_PARSER /*?? */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 9546729..2ddb191 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -21,6 +21,8 @@ * MA 02111-1307 USA */ +#define DEBUG + /* * Boot support */ @@ -34,20 +36,6 @@ #include <environment.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 @@ -56,31 +44,20 @@ extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); #include <hush.h> #endif -#ifdef CFG_INIT_RAM_LOCK -#include <asm/cache.h> -#endif - -#ifdef CONFIG_LOGBUFFER -#include <logbuff.h> -#endif - #ifdef CONFIG_HAS_DATAFLASH #include <dataflash.h> #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) -#endif +DECLARE_GLOBAL_DATA_PTR; -int gunzip (void *, int, unsigned char *, unsigned long *); +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 -static void *zalloc(void *, unsigned, unsigned); -static void zfree(void *, void *, unsigned); +#ifdef CONFIG_BZIP2 +extern void bz_internal_error(int); +#endif #if defined(CONFIG_CMD_IMI) static int image_info (unsigned long addr); @@ -92,12 +69,16 @@ 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 __I386__ -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux (void); #endif +static void print_type (image_header_t *hdr); +static image_header_t *get_kernel (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], int verify, + 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,195 +87,54 @@ 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; -#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; +typedef void boot_os_fn (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, /* of image to boot */ + int verify); /* getenv("verify")[0] != 'n' */ + +extern boot_os_fn do_bootm_linux; +static boot_os_fn do_bootm_netbsd; +#if defined(CONFIG_LYNXKDI) +static boot_os_fn do_bootm_lynxkdi; +extern void lynxkdi_boot (image_header_t *); +#endif +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 */ -image_header_t header; - -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; + int verify = getenv_verify(); - s = getenv ("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + image_header_t *hdr; + ulong os_data, os_len; - if (argc < 2) { - addr = load_addr; - } else { - addr = simple_strtoul(argv[1], NULL, 16); - } + ulong image_start, image_end; + ulong load_start, load_end; - show_boot_progress (1); - printf ("## Booting image at %08lx ...\n", addr); - - /* 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); - - 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"); - show_boot_progress (-2); - return 1; - } - show_boot_progress (3); - -#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; - } -#endif - - - /* 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); - - if (verify) { - puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-3); - 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); + /* get kernel image header, start address and length */ + hdr = get_kernel (cmdtp, flag, argc, argv, verify, + &os_data, &os_len); + if (hdr == NULL) 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)); - } - 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); - return 1; - } show_boot_progress (6); /* @@ -302,7 +142,6 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * overwrite all exception vector code, so we cannot easily * recover from any failures any more... */ - iflag = disable_interrupts(); #ifdef CONFIG_AMIGAONEG3SE @@ -316,138 +155,115 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) dcache_disable(); #endif - switch (hdr->ih_comp) { + type_name = image_get_type_name (image_get_type (hdr)); + + image_start = (ulong)hdr; + image_end = image_get_image_end (hdr); + load_start = image_get_load (hdr); + load_end = 0; + + switch (image_get_comp (hdr)) { case IH_COMP_NONE: - if(ntohl(hdr->ih_load) == addr) { - printf (" XIP %s ... ", name); + if (image_get_load (hdr) == (ulong)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 *)image_get_load (hdr), + (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) { + printf (" Uncompressing %s ... ", type_name); + if (gunzip ((void *)image_get_load (hdr), unc_len, + (uchar *)os_data, &os_len) != 0) { puts ("GUNZIP ERROR - must RESET board to recover\n"); show_boot_progress (-6); do_reset (cmdtp, flag, argc, argv); } + + 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*)image_get_load (hdr), + &unc_len, (char *)os_data, os_len, + CFG_MALLOC_LEN < (4096 * 1024), 0); if (i != BZ_OK) { printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); show_boot_progress (-6); 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", image_get_comp (hdr)); 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"); + do_reset (cmdtp, flag, argc, argv); } + show_boot_progress (8); - switch (hdr->ih_os) { + switch (image_get_os (hdr)) { 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, hdr, verify); break; + case IH_OS_NETBSD: - do_bootm_netbsd (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_netbsd (cmdtp, flag, argc, argv, hdr, verify); break; #ifdef CONFIG_LYNXKDI case IH_OS_LYNXOS: - do_bootm_lynxkdi (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_lynxkdi (cmdtp, flag, argc, argv, hdr, verify); break; #endif case IH_OS_RTEMS: - do_bootm_rtems (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_rtems (cmdtp, flag, argc, argv, hdr, verify); break; #if defined(CONFIG_CMD_ELF) case IH_OS_VXWORKS: - do_bootm_vxworks (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_vxworks (cmdtp, flag, argc, argv, hdr, verify); break; + case IH_OS_QNX: - do_bootm_qnxelf (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_qnxelf (cmdtp, flag, argc, argv, hdr, verify); break; #endif + #ifdef CONFIG_ARTOS case IH_OS_ARTOS: - do_bootm_artos (cmdtp, flag, argc, argv, - addr, len_ptr, verify); + do_bootm_artos (cmdtp, flag, argc, argv, hdr, verify); break; #endif } @@ -460,866 +276,195 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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 () +/** + * 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 + * + * 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 image_header_t *get_kernel (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], int verify, + ulong *os_data, ulong *os_len) { - char buf[256], *start, *end; - char *cmdline = getenv ("bootargs"); + image_header_t *hdr; + ulong img_addr; - /* 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="); - } + if (argc < 2) { + img_addr = load_addr; } else { - strcpy (buf, "console="); - } - - setenv ("bootargs", buf); - debug ("after silent fix-up: %s\n", buf); -} -#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) -{ - 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 - - 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; + img_addr = simple_strtoul(argv[1], NULL, 16); } -#ifdef CONFIG_LOGBUFFER - kbd=gd->bd; - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD)) - initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD; - debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN); -#endif - - /* - * 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); - -#ifdef DEBUG - printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); + show_boot_progress (1); + printf ("## Booting image at %08lx ...\n", img_addr); - do_bdinfo (NULL, 0, 0, NULL); +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (img_addr)){ + hdr = (image_header_t *)CFG_LOAD_ADDR; + read_dataflash (img_addr, image_get_header_size (), (char *)hdr); + } else #endif + hdr = (image_header_t *)img_addr; - 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; -#endif -#if defined(CONFIG_MPC5xxx) - kbd->bi_ipbfreq /= 1000000L; - kbd->bi_pcifreq /= 1000000L; -#endif /* CONFIG_MPC5xxx */ + if (!image_check_magic(hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-1); + return NULL; } + show_boot_progress (2); - kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong)) ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - -#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; - } - else -#endif - if (argc >= 3) { - debug ("Not skipping initrd\n"); - show_boot_progress (9); - - addr = simple_strtoul(argv[2], NULL, 16); - - 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); - } - - 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"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - 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 */ - - puts (" Verifying Checksum ... "); - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - - while (cdata < edata) { - ulong chunk = edata - cdata; - - if (chunk > CHUNKSZ) - chunk = CHUNKSZ; - csum = crc32 (csum, (uchar *)cdata, chunk); - cdata += chunk; - - 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"); - } - - show_boot_progress (11); - - 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); - } - - /* - * 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; - } - - len = ntohl(len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - len = data = 0; + if (!image_check_hcrc (hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-2); + return NULL; } + show_boot_progress (3); -#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); - } - - puts (" Verifying Checksum ... "); - memmove (&header, (char *)hdr, sizeof(image_header_t)); - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; - - 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); - } - - checksum = ntohl(hdr->ih_dcrc); - addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t)); - - 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 (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); - } - - 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; - } - - /* 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; - } - -#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; -#endif - - -#if defined(CONFIG_OF_FLAT_TREE) - if (*((ulong *)(of_flat_tree)) != OF_DT_HEADER) { -#else - if (fdt_check_header (of_flat_tree) != 0) { -#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); - } - } +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (img_addr)) + read_dataflash (img_addr + image_get_header_size (), + image_get_data_size (hdr), + (char *)image_get_data (hdr)); #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 */ - - if (initrd_high) { - ulong nsp; - - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * 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; - } - - 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; - } - } -#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; - } -#if defined(CONFIG_OF_LIBFDT) + /* uImage is in a system RAM, pointed to by hdr */ + print_image_hdr (hdr); -#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) { - 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); + if (verify) { + puts (" Verifying Checksum ... "); + if (!image_check_dcrc (hdr)) { + printf ("Bad Data CRC\n"); + show_boot_progress (-3); + return NULL; } 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); - } -#endif -#ifdef CONFIG_OF_BOARD_SETUP - /* Call the board-specific fixup routine */ - ft_board_setup(of_flat_tree, gd->bd); -#endif - } -#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); - - show_boot_progress (15); - -#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) - unlock_ram_in_cache(); -#endif + show_boot_progress (4); -#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 */ + if (!image_check_target_arch (hdr)) { + printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr)); + show_boot_progress (-4); + return NULL; } -#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; - - - /* - * Booting a (NetBSD) kernel image - * - * This process is pretty similar to a standalone application: - * The (first part of an multi-) image must be a stage-2 loader, - * which in turn is responsible for loading & invoking the actual - * kernel. The only differences are the parameters being passed: - * besides the board info strucure, the loader expects a command - * 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; - - - consdev = ""; -#if defined (CONFIG_8xx_CONS_SMC1) - consdev = "smc1"; -#elif defined (CONFIG_8xx_CONS_SMC2) - consdev = "smc2"; -#elif defined (CONFIG_8xx_CONS_SCC2) - consdev = "scc2"; -#elif defined (CONFIG_8xx_CONS_SCC3) - consdev = "scc3"; -#endif - - if (argc > 2) { - ulong len; - int i; - - for (i=2, len=0 ; i<argc ; i+=1) - len += strlen (argv[i]) + 1; - cmdline = malloc (len); + show_boot_progress (5); - 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) { - cmdline = ""; + 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; } + debug (" kernel data at 0x%08lx, end = 0x%08lx\n", + *os_data, *os_data + *os_len); - loader = (void (*)(bd_t *, image_header_t *, char *, char *)) ntohl(hdr->ih_ep); - - printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", - (ulong)loader); - - show_boot_progress (15); - - /* - * NetBSD Stage-2 Loader Parameters: - * r3: ptr to board info data - * r4: image address - * r5: console device - * r6: boot args string - */ - (*loader) (gd->bd, img_addr, consdev, cmdline); + return hdr; } -#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) - -/* Function that returns a character from the environment */ -extern uchar (*env_get_char)(int); - -static void -do_bootm_artos (cmd_tbl_t *cmdtp, int flag, - int argc, char *argv[], - ulong addr, - ulong *len_ptr, - int verify) -{ - ulong top; - char *s, *cmdline; - char **fwenv, **ss; - int i, j, nxt, len, envno, envsz; - bd_t *kbd; - void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); - image_header_t *hdr = &header; - - /* - * Booting an ARTOS kernel image + application - */ - - /* this used to be the top of memory, but was wrong... */ -#ifdef CONFIG_PPC - /* get stack pointer */ - asm volatile ("mr %0,1" : "=r"(top) ); -#endif - debug ("## Current stack ends at 0x%08lX ", top); - - top -= 2048; /* just to be sure */ - if (top > CFG_BOOTMAPSZ) - top = CFG_BOOTMAPSZ; - top &= ~0xF; - - 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) - s = ""; - - /* get length of cmdline, and place it */ - len = strlen(s); - top = (top - (len + 1)) & ~0xF; - cmdline = (char *)top; - debug ("## cmdline at 0x%08lX ", top); - strcpy(cmdline, s); - - /* copy bdinfo */ - top = (top - sizeof(bd_t)) & ~0xF; - debug ("## bd at 0x%08lX ", top); - kbd = (bd_t *)top; - 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) - ; - envno++; - envsz += (nxt - i) + 1; /* plus trailing zero */ - } - envno++; /* plus the terminating zero */ - debug ("## %u envvars total size %u ", envno, envsz); - - top = (top - sizeof(char **)*envno) & ~0xF; - fwenv = (char **)top; - debug ("## fwenv at 0x%08lX ", top); - - top = (top - envsz) & ~0xF; - s = (char *)top; - 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) - ; - *ss++ = s; - for (j = i; j < nxt; ++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); -} +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 +); - +/*******************************************************************/ +/* 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; + #ifndef CFG_HUSH_PARSER - if (run_command (getenv ("bootcmd"), flag) < 0) rcode = 1; + 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; + 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", + 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", + bootd, 1, 1, do_bootd, + "bootd - boot default, i.e., run 'bootcmd'\n", NULL ); #endif + +/*******************************************************************/ +/* 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 do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int arg; ulong addr; - int rcode=0; + 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; + 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; + image_header_t *hdr = (image_header_t *)addr; 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) { + if (!image_check_magic (hdr)) { 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) { + if (!image_check_hcrc (hdr)) { 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); + print_image_hdr (hdr); puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { + if (!image_check_dcrc (hdr)) { puts (" Bad Data CRC\n"); return 1; } @@ -1335,50 +480,43 @@ U_BOOT_CMD( " address 'addr' in memory; this includes verification of the\n" " image contents (magic number, header and payload checksums)\n" ); - #endif + +/*******************************************************************/ +/* imls - list all images found in flash */ +/*******************************************************************/ #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) { + 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; + for (j = 0; j < info->sector_count; ++j) { - /* Copy header so we can blank CRC field for re-calculation */ - memmove (&header, (char *)hdr, sizeof(image_header_t)); + hdr = (image_header_t *)info->start[j]; - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; + if (!hdr || !image_check_magic (hdr)) + goto next_sector; - if (crc32 (0, (uchar *)&header, sizeof(image_header_t)) - != checksum) + if (!image_check_hcrc (hdr)) 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); + print_image_hdr (hdr); puts (" Verifying Checksum ... "); - if (crc32 (0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)) { - puts (" Bad Data CRC\n"); + if (!image_check_dcrc (hdr)) { + puts ("Bad Data CRC\n"); + } else { + puts ("OK\n"); } - puts ("OK\n"); next_sector: ; } next_bank: ; @@ -1396,205 +534,187 @@ U_BOOT_CMD( ); #endif -void -print_image_hdr (image_header_t *hdr) +/*******************************************************************/ +/* helper routines */ +/*******************************************************************/ +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); + time_t timestamp = (time_t)image_get_time (hdr); struct rtc_time tm; #endif - printf (" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); + printf (" Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); + #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) to_tm (timestamp, &tm); printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); #endif - puts (" Image Type: "); print_type(hdr); - printf ("\n Data Size: %d Bytes = ", ntohl(hdr->ih_size)); - print_size (ntohl(hdr->ih_size), "\n"); + puts (" Image Type: "); + print_type (hdr); + + printf ("\n Data Size: %d Bytes = ", image_get_data_size (hdr)); + print_size (image_get_data_size (hdr), "\n"); printf (" Load Address: %08x\n" " Entry Point: %08x\n", - ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); + image_get_load (hdr), image_get_ep (hdr)); - if (hdr->ih_type == IH_TYPE_MULTI) { + if (image_check_type (hdr, IH_TYPE_MULTI)) { int i; - ulong len; - ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); + ulong data, len; + ulong count = image_multi_count (hdr); puts (" Contents:\n"); - for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { + for (i = 0; i < count; i++) { + image_multi_getimg (hdr, i, &data, &len); printf (" Image %d: %8ld Bytes = ", i, len); print_size (len, "\n"); } } } - -static void -print_type (image_header_t *hdr) +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; - } + const char *os, *arch, *type, *comp; - 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; - } + os = image_get_os_name (image_get_os (hdr)); + arch = image_get_arch_name (image_get_arch (hdr)); + type = image_get_type_name (image_get_type (hdr)); + comp = image_get_comp_name (image_get_comp (hdr)); printf ("%s %s %s (%s)", arch, os, type, comp); } -#define ZALLOC_ALIGNMENT 16 - -static void *zalloc(void *x, unsigned items, unsigned size) +#ifdef CONFIG_SILENT_CONSOLE +static void fixup_silent_linux () { - void *p; - - size *= items; - size = (size + ZALLOC_ALIGNMENT - 1) & ~(ZALLOC_ALIGNMENT - 1); + char buf[256], *start, *end; + char *cmdline = getenv ("bootargs"); - p = malloc (size); + /* Only fix cmdline when requested */ + if (!(gd->flags & GD_FLG_SILENT)) + return; - return (p); -} + 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="); + } + } else { + strcpy (buf, "console="); + } -static void zfree(void *x, void *addr, unsigned nb) -{ - free (addr); + setenv ("bootargs", buf); + debug ("after silent fix-up: %s\n", buf); } +#endif /* CONFIG_SILENT_CONSOLE */ -#define HEAD_CRC 2 -#define EXTRA_FIELD 4 -#define ORIG_NAME 8 -#define COMMENT 0x10 -#define RESERVED 0xe0 -#define DEFLATED 8 +/*******************************************************************/ +/* OS booting routines */ +/*******************************************************************/ -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - 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); - } + void (*loader)(bd_t *, image_header_t *, char *, char *); + image_header_t *img_addr; + ulong kernel_data, kernel_len; + char *consdev; + char *cmdline; - 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 */ + /* + * Booting a (NetBSD) kernel image + * + * This process is pretty similar to a standalone application: + * The (first part of an multi-) image must be a stage-2 loader, + * which in turn is responsible for loading & invoking the actual + * kernel. The only differences are the parameters being passed: + * besides the board info strucure, the loader expects a command + * line, the name of the console device, and (optionally) the + * address of the original image header. + */ - r = inflateInit2(&s, -MAX_WBITS); - if (r != Z_OK) { - printf ("Error: inflateInit2() returned %d\n", r); - return (-1); + img_addr = 0; + if (image_check_type (hdr, IH_TYPE_MULTI)) { + image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); + if (kernel_len) + img_addr = hdr; } - 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); + + consdev = ""; +#if defined (CONFIG_8xx_CONS_SMC1) + consdev = "smc1"; +#elif defined (CONFIG_8xx_CONS_SMC2) + consdev = "smc2"; +#elif defined (CONFIG_8xx_CONS_SCC2) + consdev = "scc2"; +#elif defined (CONFIG_8xx_CONS_SCC3) + consdev = "scc3"; +#endif + + if (argc > 2) { + ulong len; + int i; + + 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) { + if (i > 2) + cmdline[len++] = ' '; + strcpy (&cmdline[len], argv[i]); + len += strlen (argv[i]); + } + } else if ((cmdline = getenv ("bootargs")) == NULL) { + cmdline = ""; } - *lenp = s.next_out - (unsigned char *) dst; - inflateEnd(&s); - return (0); + 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); + + show_boot_progress (15); + + /* + * NetBSD Stage-2 Loader Parameters: + * r3: ptr to board info data + * r4: image address + * r5: console device + * r6: boot args string + */ + (*loader) (gd->bd, img_addr, consdev, cmdline); } -#ifdef CONFIG_BZIP2 -void bz_internal_error(int errcode) +#ifdef CONFIG_LYNXKDI +static void do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - printf ("BZIP2 internal error %d\n", errcode); + lynxkdi_boot (hdr); } -#endif /* CONFIG_BZIP2 */ +#endif /* CONFIG_LYNXKDI */ -static void -do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) +static void do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; - void (*entry_point)(bd_t *); + void (*entry_point)(bd_t *); - entry_point = (void (*)(bd_t *)) ntohl(hdr->ih_ep); + entry_point = (void (*)(bd_t *))image_get_ep (hdr); printf ("## Transferring control to RTEMS (at address %08lx) ...\n", (ulong)entry_point); @@ -1605,47 +725,114 @@ do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], * RTEMS Parameters: * r3: ptr to board info data */ - - (*entry_point ) ( gd->bd ); + (*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) +static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; char str[80]; - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ + 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[], - ulong addr, ulong *len_ptr, int verify) +static void do_bootm_qnxelf(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; char *local_args[2]; char str[16]; - sprintf(str, "%x", ntohl(hdr->ih_ep)); /* write entry-point into string */ + 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 -#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) +#if defined(CONFIG_ARTOS) && defined(CONFIG_PPC) +static void do_bootm_artos (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) { - lynxkdi_boot( &header ); -} + ulong top; + char *s, *cmdline; + char **fwenv, **ss; + int i, j, nxt, len, envno, envsz; + bd_t *kbd; + void (*entry)(bd_t *bd, char *cmdline, char **fwenv, ulong top); -#endif /* CONFIG_LYNXKDI */ + /* + * Booting an ARTOS kernel image + application + */ + + /* this used to be the top of memory, but was wrong... */ +#ifdef CONFIG_PPC + /* get stack pointer */ + asm volatile ("mr %0,1" : "=r"(top) ); +#endif + debug ("## Current stack ends at 0x%08lX ", top); + + top -= 2048; /* just to be sure */ + if (top > CFG_BOOTMAPSZ) + top = CFG_BOOTMAPSZ; + top &= ~0xF; + + 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) + s = ""; + + /* get length of cmdline, and place it */ + len = strlen (s); + top = (top - (len + 1)) & ~0xF; + cmdline = (char *)top; + debug ("## cmdline at 0x%08lX ", top); + strcpy (cmdline, s); + + /* copy bdinfo */ + top = (top - sizeof (bd_t)) & ~0xF; + debug ("## bd at 0x%08lX ", top); + kbd = (bd_t *)top; + 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) + ; + envno++; + envsz += (nxt - i) + 1; /* plus trailing zero */ + } + envno++; /* plus the terminating zero */ + debug ("## %u envvars total size %u ", envno, envsz); + + top = (top - sizeof (char **) * envno) & ~0xF; + fwenv = (char **)top; + debug ("## fwenv at 0x%08lX ", top); + + top = (top - envsz) & ~0xF; + s = (char *)top; + 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) + ; + *ss++ = s; + for (j = i; j < nxt; ++j) + *s++ = env_get_char (j); + *s++ = '\0'; + } + *ss++ = NULL; /* terminate */ + + entry = (void (*)(bd_t *, char *, char **, ulong))image_get_ep (hdr); + (*entry) (kbd, cmdline, fwenv, top); +} +#endif diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 3d717c0..b20a2e1 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -263,11 +263,11 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (hdr->ih_magic == IH_MAGIC) { + if (image_check_magic (hdr)) { print_image_hdr (hdr); - cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt = image_get_image_size (hdr); cnt -= SECTORSIZE; } else { puts ("\n** Bad Magic Number **\n"); diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 7349412..3b8f80b 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -836,13 +836,13 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_get_magic (hdr)) { printf ("Bad Magic Number\n"); return 1; } - print_image_hdr(hdr); + print_image_hdr (hdr); - imsize= ntohl(hdr->ih_size)+sizeof(image_header_t); + imsize= image_get_image_size (hdr); nrofblk=imsize/512; if((imsize%512)>0) nrofblk++; @@ -861,7 +861,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* Loading ok, update default load address */ load_addr = addr; - if(hdr->ih_type == IH_TYPE_KERNEL) { + if(image_check_type (hdr, IH_TYPE_KERNEL)) { /* Check if we should attempt an auto-start */ if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { char *local_args[2]; diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index f55447a..4030d04 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -221,13 +221,13 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr = &header; ulong data; - memmove (&header, (char *)fpga_data, sizeof(image_header_t)); - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + memmove (&header, (char *)fpga_data, image_get_header_size ()); + if (!image_check_magic (hdr)) { puts ("Bad Magic Number\n"); return 1; } - data = ((ulong)fpga_data + sizeof(image_header_t)); - data_size = ntohl(hdr->ih_size); + data = ((ulong)fpga_data + image_get_header_size ()); + data_size = image_get_data_size (hdr); rc = fpga_load (dev, (void *)data, data_size); } break; diff --git a/common/cmd_ide.c b/common/cmd_ide.c index c38be4f..bcd1325 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -366,7 +366,7 @@ 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; @@ -448,27 +448,23 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_check_magic (hdr)) { printf("\n** Bad Magic Number **\n"); show_boot_progress (-49); return 1; } show_boot_progress (49); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { + if (!image_check_hcrc (hdr)) { puts ("\n** Bad Header Checksum **\n"); show_boot_progress (-50); 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 = image_get_image_size (hdr); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 8d6c959..bfa39d7 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -514,16 +514,16 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, hdr = (image_header_t *) addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + if (!image_check_magic (hdr)) { + printf("\n** Bad Magic Number 0x%x **\n", image_get_magic (hdr)); show_boot_progress (-57); return 1; } show_boot_progress (57); - print_image_hdr(hdr); + print_image_hdr (hdr); - cnt = (ntohl(hdr->ih_size) + sizeof (image_header_t)); + cnt = image_get_image_size (hdr); if (jffs2) { nand_read_options_t opts; memset(&opts, 0, sizeof(opts)); @@ -982,14 +982,14 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) == IH_MAGIC) { + if (image_check_magic (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)); + printf ("\n** Bad Magic Number 0x%x **\n", image_get_magic (hdr)); show_boot_progress (-57); return 1; } diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 1cdec15..c2b27a5 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -207,7 +207,7 @@ 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; @@ -275,22 +275,18 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) == IH_MAGIC) { + if (!image_check_magic (hdr)) { printf("\n** Bad Magic Number **\n"); return 1; } - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { + if (!image_check_hcrc (hdr)) { puts ("\n** Bad Header Checksum **\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 = image_get_image_size (hdr); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; diff --git a/common/cmd_usb.c b/common/cmd_usb.c index c6b17c2..db2e754 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -311,7 +311,7 @@ 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; @@ -388,23 +388,19 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) hdr = (image_header_t *)addr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_get_magic (hdr)) { printf("\n** Bad Magic Number **\n"); return 1; } - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *)hdr, sizeof(image_header_t)) != checksum) { + if (!image_check_hcrc (hdr)) { puts ("\n** Bad Header Checksum **\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 = image_get_image_size (hdr); cnt += info.blksz - 1; cnt /= info.blksz; cnt -= 1; diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 52e0614..ab579cd 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -38,14 +38,13 @@ int do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { ulong addr = load_addr, dest = 0; - ulong data, len, checksum; + ulong data, len; ulong *len_ptr; int i, verify, part = 0; char pbuf[10], *s; - image_header_t header; + image_header_t *hdr; - s = getenv("verify"); - verify = (s && (*s == 'n')) ? 0 : 1; + verify = getenv_verify (); if (argc > 1) { addr = simple_strtoul(argv[1], NULL, 16); @@ -59,50 +58,41 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 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)); + hdr = (image_header_t *)addr; - if (ntohl(header.ih_magic) != IH_MAGIC) { + if (!image_check_magic (hdr)) { printf("Bad Magic Number\n"); return 1; } - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl(header.ih_hcrc); - header.ih_hcrc = 0; - - if (crc32(0, (char *) data, len) != checksum) { + if (!image_check_hcrc (hdr)) { printf("Bad Header Checksum\n"); return 1; } #ifdef DEBUG - print_image_hdr((image_header_t *) addr); + print_image_hdr (hdr); #endif - data = addr + sizeof (image_header_t); - len = ntohl(header.ih_size); - - if (header.ih_type != IH_TYPE_MULTI) { + if (!image_check_type (hdr, IH_TYPE_MULTI)) { printf("Wrong Image Type for %s command\n", cmdtp->name); return 1; } - if (header.ih_comp != IH_COMP_NONE) { + if (image_get_comp (hdr) != IH_COMP_NONE) { printf("Wrong Compression Type for %s command\n", cmdtp->name); return 1; } if (verify) { printf(" Verifying Checksum ... "); - if (crc32(0, (char *) data, len) != ntohl(header.ih_dcrc)) { + if (!image_check_dcrc (hdr)) { printf("Bad Data CRC\n"); return 1; } printf("OK\n"); } + data = image_get_data (hdr); len_ptr = (ulong *) data; data += 4; /* terminator */ @@ -110,7 +100,7 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) data += 4; if (argc > 2 && part > i) { u_long tail; - len = ntohl(len_ptr[i]); + len = image_to_cpu (len_ptr[i]); tail = len % 4; data += len; if (tail) { @@ -122,7 +112,7 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) printf("Bad Image Part\n"); return 1; } - len = ntohl(len_ptr[part]); + len = image_to_cpu (len_ptr[part]); if (argc > 3) { memcpy((char *) dest, (char *) data, len); 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..39e5f23 --- /dev/null +++ b/common/image.c @@ -0,0 +1,693 @@ +/* + * (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 + */ + +#define DEBUG + +#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 + +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#ifdef CONFIG_CMD_BDI +extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif + +DECLARE_GLOBAL_DATA_PTR; +#else +#include "mkimage.h" +#endif /* USE_HOSTCC*/ + +#include <image.h> + +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); + +int image_check_hcrc (image_header_t *hdr) +{ + ulong hcrc; + ulong len = image_get_header_size (); + image_header_t header; + + /* Copy header so we can blank CRC field for re-calculation */ + memmove (&header, (char *)hdr, image_get_header_size ()); + image_set_hcrc (&header, 0); + + hcrc = crc32 (0, (unsigned char *)&header, len); + + return (hcrc == image_get_hcrc (hdr)); +} + +int image_check_dcrc (image_header_t *hdr) +{ + ulong data = image_get_data (hdr); + ulong len = image_get_data_size (hdr); + ulong dcrc = crc32 (0, (unsigned char *)data, len); + + return (dcrc == image_get_dcrc (hdr)); +} + +#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)); +} + +int getenv_verify (void) +{ + char *s = getenv ("verify"); + return (s && (*s == 'n')) ? 0 : 1; +} + +void memmove_wd (void *to, void *from, size_t len, ulong chunksz) +{ +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + while (len > 0) { + size_t tail = (len > chunksz) ? chunksz : len; + WATCHDOG_RESET (); + memmove (to, from, tail); + to += tail; + from += tail; + len -= tail; + } +#else /* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ + memmove (to, from, len); +#endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ +} +#endif /* USE_HOSTCC */ + +/** + * image_multi_count - get component (sub-image) count + * @hdr: pointer to the header of the multi component image + * + * image_multi_count() returns number of components in a multi + * component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * number of components + */ +ulong image_multi_count (image_header_t *hdr) +{ + ulong i, count = 0; + ulong *size; + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (ulong *)image_get_data (hdr); + + /* count non empty slots */ + for (i = 0; size[i]; ++i) + count++; + + return count; +} + +/** + * image_multi_getimg - get component data address and size + * @hdr: pointer to the header of the multi component image + * @idx: index of the requested component + * @data: pointer to a ulong variable, will hold component data address + * @len: pointer to a ulong variable, will hold component size + * + * image_multi_getimg() returns size and data address for the requested + * component in a multi component image. + * + * Note: no checking of the image type is done, caller must pass + * a valid multi component image. + * + * returns: + * data address and size of the component, if idx is valid + * 0 in data and len, if idx is out of range + */ +void image_multi_getimg (image_header_t *hdr, ulong idx, + ulong *data, ulong *len) +{ + int i; + ulong *size; + ulong offset, tail, count, img_data; + + /* get number of component */ + count = image_multi_count (hdr); + + /* get start of the image payload, which in case of multi + * component images that points to a table of component sizes */ + size = (ulong *)image_get_data (hdr); + + /* get address of the proper component data start, which means + * skipping sizes table (add 1 for last, null entry) */ + img_data = image_get_data (hdr) + (count + 1) * sizeof (ulong); + + if (idx < count) { + *len = size[idx]; + offset = 0; + tail = 0; + + /* go over all indices preceding requested component idx */ + for (i = 0; i < idx; i++) { + /* add up i-th component size */ + offset += size[i]; + + /* add up alignment for i-th component */ + tail += (4 - size[i] % 4); + } + + /* calculate idx-th component data address */ + *data = img_data + offset + tail; + } else { + *len = 0; + *data = 0; + } +} + +#ifndef USE_HOSTCC +const char* image_get_os_name (uint8_t os) +{ + const char *name; + + switch (os) { + case IH_OS_INVALID: name = "Invalid OS"; break; + case IH_OS_NETBSD: name = "NetBSD"; break; + case IH_OS_LINUX: name = "Linux"; break; + case IH_OS_VXWORKS: name = "VxWorks"; break; + case IH_OS_QNX: name = "QNX"; break; + case IH_OS_U_BOOT: name = "U-Boot"; break; + case IH_OS_RTEMS: name = "RTEMS"; break; +#ifdef CONFIG_ARTOS + case IH_OS_ARTOS: name = "ARTOS"; break; +#endif +#ifdef CONFIG_LYNXKDI + case IH_OS_LYNXOS: name = "LynxOS"; break; +#endif + default: name = "Unknown OS"; break; + } + + return name; +} + +const char* image_get_arch_name (uint8_t arch) +{ + const char *name; + + switch (arch) { + case IH_ARCH_INVALID: name = "Invalid Architecture"; break; + case IH_ARCH_ALPHA: name = "Alpha"; break; + case IH_ARCH_ARM: name = "ARM"; break; + case IH_ARCH_AVR32: name = "AVR32"; break; + case IH_ARCH_BLACKFIN: name = "Blackfin"; break; + case IH_ARCH_I386: name = "Intel x86"; break; + case IH_ARCH_IA64: name = "IA64"; break; + case IH_ARCH_M68K: name = "M68K"; break; + case IH_ARCH_MICROBLAZE:name = "Microblaze"; break; + case IH_ARCH_MIPS64: name = "MIPS 64 Bit"; break; + case IH_ARCH_MIPS: name = "MIPS"; break; + case IH_ARCH_NIOS2: name = "Nios-II"; break; + case IH_ARCH_NIOS: name = "Nios"; break; + case IH_ARCH_PPC: name = "PowerPC"; break; + case IH_ARCH_S390: name = "IBM S390"; break; + case IH_ARCH_SH: name = "SuperH"; break; + case IH_ARCH_SPARC64: name = "SPARC 64 Bit"; break; + case IH_ARCH_SPARC: name = "SPARC"; break; + default: name = "Unknown Architecture"; break; + } + + return name; +} + +const char* image_get_type_name (uint8_t type) +{ + const char *name; + + switch (type) { + case IH_TYPE_INVALID: name = "Invalid Image"; break; + case IH_TYPE_STANDALONE:name = "Standalone Program"; break; + case IH_TYPE_KERNEL: name = "Kernel Image"; break; + case IH_TYPE_RAMDISK: name = "RAMDisk Image"; break; + case IH_TYPE_MULTI: name = "Multi-File Image"; break; + case IH_TYPE_FIRMWARE: name = "Firmware"; break; + case IH_TYPE_SCRIPT: name = "Script"; break; + case IH_TYPE_FLATDT: name = "Flat Device Tree"; break; + default: name = "Unknown Image"; break; + } + + return name; +} + +const char* image_get_comp_name (uint8_t comp) +{ + const char *name; + + switch (comp) { + case IH_COMP_NONE: name = "uncompressed"; break; + case IH_COMP_GZIP: name = "gzip compressed"; break; + case IH_COMP_BZIP2: name = "bzip2 compressed"; break; + default: name = "unknown compression"; break; + } + + return name; +} + +/** + * image_get_ramdisk - get and verify ramdisk image + * @cmdtp: command table pointer + * @flag: command flag + * @argc: command argument count + * @argv: command argument list + * @rd_addr: ramdisk image start address + * @arch: expected ramdisk architecture + * @verify: checksum verification flag + * + * image_get_ramdisk() returns a pointer to the verified ramdisk image + * header. Routine receives image start address and expected architecture + * flag. Verification done covers data and header integrity and os/type/arch + * fields checking. + * + * If dataflash support is enabled routine checks for dataflash addresses + * and handles required dataflash reads. + * + * returns: + * pointer to a ramdisk image header, if image was found and valid + * otherwise, board is reset + */ +image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong rd_addr, uint8_t arch, int verify) +{ + image_header_t *rd_hdr; + + show_boot_progress (9); + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (rd_addr)) { + rd_hdr = (image_header_t *)CFG_LOAD_ADDR; + debug (" Reading Ramdisk image header from dataflash address " + "%08lx to %08lx\n", rd_addr, (ulong)rd_hdr); + read_dataflash (rd_addr, image_get_header_size (), + (char *)rd_hdr); + } else +#endif + rd_hdr = (image_header_t *)rd_addr; + + if (!image_check_magic (rd_hdr)) { + puts ("Bad Magic Number\n"); + show_boot_progress (-10); + do_reset (cmdtp, flag, argc, argv); + } + + if (!image_check_hcrc (rd_hdr)) { + puts ("Bad Header Checksum\n"); + show_boot_progress (-11); + do_reset (cmdtp, flag, argc, argv); + } + + show_boot_progress (10); + print_image_hdr (rd_hdr); + +#ifdef CONFIG_HAS_DATAFLASH + if (addr_dataflash (rd_addr)) { + debug (" Reading Ramdisk image data from dataflash address " + "%08lx to %08lx\n", rd_addr + image_get_header_size, + (ulong)image_get_data (rd_hdr)); + + read_dataflash (rd_addr + image_get_header_size (), + image_get_data_size (rd_hdr), + (char *)image_get_data (rd_hdr)); + } +#endif + + if (verify) { + puts(" Verifying Checksum ... "); + if (!image_check_dcrc_wd (rd_hdr, CHUNKSZ)) { + puts ("Bad Data CRC\n"); + show_boot_progress (-12); + do_reset (cmdtp, flag, argc, argv); + } + puts("OK\n"); + } + + show_boot_progress (11); + + if (!image_check_os (rd_hdr, IH_OS_LINUX) || + !image_check_arch (rd_hdr, arch) || + !image_check_type (rd_hdr, IH_TYPE_RAMDISK)) { + printf ("No Linux %s Ramdisk Image\n", + image_get_arch_name(arch)); + show_boot_progress (-13); + do_reset (cmdtp, flag, argc, argv); + } + + return rd_hdr; +} + +/** + * get_ramdisk - main ramdisk handling routine + * @cmdtp: command table pointer + * @flag: command flag + * @argc: command argument count + * @argv: command argument list + * @hdr: pointer to the posiibly multi componet kernel image + * @verify: checksum verification flag + * @arch: expected ramdisk architecture + * @rd_start: pointer to a ulong variable, will hold ramdisk start address + * @rd_end: pointer to a ulong variable, will hold ramdisk end + * + * get_ramdisk() is responsible for finding a valid ramdisk image. + * Curently supported are the following ramdisk sources: + * - multicomponent kernel/ramdisk image, + * - commandline provided address of decicated ramdisk image. + * + * returns: + * rd_start and rd_end are set to ramdisk start/end addresses if + * ramdisk image is found and valid + * rd_start and rd_end are set to 0 if no ramdisk exists + * board is reset if ramdisk image is found but corrupted + */ +void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, uint8_t arch, + ulong *rd_start, ulong *rd_end) +{ + ulong rd_addr; + ulong rd_data, rd_len; + image_header_t *rd_hdr; + + if (argc >= 3) { + /* + * Look for a '-' which indicates to ignore the + * ramdisk argument + */ + if (strcmp(argv[2], "-") == 0) { + debug ("## Skipping init Ramdisk\n"); + rd_len = rd_data = 0; + } else { + /* + * Check if there is an initrd image at the + * address provided in the second bootm argument + */ + rd_addr = simple_strtoul (argv[2], NULL, 16); + printf ("## Loading init Ramdisk Image at %08lx ...\n", + rd_addr); + + rd_hdr = image_get_ramdisk (cmdtp, flag, argc, argv, + rd_addr, arch, verify); + + rd_data = image_get_data (rd_hdr); + rd_len = image_get_data_size (rd_hdr); + +#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO) + /* + *we need to copy the ramdisk to SRAM to let Linux boot + */ + memmove ((void *)image_get_load (rd_hdr), + (uchar *)rd_data, rd_len); + + rd_data = image_get_load (rd_hdr); +#endif /* CONFIG_B2 || CONFIG_EVB4510 || CONFIG_ARMADILLO */ + } + + } else if (image_check_type (hdr, IH_TYPE_MULTI)) { + /* + * Now check if we have a multifile image + * Get second entry data start address and len + */ + show_boot_progress (13); + printf ("## Loading init Ramdisk from multi component " + "Image at %08lx ...\n", (ulong)hdr); + image_multi_getimg (hdr, 1, &rd_data, &rd_len); + } else { + /* + * no initrd image + */ + show_boot_progress (14); + rd_len = rd_data = 0; + } + + if (!rd_data) { + debug ("## No init Ramdisk\n"); + *rd_start = 0; + *rd_end = 0; + } else { + *rd_start = rd_data; + *rd_end = rd_data + rd_len; + } + debug (" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n", + *rd_start, *rd_end); +} + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +/** + * ramdisk_high - relocate init ramdisk + * @rd_data: ramdisk data start address + * @rd_len: ramdisk data length + * @kbd: kernel board info copy (within BOOTMAPSZ boundary) + * @sp_limit: stack pointer limit (including BOOTMAPSZ) + * @sp: current stack pointer + * @initrd_start: pointer to a ulong variable, will hold final init ramdisk + * start address (after possible relocation) + * @initrd_end: pointer to a ulong variable, will hold final init ramdisk + * end address (after possible relocation) + * + * ramdisk_high() takes a relocation hint from "initrd_high" environement + * variable and if requested ramdisk data is moved to a specified location. + * + * returns: + * - initrd_start and initrd_end are set to final (after relocation) ramdisk + * start/end addresses if ramdisk image start and len were provided + * otherwise set initrd_start and initrd_end set to zeros + * - returns new allc_current, next free address below BOOTMAPSZ + */ +ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, + bd_t *kbd, ulong sp_limit, ulong sp, + ulong *initrd_start, ulong *initrd_end) +{ + char *s; + ulong initrd_high; + int initrd_copy_to_ram = 1; + ulong new_alloc_current = alloc_current; + + if ((s = getenv ("initrd_high")) != NULL) { + /* a value of "no" or a similar string will act like 0, + * turning the "load high" feature off. This is intentional. + */ + initrd_high = simple_strtoul (s, NULL, 16); + if (initrd_high == ~0) + initrd_copy_to_ram = 0; + } else { + /* not set, no restrictions to load high */ + initrd_high = ~0; + } + +#ifdef CONFIG_LOGBUFFER + /* Prevent initrd from overwriting logbuffer */ + if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) + initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; + debug ("## Logbuffer at 0x%08lx ", kbd->bi_memsize - LOGBUFF_LEN); +#endif + debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", + initrd_high, initrd_copy_to_ram); + + if (rd_data) { + if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ + debug (" in-place initrd\n"); + *initrd_start = rd_data; + *initrd_end = rd_data + rd_len; + } else { + new_alloc_current = alloc_current - rd_len; + *initrd_start = new_alloc_current; + *initrd_start &= ~(4096 - 1); /* align on page */ + + if (initrd_high) { + ulong nsp; + + /* + * the inital ramdisk does not need to be within + * CFG_BOOTMAPSZ as it is not accessed until after + * the mm system is initialised. + * + * do the stack bottom calculation again and see if + * the initrd will fit just below the monitor stack + * bottom without overwriting the area allocated + * for command line args and board info. + */ + nsp = sp; + nsp -= 2048; /* just to be sure */ + nsp &= ~0xF; + + if (nsp > initrd_high) /* limit as specified */ + nsp = initrd_high; + + nsp -= rd_len; + nsp &= ~(4096 - 1); /* align on page */ + + if (nsp >= sp_limit) { + *initrd_start = nsp; + new_alloc_current = alloc_current; + } + } + + 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 new_alloc_current; +} + +/** + * get_boot_sp_limit - calculate stack pointer limit + * @sp: current stack pointer + * + * get_boot_sp_limit() takes current stack pointer adrress and calculates + * stack pointer limit, below which kernel boot data (cmdline, board info, + * etc.) will be allocated. + * + * returns: + * stack pointer limit + */ +ulong get_boot_sp_limit(ulong sp) +{ + ulong sp_limit = sp; + + sp_limit -= 2048; /* just to be sure */ + + /* make sure sp_limit is within kernel mapped space */ + if (sp_limit > CFG_BOOTMAPSZ) + sp_limit = CFG_BOOTMAPSZ; + sp_limit &= ~0xF; + + return sp_limit; +} + +/** + * get_boot_cmdline - allocate and initialize kernel cmdline + * @alloc_current: current boot allocation address (counting down + * from sp_limit) + * @cmd_start: pointer to a ulong variable, will hold cmdline start + * @cmd_end: pointer to a ulong variable, will hold cmdline end + * + * get_boot_cmdline() allocates space for kernel command line below + * provided alloc_current address. If "bootargs" U-boot environemnt + * variable is present its contents is copied to allocated kernel + * command line. + * + * returns: + * alloc_current after cmdline allocation + */ +ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end) +{ + char *cmdline; + char *s; + + cmdline = (char *)((alloc_current - CFG_BARGSIZE) & ~0xF); + + if ((s = getenv("bootargs")) == NULL) + s = ""; + + strcpy(cmdline, s); + + *cmd_start = (ulong) & cmdline[0]; + *cmd_end = *cmd_start + strlen(cmdline); + + debug ("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); + + return (ulong)cmdline; +} + +/** + * get_boot_kbd - allocate and initialize kernel copy of board info + * @alloc_current: current boot allocation address (counting down + * from sp_limit) + * @kbd: double pointer to board info data + * + * get_boot_kbd() - allocates space for kernel copy of board info data. + * Space is allocated below provided alloc_current address and kernel + * board info is initialized with the current u-boot board info data. + * + * returns: + * alloc_current after kbd allocation + */ +ulong get_boot_kbd (ulong alloc_current, bd_t **kbd) +{ + *kbd = (bd_t *) (((ulong)alloc_current - sizeof(bd_t)) & ~0xF); + **kbd = *(gd->bd); + + debug ("## kernel board info at 0x%08lx\n", (ulong)*kbd); + +#if defined(DEBUG) && defined(CONFIG_CMD_BDI) + do_bdinfo(NULL, 0, 0, NULL); +#endif + + return (ulong)*kbd; +} +#endif /* CONFIG_PPC || CONFIG_M68K */ + +#endif /* USE_HOSTCC */ 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/examples/eepro100_eeprom.c b/examples/eepro100_eeprom.c index a52e68d..2b15d05 100644 --- a/examples/eepro100_eeprom.c +++ b/examples/eepro100_eeprom.c @@ -17,8 +17,9 @@ * and release the resulting code under the GPL. */ -#define _PPC_STRING_H_ /* avoid unnecessary str/mem functions */ -#define _LINUX_STRING_H_ /* avoid unnecessary str/mem functions */ +/* avoid unnecessary memcpy function */ +#define __HAVE_ARCH_MEMCPY +#define _PPC_STRING_H_ #include <common.h> #include <exports.h> diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index 2e906eb..e4189e5 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c @@ -29,24 +29,8 @@ static z_stream stream; -#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); -} +void *zalloc(void *, unsigned, unsigned); +void zfree(void *, void *, unsigned); /* Returns length of decompressed data. */ int cramfs_uncompress_block (void *dst, void *src, int srclen) diff --git a/include/asm-i386/zimage.h b/include/asm-i386/zimage.h index c7103b1..b6266e4 100644 --- a/include/asm-i386/zimage.h +++ b/include/asm-i386/zimage.h @@ -70,6 +70,5 @@ void *load_zimage(char *image, unsigned long kernel_size, int auto_boot); void boot_zimage(void *setup_base); -image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size); #endif diff --git a/include/image.h b/include/image.h index 432fa22..dbbbee9 100644 --- a/include/image.h +++ b/include/image.h @@ -1,4 +1,6 @@ /* + * (C) Copyright 2008 Semihalf + * * (C) Copyright 2000-2005 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -31,6 +33,13 @@ #ifndef __IMAGE_H__ #define __IMAGE_H__ +#include <asm/byteorder.h> +#include <command.h> +#ifndef USE_HOSTCC +#include <linux/string.h> +#include <asm/u-boot.h> +#endif + /* * Operating System Codes */ @@ -59,25 +68,25 @@ /* * CPU Architecture Codes (supported by Linux) */ -#define IH_CPU_INVALID 0 /* Invalid CPU */ -#define IH_CPU_ALPHA 1 /* Alpha */ -#define IH_CPU_ARM 2 /* ARM */ -#define IH_CPU_I386 3 /* Intel x86 */ -#define IH_CPU_IA64 4 /* IA64 */ -#define IH_CPU_MIPS 5 /* MIPS */ -#define IH_CPU_MIPS64 6 /* MIPS 64 Bit */ -#define IH_CPU_PPC 7 /* PowerPC */ -#define IH_CPU_S390 8 /* IBM S390 */ -#define IH_CPU_SH 9 /* SuperH */ -#define IH_CPU_SPARC 10 /* Sparc */ -#define IH_CPU_SPARC64 11 /* Sparc 64 Bit */ -#define IH_CPU_M68K 12 /* M68K */ -#define IH_CPU_NIOS 13 /* Nios-32 */ -#define IH_CPU_MICROBLAZE 14 /* MicroBlaze */ -#define IH_CPU_NIOS2 15 /* Nios-II */ -#define IH_CPU_BLACKFIN 16 /* Blackfin */ -#define IH_CPU_AVR32 17 /* AVR32 */ -#define IH_CPU_ST200 18 /* STMicroelectronics ST200 */ +#define IH_ARCH_INVALID 0 /* Invalid CPU */ +#define IH_ARCH_ALPHA 1 /* Alpha */ +#define IH_ARCH_ARM 2 /* ARM */ +#define IH_ARCH_I386 3 /* Intel x86 */ +#define IH_ARCH_IA64 4 /* IA64 */ +#define IH_ARCH_MIPS 5 /* MIPS */ +#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */ +#define IH_ARCH_PPC 7 /* PowerPC */ +#define IH_ARCH_S390 8 /* IBM S390 */ +#define IH_ARCH_SH 9 /* SuperH */ +#define IH_ARCH_SPARC 10 /* Sparc */ +#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */ +#define IH_ARCH_M68K 12 /* M68K */ +#define IH_ARCH_NIOS 13 /* Nios-32 */ +#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */ +#define IH_ARCH_NIOS2 15 /* Nios-II */ +#define IH_ARCH_BLACKFIN 16 /* Blackfin */ +#define IH_ARCH_AVR32 17 /* AVR32 */ +#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */ /* * Image Types @@ -157,5 +166,192 @@ typedef struct image_header { uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t; +/* + * 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. + */ +#define CHUNKSZ (64 * 1024) + +#define image_to_cpu(x) ntohl(x) +#define cpu_to_image(x) htonl(x) + +static inline uint32_t image_get_header_size (void) +{ + return (sizeof (image_header_t)); +} + +#define image_get_hdr_l(f) \ + static inline uint32_t image_get_##f(image_header_t *hdr) \ + { \ + return image_to_cpu (hdr->ih_##f); \ + } +image_get_hdr_l (magic); +image_get_hdr_l (hcrc); +image_get_hdr_l (time); +image_get_hdr_l (size); +image_get_hdr_l (load); +image_get_hdr_l (ep); +image_get_hdr_l (dcrc); + +#define image_get_hdr_b(f) \ + static inline uint8_t image_get_##f(image_header_t *hdr) \ + { \ + return hdr->ih_##f; \ + } +image_get_hdr_b (os); +image_get_hdr_b (arch); +image_get_hdr_b (type); +image_get_hdr_b (comp); + +static inline char *image_get_name (image_header_t *hdr) +{ + return (char *)hdr->ih_name; +} + +static inline uint32_t image_get_data_size (image_header_t *hdr) +{ + return image_get_size (hdr); +} + +/** + * image_get_data - get image payload start address + * @hdr: image header + * + * image_get_data() returns address of the image payload. For single + * component images it is image data start. For multi component + * images it points to the null terminated table of sub-images sizes. + * + * returns: + * image payload data start address + */ +static inline ulong image_get_data (image_header_t *hdr) +{ + return ((ulong)hdr + image_get_header_size ()); +} + +static inline uint32_t image_get_image_size (image_header_t *hdr) +{ + return (image_get_size (hdr) + image_get_header_size ()); +} +static inline ulong image_get_image_end (image_header_t *hdr) +{ + return ((ulong)hdr + image_get_image_size (hdr)); +} + +#define image_set_hdr_l(f) \ + static inline void image_set_##f(image_header_t *hdr, uint32_t val) \ + { \ + hdr->ih_##f = cpu_to_image (val); \ + } +image_set_hdr_l (magic); +image_set_hdr_l (hcrc); +image_set_hdr_l (time); +image_set_hdr_l (size); +image_set_hdr_l (load); +image_set_hdr_l (ep); +image_set_hdr_l (dcrc); + +#define image_set_hdr_b(f) \ + static inline void image_set_##f(image_header_t *hdr, uint8_t val) \ + { \ + hdr->ih_##f = val; \ + } +image_set_hdr_b (os); +image_set_hdr_b (arch); +image_set_hdr_b (type); +image_set_hdr_b (comp); + +static inline void image_set_name (image_header_t *hdr, const char *name) +{ + strncpy (image_get_name (hdr), name, IH_NMLEN); +} + +int image_check_hcrc (image_header_t *hdr); +int image_check_dcrc (image_header_t *hdr); +#ifndef USE_HOSTCC +int image_check_dcrc_wd (image_header_t *hdr, ulong chunksize); +int getenv_verify (void); +void memmove_wd (void *to, void *from, size_t len, ulong chunksz); +#endif + +static inline int image_check_magic (image_header_t *hdr) +{ + return (image_get_magic (hdr) == IH_MAGIC); +} +static inline int image_check_type (image_header_t *hdr, uint8_t type) +{ + return (image_get_type (hdr) == type); +} +static inline int image_check_arch (image_header_t *hdr, uint8_t arch) +{ + return (image_get_arch (hdr) == arch); +} +static inline int image_check_os (image_header_t *hdr, uint8_t os) +{ + return (image_get_os (hdr) == os); +} + +ulong image_multi_count (image_header_t *hdr); +void image_multi_getimg (image_header_t *hdr, ulong idx, + ulong *data, ulong *len); + +#ifndef USE_HOSTCC +static inline int image_check_target_arch (image_header_t *hdr) +{ +#if defined(__ARM__) + if (!image_check_arch (hdr, IH_ARCH_ARM)) +#elif defined(__avr32__) + if (!image_check_arch (hdr, IH_ARCH_AVR32)) +#elif defined(__bfin__) + if (!image_check_arch (hdr, IH_ARCH_BLACKFIN)) +#elif defined(__I386__) + if (!image_check_arch (hdr, IH_ARCH_I386)) +#elif defined(__M68K__) + if (!image_check_arch (hdr, IH_ARCH_M68K)) +#elif defined(__microblaze__) + if (!image_check_arch (hdr, IH_ARCH_MICROBLAZE)) +#elif defined(__mips__) + if (!image_check_arch (hdr, IH_ARCH_MIPS)) +#elif defined(__nios__) + if (!image_check_arch (hdr, IH_ARCH_NIOS)) +#elif defined(__nios2__) + if (!image_check_arch (hdr, IH_ARCH_NIOS2)) +#elif defined(__PPC__) + if (!image_check_arch (hdr, IH_ARCH_PPC)) +#elif defined(__sh__) + if (!image_check_arch (hdr, IH_ARCH_SH)) +#else +# error Unknown CPU type +#endif + return 0; + + return 1; +} + +const char* image_get_os_name (uint8_t os); +const char* image_get_arch_name (uint8_t arch); +const char* image_get_type_name (uint8_t type); +const char* image_get_comp_name (uint8_t comp); + +image_header_t* image_get_ramdisk (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong rd_addr, uint8_t arch, int verify); + +void get_ramdisk (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify, uint8_t arch, + ulong *rd_start, ulong *rd_end); + +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +ulong ramdisk_high (ulong alloc_current, ulong rd_data, ulong rd_len, + bd_t *kbd, ulong sp_limit, ulong sp, + ulong *initrd_start, ulong *initrd_end); + +ulong get_boot_sp_limit (ulong sp); +ulong get_boot_cmdline (ulong alloc_current, ulong *cmd_start, ulong *cmd_end); +ulong get_boot_kbd (ulong alloc_current, bd_t **kbd); +#endif /* CONFIG_PPC || CONFIG_M68K */ + +#endif /* USE_HOSTCC */ #endif /* __IMAGE_H__ */ diff --git a/lib_arm/Makefile b/lib_arm/Makefile index bfd5b0e..18c9e97 100644 --- a/lib_arm/Makefile +++ b/lib_arm/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = _ashldi3.o _ashrdi3.o _divsi3.o _modsi3.o _udivsi3.o _umodsi3.o -COBJS = armlinux.o board.o \ +COBJS = board.o bootm.o \ cache.o div0.o interrupts.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/lib_arm/armlinux.c b/lib_arm/bootm.c index 42098fc..31c2d67 100644 --- a/lib_arm/armlinux.c +++ b/lib_arm/bootm.c @@ -26,15 +26,9 @@ #include <image.h> #include <zlib.h> #include <asm/byteorder.h> -#ifdef CONFIG_HAS_DATAFLASH -#include <dataflash.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_SETUP_MEMORY_TAGS) || \ defined (CONFIG_CMDLINE_TAG) || \ defined (CONFIG_INITRD_TAG) || \ @@ -66,17 +60,11 @@ static void setup_videolfb_tag (gd_t *gd); static struct tag *params; #endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ -extern image_header_t header; /* from cmd_bootm.c */ - - void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + image_header_t *hdr, int verify) { - ulong len = 0, checksum; ulong initrd_start, initrd_end; - ulong data; void (*theKernel)(int zero, int arch, uint params); - image_header_t *hdr = &header; bd_t *bd = gd->bd; int machid = bd->bi_arch_number; char *s; @@ -85,7 +73,7 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], char *commandline = getenv ("bootargs"); #endif - theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep); + theKernel = (void (*)(int, int, uint))image_get_ep (hdr); s = getenv ("machid"); if (s) { @@ -93,134 +81,8 @@ void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], printf ("Using machid 0x%x from environment\n", machid); } - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* 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 - memcpy (&header, (char *) addr, - sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (unsigned char *) data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - -#ifdef CONFIG_HAS_DATAFLASH - if (addr_dataflash (addr)) { - read_dataflash (data, len, (char *) CFG_LOAD_ADDR); - data = CFG_LOAD_ADDR; - } -#endif - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (unsigned char *) data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_ARM) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux ARM Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - -#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || \ - defined(CONFIG_ARMADILLO) || defined(CONFIG_M501SK) - /* - *we need to copy the ramdisk to SRAM to let Linux boot - */ - memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len); - data = ntohl(hdr->ih_load); -#endif /* CONFIG_B2 || CONFIG_EVB4510 */ - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong 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; - } - - len = ntohl (len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - len = data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_ARM, &initrd_start, &initrd_end); show_boot_progress (15); diff --git a/lib_avr32/Makefile b/lib_avr32/Makefile index bb2938f..ebe237b 100644 --- a/lib_avr32/Makefile +++ b/lib_avr32/Makefile @@ -29,7 +29,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = memset.o -COBJS = board.o interrupts.o avr32_linux.o +COBJS = board.o interrupts.o bootm.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_avr32/avr32_linux.c b/lib_avr32/bootm.c index 62afbd2..a934cae 100644 --- a/lib_avr32/avr32_linux.c +++ b/lib_avr32/bootm.c @@ -31,13 +31,9 @@ DECLARE_GLOBAL_DATA_PTR; -extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - /* CPU-specific hook to allow flushing of caches, etc. */ extern void prepare_to_boot(void); -extern image_header_t header; /* from cmd_bootm.c */ - static struct tag *setup_start_tag(struct tag *params) { params->hdr.tag = ATAG_CORE; @@ -176,113 +172,18 @@ static void setup_end_tag(struct tag *params) } void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - unsigned long addr, unsigned long *len_ptr, int verify) + image_header_t *hdr, int verify) { - unsigned long data, len = 0; - unsigned long initrd_start, initrd_end; - unsigned long image_start, image_end; - unsigned long checksum; + ulong initrd_start, initrd_end; + void (*theKernel)(int magic, void *tagtable); - image_header_t *hdr; struct tag *params, *params_start; char *commandline = getenv("bootargs"); - hdr = (image_header_t *)addr; - image_start = addr; - image_end = addr + hdr->ih_size; + theKernel = (void *)image_get_ep (hdr); - theKernel = (void *)ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul(argv[2], NULL, 16); - - printf("## Loading RAMDISK image at %08lx ...\n", addr); - - memcpy(&header, (char *)addr, sizeof(header)); - hdr = &header; - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - puts("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset(cmdtp, flag, argc, argv); - } - - data = (unsigned long)hdr; - len = sizeof(*hdr); - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32(0, (unsigned char *)data, len) != checksum) { - puts("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset(cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr(hdr); - - data = addr + sizeof(header); - len = ntohl(hdr->ih_size); - - if (verify) { - unsigned long csum = 0; - - puts(" Verifying Checksum ... "); - csum = crc32(0, (unsigned char *)data, len); - if (csum != ntohl(hdr->ih_dcrc)) { - puts("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset(cmdtp, flag, argc, argv); - } - puts("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_AVR32) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - puts("Not a Linux/AVR32 RAMDISK image\n"); - show_boot_progress (-13); - do_reset(cmdtp, flag, argc, argv); - } - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong 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; - } - - len = ntohl (len_ptr[1]); - } else { - /* no initrd image */ - show_boot_progress (14); - len = data = 0; - } - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_AVR32, &initrd_start, &initrd_end); show_boot_progress (15); diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index a7aaef7..ac3fb28 100644 --- a/lib_blackfin/Makefile +++ b/lib_blackfin/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = memcpy.o memcmp.o memset.o memmove.o -COBJS = post.o tests.o board.o bf533_linux.o bf533_string.o cache.o muldi3.o +COBJS = post.o tests.o board.o bootm.o bf533_string.o cache.o muldi3.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_blackfin/bf533_linux.c b/lib_blackfin/bootm.c index 80a3dc7..6299415 100644 --- a/lib_blackfin/bf533_linux.c +++ b/lib_blackfin/bootm.c @@ -42,13 +42,12 @@ extern void swap_to(int device_id); #endif -extern image_header_t header; extern void flush_instruction_cache(void); extern void flush_data_cache(void); static char *make_command_line(void); void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) + image_header_t *hdr, int verify) { int (*appl) (char *cmdline); char *cmdline; @@ -57,7 +56,7 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], swap_to(FLASH); #endif - appl = (int (*)(char *))ntohl(header.ih_ep); + appl = (int (*)(char *))image_get_ep (hdr); printf("Starting Kernel at = %x\n", appl); cmdline = make_command_line(); if (icache_status()) { diff --git a/lib_generic/bzlib.c b/lib_generic/bzlib.c index 87e6a6e..0d3f9c2 100644 --- a/lib_generic/bzlib.c +++ b/lib_generic/bzlib.c @@ -1592,6 +1592,10 @@ const char * BZ_API(BZ2_bzerror) (BZFILE *b, int *errnum) } #endif +void bz_internal_error(int errcode) +{ + printf ("BZIP2 internal error %d\n", errcode); +} /*-------------------------------------------------------------*/ /*--- end bzlib.c ---*/ diff --git a/lib_i386/Makefile b/lib_i386/Makefile index e344da5..ef0ba54 100644 --- a/lib_i386/Makefile +++ b/lib_i386/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = bios.o bios_pci.o realmode_switch.o -COBJS = board.o bios_setup.o i386_linux.o zimage.o realmode.o \ +COBJS = board.o bios_setup.o bootm.o zimage.o realmode.o \ pci_type1.o pci.o video_bios.o video.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/lib_i386/bootm.c b/lib_i386/bootm.c new file mode 100644 index 0000000..ab6c2a9 --- /dev/null +++ b/lib_i386/bootm.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> +#include <asm/zimage.h> + +/*cmd_boot.c*/ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify) +{ + void *base_ptr; + + ulong os_data, os_len; + ulong initrd_start, initrd_end; + + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_I386, &initrd_start, &initrd_end); + + /* if multi-part image, we need to advance base ptr */ + if (image_check_type (hdr, IH_TYPE_MULTI)) { + image_multi_getimg (hdr, 0, &os_data, &os_len); + } else { + os_data = image_get_data (hdr); + os_len = image_get_data_size (hdr); + } + + base_ptr = load_zimage ((void*)os_data, os_len, + initrd_start, initrd_end - initrd_start, 0); + + if (NULL == base_ptr) { + printf ("## Kernel loading failed ...\n"); + do_reset(cmdtp, flag, argc, argv); + + } + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08x) ...\n", + (u32)base_ptr); +#endif + + /* we assume that the kernel is in place */ + printf("\nStarting kernel ...\n\n"); + + boot_zimage(base_ptr); + +} diff --git a/lib_i386/i386_linux.c b/lib_i386/i386_linux.c deleted file mode 100644 index b4a6f5a..0000000 --- a/lib_i386/i386_linux.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * - * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <common.h> -#include <command.h> -#include <image.h> -#include <zlib.h> -#include <asm/byteorder.h> -#include <asm/zimage.h> - -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - -extern image_header_t header; /* from cmd_bootm.c */ - - -image_header_t *fake_header(image_header_t *hdr, void *ptr, int size) -{ - /* try each supported image type in order */ - if (NULL != fake_zimage_header(hdr, ptr, size)) { - return hdr; - } - - return NULL; -} - - -void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) -{ - void *base_ptr; - - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - image_header_t *hdr = &header; - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - addr = simple_strtoul(argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)addr, sizeof(image_header_t)); - - if (ntohl(hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong)&header; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (char *)data, len) != checksum) { - printf ("Bad Header Checksum\n"); - do_reset (cmdtp, flag, argc, argv); - } - - print_image_hdr (hdr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (char *)data, len); - if (csum != ntohl(hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_I386) || - (hdr->ih_type != IH_TYPE_RAMDISK) ) { - printf ("No Linux i386 Ramdisk Image\n"); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl(len_ptr[0]) % 4; - int i; - - /* 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; - } - - len = ntohl(len_ptr[1]); - - } else { - /* - * no initrd image - */ - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - printf (" Loading Ramdisk to %08lx, end %08lx ... ", - initrd_start, initrd_end); - memmove ((void *)initrd_start, (void *)data, len); - printf ("OK\n"); - } else { - initrd_start = 0; - initrd_end = 0; - } - - /* if multi-part image, we need to advance base ptr */ - if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { - int i; - for (i=0, addr+=sizeof(int); len_ptr[i++]; addr+=sizeof(int)); - } - - base_ptr = load_zimage((void*)addr + sizeof(image_header_t), ntohl(hdr->ih_size), - initrd_start, initrd_end-initrd_start, 0); - - if (NULL == base_ptr) { - printf ("## Kernel loading failed ...\n"); - do_reset(cmdtp, flag, argc, argv); - - } - -#ifdef DEBUG - printf ("## Transferring control to Linux (at address %08x) ...\n", - (u32)base_ptr); -#endif - - /* we assume that the kernel is in place */ - printf("\nStarting kernel ...\n\n"); - - boot_zimage(base_ptr); - -} diff --git a/lib_i386/zimage.c b/lib_i386/zimage.c index 3510f2f..c3b4e59 100644 --- a/lib_i386/zimage.c +++ b/lib_i386/zimage.c @@ -212,7 +212,6 @@ void *load_zimage(char *image, unsigned long kernel_size, return setup_base; } - void boot_zimage(void *setup_base) { struct pt_regs regs; @@ -224,52 +223,3 @@ void boot_zimage(void *setup_base) regs.eflags = 0; enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s); } - - -image_header_t *fake_zimage_header(image_header_t *hdr, void *ptr, int size) -{ - /* There is no way to know the size of a zImage ... * - * so we assume that 2MB will be enough for now */ -#define ZIMAGE_SIZE 0x200000 - - /* load a 1MB, the loaded will have to be moved to its final - * position again later... */ -#define ZIMAGE_LOAD 0x100000 - - ulong checksum; - - if (KERNEL_MAGIC != *(u16*)(ptr + BOOT_FLAG_OFF)) { - /* not a zImage or bzImage */ - return NULL; - } - - if (-1 == size) { - size = ZIMAGE_SIZE; - } -#if 0 - checksum = crc32 (0, ptr, size); -#else - checksum = 0; -#endif - memset(hdr, 0, sizeof(image_header_t)); - - /* Build new header */ - hdr->ih_magic = htonl(IH_MAGIC); - hdr->ih_time = 0; - hdr->ih_size = htonl(size); - hdr->ih_load = htonl(ZIMAGE_LOAD); - hdr->ih_ep = 0; - hdr->ih_dcrc = htonl(checksum); - hdr->ih_os = IH_OS_LINUX; - hdr->ih_arch = IH_CPU_I386; - hdr->ih_type = IH_TYPE_KERNEL; - hdr->ih_comp = IH_COMP_NONE; - - strncpy((char *)hdr->ih_name, "(none)", IH_NMLEN); - - checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); - - hdr->ih_hcrc = htonl(checksum); - - return hdr; -} diff --git a/lib_m68k/Makefile b/lib_m68k/Makefile index 03784fd..d515223 100644 --- a/lib_m68k/Makefile +++ b/lib_m68k/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = -COBJS = cache.o traps.o time.o interrupts.o board.o m68k_linux.o +COBJS = cache.o traps.o time.o interrupts.o board.o bootm.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_m68k/bootm.c b/lib_m68k/bootm.c new file mode 100644 index 0000000..ac04da0 --- /dev/null +++ b/lib_m68k/bootm.c @@ -0,0 +1,130 @@ +/* + * (C) Copyright 2003 + * 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 <command.h> +#include <image.h> +#include <zlib.h> +#include <bzlib.h> +#include <watchdog.h> +#include <environment.h> +#include <asm/byteorder.h> +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define PHYSADDR(x) x + +#define LINUX_MAX_ENVS 256 +#define LINUX_MAX_ARGS 256 + +static ulong get_sp (void); +static void set_clocks_in_mhz (bd_t *kbd); + +void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, int verify) +{ + ulong sp, sp_limit, alloc_current; + + ulong rd_data_start, rd_data_end, rd_len; + ulong initrd_start, initrd_end; + + ulong cmd_start, cmd_end; + bd_t *kbd; + void (*kernel) (bd_t *, ulong, ulong, ulong, ulong); + + /* + * 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. + */ + sp = get_sp(); + debug ("## Current stack ends at 0x%08lx ", sp); + + alloc_current = sp_limit = get_boot_sp_limit(sp); + debug ("=> set upper limit to 0x%08lx\n", sp_limit); + + /* allocate space and init command line */ + alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end); + + /* allocate space for kernel copy of board info */ + alloc_current = get_boot_kbd (alloc_current, &kbd); + set_clocks_in_mhz(kbd); + + /* find kernel */ + kernel = + (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr); + + /* find ramdisk */ + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_M68K, &rd_data_start, &rd_data_end); + + rd_len = rd_data_end - rd_data_start; + alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, + kbd, sp_limit, get_sp (), + &initrd_start, &initrd_end); + + debug("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) kernel); + + show_boot_progress (15); + + /* + * 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 */ +} + +static ulong get_sp (void) +{ + ulong sp; + + asm("movel %%a7, %%d0\n" + "movel %%d0, %0\n": "=d"(sp): :"%d0"); + + return sp; +} + +static void set_clocks_in_mhz (bd_t *kbd) +{ + char *s; + + if ((s = getenv("clocks_in_mhz")) != NULL) { + /* convert all clock information to MHz */ + kbd->bi_intfreq /= 1000000L; + kbd->bi_busfreq /= 1000000L; + } +} diff --git a/lib_m68k/m68k_linux.c b/lib_m68k/m68k_linux.c deleted file mode 100644 index cc974c2..0000000 --- a/lib_m68k/m68k_linux.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * (C) Copyright 2003 - * 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 <command.h> -#include <image.h> -#include <zlib.h> -#include <bzlib.h> -#include <watchdog.h> -#include <environment.h> -#include <asm/byteorder.h> - -DECLARE_GLOBAL_DATA_PTR; - -#define PHYSADDR(x) x - -#define LINUX_MAX_ENVS 256 -#define LINUX_MAX_ARGS 256 - -#define CHUNKSZ (64 * 1024) - -#ifdef CONFIG_SHOW_BOOT_PROGRESS -# include <status_led.h> -# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) -#else -# define SHOW_BOOT_PROGRESS(arg) -#endif - -extern image_header_t header; - -void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, - int argc, char *argv[], - ulong addr, ulong * len_ptr, 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 ((s = getenv("initrd_high")) != NULL) { - /* a value of "no" or a similar string will act like 0, - * turning the "load high" feature off. This is intentional. - */ - initrd_high = simple_strtoul(s, NULL, 16); - if (initrd_high == ~0) - initrd_copy_to_ram = 0; - } else { /* not set, no restrictions to load high */ - initrd_high = ~0; - } - -#ifdef CONFIG_LOGBUFFER - kbd = gd->bd; - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < (kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD)) - initrd_high = kbd->bi_memsize - LOGBUFF_LEN - LOGBUFF_OVERHEAD; - debug("## Logbuffer at 0x%08lX ", kbd->bi_memsize - LOGBUFF_LEN); -#endif - - /* - * 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("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(sp): :"%d0"); - - 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); - -#ifdef DEBUG - printf("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end); - - do_bdinfo(NULL, 0, 0, NULL); -#endif - - if ((s = getenv("clocks_in_mhz")) != NULL) { - /* convert all clock information to MHz */ - kbd->bi_intfreq /= 1000000L; - kbd->bi_busfreq /= 1000000L; - } - - kernel = - (void (*)(bd_t *, ulong, ulong, ulong, ulong))ntohl(hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - - if (argc >= 3) { - debug("Not skipping initrd\n"); - SHOW_BOOT_PROGRESS(9); - - addr = simple_strtoul(argv[2], NULL, 16); - - 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); - } - - 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"); - SHOW_BOOT_PROGRESS(-11); - do_reset(cmdtp, flag, argc, argv); - } - - SHOW_BOOT_PROGRESS(10); - - print_image_hdr(hdr); - - data = addr + sizeof(image_header_t); - len = ntohl(hdr->ih_size); - - 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 */ - - puts(" Verifying Checksum ... "); - -#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - - while (cdata < edata) { - ulong chunk = edata - cdata; - - if (chunk > CHUNKSZ) - chunk = CHUNKSZ; - csum = crc32(csum, (uchar *) cdata, chunk); - cdata += chunk; - - 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"); - } - - SHOW_BOOT_PROGRESS(11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_M68K) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - puts("No Linux ColdFire Ramdisk Image\n"); - SHOW_BOOT_PROGRESS(-13); - do_reset(cmdtp, flag, argc, argv); - } - - /* - * 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; - } - - len = ntohl(len_ptr[1]); - - } else { - /* - * no initrd image - */ - SHOW_BOOT_PROGRESS(14); - - len = data = 0; - } - - 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 */ - - if (initrd_high) { - ulong nsp; - - /* - * the inital ramdisk does not need to be within - * CFG_BOOTMAPSZ as it is not accessed until after - * the mm system is initialised. - * - * do the stack bottom calculation again and see if - * the initrd will fit just below the monitor stack - * bottom without overwriting the area allocated - * above for command line args and board info. - */ - asm("movel %%a7, %%d0\n" - "movel %%d0, %0\n": "=d"(nsp): :"%d0"); - - 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; - } - - 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; - } - } -#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; - } - - debug("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel); - - SHOW_BOOT_PROGRESS(15); - - /* - * 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 */ -} diff --git a/lib_microblaze/Makefile b/lib_microblaze/Makefile index 82b7bea..9b317a2 100644 --- a/lib_microblaze/Makefile +++ b/lib_microblaze/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = -COBJS = board.o microblaze_linux.o time.o cache.o +COBJS = board.o bootm.o time.o cache.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_microblaze/bootm.c b/lib_microblaze/bootm.c new file mode 100644 index 0000000..bccfbe1 --- /dev/null +++ b/lib_microblaze/bootm.c @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2007 Michal Simek + * (C) Copyright 2004 Atmark Techno, Inc. + * + * Michal SIMEK <monstr@monstr.eu> + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * 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> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> + +DECLARE_GLOBAL_DATA_PTR; + +void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], + image_header_t *hdr, int verify) +{ + /* First parameter is mapped to $r5 for kernel boot args */ + void (*theKernel) (char *); + char *commandline = getenv ("bootargs"); + + theKernel = (void (*)(char *))image_get_ep (hdr); + + show_boot_progress (15); + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) theKernel); +#endif + + theKernel (commandline); +} diff --git a/lib_microblaze/microblaze_linux.c b/lib_microblaze/microblaze_linux.c deleted file mode 100644 index 68b58d4..0000000 --- a/lib_microblaze/microblaze_linux.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (C) Copyright 2007 Michal Simek - * (C) Copyright 2004 Atmark Techno, Inc. - * - * Michal SIMEK <monstr@monstr.eu> - * Yasushi SHOJI <yashi@atmark-techno.com> - * - * 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> -#include <image.h> -#include <zlib.h> -#include <asm/byteorder.h> - -DECLARE_GLOBAL_DATA_PTR; - -extern image_header_t header; /* from cmd_bootm.c */ -/*cmd_boot.c*/ -extern int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); - -void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) -{ - ulong len = 0, checksum; - ulong initrd_start, initrd_end; - ulong data; - /* First parameter is mapped to $r5 for kernel boot args */ - void (*theKernel) (char *); - image_header_t *hdr = &header; - char *commandline = getenv ("bootargs"); - int i; - - theKernel = (void (*)(char *))ntohl (hdr->ih_ep); - - /* Check if there is an initrd image */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *)addr, sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (char *)data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - - if (verify) { - ulong csum = 0; - - printf (" Verifying Checksum ... "); - csum = crc32 (0, (char *)data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_MICROBLAZE) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux Microblaze Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong tail = ntohl (len_ptr[0]) % 4; - - 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; - } - - len = ntohl (len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } - - show_boot_progress (15); - -#ifdef DEBUG - printf ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) theKernel); -#endif - - theKernel (commandline); -} diff --git a/lib_mips/Makefile b/lib_mips/Makefile index 3163f00..93cca7a 100644 --- a/lib_mips/Makefile +++ b/lib_mips/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = -COBJS = board.o time.o mips_linux.o +COBJS = board.o time.o bootm.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_mips/mips_linux.c b/lib_mips/bootm.c index 556b180..fb91c76 100644 --- a/lib_mips/mips_linux.c +++ b/lib_mips/bootm.c @@ -33,10 +33,6 @@ DECLARE_GLOBAL_DATA_PTR; #define LINUX_MAX_ENVS 256 #define LINUX_MAX_ARGS 256 -extern image_header_t header; /* from cmd_bootm.c */ - -extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); - static int linux_argc; static char ** linux_argv; @@ -49,124 +45,19 @@ static void linux_env_set (char * env_name, char * env_val); void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong * len_ptr, int verify) + image_header_t *hdr, int verify) { - ulong len = 0, checksum; ulong initrd_start, initrd_end; - ulong data; + void (*theKernel) (int, char **, char **, int *); - image_header_t *hdr = &header; char *commandline = getenv ("bootargs"); char env_buf[12]; theKernel = - (void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep); - - /* - * Check if there is an initrd image - */ - if (argc >= 3) { - show_boot_progress (9); - - addr = simple_strtoul (argv[2], NULL, 16); - - printf ("## Loading Ramdisk Image at %08lx ...\n", addr); - - /* Copy header so we can blank CRC field for re-calculation */ - memcpy (&header, (char *) addr, sizeof (image_header_t)); - - if (ntohl (hdr->ih_magic) != IH_MAGIC) { - printf ("Bad Magic Number\n"); - show_boot_progress (-10); - do_reset (cmdtp, flag, argc, argv); - } - - data = (ulong) & header; - len = sizeof (image_header_t); - - checksum = ntohl (hdr->ih_hcrc); - hdr->ih_hcrc = 0; - - if (crc32 (0, (uchar *) data, len) != checksum) { - printf ("Bad Header Checksum\n"); - show_boot_progress (-11); - do_reset (cmdtp, flag, argc, argv); - } - - show_boot_progress (10); - - print_image_hdr (hdr); - - data = addr + sizeof (image_header_t); - len = ntohl (hdr->ih_size); - - if (verify) { - ulong csum = 0; + (void (*)(int, char **, char **, int *))image_get_ep (hdr); - printf (" Verifying Checksum ... "); - csum = crc32 (0, (uchar *) data, len); - if (csum != ntohl (hdr->ih_dcrc)) { - printf ("Bad Data CRC\n"); - show_boot_progress (-12); - do_reset (cmdtp, flag, argc, argv); - } - printf ("OK\n"); - } - - show_boot_progress (11); - - if ((hdr->ih_os != IH_OS_LINUX) || - (hdr->ih_arch != IH_CPU_MIPS) || - (hdr->ih_type != IH_TYPE_RAMDISK)) { - printf ("No Linux MIPS Ramdisk Image\n"); - show_boot_progress (-13); - do_reset (cmdtp, flag, argc, argv); - } - - /* - * Now check if we have a multifile image - */ - } else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) { - ulong 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; - } - - len = ntohl (len_ptr[1]); - - } else { - /* - * no initrd image - */ - show_boot_progress (14); - - data = 0; - } - -#ifdef DEBUG - if (!data) { - printf ("No initrd\n"); - } -#endif - - if (data) { - initrd_start = data; - initrd_end = initrd_start + len; - } else { - initrd_start = 0; - initrd_end = 0; - } + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_MIPS, &initrd_start, &initrd_end); show_boot_progress (15); diff --git a/lib_nios/Makefile b/lib_nios/Makefile index 7c9d62c..d8ae7bd 100644 --- a/lib_nios/Makefile +++ b/lib_nios/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = -COBJS = board.o cache.o divmod.o nios_linux.o mult.o time.o +COBJS = board.o cache.o divmod.o bootm.o mult.o time.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_nios/nios_linux.c b/lib_nios/bootm.c index eef1757..55f7e3a 100644 --- a/lib_nios/nios_linux.c +++ b/lib_nios/bootm.c @@ -29,6 +29,6 @@ * */ void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + image__header_t *hdr, int verify) { } diff --git a/lib_nios2/Makefile b/lib_nios2/Makefile index 1ff2f29..5f996d3 100644 --- a/lib_nios2/Makefile +++ b/lib_nios2/Makefile @@ -27,7 +27,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = cache.o -COBJS = board.o divmod.o nios_linux.o mult.o time.o +COBJS = board.o divmod.o bootm.o mult.o time.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_nios2/nios_linux.c b/lib_nios2/bootm.c index 9eb3426..cb84324 100644 --- a/lib_nios2/nios_linux.c +++ b/lib_nios2/bootm.c @@ -25,13 +25,10 @@ #include <command.h> #include <asm/byteorder.h> -extern image_header_t header; /* common/cmd_bootm.c */ - void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; - void (*kernel)(void) = (void (*)(void))ntohl (hdr->ih_ep); + void (*kernel)(void) = (void (*)(void))image_get_ep (hdr); /* For now we assume the Microtronix linux ... which only * needs to be called ;-) diff --git a/lib_ppc/Makefile b/lib_ppc/Makefile index afbd5ca..61507b0 100644 --- a/lib_ppc/Makefile +++ b/lib_ppc/Makefile @@ -28,7 +28,8 @@ LIB = $(obj)lib$(ARCH).a SOBJS = ppccache.o ppcstring.o ticks.o COBJS = board.o \ - bat_rw.o cache.o extable.o kgdb.o time.o interrupts.o + bat_rw.o cache.o extable.o kgdb.o time.o interrupts.o \ + bootm.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_ppc/bootm.c b/lib_ppc/bootm.c new file mode 100644 index 0000000..69ec459 --- /dev/null +++ b/lib_ppc/bootm.c @@ -0,0 +1,376 @@ +/* + * (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 + */ + +#define DEBUG + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <malloc.h> +#include <zlib.h> +#include <bzlib.h> +#include <environment.h> +#include <asm/byteorder.h> + +#if defined(CONFIG_OF_LIBFDT) +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> + +static void fdt_error (const char *msg); +static ulong get_fdt (ulong alloc_current, cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, char **of_flat_tree); +#endif + +#ifdef CFG_INIT_RAM_LOCK +#include <asm/cache.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +static ulong get_sp (void); +static void set_clocks_in_mhz (bd_t *kbd); + +void __attribute__((noinline)) +do_bootm_linux(cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, + int verify) +{ + ulong sp, sp_limit, alloc_current; + + ulong initrd_start, initrd_end; + ulong rd_data_start, rd_data_end, rd_len; + + ulong cmd_start, cmd_end; + bd_t *kbd; + void (*kernel)(bd_t *, ulong, ulong, ulong, ulong); + +#if defined(CONFIG_OF_LIBFDT) + char *of_flat_tree; +#endif + + /* + * 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. + */ + sp = get_sp(); + debug ("## Current stack ends at 0x%08lx ", sp); + + alloc_current = sp_limit = get_boot_sp_limit(sp); + debug ("=> set upper limit to 0x%08lx\n", sp_limit); + + /* allocate space and init command line */ + alloc_current = get_boot_cmdline (alloc_current, &cmd_start, &cmd_end); + + /* allocate space for kernel copy of board info */ + alloc_current = get_boot_kbd (alloc_current, &kbd); + set_clocks_in_mhz(kbd); + + /* find kernel */ + kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep (hdr); + + /* find ramdisk */ + get_ramdisk (cmdtp, flag, argc, argv, hdr, verify, + IH_ARCH_PPC, &rd_data_start, &rd_data_end); + + rd_len = rd_data_end - rd_data_start; + + alloc_current = ramdisk_high (alloc_current, rd_data_start, rd_len, + kbd, sp_limit, get_sp (), + &initrd_start, &initrd_end); + +#if defined(CONFIG_OF_LIBFDT) + /* find flattened device tree */ + alloc_current = get_fdt (alloc_current, + cmdtp, flag, argc, argv, hdr, &of_flat_tree); + + /* + * 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) { + fdt_error ("/chosen node create failed"); + do_reset (cmdtp, flag, argc, argv); + } +#ifdef CONFIG_OF_HAS_UBOOT_ENV + if (fdt_env(of_flat_tree) < 0) { + fdt_error ("/u-boot-env node create failed"); + do_reset (cmdtp, flag, argc, argv); + } +#endif +#ifdef CONFIG_OF_HAS_BD_T + if (fdt_bd_t(of_flat_tree) < 0) { + fdt_error ("/bd_t node create failed"); + do_reset (cmdtp, flag, argc, argv); + } +#endif +#ifdef CONFIG_OF_BOARD_SETUP + /* Call the board-specific fixup routine */ + ft_board_setup(of_flat_tree, gd->bd); +#endif + } +#endif /* CONFIG_OF_LIBFDT */ + + debug ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong)kernel); + + show_boot_progress (15); + +#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) + unlock_ram_in_cache(); +#endif + +#if 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 */ + } +#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 */ +} + +static ulong get_sp (void) +{ + ulong sp; + + asm( "mr %0,1": "=r"(sp) : ); + return sp; +} + +static void set_clocks_in_mhz (bd_t *kbd) +{ + char *s; + + 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; +#endif +#if defined(CONFIG_MPC5xxx) + kbd->bi_ipbfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; +#endif /* CONFIG_MPC5xxx */ + } +} + +#if defined(CONFIG_OF_LIBFDT) +static void fdt_error (const char *msg) +{ + puts ("ERROR: "); + puts (msg); + puts (" - must RESET the board to recover.\n"); +} + +static ulong get_fdt (ulong alloc_current, + cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + image_header_t *hdr, char **of_flat_tree) +{ + image_header_t *fdt_hdr; + ulong fdt_relocate = 0; + char *fdt = NULL; + ulong new_alloc_current; + + if(argc > 3) { + fdt = (char *)simple_strtoul (argv[3], NULL, 16); + fdt_hdr = (image_header_t *)fdt; + + if (fdt_check_header (fdt) == 0) { + printf ("## Flattened Device Tree blob at %08lx\n", fdt); +#ifndef CFG_NO_FLASH + if (addr2info ((ulong)fdt) != NULL) + fdt_relocate = 1; +#endif + } else if (image_check_magic (fdt_hdr)) { + ulong image_start, image_end; + ulong load_start, load_end; + + printf ("## Flattened Device Tree Image at %08lx\n", + fdt_hdr); + + print_image_hdr (fdt_hdr); + + image_start = (ulong)fdt_hdr; + image_end = image_get_image_end (fdt_hdr); + + load_start = image_get_load (fdt_hdr); + load_end = load_start + image_get_data_size (fdt_hdr); + + if ((load_start < image_end) && (load_end > image_start)) { + fdt_error ("fdt overwritten"); + do_reset (cmdtp, flag, argc, argv); + } + + puts (" Verifying Checksum ... "); + if (!image_check_hcrc (fdt_hdr)) { + fdt_error ("fdt header checksum invalid"); + do_reset (cmdtp, flag, argc, argv); + } + + if (!image_check_dcrc (fdt_hdr)) { + fdt_error ("fdt checksum invalid"); + do_reset (cmdtp, flag, argc, argv); + } + puts ("OK\n"); + + if (!image_check_type (fdt_hdr, IH_TYPE_FLATDT)) { + fdt_error ("uImage is not a fdt"); + do_reset (cmdtp, flag, argc, argv); + } + if (image_get_comp (fdt_hdr) != IH_COMP_NONE) { + fdt_error ("uImage is compressed"); + do_reset (cmdtp, flag, argc, argv); + } + if (fdt_check_header ((char *)image_get_data (fdt_hdr)) != 0) { + fdt_error ("uImage data is not a fdt"); + do_reset (cmdtp, flag, argc, argv); + } + + memmove ((void *)image_get_load (fdt_hdr), + (void *)image_get_data (fdt_hdr), + image_get_data_size (fdt_hdr)); + + fdt = (char *)image_get_load (fdt_hdr); + } else { + fdt_error ("Did not find a Flattened Device Tree"); + do_reset (cmdtp, flag, argc, argv); + } + printf (" Booting using the fdt at 0x%x\n", + fdt); + } else if (image_check_type (hdr, IH_TYPE_MULTI)) { + ulong fdt_data, fdt_len; + + printf ("## Flattened Device Tree from multi " + "component Image at %08lX\n", (ulong)hdr); + + image_multi_getimg (hdr, 2, &fdt_data, &fdt_len); + if (fdt_len) { + + fdt = (char *)fdt_data; + printf (" Booting using the fdt at 0x%x\n", fdt); + +#ifndef CFG_NO_FLASH + /* move the blob if it is in flash (set of_relocte) */ + if (addr2info ((ulong)fdt) != NULL) + fdt_relocate = 1; +#endif + + if (fdt_check_header (fdt) != 0) { + fdt_error ("image is not a fdt"); + do_reset (cmdtp, flag, argc, argv); + } + + if (be32_to_cpu (fdt_totalsize (fdt)) != fdt_len) { + fdt_error ("fdt size != image size"); + do_reset (cmdtp, flag, argc, argv); + } + } else { + debug (" Did not find a Flattened Device Tree"); + } + } + +#ifdef CFG_BOOTMAPSZ + /* + * The blob must be within CFG_BOOTMAPSZ, + * so we flag it to be copied if it is not. + */ + if (fdt >= (char *)CFG_BOOTMAPSZ) + fdt_relocate = 1; +#endif + + /* move flattend device tree if needed */ + if (fdt_relocate) { + int err; + ulong of_start, of_len; + + of_len = be32_to_cpu (fdt_totalsize (fdt)); + + /* position on a 4K boundary before the alloc_current */ + of_start = alloc_current - of_len; + of_start &= ~(4096 - 1); /* align on page */ + + debug ("## device tree at 0x%08lX ... 0x%08lX (len=%ld=0x%lX)\n", + (ulong)fdt, (ulong)fdt + of_len - 1, + of_len, of_len); + + printf (" Loading Device Tree to %08lx, end %08lx ... ", + of_start, of_start + of_len - 1); + + err = fdt_open_into (fdt, (void *)of_start, of_len); + if (err != 0) { + fdt_error ("fdt move failed"); + do_reset (cmdtp, flag, argc, argv); + } + puts ("OK\n"); + + *of_flat_tree = (char *)of_start; + new_alloc_current = of_start; + } else { + *of_flat_tree = fdt; + new_alloc_current = alloc_current; + } + + return new_alloc_current; +} +#endif diff --git a/lib_sh/Makefile b/lib_sh/Makefile index cf127a8..edb03d0 100644 --- a/lib_sh/Makefile +++ b/lib_sh/Makefile @@ -24,7 +24,7 @@ LIB = $(obj)lib$(ARCH).a SOBJS = -COBJS = board.o sh_linux.o # time.o +COBJS = board.o bootm.o # time.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_sh/sh_linux.c b/lib_sh/bootm.c index 14b6815..4e5fe77 100644 --- a/lib_sh/sh_linux.c +++ b/lib_sh/bootm.c @@ -25,8 +25,6 @@ #include <command.h> #include <asm/byteorder.h> -extern image_header_t header; /* common/cmd_bootm.c */ - /* The SH kernel reads arguments from the empty zero page at location * 0 at the start of SDRAM. The following are copied from * arch/sh/kernel/setup.c and may require tweaking if the kernel sources @@ -60,11 +58,10 @@ static void hexdump (unsigned char *buf, int len) #endif void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], - ulong addr, ulong *len_ptr, int verify) + image_header_t *hdr, int verify) { - image_header_t *hdr = &header; char *bootargs = getenv("bootargs"); - void (*kernel) (void) = (void (*)(void)) ntohl (hdr->ih_ep); + void (*kernel) (void) = (void (*)(void))image_get_ep (hdr); /* Setup parameters */ memset(PARAM, 0, 0x1000); /* Clear zero page */ diff --git a/tools/Makefile b/tools/Makefile index af0de47..cbfca6d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -23,7 +23,7 @@ BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) ubsha1$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) -OBJ_LINKS = environment.o crc32.o sha1.o +OBJ_LINKS = environment.o crc32.o sha1.o image.o OBJ_FILES = img2srec.o mkimage.o envcrc.o ubsha1.o gen_eth_addr.o bmp_logo.o ifeq ($(ARCH),mips) @@ -137,7 +137,7 @@ $(obj)img2srec$(SFX): $(obj)img2srec.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ -$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32.o +$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32.o $(obj)image.o $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ $(STRIP) $@ @@ -173,6 +173,9 @@ $(obj)crc32.o: $(obj)crc32.c $(obj)sha1.o: $(obj)sha1.c $(CC) -g $(CFLAGS) -c -o $@ $< +$(obj)image.o: $(obj)image.c + $(CC) -g $(CFLAGS) -c -o $@ $< + $(obj)mkimage.o: $(src)mkimage.c $(CC) -g $(CFLAGS) -c -o $@ $< @@ -217,6 +220,10 @@ $(obj)sha1.c: @rm -f $(obj)sha1.c ln -s $(src)../lib_generic/sha1.c $(obj)sha1.c +$(obj)image.c: + @rm -f $(obj)image.c + ln -s $(src)../common/image.c $(obj)image.c + $(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) $(obj)./bmp_logo $(LOGO_BMP) >$@ diff --git a/tools/mkimage.c b/tools/mkimage.c index 2125130..8ced970 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -20,44 +20,7 @@ * MA 02111-1307 USA */ -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifndef __WIN32__ -#include <netinet/in.h> /* for host / network byte order conversions */ -#endif -#include <sys/mman.h> -#include <sys/stat.h> -#include <time.h> -#include <unistd.h> - -#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) -#include <inttypes.h> -#endif - -#ifdef __WIN32__ -typedef unsigned int __u32; - -#define SWAP_LONG(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -#define ntohl(a) SWAP_LONG(a) -#define htonl(a) SWAP_LONG(a) -#endif /* __WIN32__ */ - -#ifndef O_BINARY /* should be define'd on __WIN32__ */ -#define O_BINARY 0 -#endif - +#include "mkimage.h" #include <image.h> extern int errno; @@ -77,24 +40,24 @@ typedef struct table_entry { } table_entry_t; table_entry_t arch_name[] = { - { IH_CPU_INVALID, NULL, "Invalid CPU", }, - { IH_CPU_ALPHA, "alpha", "Alpha", }, - { IH_CPU_ARM, "arm", "ARM", }, - { IH_CPU_I386, "x86", "Intel x86", }, - { IH_CPU_IA64, "ia64", "IA64", }, - { IH_CPU_M68K, "m68k", "MC68000", }, - { IH_CPU_MICROBLAZE, "microblaze", "MicroBlaze", }, - { IH_CPU_MIPS, "mips", "MIPS", }, - { IH_CPU_MIPS64, "mips64", "MIPS 64 Bit", }, - { IH_CPU_NIOS, "nios", "NIOS", }, - { IH_CPU_NIOS2, "nios2", "NIOS II", }, - { IH_CPU_PPC, "ppc", "PowerPC", }, - { IH_CPU_S390, "s390", "IBM S390", }, - { IH_CPU_SH, "sh", "SuperH", }, - { IH_CPU_SPARC, "sparc", "SPARC", }, - { IH_CPU_SPARC64, "sparc64", "SPARC 64 Bit", }, - { IH_CPU_BLACKFIN, "blackfin", "Blackfin", }, - { IH_CPU_AVR32, "avr32", "AVR32", }, + { IH_ARCH_INVALID, NULL, "Invalid CPU", }, + { 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", "MC68000", }, + { 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, "", "", }, }; @@ -167,7 +130,7 @@ int lflag = 0; int vflag = 0; int xflag = 0; int opt_os = IH_OS_LINUX; -int opt_arch = IH_CPU_PPC; +int opt_arch = IH_ARCH_PPC; int opt_type = IH_TYPE_KERNEL; int opt_comp = IH_COMP_GZIP; @@ -270,7 +233,7 @@ NXTARG: ; ep = addr; /* If XIP, entry point must be after the U-Boot header */ if (xflag) - ep += sizeof(image_header_t); + ep += image_get_header_size (); } /* @@ -278,11 +241,11 @@ NXTARG: ; * the size of the U-Boot header. */ if (xflag) { - if (ep != addr + sizeof(image_header_t)) { + if (ep != addr + image_get_header_size ()) { fprintf (stderr, "%s: For XIP, the entry point must be the load addr + %lu\n", cmdname, - (unsigned long)sizeof(image_header_t)); + (unsigned long)image_get_header_size ()); exit (EXIT_FAILURE); } } @@ -313,7 +276,7 @@ NXTARG: ; exit (EXIT_FAILURE); } - if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { + if ((unsigned)sbuf.st_size < image_get_header_size ()) { fprintf (stderr, "%s: Bad size: \"%s\" is no valid image\n", cmdname, imagefile); @@ -329,36 +292,30 @@ NXTARG: ; } /* - * create copy of header so that we can blank out the - * checksum field for checking - this can't be done - * on the PROT_READ mapped data. + * image_check_hcrc() creates copy of header so that + * we can blank out the checksum field for checking - + * this can't be done on the PROT_READ mapped data. */ - memcpy (hdr, ptr, sizeof(image_header_t)); + hdr = (image_header_t *)ptr; - if (ntohl(hdr->ih_magic) != IH_MAGIC) { + if (!image_check_magic (hdr)) { fprintf (stderr, "%s: Bad Magic Number: \"%s\" is no valid image\n", cmdname, imagefile); exit (EXIT_FAILURE); } - data = (char *)hdr; - len = sizeof(image_header_t); - - checksum = ntohl(hdr->ih_hcrc); - hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ - - if (crc32 (0, data, len) != checksum) { + if (!image_check_hcrc (hdr)) { fprintf (stderr, "%s: ERROR: \"%s\" has bad header checksum!\n", cmdname, imagefile); exit (EXIT_FAILURE); } - data = (char *)(ptr + sizeof(image_header_t)); - len = sbuf.st_size - sizeof(image_header_t) ; + data = (char *)image_get_data (hdr); + len = sbuf.st_size - image_get_header_size (); - if (crc32 (0, data, len) != ntohl(hdr->ih_dcrc)) { + if (crc32(0, data, len) != image_get_dcrc (hdr)) { fprintf (stderr, "%s: ERROR: \"%s\" has corrupted data!\n", cmdname, imagefile); @@ -379,9 +336,9 @@ NXTARG: ; * * write dummy header, to be fixed later */ - memset (hdr, 0, sizeof(image_header_t)); + memset (hdr, 0, image_get_header_size ()); - if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) { + if (write(ifd, hdr, image_get_header_size ()) != image_get_header_size ()) { fprintf (stderr, "%s: Write error on %s: %s\n", cmdname, imagefile, strerror(errno)); exit (EXIT_FAILURE); @@ -404,7 +361,7 @@ NXTARG: ; cmdname, file, strerror(errno)); exit (EXIT_FAILURE); } - size = htonl(sbuf.st_size); + size = cpu_to_image (sbuf.st_size); } else { size = 0; } @@ -469,27 +426,27 @@ NXTARG: ; hdr = (image_header_t *)ptr; checksum = crc32 (0, - (const char *)(ptr + sizeof(image_header_t)), - sbuf.st_size - sizeof(image_header_t) + (const char *)(ptr + image_get_header_size ()), + sbuf.st_size - image_get_header_size () ); /* Build new header */ - hdr->ih_magic = htonl(IH_MAGIC); - hdr->ih_time = htonl(sbuf.st_mtime); - hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t)); - hdr->ih_load = htonl(addr); - hdr->ih_ep = htonl(ep); - hdr->ih_dcrc = htonl(checksum); - hdr->ih_os = opt_os; - hdr->ih_arch = opt_arch; - hdr->ih_type = opt_type; - hdr->ih_comp = opt_comp; + image_set_magic (hdr, IH_MAGIC); + image_set_time (hdr, sbuf.st_mtime); + image_set_size (hdr, sbuf.st_size - image_get_header_size ()); + image_set_load (hdr, addr); + image_set_ep (hdr, ep); + image_set_dcrc (hdr, checksum); + image_set_os (hdr, opt_os); + image_set_arch (hdr, opt_arch); + image_set_type (hdr, opt_type); + image_set_comp (hdr, opt_comp); - strncpy((char *)hdr->ih_name, name, IH_NMLEN); + image_set_name (hdr, name); - checksum = crc32(0,(const char *)hdr,sizeof(image_header_t)); + checksum = crc32 (0, (const char *)hdr, image_get_header_size ()); - hdr->ih_hcrc = htonl(checksum); + image_set_hcrc (hdr, checksum); print_header (hdr); @@ -554,14 +511,14 @@ copy_file (int ifd, const char *datafile, int pad) * reserved for it. */ - if ((unsigned)sbuf.st_size < sizeof(image_header_t)) { + if ((unsigned)sbuf.st_size < image_get_header_size ()) { fprintf (stderr, "%s: Bad size: \"%s\" is too small for XIP\n", cmdname, datafile); exit (EXIT_FAILURE); } - for (p=ptr; p < ptr+sizeof(image_header_t); p++) { + for (p = ptr; p < ptr + image_get_header_size (); p++) { if ( *p != 0xff ) { fprintf (stderr, "%s: Bad file: \"%s\" has invalid buffer for XIP\n", @@ -570,7 +527,7 @@ copy_file (int ifd, const char *datafile, int pad) } } - offset = sizeof(image_header_t); + offset = image_get_header_size (); } size = sbuf.st_size - offset; @@ -620,22 +577,23 @@ print_header (image_header_t *hdr) time_t timestamp; uint32_t size; - timestamp = (time_t)ntohl(hdr->ih_time); - size = ntohl(hdr->ih_size); + timestamp = (time_t)image_get_time (hdr); + size = image_get_data_size (hdr); - printf ("Image Name: %.*s\n", IH_NMLEN, hdr->ih_name); + printf ("Image Name: %.*s\n", IH_NMLEN, image_get_name (hdr)); printf ("Created: %s", ctime(×tamp)); printf ("Image Type: "); print_type(hdr); printf ("Data Size: %d Bytes = %.2f kB = %.2f MB\n", size, (double)size / 1.024e3, (double)size / 1.048576e6 ); - printf ("Load Address: 0x%08X\n", ntohl(hdr->ih_load)); - printf ("Entry Point: 0x%08X\n", ntohl(hdr->ih_ep)); + printf ("Load Address: 0x%08X\n", image_get_load (hdr)); + printf ("Entry Point: 0x%08X\n", image_get_ep (hdr)); - if (hdr->ih_type == IH_TYPE_MULTI || hdr->ih_type == IH_TYPE_SCRIPT) { + if (image_check_type (hdr, IH_TYPE_MULTI) || + image_check_type (hdr, IH_TYPE_SCRIPT)) { int i, ptrs; uint32_t pos; uint32_t *len_ptr = (uint32_t *) ( - (unsigned long)hdr + sizeof(image_header_t) + (unsigned long)hdr + image_get_header_size () ); /* determine number of images first (to calculate image offsets) */ @@ -643,14 +601,14 @@ print_header (image_header_t *hdr) ; ptrs = i; /* null pointer terminates list */ - pos = sizeof(image_header_t) + ptrs * sizeof(long); + pos = image_get_header_size () + ptrs * sizeof(long); printf ("Contents:\n"); for (i=0; len_ptr[i]; ++i) { - size = ntohl(len_ptr[i]); + size = image_to_cpu (len_ptr[i]); printf (" Image %d: %8d Bytes = %4d kB = %d MB\n", i, size, size>>10, size>>20); - if (hdr->ih_type == IH_TYPE_SCRIPT && i > 0) { + if (image_check_type (hdr, IH_TYPE_SCRIPT) && i > 0) { /* * the user may need to know offsets * if planning to do something with @@ -671,10 +629,10 @@ static void print_type (image_header_t *hdr) { printf ("%s %s %s (%s)\n", - put_arch (hdr->ih_arch), - put_os (hdr->ih_os ), - put_type (hdr->ih_type), - put_comp (hdr->ih_comp) + put_arch (image_get_arch (hdr)), + put_os (image_get_os (hdr)), + put_type (image_get_type (hdr)), + put_comp (image_get_comp (hdr)) ); } diff --git a/tools/mkimage.h b/tools/mkimage.h new file mode 100644 index 0000000..8b05bb1 --- /dev/null +++ b/tools/mkimage.h @@ -0,0 +1,59 @@ +/* + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * All rights reserved. + * + * 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 <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef __WIN32__ +#include <netinet/in.h> /* for host / network byte order conversions */ +#endif +#include <sys/mman.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> + +#if defined(__BEOS__) || defined(__NetBSD__) || defined(__APPLE__) +#include <inttypes.h> +#endif + +#ifdef __WIN32__ +typedef unsigned int __u32; + +#define SWAP_LONG(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +#define ntohl(a) SWAP_LONG(a) +#define htonl(a) SWAP_LONG(a) +#endif /* __WIN32__ */ + +#ifndef O_BINARY /* should be define'd on __WIN32__ */ +#define O_BINARY 0 +#endif |