diff options
| -rw-r--r-- | CHANGELOG | 3 | ||||
| -rw-r--r-- | board/stxxtc/oftree.dts | 52 | ||||
| -rw-r--r-- | common/Makefile.orig | 80 | ||||
| -rw-r--r-- | common/cmd_bootm.c.orig | 1379 | ||||
| -rw-r--r-- | common/ft_build.c | 695 | ||||
| -rw-r--r-- | include/ft_build.h | 66 | 
6 files changed, 2275 insertions, 0 deletions
| @@ -2,6 +2,9 @@  Changes for U-Boot 1.1.4:  ====================================================================== +* Add missing files for Pantelis Antoniou's patch +  Patch by Pantelis Antoniou, 04 Sep 2005 +  * Fix problem in ppc4xx eth-driver without ethaddr (only without    CONFIG_NET_MULTI set)    Patch by Stefan Roese, 10 Oct 2005 diff --git a/board/stxxtc/oftree.dts b/board/stxxtc/oftree.dts new file mode 100644 index 000000000..e3f301794 --- /dev/null +++ b/board/stxxtc/oftree.dts @@ -0,0 +1,52 @@ +/ { +	model = "STXXTC V1"; +	compatible = "STXXTC"; +	#address-cells = <2>; +	#size-cells = <2>; + +	cpus { +		linux,phandle = <1>; +		#address-cells = <1>; +		#size-cells = <0>; +		PowerPC,MPC870@0 { +			linux,phandle = <3>; +			name = "PowerPC,MPC870"; +			device_type = "cpu"; +			reg = <0>; +			clock-frequency = <0>;		/* place-holder for runtime fillup */ +			timebase-frequency = <0>;	/* dido */ +			linux,boot-cpu; +			i-cache-size = <2000>; +			d-cache-size = <2000>; +			32-bit; +		}; +	}; + +	memory@0 { +		device_type = "memory"; +		reg = <00000000 00000000 00000000 20000000>; +	}; + +	/* copy of the bd_t information (place-holders) */ +	bd_t { +		memstart	= <0>; +		memsize		= <0>; +		flashstart	= <0>; +		flashsize	= <0>; +		flashoffset	= <0>; +		sramstart	= <0>; +		sramsize	= <0>; + +		immr_base	= <0>; + +		bootflags	= <0>; +		ip_addr		= <0>; +		enetaddr	= [ 00 00 00 00 00 00 ]; +		ethspeed	= <0>; +		intfreq		= <0>; +		busfreq		= <0>; + +		baudrate	= <0>; +	}; + +}; diff --git a/common/Makefile.orig b/common/Makefile.orig new file mode 100644 index 000000000..6366e0226 --- /dev/null +++ b/common/Makefile.orig @@ -0,0 +1,80 @@ +# +# (C) Copyright 2004 +# 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 $(TOPDIR)/config.mk + +LIB	= libcommon.a + +AOBJS	= + +COBJS	= main.o ACEX1K.o altera.o bedbug.o circbuf.o \ +	  cmd_ace.o cmd_autoscript.o \ +	  cmd_bdinfo.o cmd_bedbug.o cmd_bmp.o cmd_boot.o cmd_bootm.o \ +	  cmd_cache.o cmd_console.o \ +	  cmd_date.o cmd_dcr.o cmd_diag.o cmd_display.o cmd_doc.o cmd_dtt.o \ +	  cmd_eeprom.o cmd_elf.o cmd_ext2.o \ +	  cmd_fat.o cmd_fdc.o cmd_fdos.o cmd_flash.o cmd_fpga.o \ +	  cmd_i2c.o cmd_ide.o cmd_immap.o cmd_itest.o cmd_jffs2.o \ +	  cmd_load.o cmd_log.o \ +	  cmd_mem.o cmd_mii.o cmd_misc.o cmd_mmc.o \ +	  cmd_nand.o cmd_net.o cmd_nvedit.o \ +	  cmd_pci.o cmd_pcmcia.o cmd_portio.o \ +	  cmd_reginfo.o cmd_reiser.o cmd_scsi.o cmd_spi.o cmd_universe.o \ +	  cmd_usb.o cmd_vfd.o \ +	  command.o console.o devices.o dlmalloc.o docecc.o \ +	  environment.o env_common.o \ +	  env_nand.o env_dataflash.o env_flash.o env_eeprom.o \ +	  env_nvram.o env_nowhere.o \ +	  exports.o \ +	  flash.o fpga.o \ +	  hush.o kgdb.o lcd.o lists.o lynxkdi.o \ +	  memsize.o miiphybb.o miiphyutil.o \ +	  s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ +	  usb.o usb_kbd.o usb_storage.o \ +	  virtex2.o xilinx.o + +OBJS	= $(AOBJS) $(COBJS) + +CPPFLAGS += -I.. + +all:	$(LIB) $(AOBJS) + +$(LIB): .depend $(OBJS) +	$(AR) crv $@ $(OBJS) + +environment.o: environment.c ../tools/envcrc +	$(CC) $(AFLAGS) -Wa,--no-warn \ +		-DENV_CRC=$(shell ../tools/envcrc) \ +		-c -o $@ environment.c + +../tools/envcrc: +	$(MAKE) -C ../tools + +######################################################################### + +.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/common/cmd_bootm.c.orig b/common/cmd_bootm.c.orig new file mode 100644 index 000000000..ab6ccbb07 --- /dev/null +++ b/common/cmd_bootm.c.orig @@ -0,0 +1,1379 @@ +/* + * (C) Copyright 2000-2002 + * 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 + */ + +/* + * Boot support + */ +#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> + + /*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 <rtc.h> +#endif + +#ifdef CFG_HUSH_PARSER +#include <hush.h> +#endif + +#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 + +#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 + +int  gunzip (void *, int, unsigned char *, unsigned long *); + +static void *zalloc(void *, unsigned, unsigned); +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 <flash.h> +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__ +image_header_t *fake_header(image_header_t *hdr, void *ptr, int size); +#endif + +/* + *  Continue booting an OS image; caller already has: + *  - copied image header to global variable `header' + *  - checked header magic number, checksums (both header & image), + *  - verified image architecture (PPC) and type (KERNEL or MULTI), + *  - 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; +#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; + +ulong load_addr = CFG_LOAD_ADDR;		/* Default Load Address */ + +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 = 0x400000; +	int	i, verify; +	char	*name, *s; +	int	(*appl)(int, char *[]); +	image_header_t *hdr = &header; + +	s = getenv ("verify"); +	verify = (s && (*s == 'n')) ? 0 : 1; + +	if (argc < 2) { +		addr = load_addr; +	} else { +		addr = simple_strtoul(argv[1], NULL, 16); +	} + +	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, (char *)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, (char *)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(__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) +#elif defined(__nios2__) +	if (hdr->ih_arch != IH_CPU_NIOS2) +#else +# error Unknown CPU type +#endif +	{ +		printf ("Unsupported Architecture 0x%x\n", hdr->ih_arch); +		SHOW_BOOT_PROGRESS (-4); +		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); + +	/* +	 * We have reached the point of no return: we are going to +	 * overwrite all exception vector code, so we cannot easily +	 * recover from any failures any more... +	 */ + +	iflag = disable_interrupts(); + +#ifdef CONFIG_AMIGAONEG3SE +	/* +	 * We've possible left the caches enabled during +	 * bios emulation, so turn them off again +	 */ +	icache_disable(); +	invalidate_l1_instruction_cache(); +	flush_data_cache(); +	dcache_disable(); +#endif + +	switch (hdr->ih_comp) { +	case IH_COMP_NONE: +		if(ntohl(hdr->ih_load) == addr) { +			printf ("   XIP %s ... ", 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 */ +		} +		break; +	case IH_COMP_GZIP: +		printf ("   Uncompressing %s ... ", name); +		if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, +			    (uchar *)data, &len) != 0) { +			puts ("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); +		/* +		 * 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); +		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(); +		printf ("Unimplemented compression type %d\n", hdr->ih_comp); +		SHOW_BOOT_PROGRESS (-7); +		return 1; +	} +	puts ("OK\n"); +	SHOW_BOOT_PROGRESS (7); + +	switch (hdr->ih_type) { +	case IH_TYPE_STANDALONE: +		if (iflag) +			enable_interrupts(); + +		/* 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; +	} +	SHOW_BOOT_PROGRESS (8); + +	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; +	case IH_OS_NETBSD: +	    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, +			      addr, len_ptr, verify); +	    break; +	case IH_OS_QNX: +	    do_bootm_qnxelf (cmdtp, flag, argc, 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); +#ifdef DEBUG +	puts ("\n## Control returned to monitor - resetting...\n"); +	do_reset (cmdtp, flag, argc, argv); +#endif +	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" +); + +#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, +		int	argc, char *argv[], +		ulong	addr, +		ulong	*len_ptr, +		int	verify) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	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( "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); + +	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; +#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 */ +	} + +	kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))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 */ +		memmove (&header, (char *)addr, sizeof(image_header_t)); + +		if (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 = hdr->ih_hcrc; +		hdr->ih_hcrc = 0; + +		if (crc32 (0, (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(image_header_t); +		len  = 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, (char *)cdata, chunk); +				cdata += chunk; + +				WATCHDOG_RESET(); +			} +#else	/* !(CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG) */ +			csum = crc32 (0, (char *)data, len); +#endif	/* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + +			if (csum != 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 (!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; +	} + + +	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 +	/* +	 * Linux Kernel Parameters: +	 *   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); +} +#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) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	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); + +		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 = ""; +	} + +	loader = (void (*)(bd_t *, image_header_t *, char *, char *)) 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); +} + +#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[]) +{ +	int rcode = 0; +#ifndef CFG_HUSH_PARSER +	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; +#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) +int do_iminfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	int	arg; +	ulong	addr; +	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; +	} +	return rcode; +} + +static int image_info (ulong addr) +{ +	ulong	data, len, checksum; +	image_header_t *hdr = &header; + +	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) { +		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, (char *)data, len) != checksum) { +		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); + +	puts ("   Verifying Checksum ... "); +	if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) { +		puts ("   Bad Data CRC\n"); +		return 1; +	} +	puts ("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 data, len, checksum; + +	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<CFG_MAX_FLASH_SECT; ++j) { + +			if (!(hdr=(image_header_t *)info->start[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 ); + +			data = (ulong)hdr + sizeof(image_header_t); +			len  = ntohl(hdr->ih_size); + +			puts ("   Verifying Checksum ... "); +			if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) { +				puts ("   Bad Data CRC\n"); +			} +			puts ("OK\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) +{ +#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) +	time_t timestamp = (time_t)ntohl(hdr->ih_time); +	struct rtc_time tm; +#endif + +	printf ("   Image Name:   %.*s\n", IH_NMLEN, hdr->ih_name); +#if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP) +	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	/* CFG_CMD_DATE, CONFIG_TIMESTAMP */ +	puts ("   Image Type:   "); print_type(hdr); +	printf ("\n   Data Size:    %d Bytes = ", ntohl(hdr->ih_size)); +	print_size (ntohl(hdr->ih_size), "\n"); +	printf ("   Load Address: %08x\n" +		"   Entry Point:  %08x\n", +		 ntohl(hdr->ih_load), ntohl(hdr->ih_ep)); + +	if (hdr->ih_type == IH_TYPE_MULTI) { +		int i; +		ulong len; +		ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t)); + +		puts ("   Contents:\n"); +		for (i=0; (len = ntohl(*len_ptr)); ++i, ++len_ptr) { +			printf ("   Image %d: %8ld Bytes = ", i, len); +			print_size (len, "\n"); +		} +	} +} + + +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; +	} + +	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_I386:	arch = "Intel x86";		break; +	case IH_CPU_IA64:	arch = "IA64";			break; +	case IH_CPU_MIPS:	arch = "MIPS";			break; +	case IH_CPU_MIPS64:	arch = "MIPS 64 Bit";		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_SPARC:	arch = "SPARC";			break; +	case IH_CPU_SPARC64:	arch = "SPARC 64 Bit";		break; +	case IH_CPU_M68K:	arch = "M68K"; 			break; +	case IH_CPU_MICROBLAZE:	arch = "Microblaze"; 		break; +	case IH_CPU_NIOS:	arch = "Nios";			break; +	case IH_CPU_NIOS2:	arch = "Nios-II";		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; +	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; +	} + +	printf ("%s %s %s (%s)", arch, os, type, comp); +} + +#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); +} + +#define HEAD_CRC	2 +#define EXTRA_FIELD	4 +#define ORIG_NAME	8 +#define COMMENT		0x10 +#define RESERVED	0xe0 + +#define DEFLATED	8 + +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); +} + +#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[], +		  ulong addr, ulong *len_ptr, int verify) +{ +	image_header_t *hdr = &header; +	char str[80]; + +	sprintf(str, "%x", hdr->ih_ep); /* 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) +{ +	image_header_t *hdr = &header; +	char *local_args[2]; +	char str[16]; + +	sprintf(str, "%x", hdr->ih_ep); /* 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 /* 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 */ diff --git a/common/ft_build.c b/common/ft_build.c new file mode 100644 index 000000000..624a1e165 --- /dev/null +++ b/common/ft_build.c @@ -0,0 +1,695 @@ +/* + * OF flat tree builder + */ + +#include <common.h> +#include <malloc.h> +#include <environment.h> + +#include <asm/errno.h> +#include <stddef.h> + +#include <ft_build.h> + +#ifdef CONFIG_OF_FLAT_TREE + +/* align addr on a size boundary - adjust address up if needed -- Cort */ +#define _ALIGN(addr,size)       (((addr)+(size)-1)&(~((size)-1))) + +static void ft_put_word(struct ft_cxt *cxt, u32 v) +{ +	if (cxt->overflow)	/* do nothing */ +		return; + +	/* check for overflow */ +	if (cxt->p + 4 > cxt->pstr) { +		cxt->overflow = 1; +		return; +	} + +	*(u32 *) cxt->p = cpu_to_be32(v); +	cxt->p += 4; +} + +static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz) +{ +	u8 *p; + +	if (cxt->overflow)	/* do nothing */ +		return; + +	/* next pointer pos */ +	p = (u8 *) _ALIGN((unsigned long)cxt->p + sz, 4); + +	/* check for overflow */ +	if (p > cxt->pstr) { +		cxt->overflow = 1; +		return; +	} + +	memcpy(cxt->p, data, sz); +	if ((sz & 3) != 0) +		memset(cxt->p + sz, 0, 4 - (sz & 3)); +	cxt->p = p; +} + +void ft_begin_node(struct ft_cxt *cxt, const char *name) +{ +	ft_put_word(cxt, OF_DT_BEGIN_NODE); +	ft_put_bin(cxt, name, strlen(name) + 1); +} + +void ft_end_node(struct ft_cxt *cxt) +{ +	ft_put_word(cxt, OF_DT_END_NODE); +} + +void ft_nop(struct ft_cxt *cxt) +{ +	ft_put_word(cxt, OF_DT_NOP); +} + +static int lookup_string(struct ft_cxt *cxt, const char *name) +{ +	u8 *p; + +	p = cxt->pstr; +	while (p < cxt->pstr_begin) { +		if (strcmp(p, name) == 0) +			return p - cxt->p_begin; +		p += strlen(p) + 1; +	} + +	return -1; +} + +void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz) +{ +	int len, off; + +	if (cxt->overflow) +		return; + +	len = strlen(name) + 1; + +	off = lookup_string(cxt, name); +	if (off == -1) { +		/* check if we have space */ +		if (cxt->p + 12 + sz + len > cxt->pstr) { +			cxt->overflow = 1; +			return; +		} + +		cxt->pstr -= len; +		memcpy(cxt->pstr, name, len); +		off = cxt->pstr - cxt->p_begin; +	} + +	/* now put offset from beginning of *STRUCTURE* */ +	/* will be fixed up at the end */ +	ft_put_word(cxt, OF_DT_PROP); +	ft_put_word(cxt, sz); +	ft_put_word(cxt, off); +	ft_put_bin(cxt, data, sz); +} + +void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str) +{ +	ft_prop(cxt, name, str, strlen(str) + 1); +} + +void ft_prop_int(struct ft_cxt *cxt, const char *name, int val) +{ +	u32 v = cpu_to_be32((u32) val); + +	ft_prop(cxt, name, &v, 4); +} + +/* start construction of the flat OF tree */ +void ft_begin(struct ft_cxt *cxt, void *blob, int max_size) +{ +	struct boot_param_header *bph = blob; +	u32 off; + +	/* clear the cxt */ +	memset(cxt, 0, sizeof(*cxt)); + +	cxt->bph = bph; +	cxt->max_size = max_size; + +	/* zero everything in the header area */ +	memset(bph, 0, sizeof(*bph)); + +	bph->magic = cpu_to_be32(OF_DT_HEADER); +	bph->version = cpu_to_be32(0x10); +	bph->last_comp_version = cpu_to_be32(0x10); + +	/* start pointers */ +	cxt->pres_begin = (u8 *) _ALIGN((unsigned long)(bph + 1), 8); +	cxt->pres = cxt->pres_begin; + +	off = (unsigned long)cxt->pres_begin - (unsigned long)bph; +	bph->off_mem_rsvmap = cpu_to_be32(off); + +	((u64 *) cxt->pres)[0] = 0;	/* phys = 0, size = 0, terminate */ +	((u64 *) cxt->pres)[1] = 0; + +	cxt->p_anchor = cxt->pres + 16;	/* over the terminator */ +} + +/* add a reserver physical area to the rsvmap */ +void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size) +{ +	((u64 *) cxt->pres)[0] = cpu_to_be64(physaddr);	/* phys = 0, size = 0, terminate */ +	((u64 *) cxt->pres)[1] = cpu_to_be64(size); + +	cxt->pres += 18;	/* advance */ + +	((u64 *) cxt->pres)[0] = 0;	/* phys = 0, size = 0, terminate */ +	((u64 *) cxt->pres)[1] = 0; + +	/* keep track of size */ +	cxt->res_size = cxt->pres + 16 - cxt->pres_begin; + +	cxt->p_anchor = cxt->pres + 16;	/* over the terminator */ +} + +void ft_begin_tree(struct ft_cxt *cxt) +{ +	cxt->p_begin = cxt->p_anchor; +	cxt->pstr_begin = (char *)cxt->bph + cxt->max_size;	/* point at the end */ + +	cxt->p = cxt->p_begin; +	cxt->pstr = cxt->pstr_begin; +} + +int ft_end_tree(struct ft_cxt *cxt) +{ +	struct boot_param_header *bph = cxt->bph; +	int off, sz, sz1; +	u32 tag, v; +	u8 *p; + +	ft_put_word(cxt, OF_DT_END); + +	if (cxt->overflow) +		return -ENOMEM; + +	/* size of the areas */ +	cxt->struct_size = cxt->p - cxt->p_begin; +	cxt->strings_size = cxt->pstr_begin - cxt->pstr; + +	/* the offset we must move */ +	off = (cxt->pstr_begin - cxt->p_begin) - cxt->strings_size; + +	/* the new strings start */ +	cxt->pstr_begin = cxt->p_begin + cxt->struct_size; + +	/* move the whole string area */ +	memmove(cxt->pstr_begin, cxt->pstr, cxt->strings_size); + +	/* now perform the fixup of the strings */ +	p = cxt->p_begin; +	while ((tag = be32_to_cpu(*(u32 *) p)) != OF_DT_END) { +		p += 4; + +		if (tag == OF_DT_BEGIN_NODE) { +			p = (u8 *) _ALIGN((unsigned long)p + strlen(p) + 1, 4); +			continue; +		} + +		if (tag == OF_DT_END_NODE || tag == OF_DT_NOP) +			continue; + +		if (tag != OF_DT_PROP) +			return -EINVAL; + +		sz = be32_to_cpu(*(u32 *) p); +		p += 4; + +		v = be32_to_cpu(*(u32 *) p); +		v -= off; +		*(u32 *) p = cpu_to_be32(v);	/* move down */ +		p += 4; + +		p = (u8 *) _ALIGN((unsigned long)p + sz, 4); +	} + +	/* fix sizes */ +	p = (char *)cxt->bph; +	sz = (cxt->pstr_begin + cxt->strings_size) - p; +	sz1 = _ALIGN(sz, 16);	/* align at 16 bytes */ +	if (sz != sz1) +		memset(p + sz, 0, sz1 - sz); +	bph->totalsize = cpu_to_be32(sz1); +	bph->off_dt_struct = cpu_to_be32(cxt->p_begin - p); +	bph->off_dt_strings = cpu_to_be32(cxt->pstr_begin - p); + +	/* the new strings start */ +	cxt->pstr_begin = cxt->p_begin + cxt->struct_size; +	cxt->pstr = cxt->pstr_begin + cxt->strings_size; + +	return 0; +} + +/**********************************************************************/ + +static inline int isprint(int c) +{ +	return c >= 0x20 && c <= 0x7e; +} + +static int is_printable_string(const void *data, int len) +{ +	const char *s = data; +	const char *ss; + +	/* zero length is not */ +	if (len == 0) +		return 0; + +	/* must terminate with zero */ +	if (s[len - 1] != '\0') +		return 0; + +	ss = s; +	while (*s && isprint(*s)) +		s++; + +	/* not zero, or not done yet */ +	if (*s != '\0' || (s + 1 - ss) < len) +		return 0; + +	return 1; +} + +static void print_data(const void *data, int len) +{ +	int i; +	const u8 *s; + +	/* no data, don't print */ +	if (len == 0) +		return; + +	if (is_printable_string(data, len)) { +		printf(" = \"%s\"", (char *)data); +		return; +	} + +	switch (len) { +	case 1:		/* byte */ +		printf(" = <0x%02x>", (*(u8 *) data) & 0xff); +		break; +	case 2:		/* half-word */ +		printf(" = <0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff); +		break; +	case 4:		/* word */ +		printf(" = <0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); +		break; +	case 8:		/* double-word */ +		printf(" = <0x%16llx>", be64_to_cpu(*(uint64_t *) data)); +		break; +	default:		/* anything else... hexdump */ +		printf(" = ["); +		for (i = 0, s = data; i < len; i++) +			printf("%02x%s", s[i], i < len - 1 ? " " : ""); +		printf("]"); + +		break; +	} +} + +void ft_dump_blob(const void *bphp) +{ +	const struct boot_param_header *bph = bphp; +	const uint64_t *p_rsvmap = (const uint64_t *) +		((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap)); +	const u32 *p_struct = (const u32 *) +		((const char *)bph + be32_to_cpu(bph->off_dt_struct)); +	const u32 *p_strings = (const u32 *) +		((const char *)bph + be32_to_cpu(bph->off_dt_strings)); +	u32 tag; +	const u32 *p; +	const char *s, *t; +	int depth, sz, shift; +	int i; +	uint64_t addr, size; + +	if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { +		/* not valid tree */ +		return; +	} + +	depth = 0; +	shift = 4; + +	for (i = 0;; i++) { +		addr = be64_to_cpu(p_rsvmap[i * 2]); +		size = be64_to_cpu(p_rsvmap[i * 2 + 1]); +		if (addr == 0 && size == 0) +			break; + +		printf("/memreserve/ 0x%llx 0x%llx;\n", addr, size); +	} + +	p = p_struct; +	while ((tag = be32_to_cpu(*p++)) != OF_DT_END) { + +		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ + +		if (tag == OF_DT_BEGIN_NODE) { +			s = (const char *)p; +			p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4); + +			printf("%*s%s {\n", depth * shift, "", s); + +			depth++; +			continue; +		} + +		if (tag == OF_DT_END_NODE) { +			depth--; + +			printf("%*s};\n", depth * shift, ""); +			continue; +		} + +		if (tag == OF_DT_NOP) { +			printf("%*s[NOP]\n", depth * shift, ""); +			continue; +		} + +		if (tag != OF_DT_PROP) { +			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", +				depth * shift, "", tag); +			break; +		} +		sz = be32_to_cpu(*p++); +		s = (const char *)p_strings + be32_to_cpu(*p++); +		t = (const char *)p; +		p = (const u32 *)_ALIGN((unsigned long)p + sz, 4); +		printf("%*s%s", depth * shift, "", s); +		print_data(t, sz); +		printf(";\n"); +	} +} + +void ft_backtrack_node(struct ft_cxt *cxt) +{ +	if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE) +		return;		/* XXX only for node */ + +	cxt->p -= 4; +} + +/* note that the root node of the blob is "peeled" off */ +void ft_merge_blob(struct ft_cxt *cxt, void *blob) +{ +	struct boot_param_header *bph = (struct boot_param_header *)blob; +	u32 *p_struct = (u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_struct)); +	u32 *p_strings = +	    (u32 *) ((char *)bph + be32_to_cpu(bph->off_dt_strings)); +	u32 tag, *p; +	char *s, *t; +	int depth, sz; + +	if (be32_to_cpu(*(u32 *) (cxt->p - 4)) != OF_DT_END_NODE) +		return;		/* XXX only for node */ + +	cxt->p -= 4; + +	depth = 0; +	p = p_struct; +	while ((tag = be32_to_cpu(*p++)) != OF_DT_END) { + +		/* printf("tag: 0x%08x (%d) - %d\n", tag, p - p_struct, depth); */ + +		if (tag == OF_DT_BEGIN_NODE) { +			s = (char *)p; +			p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4); + +			if (depth++ > 0) +				ft_begin_node(cxt, s); + +			continue; +		} + +		if (tag == OF_DT_END_NODE) { +			ft_end_node(cxt); +			if (--depth == 0) +				break; +			continue; +		} + +		if (tag == OF_DT_NOP) +			continue; + +		if (tag != OF_DT_PROP) +			break; + +		sz = be32_to_cpu(*p++); +		s = (char *)p_strings + be32_to_cpu(*p++); +		t = (char *)p; +		p = (u32 *) _ALIGN((unsigned long)p + sz, 4); + +		ft_prop(cxt, s, t, sz); +	} +} + +void *ft_get_prop(void *bphp, const char *propname, int *szp) +{ +	struct boot_param_header *bph = bphp; +	uint32_t *p_struct = +	    (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_struct)); +	uint32_t *p_strings = +	    (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_strings)); +	uint32_t version = be32_to_cpu(bph->version); +	uint32_t tag; +	uint32_t *p; +	char *s, *t; +	char *ss; +	int sz; +	static char path[256], prop[256]; + +	path[0] = '\0'; + +	p = p_struct; +	while ((tag = be32_to_cpu(*p++)) != OF_DT_END) { + +		if (tag == OF_DT_BEGIN_NODE) { +			s = (char *)p; +			p = (uint32_t *) _ALIGN((unsigned long)p + strlen(s) + +						1, 4); +			strcat(path, s); +			strcat(path, "/"); +			continue; +		} + +		if (tag == OF_DT_END_NODE) { +			path[strlen(path) - 1] = '\0'; +			ss = strrchr(path, '/'); +			if (ss != NULL) +				ss[1] = '\0'; +			continue; +		} + +		if (tag == OF_DT_NOP) +			continue; + +		if (tag != OF_DT_PROP) +			break; + +		sz = be32_to_cpu(*p++); +		s = (char *)p_strings + be32_to_cpu(*p++); +		if (version < 0x10 && sz >= 8) +			p = (uint32_t *) _ALIGN((unsigned long)p, 8); +		t = (char *)p; +		p = (uint32_t *) _ALIGN((unsigned long)p + sz, 4); + +		strcpy(prop, path); +		strcat(prop, s); + +		if (strcmp(prop, propname) == 0) { +			*szp = sz; +			return t; +		} +	} + +	return NULL; +} + +/********************************************************************/ + +extern unsigned char oftree_dtb[]; +extern unsigned int oftree_dtb_len; + +/* Function that returns a character from the environment */ +extern uchar(*env_get_char) (int); + +#define BDM(x)	{	.name = #x, .offset = offsetof(bd_t, bi_ ##x ) } + +static const struct { +	const char *name; +	int offset; +} bd_map[] = { +	BDM(memstart), +	BDM(memsize), +	BDM(flashstart), +	BDM(flashsize), +	BDM(flashoffset), +	BDM(sramstart), +	BDM(sramsize), +#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \ +	|| defined(CONFIG_E500) +	BDM(immr_base), +#endif +#if defined(CONFIG_MPC5xxx) +	BDM(mbar_base), +#endif +#if defined(CONFIG_MPC83XX) +	BDM(immrbar), +#endif +#if defined(CONFIG_MPC8220) +	BDM(mbar_base), +	BDM(inpfreq), +	BDM(pcifreq), +	BDM(pevfreq), +	BDM(flbfreq), +	BDM(vcofreq), +#endif +	BDM(bootflags), +	BDM(ip_addr), +	BDM(intfreq), +	BDM(busfreq), +#ifdef CONFIG_CPM2 +	BDM(cpmfreq), +	BDM(brgfreq), +	BDM(sccfreq), +	BDM(vco), +#endif +#if defined(CONFIG_MPC5xxx) +	BDM(ipbfreq), +	BDM(pcifreq), +#endif +	BDM(baudrate), +}; + +void ft_setup(void *blob, int size, bd_t * bd) +{ +	DECLARE_GLOBAL_DATA_PTR; +	u8 *end; +	u32 *p; +	int len; +	struct ft_cxt cxt; +	int i, k, nxt; +	static char tmpenv[256]; +	char *s, *lval, *rval; +	ulong clock; +	uint32_t v; + +	/* disable OF tree; booting old kernel */ +	if (getenv("disable_of") != NULL) { +		memcpy(blob, bd, sizeof(*bd)); +		return; +	} + +	ft_begin(&cxt, blob, size); + +	/* fs_add_rsvmap not used */ + +	ft_begin_tree(&cxt); + +	ft_begin_node(&cxt, ""); + +	ft_end_node(&cxt); + +	/* copy RO tree */ +	ft_merge_blob(&cxt, oftree_dtb); + +	/* back into root */ +	ft_backtrack_node(&cxt); + +	ft_begin_node(&cxt, "u-boot-env"); + +	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { +		for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) ; +		s = tmpenv; +		for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k) +			*s++ = env_get_char(k); +		*s++ = '\0'; +		lval = tmpenv; +		s = strchr(tmpenv, '='); +		if (s != NULL) { +			*s++ = '\0'; +			rval = s; +		} else +			continue; +		ft_prop_str(&cxt, lval, rval); +	} + +	ft_end_node(&cxt); + +	ft_begin_node(&cxt, "chosen"); + +	ft_prop_str(&cxt, "name", "chosen"); +	ft_prop_str(&cxt, "bootargs", getenv("bootargs")); +	ft_prop_int(&cxt, "linux,platform", 0x600);	/* what is this? */ + +	ft_end_node(&cxt); + +	ft_end_node(&cxt);	/* end root */ + +	ft_end_tree(&cxt); + +	/* +	   printf("merged OF-tree\n"); +	   ft_dump_blob(blob); +	 */ + +	/* paste the bd_t at the end of the flat tree */ +	end = (char *)blob + +	    be32_to_cpu(((struct boot_param_header *)blob)->totalsize); +	memcpy(end, bd, sizeof(*bd)); + +#ifdef CONFIG_PPC + +	for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { +		sprintf(tmpenv, "/bd_t/%s", bd_map[i].name); +		v = *(uint32_t *)((char *)bd + bd_map[i].offset); + +		p = ft_get_prop(blob, tmpenv, &len); +		if (p != NULL) +			*p = cpu_to_be32(v); +	} + +	p = ft_get_prop(blob, "/bd_t/enetaddr", &len); +	if (p != NULL) +		memcpy(p, bd->bi_enetaddr, 6); + +	p = ft_get_prop(blob, "/bd_t/ethspeed", &len); +	if (p != NULL) +		*p = cpu_to_be32((uint32_t) bd->bi_ethspeed); + +	clock = bd->bi_intfreq; +	p = ft_get_prop(blob, "/cpus/" OF_CPU "/clock-frequency", &len); +	if (p != NULL) +		*p = cpu_to_be32(clock); + +#ifdef OF_TBCLK +	clock = OF_TBCLK; +	p = ft_get_prop(blob, "/cpus/" OF_CPU "/timebase-frequency", &len); +	if (p != NULL) +		*p = cpu_to_be32(OF_TBCLK); +#endif + +#endif				/* __powerpc__ */ + +	/* +	   printf("final OF-tree\n"); +	   ft_dump_blob(blob); +	 */ + +} + +#endif diff --git a/include/ft_build.h b/include/ft_build.h new file mode 100644 index 000000000..9104b1a55 --- /dev/null +++ b/include/ft_build.h @@ -0,0 +1,66 @@ +/* + * OF Flat tree builder + * + */ + +#ifndef FT_BUILD_H +#define FT_BUILD_H + +#include <linux/types.h> +#include <asm/u-boot.h> + +/* Definitions used by the flattened device tree */ +#define OF_DT_HEADER		0xd00dfeed	/* marker */ +#define OF_DT_BEGIN_NODE	0x1	/* Start of node, full name */ +#define OF_DT_END_NODE		0x2	/* End node */ +#define OF_DT_PROP		0x3	/* Property: name off, size, +					 * content */ +#define OF_DT_NOP		0x4	/* nop */ +#define OF_DT_END		0x9 + +#define OF_DT_VERSION		0x10 + +struct boot_param_header { +	u32 magic;		/* magic word OF_DT_HEADER */ +	u32 totalsize;		/* total size of DT block */ +	u32 off_dt_struct;	/* offset to structure */ +	u32 off_dt_strings;	/* offset to strings */ +	u32 off_mem_rsvmap;	/* offset to memory reserve map */ +	u32 version;		/* format version */ +	u32 last_comp_version;	/* last compatible version */ +	/* version 2 fields below */ +	u32 boot_cpuid_phys;	/* Physical CPU id we're booting on */ +	/* version 3 fields below */ +	u32 dt_strings_size;	/* size of the DT strings block */ +}; + +struct ft_cxt { +	struct boot_param_header *bph; +	int max_size;		/* maximum size of tree */ +	int overflow;		/* set when this happens */ +	u8 *p, *pstr, *pres;	/* running pointers */ +	u8 *p_begin, *pstr_begin, *pres_begin;	/* starting pointers */ +	u8 *p_anchor;		/* start of constructed area */ +	int struct_size, strings_size, res_size; +}; + +void ft_begin_node(struct ft_cxt *cxt, const char *name); +void ft_end_node(struct ft_cxt *cxt); + +void ft_begin_tree(struct ft_cxt *cxt); +int ft_end_tree(struct ft_cxt *cxt); + +void ft_nop(struct ft_cxt *cxt); +void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz); +void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str); +void ft_prop_int(struct ft_cxt *cxt, const char *name, int val); +void ft_begin(struct ft_cxt *cxt, void *blob, int max_size); +void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size); + +void ft_setup(void *blob, int size, bd_t * bd); + +void ft_dump_blob(const void *bphp); +void ft_merge_blob(struct ft_cxt *cxt, void *blob); +void *ft_get_prop(void *bphp, const char *propname, int *szp); + +#endif |