2 * (C) Copyright 2000-2006
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33 #include <LzmaWrapper.h>
34 #include <environment.h>
35 #include <asm/byteorder.h>
37 DECLARE_GLOBAL_DATA_PTR;
39 #ifdef CFG_HUSH_PARSER
44 extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
47 extern void eth_halt(void);
49 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
54 * Continue booting an OS image; caller already has:
55 * - copied image header to global variable `header'
56 * - checked header magic number, checksums (both header & image),
57 * - verified image architecture (PPC) and type (KERNEL or MULTI),
58 * - loaded (first part of) image to header load address,
59 * - disabled interrupts.
61 extern void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
63 #ifdef CONFIG_SILENT_CONSOLE
64 static void fixup_silent_linux(void);
67 #if (CONFIG_COMMANDS & CFG_CMD_IMI)
68 static int image_info(unsigned long addr);
71 image_header_t header;
72 ulong load_addr = CFG_LOAD_ADDR; /* default load address */
74 #if !defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) && \
75 !defined(CONFIG_FOR_DLINK_DIR505_A1) && \
76 !defined(CONFIG_FOR_DRAGINO_V2) && \
77 !defined(CONFIG_FOR_MESH_POTATO_V2) && \
78 !defined(CONFIG_FOR_BSB)
79 void fake_image_header(image_header_t *hdr, tplink_image_header_t *tpl_hdr){
80 memset(hdr, 0, sizeof(image_header_t));
82 /* Build new header */
83 hdr->ih_magic = htonl(IH_MAGIC);
86 hdr->ih_size = htonl(tpl_hdr->kernelLen);
87 hdr->ih_load = htonl(tpl_hdr->kernelTextAddr);
88 hdr->ih_ep = htonl(tpl_hdr->kernelEntryPoint);
90 hdr->ih_os = IH_OS_LINUX;
91 hdr->ih_arch = IH_CPU_MIPS;
92 hdr->ih_type = IH_TYPE_KERNEL;
93 hdr->ih_comp = IH_COMP_LZMA;
95 strncpy((char *)hdr->ih_name, (char *)tpl_hdr->signiture_1, IH_NMLEN);
97 #endif /* if !defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) && !defined(CONFIG_FOR_DLINK_DIR505_A1) && !defined(CONFIG_FOR_DRAGINO_V2) && !defined(CONFIG_FOR_MESH_POTATO_V2) && !defined(CONFIG_FOR_BSB) */
99 int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){
100 ulong addr, data, len;
101 uint unc_len = CFG_BOOTM_LEN;
103 image_header_t *hdr = &header;
104 #if !defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) && \
105 !defined(CONFIG_FOR_DLINK_DIR505_A1) && \
106 !defined(CONFIG_FOR_DRAGINO_V2) && \
107 !defined(CONFIG_FOR_MESH_POTATO_V2) && \
108 !defined(CONFIG_FOR_BSB)
109 tplink_image_header_t *fileTag;
115 addr = simple_strtoul(argv[1], NULL, 16);
118 printf("Booting image at: 0x%08lX\n", addr);
120 #if defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) || \
121 defined(CONFIG_FOR_DLINK_DIR505_A1) || \
122 defined(CONFIG_FOR_DRAGINO_V2) || \
123 defined(CONFIG_FOR_MESH_POTATO_V2) || \
124 defined(CONFIG_FOR_BSB)
125 memmove(&header, (char *)addr, sizeof(image_header_t));
126 print_image_hdr(hdr);
128 data = addr + sizeof(image_header_t);
130 fileTag = (tplink_image_header_t *)addr;
131 print_image_hdr(fileTag);
133 fake_image_header(hdr, fileTag);
135 data = addr + TAG_LEN;
138 len = ntohl(hdr->ih_size);
141 * We have reached the point of no return: we are going to
142 * overwrite all exception vector code, so we cannot easily
143 * recover from any failures any more...
145 #ifdef CONFIG_NETCONSOLE
147 * Stop the ethernet stack if NetConsole could have
153 #if defined(CONFIG_AR7100) || defined(CONFIG_AR7240)
155 * Flush everything, restore caches for linux
157 //mips_cache_flush();
158 //mips_icache_flush_ix();
160 /* XXX - this causes problems when booting from flash */
161 /* dcache_disable(); */
164 /* case IH_COMP_LZMA:*/
165 puts("Uncompressing kernel image... ");
167 i = lzma_inflate((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), (int *)&unc_len);
169 if(i != LZMA_RESULT_OK){
170 printf("## Error: LZMA error num: %d\n", i);
176 #ifdef CONFIG_SILENT_CONSOLE
177 fixup_silent_linux();
180 do_bootm_linux(cmdtp, flag, argc, argv);
183 puts("\n## Error: control returned to monitor - resetting...\n");
184 do_reset(cmdtp, flag, argc, argv);
190 U_BOOT_CMD(bootm, 2, 1, do_bootm, "boot application image from memory\n", "[addr]\n"
191 "\t- boot application image stored in memory at address 'addr'\n");
193 #ifdef CONFIG_SILENT_CONSOLE
194 static void fixup_silent_linux(){
195 char buf[256], *start, *end;
196 char *cmdline = getenv("bootargs");
198 /* Only fix cmdline when requested */
199 if(!(gd->flags & GD_FLG_SILENT)){
204 printf("before silent fix-up: %s\n", cmdline);
208 if((start = strstr(cmdline, "console=")) != NULL){
209 end = strchr(start, ' ');
210 strncpy(buf, cmdline, (start - cmdline + 8));
212 strcpy(buf + (start - cmdline + 8), end);
214 buf[start - cmdline + 8] = '\0';
217 strcpy(buf, cmdline);
218 strcat(buf, " console=");
221 strcpy(buf, "console=");
224 setenv("bootargs", buf);
225 debug("after silent fix-up: %s\n", buf);
227 #endif /* CONFIG_SILENT_CONSOLE */
229 #if defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) || \
230 defined(CONFIG_FOR_DLINK_DIR505_A1) || \
231 defined(CONFIG_FOR_DRAGINO_V2) || \
232 defined(CONFIG_FOR_MESH_POTATO_V2) || \
233 defined(CONFIG_FOR_BSB)
234 static void print_type(image_header_t *hdr){
235 char *os, *arch, *type, *comp;
264 switch(hdr->ih_arch){
266 arch = "Invalid CPU";
284 arch = "MIPS 64 Bit";
299 arch = "SPARC 64 Bit";
304 case IH_CPU_MICROBLAZE:
314 arch = "Unknown Architecture";
318 switch(hdr->ih_type){
319 case IH_TYPE_INVALID:
320 type = "Invalid Image";
322 case IH_TYPE_STANDALONE:
323 type = "Standalone Program";
326 type = "Kernel Image";
328 case IH_TYPE_RAMDISK:
329 type = "RAMDisk Image";
332 type = "Multi-File Image";
334 case IH_TYPE_FIRMWARE:
341 type = "Unknown Image";
345 switch(hdr->ih_comp){
347 comp = "uncompressed";
350 comp = "gzip compressed";
353 comp = "bzip2 compressed";
356 comp = "lzma compressed";
359 comp = "unknown compression";
363 printf("%s %s %s (%s)", arch, os, type, comp);
366 void print_image_hdr(image_header_t *hdr){
367 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
368 time_t timestamp = (time_t)ntohl(hdr->ih_time);
372 printf("\n Image name: %.*s\n", IH_NMLEN, hdr->ih_name);
374 #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
375 to_tm(timestamp, &tm);
376 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);
377 #endif /* CFG_CMD_DATE, CONFIG_TIMESTAMP */
379 puts(" Image type: ");
382 printf("\n Data size: %d Bytes = ", ntohl(hdr->ih_size));
383 print_size(ntohl(hdr->ih_size), "\n");
385 printf(" Load address: 0x%08X\n Entry point: 0x%08X\n", ntohl(hdr->ih_load), ntohl(hdr->ih_ep));
387 if(hdr->ih_type == IH_TYPE_MULTI){
390 ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
392 puts(" Contents:\n");
394 for(i = 0; (len = ntohl(*len_ptr)); ++i, ++len_ptr){
395 printf(" Image %d: %8ld Bytes = ", i, len);
396 print_size(len, "\n");
403 void print_image_hdr(tplink_image_header_t *hdr){
404 printf("\n Image name: %.*s %.*s\n", SIG_LEN, hdr->signiture_1, SIG_LEN_2, hdr->signiture_2);
405 puts(" Image type: MIPS Linux Kernel Image (lzma compressed)\n");
406 printf(" Data size: %d Bytes = ", ntohl(hdr->kernelLen));
407 print_size(ntohl(hdr->kernelLen), "\n");
408 printf(" Load address: 0x%08X\n Entry point: 0x%08X\n\n", ntohl(hdr->kernelTextAddr), ntohl(hdr->kernelEntryPoint));
410 #endif /* defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) || defined(CONFIG_FOR_DLINK_DIR505_A1) || defined(CONFIG_FOR_DRAGINO_V2) || defined(CONFIG_FOR_MESH_POTATO_V2) || defined(CONFIG_FOR_BSB) */
412 #if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
413 int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){
415 #ifndef CFG_HUSH_PARSER
416 if(run_command (getenv ("bootcmd"), flag) < 0){
420 if(parse_string_outer(getenv("bootcmd"), FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0){
427 U_BOOT_CMD(boot, 1, 1, do_bootd, "boot default, i.e., run 'bootcmd'\n", NULL);
429 /* keep old command name "bootd" for backward compatibility */
430 U_BOOT_CMD(bootd, 1, 1, do_bootd, "boot default, i.e., run 'bootcmd'\n", NULL);
432 #endif /* CONFIG_COMMANDS & CFG_CMD_BOOTD */
434 #if (CONFIG_COMMANDS & CFG_CMD_IMI)
435 int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){
440 addr = simple_strtoul(argv[1], NULL, 16);
441 return image_info(addr);
444 if(cmdtp->help != NULL){
445 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
447 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
450 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
458 static int image_info(ulong addr){
459 ulong data, len, checksum;
460 image_header_t *hdr = &header;
462 printf("\nChecking image at 0x%08lX...\n", addr);
464 /* Copy header so we can blank CRC field for re-calculation */
465 memmove(&header, (char *)addr, sizeof(image_header_t));
467 data = (ulong)&header;
468 len = sizeof(image_header_t);
470 checksum = ntohl(hdr->ih_hcrc);
473 if(crc32(0, (uchar *)data, len) != checksum){
474 puts("## Error: bad header checksum!\n");
478 /* for multi-file images we need the data part, too */
479 print_image_hdr((image_header_t *)addr);
481 data = addr + sizeof(image_header_t);
482 len = ntohl(hdr->ih_size);
484 puts(" Verifying checksum... ");
486 if(crc32(0, (uchar *)data, len) != ntohl(hdr->ih_dcrc)){
487 puts("bad data CRC!\n");
496 U_BOOT_CMD(iminfo, 2, 1, do_iminfo, "print firmware header\n", "address\n"
497 "\t- print header information for firmware image startting at address 'address'\n"
500 #endif /* CFG_CMD_IMI */