diff options
Diffstat (limited to 'lib_microblaze/microblaze_linux.c')
| -rw-r--r-- | lib_microblaze/microblaze_linux.c | 146 | 
1 files changed, 143 insertions, 3 deletions
| diff --git a/lib_microblaze/microblaze_linux.c b/lib_microblaze/microblaze_linux.c index b3a081551..2c7885c1f 100644 --- a/lib_microblaze/microblaze_linux.c +++ b/lib_microblaze/microblaze_linux.c @@ -1,6 +1,8 @@  /* + * (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 @@ -13,7 +15,7 @@   *   * This program is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License @@ -24,8 +26,146 @@  #include <common.h>  #include <command.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> -void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], -		ulong addr, ulong *len_ptr, int   verify) +DECLARE_GLOBAL_DATA_PTR; + +#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;	/* 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);  } |