# # Author: Robert Schwebel # # Description: Changelog Entry: # # * Patch by Holger Schurig, Robert Schwebel, 13 May 2004: # Add a 'bootz' command to boot normal Linux zImages in # case you don't need the features of U-Boot's uImage. # # State: 2004-05-13: submitted # # 2004-05-13: # # WD: "The newly added code is not added to any Makefile, # so it does not get compiled at all. If you add it, you # will see that it is highly unportable; for example on # a PowerPC system you get: cmd_bootz.c:29:17: tag.h: # No such file or directory. Most of the code seems to be # for # ARM only (functions like setup_*_tag() don't exist for # PowerPC or MIPS or ...). Please make this code usable # for # other architectures as well and resubmit." # # 2004-05-13: # # WD: "May I ask you to factor out the relevant code in # lib_arm/armlinux.c so we have a set of functions which # can be used by both the bootm and bootz commands? # And maybe we don't need to do even this - probably # cmd_bootm.c can be split in a "header checking" and a # "boot the image part" - so that the "bootm" command # uses both, and "bootz" ignores the header checking." # # 2004-05-15: rewritten, resubmit # diff -urN u-boot-maintainance/common/cmd_bootm.c u-boot-maintainance-bootz/common/cmd_bootm.c --- u-boot-maintainance/common/cmd_bootm.c 2004-05-15 13:13:10.000000000 +0200 +++ u-boot-maintainance-bootz/common/cmd_bootm.c 2004-05-15 16:30:51.000000000 +0200 @@ -64,6 +64,25 @@ #include #endif +/* we have to find out the header architecture entry */ +#if defined(__PPC__) +#define HEADER_ARCH IH_CPU_PPC +#elif defined(__ARM__) +#define HEADER_ARCH IH_CPU_ARM +#elif defined(__I386__) +#define HEADER_ARCH IH_CPU_I386 +#elif defined(__mips__) +#define HEADER_ARCH IH_CPU_MIPS +#elif defined(__nios__) +#define HEADER_ARCH IH_CPU_NIOS +#elif defined(__M68K__) +#define HEADER_ARCH IH_CPU_M68K +#elif defined(__microblaze__) +#define HEADER_ARCH IH_CPU_MICROBLAZE +#else +#error Unknown CPU type +#endif + /* * Some systems (for example LWMON) have very short watchdog periods; * we must make sure to split long operations like memmove() or @@ -155,11 +174,8 @@ s = getenv ("verify"); verify = (s && (*s == 'n')) ? 0 : 1; - if (argc < 2) { - addr = load_addr; - } else { - addr = simple_strtoul(argv[1], NULL, 16); - } + /* use user supplied or default load address */ + addr = (argc < 2) ? load_addr : simple_strtoul(argv[1], NULL, 16); SHOW_BOOT_PROGRESS (1); printf ("## Booting image at %08lx ...\n", addr); @@ -171,26 +187,32 @@ } else #endif memmove (&header, (char *)addr, sizeof(image_header_t)); - + + /* + * If this is no uImage, try to find out what it is and create a + * faked header to start image with the normal mechanisms + */ 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) { + +#if defined(__I386__) || \ + defined(__ARM__) + if (fake_header(hdr, (void*)addr, -1)) { /* to compensate for the addition below */ addr -= sizeof(image_header_t); - /* turnof verify, - * fake_header() does not fake the data crc - */ + printf ("Warning: no uImage, turning off verify\n"); verify = 0; } else -#endif /* __I386__ */ - { - puts ("Bad Magic Number\n"); - SHOW_BOOT_PROGRESS (-1); - return 1; - } +#endif + { + puts ("Bad Magic Number\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } } + SHOW_BOOT_PROGRESS (2); + /* check header CRC32 */ data = (ulong)&header; len = sizeof(image_header_t); @@ -198,14 +220,15 @@ hdr->ih_hcrc = 0; if (crc32 (0, (char *)data, len) != checksum) { - puts ("Bad Header Checksum\n"); + puts ("Bad Header CRC\n"); SHOW_BOOT_PROGRESS (-2); return 1; } + SHOW_BOOT_PROGRESS (3); /* for multi-file images we need the data part, too */ - print_image_hdr ((image_header_t *)addr); + print_image_hdr (hdr); data = addr + sizeof(image_header_t); len = ntohl(hdr->ih_size); @@ -226,41 +249,28 @@ } puts ("OK\n"); } + SHOW_BOOT_PROGRESS (4); + /* check if header was created for correct CPU type */ len_ptr = (ulong *)data; -#if defined(__PPC__) - if (hdr->ih_arch != IH_CPU_PPC) -#elif defined(__ARM__) - 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) -#elif defined(__M68K__) - if (hdr->ih_arch != IH_CPU_M68K) -#elif defined(__microblaze__) - if (hdr->ih_arch != IH_CPU_MICROBLAZE) -#else -# error Unknown CPU type -#endif + if (hdr->ih_arch != HEADER_ARCH) { printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch); SHOW_BOOT_PROGRESS (-4); return 1; } + SHOW_BOOT_PROGRESS (5); + /* check what kind of an image we have here */ switch (hdr->ih_type) { case IH_TYPE_STANDALONE: name = "Standalone Application"; /* A second argument overwrites the load address */ - if (argc > 2) { + if (argc > 2) hdr->ih_load = simple_strtoul(argv[2], NULL, 16); - } break; case IH_TYPE_KERNEL: name = "Kernel Image"; @@ -277,6 +287,7 @@ SHOW_BOOT_PROGRESS (-5); return 1; } + SHOW_BOOT_PROGRESS (6); /* @@ -289,7 +300,7 @@ #ifdef CONFIG_AMIGAONEG3SE /* - * We've possible left the caches enabled during + * We've possibly left the caches enabled during * bios emulation, so turn them off again */ icache_disable(); @@ -298,6 +309,7 @@ dcache_disable(); #endif + /* find out compression type */ switch (hdr->ih_comp) { case IH_COMP_NONE: if(ntohl(hdr->ih_load) == addr) { @@ -361,6 +373,7 @@ puts ("OK\n"); SHOW_BOOT_PROGRESS (7); + /* find out image type, handle standalone and unknown here */ switch (hdr->ih_type) { case IH_TYPE_STANDALONE: if (iflag) @@ -391,6 +404,7 @@ } SHOW_BOOT_PROGRESS (8); + /* image is OS kernel, find out which one */ switch (hdr->ih_os) { default: /* handled by (original) Linux case */ case IH_OS_LINUX: @@ -436,6 +450,8 @@ } SHOW_BOOT_PROGRESS (-9); + + /* we should never reach this point */ #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); do_reset (cmdtp, flag, argc, argv); diff -urN u-boot-maintainance/lib_arm/armlinux.c u-boot-maintainance-bootz/lib_arm/armlinux.c --- u-boot-maintainance/lib_arm/armlinux.c 2004-05-13 18:49:18.000000000 +0200 +++ u-boot-maintainance-bootz/lib_arm/armlinux.c 2004-05-15 16:32:04.000000000 +0200 @@ -71,7 +71,20 @@ #endif extern image_header_t header; /* from cmd_bootm.c */ +extern int fake_zimage_header (image_header_t *uimage_hdr, void *ptr, int size); +/** + * fake_header - create an uImage header in case we don't have one + */ +image_header_t * fake_header(image_header_t * uimage_hdr, void *ptr, int size) +{ + /* try each supported image type in order */ + if (fake_zimage_header(uimage_hdr, ptr, size)) + return uimage_hdr; + + /* image type is still unknown, exit */ + return NULL; +} void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], ulong addr, ulong *len_ptr, int verify) diff -urN u-boot-maintainance/lib_arm/Makefile u-boot-maintainance-bootz/lib_arm/Makefile --- u-boot-maintainance/lib_arm/Makefile 2002-09-08 21:49:36.000000000 +0200 +++ u-boot-maintainance-bootz/lib_arm/Makefile 2004-05-15 15:06:48.000000000 +0200 @@ -28,7 +28,7 @@ AOBJS = _udivsi3.o _umodsi3.o COBJS = armlinux.o board.o \ - cache.o div0.o + cache.o div0.o zimage.o OBJS = $(AOBJS) $(COBJS) diff -urN u-boot-maintainance/lib_arm/zimage.c u-boot-maintainance-bootz/lib_arm/zimage.c --- u-boot-maintainance/lib_arm/zimage.c 1970-01-01 01:00:00.000000000 +0100 +++ u-boot-maintainance-bootz/lib_arm/zimage.c 2004-05-15 16:14:04.000000000 +0200 @@ -0,0 +1,71 @@ +/* + * (C) Copyright 2004 + * Robert Schwebel, Pengutronix, r.schwebel@pengutronix.de + * + * Derived from the i386 variant + * + * 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 + */ + +/* Linux ARM zImage loading */ + +#include +#include + +/* + * 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 + +image_header_t * fake_zimage_header(image_header_t * hdr, void *ptr, int size) +{ + ulong checksum = 0; + + /* check if we really have a ARM zImage magic number */ + if (*((unsigned long *) ((char *)ptr + 0x24)) != 0x016F2818) + return NULL; + + printf ("## Image is zImage, creating header\n"); + + if (size == -1) + size = ZIMAGE_SIZE; + + 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((unsigned long)ptr); + hdr->ih_ep = htonl((unsigned long)ptr); + hdr->ih_dcrc = htonl(checksum); + hdr->ih_os = IH_OS_LINUX; + hdr->ih_arch = IH_CPU_ARM; + hdr->ih_type = IH_TYPE_KERNEL; + hdr->ih_comp = IH_COMP_NONE; + + strncpy((char *) hdr->ih_name, "zImage", IH_NMLEN); + + checksum = crc32(0, (const char *) hdr, sizeof (image_header_t)); + + hdr->ih_hcrc = htonl(checksum); + + return hdr; +}