diff options
| author | Wolfgang Denk <wd@denx.de> | 2007-08-11 02:14:05 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2007-08-11 02:14:05 +0200 | 
| commit | 308e2b3a6c3fd84fceada79b3d4a559280d326a6 (patch) | |
| tree | 452e7ed9e0ed6c11cc4a73a3a588a72cbc2646b7 | |
| parent | 923efd286411ed052d9e074f59f8986d6081061c (diff) | |
| parent | 5fe6be6208dda852c3564e384bd78d75784dea3e (diff) | |
| download | olio-uboot-2014.01-308e2b3a6c3fd84fceada79b3d4a559280d326a6.tar.xz olio-uboot-2014.01-308e2b3a6c3fd84fceada79b3d4a559280d326a6.zip | |
Merge with /home/wd/git/u-boot/custodian/u-boot-fdt
| -rw-r--r-- | common/cmd_bootm.c | 208 | ||||
| -rw-r--r-- | common/cmd_fdt.c | 619 | ||||
| -rw-r--r-- | common/fdt_support.c | 101 | ||||
| -rw-r--r-- | include/fdt_support.h | 6 | ||||
| -rw-r--r-- | include/libfdt.h | 8 | ||||
| -rw-r--r-- | include/libfdt_env.h | 2 | ||||
| -rw-r--r-- | libfdt/fdt.c | 5 | ||||
| -rw-r--r-- | libfdt/fdt_ro.c | 173 | ||||
| -rw-r--r-- | libfdt/fdt_rw.c | 5 | ||||
| -rw-r--r-- | libfdt/fdt_strerror.c | 5 | ||||
| -rw-r--r-- | libfdt/fdt_sw.c | 5 | ||||
| -rw-r--r-- | libfdt/fdt_wip.c | 5 | 
12 files changed, 689 insertions, 453 deletions
| diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 2436581b1..e19f83e48 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -45,8 +45,8 @@  DECLARE_GLOBAL_DATA_PTR; - /*cmd_boot.c*/ - extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +/*cmd_boot.c*/ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);  #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)  #include <rtc.h> @@ -362,7 +362,6 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  		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; @@ -741,59 +740,65 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  	if(argc > 3) {  		of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);  		hdr = (image_header_t *)of_flat_tree; -#if defined(CONFIG_OF_LIBFDT) -		if (fdt_check_header(of_flat_tree) == 0) { +#if defined(CONFIG_OF_FLAT_TREE) +		if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {  #else -		if (*(ulong *)of_flat_tree == OF_DT_HEADER) { +		if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {  #endif  #ifndef CFG_NO_FLASH  			if (addr2info((ulong)of_flat_tree) != NULL)  				of_data = (ulong)of_flat_tree;  #endif  		} else if (ntohl(hdr->ih_magic) == IH_MAGIC) { -			printf("## Flat Device Tree Image at %08lX\n", hdr); +			printf("## Flat Device Tree at %08lX\n", hdr);  			print_image_hdr(hdr);  			if ((ntohl(hdr->ih_load) <  ((unsigned long)hdr + ntohl(hdr->ih_size) + sizeof(hdr))) &&  			   ((ntohl(hdr->ih_load) + ntohl(hdr->ih_size)) > (unsigned long)hdr)) { -				printf ("ERROR: Load address overwrites Flat Device Tree uImage\n"); -				return; +				puts ("ERROR: fdt overwritten - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			} -			printf("   Verifying Checksum ... "); +			puts ("   Verifying Checksum ... ");  			memmove (&header, (char *)hdr, sizeof(image_header_t));  			checksum = ntohl(header.ih_hcrc);  			header.ih_hcrc = 0;  			if(checksum != crc32(0, (uchar *)&header, sizeof(image_header_t))) { -				printf("ERROR: Flat Device Tree header checksum is invalid\n"); -				return; +				puts ("ERROR: fdt header checksum invalid - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			}  			checksum = ntohl(hdr->ih_dcrc);  			addr = (ulong)((uchar *)(hdr) + sizeof(image_header_t));  			if(checksum != crc32(0, (uchar *)addr, ntohl(hdr->ih_size))) { -				printf("ERROR: Flat Device Tree checksum is invalid\n"); -				return; +				puts ("ERROR: fdt checksum invalid - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			} -			printf("OK\n"); +			puts ("OK\n");  			if (ntohl(hdr->ih_type) != IH_TYPE_FLATDT) { -				printf ("ERROR: uImage not Flat Device Tree type\n"); -				return; +				puts ("ERROR: uImage is not a fdt - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			}  			if (ntohl(hdr->ih_comp) != IH_COMP_NONE) { -				printf("ERROR: uImage is not uncompressed\n"); -				return; +				puts ("ERROR: uImage is compressed - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			} -#if defined(CONFIG_OF_LIBFDT) -			if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) == 0) { -#else +#if defined(CONFIG_OF_FLAT_TREE)  			if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) { +#else +			if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {  #endif -				printf ("ERROR: uImage data is not a flat device tree\n"); -				return; +				puts ("ERROR: uImage data is not a fdt - " +					"must RESET the board to recover.\n"); +				do_reset (cmdtp, flag, argc, argv);  			}  			memmove((void *)ntohl(hdr->ih_load), @@ -801,10 +806,11 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  				ntohl(hdr->ih_size));  			of_flat_tree = (char *)ntohl(hdr->ih_load);  		} else { -			printf ("Did not find a flat flat device tree at address %08lX\n", of_flat_tree); -			return; +			puts ("Did not find a flat Flat Device Tree.\n" +				"Must RESET the board to recover.\n"); +			do_reset (cmdtp, flag, argc, argv);  		} -		printf ("   Booting using flat device tree at 0x%x\n", +		printf ("   Booting using the fdt at 0x%x\n",  				of_flat_tree);  	} else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1]) && (len_ptr[2])) {  		u_long tail    = ntohl(len_ptr[0]) % 4; @@ -828,22 +834,24 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  			of_data += 4 - tail;  		} -#if defined(CONFIG_OF_LIBFDT) -		if (fdt_check_header((void *)of_data) != 0) { +#if defined(CONFIG_OF_FLAT_TREE) +		if (*((ulong *)(of_flat_tree + sizeof(image_header_t))) != OF_DT_HEADER) {  #else -		if (((struct boot_param_header *)of_data)->magic != OF_DT_HEADER) { +		if (fdt_check_header(of_flat_tree + sizeof(image_header_t)) != 0) {  #endif -			printf ("ERROR: image is not a flat device tree\n"); -			return; +			puts ("ERROR: image is not a fdt - " +				"must RESET the board to recover.\n"); +			do_reset (cmdtp, flag, argc, argv);  		} -#if defined(CONFIG_OF_LIBFDT) -		if (be32_to_cpu(fdt_totalsize(of_data)) !=  ntohl(len_ptr[2])) { -#else +#if defined(CONFIG_OF_FLAT_TREE)  		if (((struct boot_param_header *)of_data)->totalsize != ntohl(len_ptr[2])) { +#else +		if (be32_to_cpu(fdt_totalsize(of_data)) !=  ntohl(len_ptr[2])) {  #endif -			printf ("ERROR: flat device tree size does not agree with image\n"); -			return; +			puts ("ERROR: fdt size != image size - " +				"must RESET the board to recover.\n"); +			do_reset (cmdtp, flag, argc, argv);  		}  	}  #endif @@ -916,15 +924,6 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  		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 -  #if defined(CONFIG_OF_LIBFDT)  	/* move of_flat_tree if needed */  	if (of_data) { @@ -944,32 +943,41 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  		of_flat_tree = (char *)of_start;  		printf ("   Loading Device Tree to %08lx, end %08lx ... ",  			of_start, of_start + of_len - 1); -		err = fdt_open_into((void *)of_start, (void *)of_data, of_len); +		err = fdt_open_into((void *)of_data, (void *)of_start, of_len);  		if (err != 0) { -			printf ("libfdt: %s " __FILE__ " %d\n", fdt_strerror(err), __LINE__); -		} -		/* -		 * Add the chosen node if it doesn't exist, add the env and bd_t -		 * if the user wants it (the logic is in the subroutines). -		 */ -		if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { -				printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree); -				return; +			puts ("ERROR: fdt move failed - " +				"must RESET the board to recover.\n"); +			do_reset (cmdtp, flag, argc, argv);  		} +	} +	/* +	 * Add the chosen node if it doesn't exist, add the env and bd_t +	 * if the user wants it (the logic is in the subroutines). +	 */ +	if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { +		puts ("ERROR: /chosen node create failed - " +			"must RESET the board to recover.\n"); +		do_reset (cmdtp, flag, argc, argv); +	}  #ifdef CONFIG_OF_HAS_UBOOT_ENV -		if (fdt_env(of_flat_tree) < 0) { -				printf("Failed creating the /u-boot-env node, aborting.\n"); -				return; -		} +	if (fdt_env(of_flat_tree) < 0) { +		puts ("ERROR: /u-boot-env node create failed - " +			"must RESET the board to recover.\n"); +		do_reset (cmdtp, flag, argc, argv); +	}  #endif  #ifdef CONFIG_OF_HAS_BD_T -		if (fdt_bd_t(of_flat_tree) < 0) { -				printf("Failed creating the /bd_t node, aborting.\n"); -				return; -		} -#endif +	if (fdt_bd_t(of_flat_tree) < 0) { +		puts ("ERROR: /bd_t node create failed - " +			"must RESET the board to recover.\n"); +		do_reset (cmdtp, flag, argc, argv);  	}  #endif +#ifdef CONFIG_OF_BOARD_SETUP +	/* Call the board-specific fixup routine */ +	ft_board_setup(of_flat_tree, gd->bd); +#endif +#endif /* CONFIG_OF_LIBFDT */  #if defined(CONFIG_OF_FLAT_TREE)  	/* move of_flat_tree if needed */  	if (of_data) { @@ -989,8 +997,36 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  			of_start, of_start + of_len - 1);  		memmove ((void *)of_start, (void *)of_data, of_len);  	} +	/* +	 * Create the /chosen node and modify the blob with board specific +	 * values as needed. +	 */ +	ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); +	/* ft_dump_blob(of_flat_tree); */ +#endif +	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 +#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) +	if (of_flat_tree) {	/* device tree; boot new style */ +		/* +		 * Linux Kernel Parameters (passing device tree): +		 *   r3: pointer to the fdt, followed by the board info data +		 *   r4: physical pointer to the kernel itself +		 *   r5: NULL +		 *   r6: NULL +		 *   r7: NULL +		 */ +		(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); +		/* does not return */ +	} +#endif  	/*  	 * Linux Kernel Parameters (passing board info data):  	 *   r3: ptr to board info data @@ -999,46 +1035,8 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag,  	 *   r6: Start of command line string  	 *   r7: End   of command line string  	 */ -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	if (!of_flat_tree)	/* no device tree; boot old style */ -#endif -		(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); -		/* does not return */ - -#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT) -	/* -	 * Linux Kernel Parameters (passing device tree): -	 *   r3: ptr to OF flat tree, followed by the board info data -	 *   r4: physical pointer to the kernel itself -	 *   r5: NULL -	 *   r6: NULL -	 *   r7: NULL -	 */ -#if defined(CONFIG_OF_FLAT_TREE) -	ft_setup(of_flat_tree, kbd, initrd_start, initrd_end); -	/* ft_dump_blob(of_flat_tree); */ -#endif -#if defined(CONFIG_OF_LIBFDT) -	if (fdt_chosen(of_flat_tree, initrd_start, initrd_end, 0) < 0) { -		printf("Failed creating the /chosen node (0x%08X), aborting.\n", of_flat_tree); -		return; -	} -#ifdef CONFIG_OF_HAS_UBOOT_ENV -	if (fdt_env(of_flat_tree) < 0) { -		printf("Failed creating the /u-boot-env node, aborting.\n"); -		return; -	} -#endif -#ifdef CONFIG_OF_HAS_BD_T -	if (fdt_bd_t(of_flat_tree) < 0) { -		printf("Failed creating the /bd_t node, aborting.\n"); -		return; -	} -#endif -#endif /* if defined(CONFIG_OF_LIBFDT) */ - -	(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0); -#endif +	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end); +	/* does not return */  }  #endif /* CONFIG_PPC */ diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 08fe3512d..571b8f14d 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -37,46 +37,32 @@  #include <fdt_support.h>  #define MAX_LEVEL	32		/* how deeply nested we will go */ -#define SCRATCHPAD	1024	/* bytes of scratchpad memory */ +#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_parse_prop(char *pathp, char *prop, char *newval, +	char *data, int *len); +static int fdt_print(char *pathp, char *prop, int depth);  /*   * 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') { +	if (argv[1][0] == 'a') {  		/*  		 * Set the address [and length] of the fdt.  		 */ @@ -94,7 +80,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			 */  			len =  simple_strtoul(argv[3], NULL, 16);  			if (len < fdt_totalsize(fdt)) { -				printf ("New length %d < existing length %d, ignoring.\n", +				printf ("New length %d < existing length %d, " +					"ignoring.\n",  					len, fdt_totalsize(fdt));  			} else {  				/* @@ -102,7 +89,8 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  				 */  				err = fdt_open_into(fdt, fdt, len);  				if (err != 0) { -					printf ("libfdt: %s\n", fdt_strerror(err)); +					printf ("libfdt fdt_open_into(): %s\n", +						fdt_strerror(err));  				}  			}  		} @@ -110,12 +98,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	/********************************************************************  	 * Move the fdt  	 ********************************************************************/ -	} else if (op == 'm') { +	} else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) {  		struct fdt_header *newaddr;  		int  len;  		int  err; -		if (argc != 5) { +		if (argc < 4) {  			printf ("Usage:\n%s\n", cmdtp->usage);  			return 1;  		} @@ -128,12 +116,22 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  			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; +		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16); + +		/* +		 * If the user specifies a length, use that.  Otherwise use the +		 * current length. +		 */ +		if (argc <= 4) { +			len = fdt_totalsize(fdt); +		} else { +			len = simple_strtoul(argv[4], NULL, 16); +			if (len < fdt_totalsize(fdt)) { +				printf ("New length 0x%X < existing length " +					"0x%X, aborting.\n", +					len, fdt_totalsize(fdt)); +				return 1; +			}  		}  		/* @@ -141,26 +139,59 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		 */  		err = fdt_open_into(fdt, newaddr, len);  		if (err != 0) { -			printf ("libfdt: %s\n", fdt_strerror(err)); +			printf ("libfdt fdt_open_into(): %s\n", +				fdt_strerror(err));  			return 1;  		}  		fdt = newaddr;  	/******************************************************************** -	 * Set the value of a node in the fdt. +	 * Make a new node  	 ********************************************************************/ -	} else if (op == 's') { +	} else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) {  		char *pathp;		/* path */ -		char *prop;			/* property */ -		struct fdt_property *nodep;	/* node struct pointer */ +		char *nodep;		/* new node to add */ +		int  nodeoffset;	/* node offset from libfdt */ +		int  err; + +		/* +		 * Parameters: Node path, new node to be appended to the path. +		 */ +		if (argc < 4) { +			printf ("Usage:\n%s\n", cmdtp->usage); +			return 1; +		} + +		pathp = argv[2]; +		nodep = argv[3]; + +		nodeoffset = fdt_find_node_by_path (fdt, pathp); +		if (nodeoffset < 0) { +			/* +			 * Not found or something else bad happened. +			 */ +			printf ("libfdt fdt_find_node_by_path() returned %s\n", +				fdt_strerror(nodeoffset)); +			return 1; +		} +		err = fdt_add_subnode(fdt, nodeoffset, nodep); +		if (err < 0) { +			printf ("libfdt fdt_add_subnode(): %s\n", +				fdt_strerror(err)); +			return 1; +		} + +	/******************************************************************** +	 * Set the value of a property in the fdt. +	 ********************************************************************/ +	} else if (argv[1][0] == 's') { +		char *pathp;		/* path */ +		char *prop;		/* property */  		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 */ +		static char data[SCRATCHPAD];	/* storage for the property */ +		int  len;		/* new length of the property */ +		int  ret;		/* return value */  		/*  		 * Parameters: Node path, property, value. @@ -174,121 +205,38 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		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) { +		nodeoffset = fdt_find_node_by_path (fdt, pathp); +		if (nodeoffset < 0) {  			/* -			 * The specified property has no value +			 * Not found or something else bad happened.  			 */ -			printf("%s has no value, cannot set one (yet).\n", prop); +			printf ("libfdt fdt_find_node_by_path() returned %s\n", +				fdt_strerror(nodeoffset));  			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_parse_prop(pathp, prop, newval, data, &len); +		if (ret != 0) +			return ret; -			ret = fdt_setprop(fdt, nodeoffset, prop, data, len); -			if (ret < 0) { -				printf ("libfdt %s\n", fdt_strerror(ret)); -				return 1; -			} +		ret = fdt_setprop(fdt, nodeoffset, prop, data, len); +		if (ret < 0) { +			printf ("libfdt fdt_setprop(): %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"; +	} else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {  		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 */ +		char *prop;		/* property */ +		int  ret;		/* return value */  		/*  		 * list is an alias for print, but limited to 1 level  		 */ -		if (op == 'l') { +		if (argv[1][0] == 'l') {  			depth = 1;  		} @@ -302,99 +250,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		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; -		} +		ret = fdt_print(pathp, prop, depth); +		if (ret != 0) +			return ret;  	/********************************************************************  	 * Remove a property/node  	 ********************************************************************/ -	} else if (op == 'r') { +	} else if (argv[1][0] == 'r') {  		int  nodeoffset;	/* node offset from libfdt */  		int  err; @@ -402,17 +265,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		 * 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; -			} +		nodeoffset = fdt_find_node_by_path (fdt, argv[2]); +		if (nodeoffset < 0) { +			/* +			 * Not found or something else bad happened. +			 */ +			printf ("libfdt fdt_find_node_by_path() returned %s\n", +				fdt_strerror(nodeoffset)); +			return 1;  		}  		/*  		 * Do the delete.  A fourth parameter means delete a property, @@ -421,39 +281,40 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  		if (argc > 3) {  			err = fdt_delprop(fdt, nodeoffset, argv[3]);  			if (err < 0) { -				printf("fdt_delprop libfdt: %s\n", fdt_strerror(err)); +				printf("libfdt fdt_delprop():  %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)); +				printf("libfdt fdt_del_node():  %s\n", +					fdt_strerror(err));  				return err;  			}  		} - -	/******************************************************************** -	 * Create a chosen node -	 ********************************************************************/ -	} else if (op == 'c') { +	} +#ifdef CONFIG_OF_BOARD_SETUP +	/* Call the board-specific fixup routine */ +	else if (argv[1][0] == 'b') +		ft_board_setup(fdt, gd->bd); +#endif +	/* Create a chosen node */ +	else if (argv[1][0] == 'c')  		fdt_chosen(fdt, 0, 0, 1); -	/******************************************************************** -	 * Create a u-boot-env node -	 ********************************************************************/ -	} else if (op == 'e') { +#ifdef CONFIG_OF_HAS_UBOOT_ENV +	/* Create a u-boot-env node */ +	else if (argv[1][0] == 'e')  		fdt_env(fdt); - -	/******************************************************************** -	 * Create a bd_t node -	 ********************************************************************/ -	} else if (op == 'b') { +#endif +#ifdef CONFIG_OF_HAS_BD_T +	/* Create a bd_t node */ +	else if (argv[1][0] == 'b')  		fdt_bd_t(fdt); - -	/******************************************************************** -	 * Unrecognized command -	 ********************************************************************/ -	} else { +#endif +	else { +		/* Unrecognized command */  		printf ("Usage:\n%s\n", cmdtp->usage);  		return 1;  	} @@ -461,7 +322,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  	return 0;  } -/********************************************************************/ +/****************************************************************************/  static int fdt_valid(void)  { @@ -477,19 +338,21 @@ static int fdt_valid(void)  		return 1;	/* valid */  	if (err < 0) { -		printf("libfdt: %s", fdt_strerror(err)); +		printf("libfdt fdt_check_header(): %s", fdt_strerror(err));  		/*  		 * Be more informative on bad version.  		 */  		if (err == -FDT_ERR_BADVERSION) {  			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) {  				printf (" - too old, fdt $d < %d", -					fdt_version(fdt), FDT_FIRST_SUPPORTED_VERSION); +					fdt_version(fdt), +					FDT_FIRST_SUPPORTED_VERSION);  				fdt = NULL;  			}  			if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) {  				printf (" - too new, fdt $d > %d", -					fdt_version(fdt), FDT_LAST_SUPPORTED_VERSION); +					fdt_version(fdt), +					FDT_LAST_SUPPORTED_VERSION);  				fdt = NULL;  			}  			return 0; @@ -500,13 +363,91 @@ static int fdt_valid(void)  	return 1;  } -/********************************************************************/ +/****************************************************************************/ + +/* + * Parse the user's input, partially heuristic.  Valid formats: + * <00>		- hex byte + * <0011>	- hex half word (16 bits) + * <00112233>	- hex word (32 bits) + *		- hex double words (64 bits) are not supported, must use + *			a byte stream instead. + * [00 11 22 .. nn] - byte stream + * "string"	- If the the value doesn't start with "<" or "[", it is + *			treated as a string.  Note that the quotes are + *			stripped by the parser before we get the string. + */ +static int fdt_parse_prop(char *pathp, char *prop, char *newval, +	char *data, int *len) +{ +	char *cp;		/* temporary char pointer */ +	unsigned long tmp;	/* holds converted values */ + +	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) { +				*data = tmp & 0xFF; +				data  += 1; +				*len += 1; +			} else if ((newval - cp) <= 4) { +				*(uint16_t *)data = __cpu_to_be16(tmp); +				data  += 2; +				*len += 2; +			} else if ((newval - cp) <= 8) { +				*(uint32_t *)data = __cpu_to_be32(tmp); +				data  += 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); +			*data++ = tmp & 0xFF; +			*len    = *len + 1; +			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); +	} +	return 0; +} + +/****************************************************************************/  /* - * 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> + * Heuristic to guess if this is a string or concatenated strings.   */  static int is_printable_string(const void *data, int len) @@ -546,6 +487,12 @@ static int is_printable_string(const void *data, int len)  	return 1;  } + +/* + * Print the property in the best format, a heuristic guess.  Print as + * a string, concatenated strings, a byte, word, double word, or (if all + * else fails) it is printed as a stream of bytes. + */  static void print_data(const void *data, int len)  {  	int j; @@ -601,32 +548,146 @@ static void print_data(const void *data, int len)  	}  } +/****************************************************************************/ + +/* + * Recursively print (a portion of) the fdt.  The depth parameter + * determines how deeply nested the fdt is printed. + */ +static int fdt_print(char *pathp, char *prop, int depth) +{ +	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"; +	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 */ + +	nodeoffset = fdt_find_node_by_path (fdt, pathp); +	if (nodeoffset < 0) { +		/* +		 * Not found or something else bad happened. +		 */ +		printf ("libfdt fdt_find_node_by_path() returned %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) { +			/* no property value */ +			printf("%s %s\n", pathp, prop); +			return 0; +		} else if (len > 0) { +			printf("%s=", prop); +			print_data (nodep, len); +			printf("\n"); +			return 0; +		} else { +			printf ("libfdt fdt_getprop(): %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. " +					"Aborting.\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 fdt_getprop(): %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; +	} +	return 0; +} +  /********************************************************************/  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" +#ifdef CONFIG_OF_BOARD_SETUP +	"fdt boardsetup                      - Do board-specific set up\n" +#endif  	"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" +	"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" +	"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" +	"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" +	" If the property you are setting/printing has a '#' character or spaces,\n" +	"     you MUST escape it with a \\ character 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" diff --git a/common/fdt_support.c b/common/fdt_support.c index 69099c427..caaa682a4 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -37,6 +37,10 @@   */  DECLARE_GLOBAL_DATA_PTR; +/* + * fdt points to our working device tree. + */ +struct fdt_header *fdt;  /********************************************************************/ @@ -45,13 +49,12 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  	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; +	u32   tmp;		/* used to set 32 bit integer properties */ +	char  *str;		/* used to set string properties */  	err = fdt_check_header(fdt);  	if (err < 0) { -		printf("libfdt: %s\n", fdt_strerror(err)); +		printf("fdt_chosen: %s\n", fdt_strerror(err));  		return err;  	} @@ -63,11 +66,12 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  		err = fdt_num_reservemap(fdt, &used, &total);  		if (err < 0) { -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("fdt_chosen: %s\n", fdt_strerror(err));  			return err;  		}  		if (used >= total) { -			printf("fdt_chosen: no room in the reserved map (%d of %d)\n", +			printf("WARNING: " +				"no room in the reserved map (%d of %d)\n",  				used, total);  			return -1;  		} @@ -84,7 +88,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  		err = fdt_replace_reservemap_entry(fdt, j,  			initrd_start, initrd_end - initrd_start + 1);  		if (err < 0) { -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("fdt_chosen: %s\n", fdt_strerror(err));  			return err;  		}  	} @@ -92,7 +96,7 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  	/*  	 * Find the "chosen" node.  	 */ -	nodeoffset = fdt_path_offset (fdt, "/chosen"); +	nodeoffset = fdt_find_node_by_path (fdt, "/chosen");  	/*  	 * If we have a "chosen" node already the "force the writing" @@ -110,7 +114,8 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  		 */  		nodeoffset = fdt_add_subnode(fdt, 0, "chosen");  		if (nodeoffset < 0) { -			printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +			printf("WARNING: could not create /chosen %s.\n", +				fdt_strerror(nodeoffset));  			return nodeoffset;  		}  	} @@ -120,42 +125,35 @@ int fdt_chosen(void *fdt, ulong initrd_start, ulong initrd_end, int force)  	 */  	str = getenv("bootargs");  	if (str != NULL) { -		err = fdt_setprop(fdt, nodeoffset, "bootargs", str, strlen(str)+1); +		err = fdt_setprop(fdt, nodeoffset, +			"bootargs", str, strlen(str)+1);  		if (err < 0) -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("WARNING: could not set bootargs %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)); +		err = fdt_setprop(fdt, nodeoffset, +			 "linux,initrd-start", &tmp, sizeof(tmp));  		if (err < 0) -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("WARNING: " +				"could not set linux,initrd-start %s.\n", +				fdt_strerror(err));  		tmp = __cpu_to_be32(initrd_end); -		err = fdt_setprop(fdt, nodeoffset, "linux,initrd-end", &tmp, sizeof(tmp)); +		err = fdt_setprop(fdt, nodeoffset, +			"linux,initrd-end", &tmp, sizeof(tmp));  		if (err < 0) -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("WARNING: could not set linux,initrd-end %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); +	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)); +		printf("WARNING: could not set linux,stdout-path %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  	return err;  } @@ -177,7 +175,7 @@ int fdt_env(void *fdt)  	err = fdt_check_header(fdt);  	if (err < 0) { -		printf("libfdt: %s\n", fdt_strerror(err)); +		printf("fdt_env: %s\n", fdt_strerror(err));  		return err;  	} @@ -185,11 +183,11 @@ int fdt_env(void *fdt)  	 * 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"); +	nodeoffset = fdt_find_node_by_path (fdt, "/u-boot-env");  	if (nodeoffset >= 0) {  		err = fdt_del_node(fdt, nodeoffset);  		if (err < 0) { -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("fdt_env: %s\n", fdt_strerror(err));  			return err;  		}  	} @@ -198,7 +196,8 @@ int fdt_env(void *fdt)  	 */  	nodeoffset = fdt_add_subnode(fdt, 0, "u-boot-env");  	if (nodeoffset < 0) { -		printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +		printf("WARNING: could not create /u-boot-env %s.\n", +			fdt_strerror(nodeoffset));  		return nodeoffset;  	} @@ -226,7 +225,8 @@ int fdt_env(void *fdt)  			continue;  		err = fdt_setprop(fdt, nodeoffset, lval, rval, strlen(rval)+1);  		if (err < 0) { -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("WARNING: could not set %s %s.\n", +				lval, fdt_strerror(err));  			return err;  		}  	} @@ -292,12 +292,12 @@ int fdt_bd_t(void *fdt)  	bd_t *bd = gd->bd;  	int   nodeoffset;  	int   err; -	u32   tmp;			/* used to set 32 bit integer properties */ +	u32   tmp;		/* used to set 32 bit integer properties */  	int i;  	err = fdt_check_header(fdt);  	if (err < 0) { -		printf("libfdt: %s\n", fdt_strerror(err)); +		printf("fdt_bd_t: %s\n", fdt_strerror(err));  		return err;  	} @@ -305,11 +305,11 @@ int fdt_bd_t(void *fdt)  	 * 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"); +	nodeoffset = fdt_find_node_by_path (fdt, "/bd_t");  	if (nodeoffset >= 0) {  		err = fdt_del_node(fdt, nodeoffset);  		if (err < 0) { -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("fdt_bd_t: %s\n", fdt_strerror(err));  			return err;  		}  	} @@ -318,7 +318,9 @@ int fdt_bd_t(void *fdt)  	 */  	nodeoffset = fdt_add_subnode(fdt, 0, "bd_t");  	if (nodeoffset < 0) { -		printf("libfdt: %s\n", fdt_strerror(nodeoffset)); +		printf("WARNING: could not create /bd_t %s.\n", +			fdt_strerror(nodeoffset)); +		printf("fdt_bd_t: %s\n", fdt_strerror(nodeoffset));  		return nodeoffset;  	}  	/* @@ -326,20 +328,23 @@ int fdt_bd_t(void *fdt)  	 */  	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)); +		err = fdt_setprop(fdt, nodeoffset, +			bd_map[i].name, &tmp, sizeof(tmp));  		if (err < 0) -			printf("libfdt: %s\n", fdt_strerror(err)); +			printf("WARNING: could not set %s %s.\n", +				bd_map[i].name, 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)); +		printf("WARNING: could not set enetaddr %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)); - +		printf("WARNING: could not set ethspeed %s.\n", +			fdt_strerror(err));  	return 0;  }  #endif /* ifdef CONFIG_OF_HAS_BD_T */ diff --git a/include/fdt_support.h b/include/fdt_support.h index a27683474..60fa423b3 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -38,5 +38,11 @@ int fdt_env(void *fdt);  int fdt_bd_t(void *fdt);  #endif +#ifdef CONFIG_OF_BOARD_SETUP +void ft_board_setup(void *blob, bd_t *bd); +void ft_cpu_setup(void *blob, bd_t *bd); +void ft_pci_setup(void *blob, bd_t *bd); +#endif +  #endif /* ifdef CONFIG_OF_LIBFDT */  #endif /* ifndef __FDT_SUPPORT_H */ diff --git a/include/libfdt.h b/include/libfdt.h index f8bac73a3..340e89d9c 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -77,7 +77,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  			       const char *name, int namelen);  int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); -int fdt_path_offset(const void *fdt, const char *path); +int fdt_find_node_by_path(const void *fdt, const char *path); +int fdt_find_node_by_type(const void *fdt, int nodeoffset, const char *type); + +int fdt_node_is_compatible(const void *fdt, int nodeoffset, +			   const char *compat); +int fdt_find_compatible_node(const void *fdt, int nodeoffset, +			     const char *type, const char *compat);  struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,  				      const char *name, int *lenp); diff --git a/include/libfdt_env.h b/include/libfdt_env.h index e746314b1..78f725830 100644 --- a/include/libfdt_env.h +++ b/include/libfdt_env.h @@ -26,7 +26,7 @@  #include <asm/byteorder.h>  #include <linux/string.h> -struct fdt_header *fdt;         /* Pointer to the working fdt */ +extern struct fdt_header *fdt;  /* Pointer to the working fdt */  #define fdt32_to_cpu(x)		__be32_to_cpu(x)  #define cpu_to_fdt32(x)		__cpu_to_be32(x) diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 212b83838..1ee67ad19 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -83,3 +86,5 @@ int fdt_move(const void *fdt, void *buf, int bufsize)  	memmove(buf, fdt, fdt_totalsize(fdt));  	return 0;  } + +#endif /* CONFIG_OF_LIBFDT */ diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 4e2c325b4..ffd9209b1 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -48,6 +51,33 @@ static int offset_streq(const void *fdt, int offset,  }  /* + * Checks if the property name matches. + */ +static int prop_name_eq(const void *fdt, int offset, const char *name, +			struct fdt_property **prop, int *lenp) +{ +	int namestroff, len; + +	*prop = fdt_offset_ptr_typed(fdt, offset, *prop); +	if (! *prop) +		return -FDT_ERR_BADSTRUCTURE; + +	namestroff = fdt32_to_cpu((*prop)->nameoff); +	if (streq(fdt_string(fdt, namestroff), name)) { +		len = fdt32_to_cpu((*prop)->len); +		*prop = fdt_offset_ptr(fdt, offset, +				       sizeof(**prop) + len); +		if (*prop) { +			if (lenp) +				*lenp = len; +			return 1; +		} else +			return -FDT_ERR_BADSTRUCTURE; +	} +	return 0; +} + +/*   * Return a pointer to the string at the given string offset.   */  char *fdt_string(const void *fdt, int stroffset) @@ -56,6 +86,118 @@ char *fdt_string(const void *fdt, int stroffset)  }  /* + * Check if the specified node is compatible by comparing the tokens + * in its "compatible" property with the specified string: + * + *   nodeoffset - starting place of the node + *   compat     - the string to match to one of the tokens in the + *                "compatible" list. + */ +int fdt_node_is_compatible(const void *fdt, int nodeoffset, +			   const char *compat) +{ +	const char* cp; +	int cplen, len; + +	cp = fdt_getprop(fdt, nodeoffset, "compatible", &cplen); +	if (cp == NULL) +		return 0; +	while (cplen > 0) { +		if (strncmp(cp, compat, strlen(compat)) == 0) +			return 1; +		len = strlen(cp) + 1; +		cp += len; +		cplen -= len; +	} + +	return 0; +} + +/* + * Find a node by its device type property. On success, the offset of that + * node is returned or an error code otherwise: + * + *   nodeoffset - the node to start searching from or 0, the node you pass + *                will not be searched, only the next one will; typically, + *                you pass 0 to start the search and then what the previous + *                call returned. + *   type       - the device type string to match against. + */ +int fdt_find_node_by_type(const void *fdt, int nodeoffset, const char *type) +{ +	int offset, nextoffset; +	struct fdt_property *prop; +	uint32_t tag; +	int len, ret; + +	CHECK_HEADER(fdt); + +	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL); +	if (tag != FDT_BEGIN_NODE) +		return -FDT_ERR_BADOFFSET; +	if (nodeoffset) +		nodeoffset = 0;	/* start searching with next node */ + +	while (1) { +		offset = nextoffset; +		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL); + +		switch (tag) { +		case FDT_BEGIN_NODE: +			nodeoffset = offset; +			break; + +		case FDT_PROP: +			if (nodeoffset == 0) +				break; +			ret = prop_name_eq(fdt, offset, "device_type", +					   &prop, &len); +			if (ret < 0) +				return ret; +			else if (ret > 0 && +				 strncmp(prop->data, type, len - 1) == 0) +			    return nodeoffset; +			break; + +		case FDT_END_NODE: +		case FDT_NOP: +			break; + +		case FDT_END: +			return -FDT_ERR_NOTFOUND; + +		default: +			return -FDT_ERR_BADSTRUCTURE; +		} +	} +} + +/* + * Find a node based on its device type and one of the tokens in its its + * "compatible" property. On success, the offset of that node is returned + * or an error code otherwise: + * + *   nodeoffset - the node to start searching from or 0, the node you pass + *                will not be searched, only the next one will; typically, + *                you pass 0 to start the search and then what the previous + *                call returned. + *   type       - the device type string to match against. + *   compat     - the string to match to one of the tokens in the + *                "compatible" list. + */ +int fdt_find_compatible_node(const void *fdt, int nodeoffset, +			     const char *type, const char *compat) +{ +	int offset; + +	offset = fdt_find_node_by_type(fdt, nodeoffset, type); +	if (offset < 0 || fdt_node_is_compatible(fdt, offset, compat)) +		return offset; + +	return -FDT_ERR_NOTFOUND; +} + +/*   * Return the node offset of the node specified by:   *   parentoffset - starting place (0 to start at the root)   *   name         - name being searched for @@ -129,7 +271,7 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,   * Searches for the node corresponding to the given path and returns the   * offset of that node.   */ -int fdt_path_offset(const void *fdt, const char *path) +int fdt_find_node_by_path(const void *fdt, const char *path)  {  	const char *end = path + strlen(path);  	const char *p = path; @@ -141,6 +283,10 @@ int fdt_path_offset(const void *fdt, const char *path)  	if (*path != '/')  		return -FDT_ERR_BADPATH; +	/* Handle the root path: root offset is 0 */ +	if (strcmp(path, "/") == 0) +		return 0; +  	while (*p) {  		const char *q; @@ -184,7 +330,6 @@ struct fdt_property *fdt_get_property(const void *fdt,  	int level = 0;  	uint32_t tag;  	struct fdt_property *prop; -	int namestroff;  	int offset, nextoffset;  	int err; @@ -224,24 +369,11 @@ struct fdt_property *fdt_get_property(const void *fdt,  			if (level != 0)  				continue; -			err = -FDT_ERR_BADSTRUCTURE; -			prop = fdt_offset_ptr_typed(fdt, offset, prop); -			if (! prop) -				goto fail; -			namestroff = fdt32_to_cpu(prop->nameoff); -			if (streq(fdt_string(fdt, namestroff), name)) { -				/* Found it! */ -				int len = fdt32_to_cpu(prop->len); -				prop = fdt_offset_ptr(fdt, offset, -						      sizeof(*prop)+len); -				if (! prop) -					goto fail; - -				if (lenp) -					*lenp = len; - +			err = prop_name_eq(fdt, offset, name, &prop, lenp); +			if (err > 0)  				return prop; -			} +			else if (err < 0) +				goto fail;  			break;  		case FDT_NOP: @@ -400,3 +532,6 @@ int fdt_get_reservemap(void *fdt, int n, struct fdt_reserve_entry *re)  	}  	return 0;  } + +#endif /* CONFIG_OF_LIBFDT */ + diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index aaafc5364..693bfe43a 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -291,3 +294,5 @@ int fdt_pack(void *fdt)  	fdt_set_header(fdt, totalsize, _blob_data_size(fdt));  	return 0;  } + +#endif /* CONFIG_OF_LIBFDT */ diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c index 7f231ce46..b49c952f3 100644 --- a/libfdt/fdt_strerror.c +++ b/libfdt/fdt_strerror.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -62,3 +65,5 @@ const char *fdt_strerror(int errval)  	return "<unknown error>";  } + +#endif /* CONFIG_OF_LIBFDT */ diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 672f4ddd9..c7eea8ff3 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -224,3 +227,5 @@ int fdt_finish(void *fdt)  	fdt_set_header(fdt, magic, FDT_MAGIC);  	return 0;  } + +#endif /* CONFIG_OF_LIBFDT */ diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 2d2ed37c4..2d39aabe1 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -16,6 +16,9 @@   * License along with this library; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA   */ +#include "config.h" +#if CONFIG_OF_LIBFDT +  #include "libfdt_env.h"  #include <fdt.h> @@ -135,3 +138,5 @@ int fdt_replace_reservemap_entry(void *fdt, int n, uint64_t addr, uint64_t size)  	return 0;  } + +#endif /* CONFIG_OF_LIBFDT */ |