diff options
Diffstat (limited to 'common/cmd_fdt.c')
| -rw-r--r-- | common/cmd_fdt.c | 874 | 
1 files changed, 874 insertions, 0 deletions
| diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c new file mode 100644 index 000000000..968bade62 --- /dev/null +++ b/common/cmd_fdt.c @@ -0,0 +1,874 @@ +/* + * (C) Copyright 2007 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com + * Based on code written by: + *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and + *   Matthew McClintock <msm@freescale.com> + * + * 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 <common.h> +#include <command.h> +#include <linux/ctype.h> +#include <linux/types.h> + +#ifdef CONFIG_OF_LIBFDT +#include <asm/global_data.h> +#include <fdt.h> +#include <libfdt.h> + +#define MAX_LEVEL	32		/* how deeply nested we will go */ +#define SCRATCHPAD	1024	/* bytes of scratchpad memory */ + +/* + * Global data (for the gd->bd) + */ +DECLARE_GLOBAL_DATA_PTR; + +/* + * Scratchpad memory. + */ +static char data[SCRATCHPAD]; + + +/* + * Function prototypes/declarations. + */ +static int fdt_valid(void); +static void print_data(const void *data, int len); +static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end); +static int fdt_env(void *fdt); +static int fdt_bd_t(void *fdt); + + +/* + * Flattened Device Tree command, see the help for parameter definitions. + */ +int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +	char		op; + +	if (argc < 2) { +		printf ("Usage:\n%s\n", cmdtp->usage); +		return 1; +	} + +	/* +	 * Figure out which subcommand was given +	 */ +	op = argv[1][0]; +	/******************************************************************** +	 * Set the address of the fdt +	 ********************************************************************/ +	if (op == 'a') { +		/* +		 * Set the address [and length] of the fdt. +		 */ +		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + +		if (!fdt_valid()) { +			return 1; +		} + +		if (argc >= 4) { +			int  len; +			int  err; +			/* +			 * Optional new length +			 */ +			len =  simple_strtoul(argv[3], NULL, 16); +			if (len < fdt_totalsize(fdt)) { +				printf ("New length %d < existing length %d, ignoring.\n", +					len, fdt_totalsize(fdt)); +			} else { +				/* +				 * Open in place with a new length. +				 */ +				err = fdt_open_into(fdt, fdt, len); +				if (err != 0) { +					printf ("libfdt: %s\n", fdt_strerror(err)); +				} +			} +		} + +	/******************************************************************** +	 * Move the fdt +	 ********************************************************************/ +	} else if (op == 'm') { +		struct fdt_header *newaddr; +		int  len; +		int  err; + +		if (argc != 5) { +			printf ("Usage:\n%s\n", cmdtp->usage); +			return 1; +		} + +		/* +		 * Set the address and length of the fdt. +		 */ +		fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); +		if (!fdt_valid()) { +			return 1; +		} + +		newaddr = (struct fdt_header *)simple_strtoul(argv[3], NULL, 16); +		len     =  simple_strtoul(argv[4], NULL, 16); +		if (len < fdt_totalsize(fdt)) { +			printf ("New length %d < existing length %d, aborting.\n", +				len, fdt_totalsize(fdt)); +			return 1; +		} + +		/* +		 * Copy to the new location. +		 */ +		err = fdt_open_into(fdt, newaddr, len); +		if (err != 0) { +			printf ("libfdt: %s\n", fdt_strerror(err)); +			return 1; +		} +		fdt = newaddr; + +	/******************************************************************** +	 * Set the value of a node in the fdt. +	 ********************************************************************/ +	} else if (op == 's') { +		char *pathp;		/* path */ +		char *prop;			/* property */ +		struct fdt_property *nodep;	/* node struct pointer */ +		char *newval;		/* value from the user (as a string) */ +		char *vp;			/* temporary value pointer */ +		char *cp;			/* temporary char pointer */ +		int  nodeoffset;	/* node offset from libfdt */ +		int  len;			/* new length of the property */ +		int  oldlen;		/* original length of the property */ +		unsigned long tmp;	/* holds converted values */ +		int  ret;			/* return value */ + +		/* +		 * Parameters: Node path, property, value. +		 */ +		if (argc < 5) { +			printf ("Usage:\n%s\n", cmdtp->usage); +			return 1; +		} + +		pathp  = argv[2]; +		prop   = argv[3]; +		newval = argv[4]; + +		if (strcmp(pathp, "/") == 0) { +			nodeoffset = 0; +		} else { +			nodeoffset = fdt_path_offset (fdt, pathp); +			if (nodeoffset < 0) { +				/* +			 	 * Not found or something else bad happened. +			 	 */ +				printf ("libfdt: %s\n", fdt_strerror(nodeoffset)); +				return 1; +			} +		} +		nodep = fdt_getprop (fdt, nodeoffset, prop, &oldlen); +		if (oldlen < 0) { +			printf ("libfdt %s\n", fdt_strerror(oldlen)); +			return 1; +		} else if (oldlen == 0) { +			/* +			 * The specified property has no value +			 */ +			printf("%s has no value, cannot set one (yet).\n", prop); +			return 1; +		} else { +			/* +			 * Convert the new property +			 */ +			vp = data; +			if (*newval == '<') { +				/* +				 * Bigger values than bytes. +				 */ +				len = 0; +				newval++; +				while ((*newval != '>') && (*newval != '\0')) { +					cp = newval; +					tmp = simple_strtoul(cp, &newval, 16); +					if ((newval - cp) <= 2) { +						*vp = tmp & 0xFF; +						vp  += 1; +						len += 1; +					} else if ((newval - cp) <= 4) { +						*(uint16_t *)vp = __cpu_to_be16(tmp); +						vp  += 2; +						len += 2; +					} else if ((newval - cp) <= 8) { +						*(uint32_t *)vp = __cpu_to_be32(tmp); +						vp  += 4; +						len += 4; +					} else { +						printf("Sorry, I could not convert \"%s\"\n", cp); +						return 1; +					} +					while (*newval == ' ') +						newval++; +				} +				if (*newval != '>') { +					printf("Unexpected character '%c'\n", *newval); +					return 1; +				} +			} else if (*newval == '[') { +				/* +				 * Byte stream.  Convert the values. +				 */ +				len = 0; +				newval++; +				while ((*newval != ']') && (*newval != '\0')) { +					tmp = simple_strtoul(newval, &newval, 16); +					*vp++ = tmp & 0xFF; +					len++; +					while (*newval == ' ') +						newval++; +				} +				if (*newval != ']') { +					printf("Unexpected character '%c'\n", *newval); +					return 1; +				} +			} else { +				/* +				 * Assume it is a string.  Copy it into our data area for +				 * convenience (including the terminating '\0'). +				 */ +				len = strlen(newval) + 1; +				strcpy(data, newval); +			} + +			ret = fdt_setprop(fdt, nodeoffset, prop, data, len); +			if (ret < 0) { +				printf ("libfdt %s\n", fdt_strerror(ret)); +				return 1; +			} +		} + +	/******************************************************************** +	 * Print (recursive) / List (single level) +	 ********************************************************************/ +	} else if ((op == 'p') || (op == 'l')) { +		/* +		 * Recursively print (a portion of) the fdt. +		 */ +		static int offstack[MAX_LEVEL]; +		static char tabs[MAX_LEVEL+1] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; +		int depth = MAX_LEVEL;	/* how deep to print */ +		char *pathp;		/* path */ +		char *prop;			/* property */ +		void *nodep;		/* property node pointer */ +		int  nodeoffset;	/* node offset from libfdt */ +		int  nextoffset;	/* next node offset from libfdt */ +		uint32_t tag;		/* tag */ +		int  len;			/* length of the property */ +		int  level = 0;		/* keep track of nesting level */ + +		/* +		 * list is an alias for print, but limited to 1 level +		 */ +		if (op == 'l') { +			depth = 1; +		} + +		/* +		 * Get the starting path.  The root node is an oddball, +		 * the offset is zero and has no name. +		 */ +		pathp = argv[2]; +		if (argc > 3) +			prop = argv[3]; +		else +			prop = NULL; + +		if (strcmp(pathp, "/") == 0) { +			nodeoffset = 0; +			printf("/"); +		} else { +			nodeoffset = fdt_path_offset (fdt, pathp); +			if (nodeoffset < 0) { +				/* +				 * Not found or something else bad happened. +				 */ +				printf ("libfdt %s\n", fdt_strerror(nodeoffset)); +				return 1; +			} +		} +		/* +		 * The user passed in a property as well as node path.  Print only +		 * the given property and then return. +		 */ +		if (prop) { +			nodep = fdt_getprop (fdt, nodeoffset, prop, &len); +			if (len == 0) { +				printf("%s %s\n", pathp, prop);	/* no property value */ +				return 0; +			} else if (len > 0) { +				printf("%s=", prop); +				print_data (nodep, len); +				printf("\n"); +				return 0; +			} else { +				printf ("libfdt %s\n", fdt_strerror(len)); +				return 1; +			} +		} + +		/* +		 * The user passed in a node path and no property, print the node +		 * and all subnodes. +		 */ +		offstack[0] = nodeoffset; + +		while(level >= 0) { +			tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, &pathp); +			switch(tag) { +			case FDT_BEGIN_NODE: +				if(level <= depth) +					printf("%s%s {\n", &tabs[MAX_LEVEL - level], pathp); +				level++; +				offstack[level] = nodeoffset; +				if (level >= MAX_LEVEL) { +					printf("Aaaiii <splat> nested too deep.\n"); +					return 1; +				} +				break; +			case FDT_END_NODE: +				level--; +				if(level <= depth) +					printf("%s};\n", &tabs[MAX_LEVEL - level]); +				if (level == 0) { +					level = -1;		/* exit the loop */ +				} +				break; +			case FDT_PROP: +				nodep = fdt_getprop (fdt, offstack[level], pathp, &len); +				if (len < 0) { +					printf ("libfdt %s\n", fdt_strerror(len)); +					return 1; +				} else if (len == 0) { +					/* the property has no value */ +					if(level <= depth) +						printf("%s%s;\n", &tabs[MAX_LEVEL - level], pathp); +				} else { +					if(level <= depth) { +						printf("%s%s=", &tabs[MAX_LEVEL - level], pathp); +						print_data (nodep, len); +						printf(";\n"); +					} +				} +				break; +			case FDT_NOP: +				break; +			case FDT_END: +				return 1; +			default: +				if(level <= depth) +					printf("Unknown tag 0x%08X\n", tag); +				return 1; +			} +			nodeoffset = nextoffset; +		} + +	/******************************************************************** +	 * Remove a property/node +	 ********************************************************************/ +	} else if (op == 'r') { +		int  nodeoffset;	/* node offset from libfdt */ +		int  err; + +		/* +		 * Get the path.  The root node is an oddball, the offset +		 * is zero and has no name. +		 */ +		if (strcmp(argv[2], "/") == 0) { +			nodeoffset = 0; +		} else { +			nodeoffset = fdt_path_offset (fdt, argv[2]); +			if (nodeoffset < 0) { +				/* +				 * Not found or something else bad happened. +				 */ +				printf ("libfdt %s\n", fdt_strerror(nodeoffset)); +				return 1; +			} +		} +		/* +		 * Do the delete.  A fourth parameter means delete a property, +		 * otherwise delete the node. +		 */ +		if (argc > 3) { +			err = fdt_delprop(fdt, nodeoffset, argv[3]); +			if (err < 0) { +				printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); +				return err; +			} +		} else { +			err = fdt_del_node(fdt, nodeoffset); +			if (err < 0) { +				printf("fdt_del_node libfdt: %s\n", fdt_strerror(err)); +				return err; +			} +		} + +	/******************************************************************** +	 * Create a chosen node +	 ********************************************************************/ +	} else if (op == 'c') { +		fdt_chosen(fdt, 0, 0); + +	/******************************************************************** +	 * Create a u-boot-env node +	 ********************************************************************/ +	} else if (op == 'e') { +		fdt_env(fdt); + +	/******************************************************************** +	 * Create a bd_t node +	 ********************************************************************/ +	} else if (op == 'b') { +		fdt_bd_t(fdt); + +	/******************************************************************** +	 * Unrecognized command +	 ********************************************************************/ +	} else { +		printf ("Usage:\n%s\n", cmdtp->usage); +		return 1; +	} + +	return 0; +} + +/********************************************************************/ + +static int fdt_valid(void) +{ +	if (fdt == NULL) { +		printf ("The address of the fdt is invalid.\n"); +		return 0; +	} +	if (!fdt || (fdt_magic(fdt) != FDT_MAGIC)) { +		fdt = NULL; +		printf ("Unrecognized fdt: bad magic\n"); +		return 0; +	} +	if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) { +		printf ("Unsupported fdt version: $d < %d\n", +			FDT_FIRST_SUPPORTED_VERSION, fdt_version(fdt)); +		fdt = NULL; +		return 0; +	} +	if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) { +		printf ("Unsupported fdt version: $d > %d\n", +			fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION); +		fdt = NULL; +		return 0; +	} +	return 1; +} + +/********************************************************************/ + +/* + * OF flat tree handling + * Written by: Pantelis Antoniou <pantelis.antoniou@gmail.com> + * Updated by: Matthew McClintock <msm@freescale.com> + * Converted to libfdt by: Gerald Van Baren <vanbaren@cideas.com> + */ + +static int is_printable_string(const void *data, int len) +{ +	const char *s = data; + +	/* zero length is not */ +	if (len == 0) +		return 0; + +	/* must terminate with zero */ +	if (s[len - 1] != '\0') +		return 0; + +	/* printable or a null byte (concatenated strings) */ +	while (((*s == '\0') || isprint(*s)) && (len > 0)) { +		/* +		 * If we see a null, there are three possibilities: +		 * 1) If len == 1, it is the end of the string, printable +		 * 2) Next character also a null, not printable. +		 * 3) Next character not a null, continue to check. +		 */ +		if (s[0] == '\0') { +			if (len == 1) +				return 1; +			if (s[1] == '\0') +				return 0; +		} +		s++; +		len--; +	} + +	/* Not the null termination, or not done yet: not printable */ +	if (*s != '\0' || (len != 0)) +		return 0; + +	return 1; +} + +static void print_data(const void *data, int len) +{ +	int j; +	const u8 *s; + +	/* no data, don't print */ +	if (len == 0) +		return; + +	/* +	 * It is a string, but it may have multiple strings (embedded '\0's). +	 */ +	if (is_printable_string(data, len)) { +		puts("\""); +		j = 0; +		while (j < len) { +			if (j > 0) +				puts("\", \""); +			puts(data); +			j    += strlen(data) + 1; +			data += strlen(data) + 1; +		} +		puts("\""); +		return; +	} + +	switch (len) { +	case 1:	 /* byte */ +		printf("<%02x>", (*(u8 *) data) & 0xff); +		break; +	case 2:	 /* half-word */ +		printf("<%04x>", be16_to_cpu(*(u16 *) data) & 0xffff); +		break; +	case 4:	 /* word */ +		printf("<%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); +		break; +	case 8:	 /* double-word */ +#if __WORDSIZE == 64 +		printf("<%016llx>", be64_to_cpu(*(uint64_t *) data)); +#else +		printf("<%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU); +		data += 4; +		printf("%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); +#endif +		break; +	default:		/* anything else... hexdump */ +		printf("["); +		for (j = 0, s = data; j < len; j++) +			printf("%02x%s", s[j], j < len - 1 ? " " : ""); +		printf("]"); + +		break; +	} +} + +/********************************************************************/ + +static int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end) +{ +	bd_t *bd = gd->bd; +	int   nodeoffset; +	int   err; +	u32   tmp;			/* used to set 32 bit integer properties */ +	char  *str;			/* used to set string properties */ +	ulong clock; + +	if (initrd_start && initrd_end) { +		err = fdt_add_reservemap_entry(fdt, +			initrd_start, initrd_end - initrd_start + 1); +		if (err < 0) { +			printf("libfdt: %s\n", fdt_strerror(err)); +			return err; +		} +	} + +	/* +	 * See if we already have a "chosen" node, create it if not. +	 */ +	nodeoffset = fdt_path_offset (fdt, "/chosen"); +	if (nodeoffset < 0) { +		/* +		 * Create a new node "/chosen" (offset 0 is root level) +		 */ +		nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); +		if (nodeoffset < 0) { +			printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +			return nodeoffset; +		} +	} + +	str = getenv("bootargs"); +	if (str != NULL) { +		err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +	} +	if (initrd_start && initrd_end) { +		tmp = __cpu_to_be32(initrd_start); +		err = fdt_setprop(fdt, nodeoffset, "linux,initrd-start", &tmp, sizeof(tmp)); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +		tmp = __cpu_to_be32(initrd_end); +		err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp)); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +	} +#ifdef OF_STDOUT_PATH +	err = fdt_setprop(fdt, nodeoffset, "linux,stdout-path", OF_STDOUT_PATH, strlen(OF_STDOUT_PATH)+1); +	if (err < 0) +		printf("libfdt: %s\n", fdt_strerror(err)); +#endif + +	nodeoffset = fdt_path_offset (fdt, "/cpus"); +	if (nodeoffset >= 0) { +		clock = cpu_to_be32(bd->bi_intfreq); +		err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +	} +#ifdef OF_TBCLK +	nodeoffset = fdt_path_offset (fdt, "/cpus/" OF_CPU "/timebase-frequency"); +	if (nodeoffset >= 0) { +		clock = cpu_to_be32(OF_TBCLK); +		err = fdt_setprop(fdt, nodeoffset, "clock-frequency", &clock, 4); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +	} +#endif +} + +/********************************************************************/ + +#ifdef CONFIG_OF_HAS_BD_T + +/* 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), +}; + +static int fdt_env(void *fdt) +{ +	int   nodeoffset; +	int   err; +	int   k, nxt; +	int i; +	static char tmpenv[256]; + +	/* +	 * See if we already have a "u-boot-env" node, delete it if so. +	 * Then create a new empty node. +	 */ +	nodeoffset = fdt_path_offset (fdt, "/u-boot-env"); +	if (nodeoffset >= 0) { +		err = fdt_del_node(fdt, nodeoffset); +		if (err < 0) { +			printf("libfdt: %s\n", fdt_strerror(err)); +			return err; +		} +	} +	/* +	 * Create a new node "/u-boot-env" (offset 0 is root level) +	 */ +	nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env"); +	if (nodeoffset < 0) { +		printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +		return nodeoffset; +	} + +	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) { +		char *s, *lval, *rval; + +		/* +		 * Find the end of the name=definition +		 */ +		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; +		/* +		 * Find the first '=': it separates the name from the value +		 */ +		s = strchr(tmpenv, '='); +		if (s != NULL) { +			*s++ = '\0'; +			rval = s; +		} else +			continue; +		err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1); +		if (err < 0) { +			printf("\"%s\" - libfdt: %s\n", lval, fdt_strerror(err)); +			return err; +		} +	} +	return 0; +} +#endif /* CONFIG_OF_HAS_UBOOT_ENV */ + +/********************************************************************/ + +#ifdef CONFIG_OF_HAS_BD_T +static int fdt_bd_t(void *fdt) +{ +	bd_t *bd = gd->bd; +	int   nodeoffset; +	int   err; +	u32   tmp;			/* used to set 32 bit integer properties */ +	int i; + +	/* +	 * See if we already have a "bd_t" node, delete it if so. +	 * Then create a new empty node. +	 */ +	nodeoffset = fdt_path_offset (fdt, "/bd_t"); +	if (nodeoffset >= 0) { +		err = fdt_del_node(fdt, nodeoffset); +		if (err < 0) { +			printf("libfdt: %s\n", fdt_strerror(err)); +			return err; +		} +	} +	/* +	 * Create a new node "/bd_t" (offset 0 is root level) +	 */ +	nodeoffset = fdt_add_subnode(fdt, 0, "bd_t"); +	if (nodeoffset < 0) { +		printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +		return nodeoffset; +	} +	/* +	 * Use the string/pointer structure to create the entries... +	 */ +	for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) { +		tmp = cpu_to_be32(getenv("bootargs")); +		err = fdt_setprop(fdt, nodeoffset, bd_map[i].name, &tmp, sizeof(tmp)); +		if (err < 0) +			printf("libfdt: %s\n", fdt_strerror(err)); +	} +	/* +	 * Add a couple of oddball entries... +	 */ +	err = fdt_setprop(fdt, nodeoffset, "enetaddr", &bd->bi_enetaddr, 6); +	if (err < 0) +		printf("libfdt: %s\n", fdt_strerror(err)); +	err = fdt_setprop(fdt, nodeoffset, "ethspeed", &bd->bi_ethspeed, 4); +	if (err < 0) +		printf("libfdt: %s\n", fdt_strerror(err)); + +#ifdef CONFIG_OF_BOARD_SETUP +	ft_board_setup(fdt, bd); +#endif + +	return 0; +} +#endif /* CONFIG_OF_HAS_BD_T */ + +/********************************************************************/ + +U_BOOT_CMD( +	fdt,	5,	0,	do_fdt, +	"fdt     - flattened device tree utility commands\n", +	    "addr   <addr> [<length>]        - Set the fdt location to <addr>\n" +	"fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr>\n" +	"fdt print  <path> [<prop>]          - Recursive print starting at <path>\n" +	"fdt list   <path> [<prop>]          - Print one level starting at <path>\n" +	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n" +	"fdt mknode <path> <node>            - Create a new node after <path>\n" +	"fdt rm     <path> [<prop>]          - Delete the node or <property>\n" +	"fdt chosen - Add/update the \"/chosen\" branch in the tree\n" +#ifdef CONFIG_OF_HAS_UBOOT_ENV +	"fdt env    - Add/replace the \"/u-boot-env\" branch in the tree\n" +#endif +#ifdef CONFIG_OF_HAS_BD_T +	"fdt bd_t   - Add/replace the \"/bd_t\" branch in the tree\n" +#endif +	"Hints:\n" +	" * Set a larger length with the fdt addr command to add to the blob.\n" +	" * If the property you are setting/printing has a '#' character,\n" +	"     you MUST escape it with a \\ character or quote it with \" or\n" +	"     it will be ignored as a comment.\n" +	" * If the value has spaces in it, you MUST escape the spaces with\n" +	"     \\ characters or quote it with \"\"\n" +	"Examples: fdt print /               # print the whole tree\n" +	"          fdt print /cpus \"#address-cells\"\n" +	"          fdt set   /cpus \"#address-cells\" \"[00 00 00 01]\"\n" +); + +#endif /* CONFIG_OF_FLAT_TREE */ |