X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=common%2Fcmd_bootm.c;h=e30d212b0c9be94ac7927cd47eae121969f059f1;hb=b13fb01a62708492cae4b33c4d6fa9ae127905f4;hp=4c0d1f5bde589e06c4987857526464852041c86c;hpb=c7de829c796978e519984df2f1c8cfcf921a39a4;p=kernel%2Fu-boot.git diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 4c0d1f5..e30d212 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -27,11 +27,16 @@ #include #include #include -#include #include #include #include +#include +#include #include + + /*cmd_boot.c*/ + extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) #include #endif @@ -51,6 +56,14 @@ #include #endif +#ifdef CONFIG_LOGBUFFER +#include +#endif + +#ifdef CONFIG_HAS_DATAFLASH +#include +#endif + /* * Some systems (for example LWMON) have very short watchdog periods; * we must make sure to split long operations like memmove() or @@ -68,6 +81,13 @@ static void zfree(void *, void *, unsigned); #if (CONFIG_COMMANDS & CFG_CMD_IMI) static int image_info (unsigned long addr); #endif + +#if (CONFIG_COMMANDS & CFG_CMD_IMLS) +#include +extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* 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__ @@ -88,18 +108,33 @@ typedef void boot_os_Fcn (cmd_tbl_t *cmdtp, int flag, 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; #if (CONFIG_COMMANDS & CFG_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[] ); #endif /* CFG_CMD_ELF */ +#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 * ); +#endif image_header_t header; @@ -111,9 +146,10 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong addr; ulong data, len, checksum; ulong *len_ptr; + uint unc_len = 0x400000; int i, verify; char *name, *s; - int (*appl)(cmd_tbl_t *, int, int, char *[]); + int (*appl)(int, char *[]); image_header_t *hdr = &header; s = getenv ("verify"); @@ -129,6 +165,11 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) 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) { @@ -164,11 +205,18 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) SHOW_BOOT_PROGRESS (3); /* for multi-file images we need the data part, too */ - print_image_hdr (hdr); + print_image_hdr ((image_header_t *)addr); 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) { printf (" Verifying Checksum ... "); if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) { @@ -188,6 +236,10 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) if (hdr->ih_arch != IH_CPU_ARM) #elif defined(__I386__) if (hdr->ih_arch != IH_CPU_I386) +#elif defined(__mips__) + if (hdr->ih_arch != IH_CPU_MIPS) +#elif defined(__nios__) + if (hdr->ih_arch != IH_CPU_NIOS) #else # error Unknown CPU type #endif @@ -199,17 +251,24 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) SHOW_BOOT_PROGRESS (5); switch (hdr->ih_type) { - case IH_TYPE_STANDALONE: name = "Standalone Application"; - 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; + case IH_TYPE_STANDALONE: + name = "Standalone Application"; + /* A second argument overwrites the load address */ + if (argc > 2) { + hdr->ih_load = 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; @@ -226,7 +285,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #ifdef CONFIG_AMIGAONEG3SE /* - * We've possible left the caches enabled during + * We've possible left the caches enabled during * bios emulation, so turn them off again */ icache_disable(); @@ -262,13 +321,26 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; case IH_COMP_GZIP: printf (" Uncompressing %s ... ", name); - if (gunzip ((void *)ntohl(hdr->ih_load), 0x400000, + if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, (uchar *)data, (int *)&len) != 0) { printf ("GUNZIP ERROR - must RESET board to recover\n"); SHOW_BOOT_PROGRESS (-6); do_reset (cmdtp, flag, argc, argv); } break; +#ifdef CONFIG_BZIP2 + case IH_COMP_BZIP2: + printf (" Uncompressing %s ... ", name); + i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), + &unc_len, (char *)data, len, 0, 0); + if (i != BZ_OK) { + printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); + SHOW_BOOT_PROGRESS (-6); + udelay(100000); + do_reset (cmdtp, flag, argc, argv); + } + break; +#endif /* CONFIG_BZIP2 */ default: if (iflag) enable_interrupts(); @@ -281,12 +353,21 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) switch (hdr->ih_type) { case IH_TYPE_STANDALONE: - appl = (int (*)(cmd_tbl_t *, int, int, char *[]))ntohl(hdr->ih_ep); if (iflag) enable_interrupts(); - (*appl)(cmdtp, flag, argc-1, &argv[1]); - break; + /* 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 */ @@ -303,6 +384,9 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) switch (hdr->ih_os) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: +#ifdef CONFIG_SILENT_CONSOLE + fixup_silent_linux(); +#endif do_bootm_linux (cmdtp, flag, argc, argv, addr, len_ptr, verify); break; @@ -310,6 +394,19 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) do_bootm_netbsd (cmdtp, flag, argc, argv, addr, len_ptr, verify); break; + +#ifdef CONFIG_LYNXKDI + case IH_OS_LYNXOS: + do_bootm_lynxkdi (cmdtp, flag, argc, argv, + addr, len_ptr, verify); + break; +#endif + + case IH_OS_RTEMS: + do_bootm_rtems (cmdtp, flag, argc, argv, + addr, len_ptr, verify); + break; + #if (CONFIG_COMMANDS & CFG_CMD_ELF) case IH_OS_VXWORKS: do_bootm_vxworks (cmdtp, flag, argc, argv, @@ -320,6 +417,12 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) addr, len_ptr, verify); break; #endif /* CFG_CMD_ELF */ +#ifdef CONFIG_ARTOS + case IH_OS_ARTOS: + do_bootm_artos (cmdtp, flag, argc, argv, + addr, len_ptr, verify); + break; +#endif } SHOW_BOOT_PROGRESS (-9); @@ -330,6 +433,48 @@ 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" + " passing arguments 'arg ...'; when booting a Linux kernel,\n" + " 'arg' can be the address of an initrd image\n" +); + +#ifdef CONFIG_SILENT_CONSOLE +static void +fixup_silent_linux () +{ + DECLARE_GLOBAL_DATA_PTR; + char buf[256], *start, *end; + char *cmdline = getenv ("bootargs"); + + /* Only fix cmdline when requested */ + if (!(gd->flags & GD_FLG_SILENT)) + return; + + debug ("before silent fix-up: %s\n", cmdline); + if (cmdline) { + if ((start = strstr (cmdline, "console=")) != NULL) { + end = strchr (start, ' '); + strncpy (buf, cmdline, (start - cmdline + 8)); + if (end) + strcpy (buf + (start - cmdline + 8), end); + else + buf[start - cmdline + 8] = '\0'; + } else { + strcpy (buf, cmdline); + strcat (buf, " console="); + } + } else { + strcpy (buf, "console="); + } + + setenv ("bootargs", buf); + debug ("after silent fix-up: %s\n", buf); +} +#endif /* CONFIG_SILENT_CONSOLE */ + #ifdef CONFIG_PPC static void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, @@ -346,6 +491,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, ulong cmd_start, cmd_end; ulong initrd_high; ulong data; + int initrd_copy_to_ram = 1; char *cmdline; char *s; bd_t *kbd; @@ -357,19 +503,18 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, * turning the "load high" feature off. This is intentional. */ initrd_high = simple_strtoul(s, NULL, 16); - } else { /* not set, no restrictions to load high */ + 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; - if ((s = getenv ("logstart")) != NULL) { - kbd->bi_sramstart = simple_strtoul(s, NULL, 16); - /* Prevent initrd from overwriting logbuffer */ - if (initrd_high < kbd->bi_sramstart) - initrd_high = kbd->bi_sramstart-1024; - } - debug ("## Logbuffer at 0x%08lX ", kbd->bi_sramstart); + /* 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 /* @@ -416,12 +561,16 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, /* convert all clock information to MHz */ kbd->bi_intfreq /= 1000000L; kbd->bi_busfreq /= 1000000L; -#if defined(CONFIG_8260) +#if defined(CONFIG_8260) || defined(CONFIG_MPC8560) kbd->bi_cpmfreq /= 1000000L; kbd->bi_brgfreq /= 1000000L; kbd->bi_sccfreq /= 1000000L; kbd->bi_vco /= 1000000L; #endif /* CONFIG_8260 */ +#if defined(CONFIG_MPC5XXXX) + kbd->bi_ipbfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; +#endif /* CONFIG_MPC5XXXX */ } kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))hdr->ih_ep; @@ -542,6 +691,10 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, } 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 */ @@ -596,6 +749,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, memmove ((void *)initrd_start, (void *)data, len); #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ printf ("OK\n"); + } } else { initrd_start = 0; initrd_end = 0; @@ -607,7 +761,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, SHOW_BOOT_PROGRESS (15); -#ifdef CFG_INIT_RAM_LOCK +#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) unlock_ram_in_cache(); #endif /* @@ -620,7 +774,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, */ (*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); } -#endif /* CONFIG_ARM */ +#endif /* CONFIG_PPC */ static void do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, @@ -702,6 +856,99 @@ do_bootm_netbsd (cmd_tbl_t *cmdtp, int flag, (*loader) (gd->bd, img_addr, consdev, cmdline); } +#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) +{ + DECLARE_GLOBAL_DATA_PTR; + 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); +} +#endif + + #if (CONFIG_COMMANDS & CFG_CMD_BOOTD) int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { @@ -714,6 +961,20 @@ int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #endif return rcode; } + +U_BOOT_CMD( + boot, 1, 1, do_bootd, + "boot - boot default, i.e., run 'bootcmd'\n", + NULL +); + +/* keep old command name "bootd" for backward compatibility */ +U_BOOT_CMD( + bootd, 1, 1, do_bootd, + "bootd - boot default, i.e., run 'bootcmd'\n", + NULL +); + #endif #if (CONFIG_COMMANDS & CFG_CMD_IMI) @@ -774,8 +1035,68 @@ static int image_info (ulong addr) printf ("OK\n"); return 0; } + +U_BOOT_CMD( + iminfo, CFG_MAXARGS, 1, do_iminfo, + "iminfo - print header information for application image\n", + "addr [addr ...]\n" + " - print header information for application image starting at\n" + " address 'addr' in memory; this includes verification of the\n" + " image contents (magic number, header and payload checksums)\n" +); + #endif /* CFG_CMD_IMI */ +#if (CONFIG_COMMANDS & CFG_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 checksum; + + for (i=0, info=&flash_info[0]; iflash_id == FLASH_UNKNOWN) + goto next_bank; + for (j=0; jstart[j]) || + (ntohl(hdr->ih_magic) != IH_MAGIC)) + goto next_sector; + + /* Copy header so we can blank CRC field for re-calculation */ + memmove (&header, (char *)hdr, sizeof(image_header_t)); + + checksum = ntohl(header.ih_hcrc); + header.ih_hcrc = 0; + + if (crc32 (0, (char *)&header, sizeof(image_header_t)) + != checksum) + goto next_sector; + + printf ("Image at %08lX:\n", (ulong)hdr); + print_image_hdr( hdr ); + putc ('\n'); +next_sector: ; + } +next_bank: ; + } + + return (0); +} + +U_BOOT_CMD( + imls, 1, 1, do_imls, + "imls - list all images found in flash\n", + "\n" + " - Prints information about all images found at sector\n" + " boundaries in flash.\n" +); +#endif /* CFG_CMD_IMLS */ + void print_image_hdr (image_header_t *hdr) { @@ -823,6 +1144,13 @@ print_type (image_header_t *hdr) 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; } @@ -839,6 +1167,7 @@ print_type (image_header_t *hdr) case IH_CPU_SH: arch = "SuperH"; break; case IH_CPU_SPARC: arch = "SPARC"; break; case IH_CPU_SPARC64: arch = "SPARC 64 Bit"; break; + case IH_CPU_M68K: arch = "M68K"; break; default: arch = "Unknown Architecture"; break; } @@ -945,6 +1274,36 @@ int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) return (0); } +#ifdef CONFIG_BZIP2 +void bz_internal_error(int errcode) +{ + printf ("BZIP2 internal error %d\n", errcode); +} +#endif /* CONFIG_BZIP2 */ + +static void +do_bootm_rtems (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + ulong addr, ulong *len_ptr, int verify) +{ + DECLARE_GLOBAL_DATA_PTR; + image_header_t *hdr = &header; + void (*entry_point)(bd_t *); + + entry_point = (void (*)(bd_t *)) hdr->ih_ep; + + printf ("## Transferring control to RTEMS (at address %08lx) ...\n", + (ulong)entry_point); + + SHOW_BOOT_PROGRESS (15); + + /* + * RTEMS Parameters: + * r3: ptr to board info data + */ + + (*entry_point ) ( gd->bd ); +} + #if (CONFIG_COMMANDS & CFG_CMD_ELF) static void do_bootm_vxworks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], @@ -972,3 +1331,16 @@ do_bootm_qnxelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], do_bootelf(cmdtp, 0, 2, local_args); } #endif /* CFG_CMD_ELF */ + +#ifdef CONFIG_LYNXKDI +static void +do_bootm_lynxkdi (cmd_tbl_t *cmdtp, int flag, + int argc, char *argv[], + ulong addr, + ulong *len_ptr, + int verify) +{ + lynxkdi_boot( &header ); +} + +#endif /* CONFIG_LYNXKDI */