fdt: Add get commands to fdt
Add commands to access data in the fdt. This allows data from a dtb or itb to be accessed from the shell scripts. Signed-off-by: Joe Hershberger <joe.hershberger@ni.com>
This commit is contained in:
		
							parent
							
								
									f0a29d4331
								
							
						
					
					
						commit
						bc80295b62
					
				
							
								
								
									
										144
									
								
								common/cmd_fdt.c
								
								
								
								
							
							
						
						
									
										144
									
								
								common/cmd_fdt.c
								
								
								
								
							|  | @ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR; | ||||||
| static int fdt_valid(void); | static int fdt_valid(void); | ||||||
| static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); | static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); | ||||||
| static int fdt_print(const char *pathp, char *prop, int depth); | static int fdt_print(const char *pathp, char *prop, int depth); | ||||||
|  | static int is_printable_string(const void *data, int len); | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * The working_fdt points to our working flattened device tree. |  * The working_fdt points to our working flattened device tree. | ||||||
|  | @ -63,6 +64,34 @@ void set_working_fdt_addr(void *addr) | ||||||
| 	setenv("fdtaddr", buf); | 	setenv("fdtaddr", buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Get a value from the fdt and format it to be set in the environment | ||||||
|  |  */ | ||||||
|  | static int fdt_value_setenv(const void *nodep, int len, const char *var) | ||||||
|  | { | ||||||
|  | 	if (is_printable_string(nodep, len)) | ||||||
|  | 		setenv(var, (void *)nodep); | ||||||
|  | 	else if (len == 4) { | ||||||
|  | 		char buf[11]; | ||||||
|  | 
 | ||||||
|  | 		sprintf(buf, "0x%08X", *(uint32_t *)nodep); | ||||||
|  | 		setenv(var, buf); | ||||||
|  | 	} else if (len%4 == 0 && len <= 20) { | ||||||
|  | 		/* Needed to print things like sha1 hashes. */ | ||||||
|  | 		char buf[41]; | ||||||
|  | 		int i; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < len; i += sizeof(unsigned int)) | ||||||
|  | 			sprintf(buf + (i * 2), "%08x", | ||||||
|  | 				*(unsigned int *)(nodep + i)); | ||||||
|  | 		setenv(var, buf); | ||||||
|  | 	} else { | ||||||
|  | 		printf("error: unprintable value\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Flattened Device Tree command, see the help for parameter definitions. |  * Flattened Device Tree command, see the help for parameter definitions. | ||||||
|  */ |  */ | ||||||
|  | @ -253,6 +282,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 	/********************************************************************
 | ||||||
|  | 	 * Get the value of a property in the working_fdt. | ||||||
|  | 	 ********************************************************************/ | ||||||
|  | 	} else if (argv[1][0] == 'g') { | ||||||
|  | 		char *subcmd;		/* sub-command */ | ||||||
|  | 		char *pathp;		/* path */ | ||||||
|  | 		char *prop;		/* property */ | ||||||
|  | 		char *var;		/* variable to store result */ | ||||||
|  | 		int  nodeoffset;	/* node offset from libfdt */ | ||||||
|  | 		const void *nodep;	/* property node pointer */ | ||||||
|  | 		int  len = 0;		/* new length of the property */ | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * Parameters: Node path, property, optional value. | ||||||
|  | 		 */ | ||||||
|  | 		if (argc < 5) | ||||||
|  | 			return CMD_RET_USAGE; | ||||||
|  | 
 | ||||||
|  | 		subcmd = argv[2]; | ||||||
|  | 
 | ||||||
|  | 		if (argc < 6 && subcmd[0] != 's') | ||||||
|  | 			return CMD_RET_USAGE; | ||||||
|  | 
 | ||||||
|  | 		var    = argv[3]; | ||||||
|  | 		pathp  = argv[4]; | ||||||
|  | 		prop   = argv[5]; | ||||||
|  | 
 | ||||||
|  | 		nodeoffset = fdt_path_offset(working_fdt, pathp); | ||||||
|  | 		if (nodeoffset < 0) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * Not found or something else bad happened. | ||||||
|  | 			 */ | ||||||
|  | 			printf("libfdt fdt_path_offset() returned %s\n", | ||||||
|  | 				fdt_strerror(nodeoffset)); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { | ||||||
|  | 			int reqIndex = -1; | ||||||
|  | 			int startDepth = fdt_node_depth( | ||||||
|  | 				working_fdt, nodeoffset); | ||||||
|  | 			int curDepth = startDepth; | ||||||
|  | 			int curIndex = -1; | ||||||
|  | 			int nextNodeOffset = fdt_next_node( | ||||||
|  | 				working_fdt, nodeoffset, &curDepth); | ||||||
|  | 
 | ||||||
|  | 			if (subcmd[0] == 'n') | ||||||
|  | 				reqIndex = simple_strtoul(argv[5], NULL, 16); | ||||||
|  | 
 | ||||||
|  | 			while (curDepth > startDepth) { | ||||||
|  | 				if (curDepth == startDepth + 1) | ||||||
|  | 					curIndex++; | ||||||
|  | 				if (subcmd[0] == 'n' && curIndex == reqIndex) { | ||||||
|  | 					const char *nodeName = fdt_get_name( | ||||||
|  | 					    working_fdt, nextNodeOffset, NULL); | ||||||
|  | 
 | ||||||
|  | 					setenv(var, (char *)nodeName); | ||||||
|  | 					return 0; | ||||||
|  | 				} | ||||||
|  | 				nextNodeOffset = fdt_next_node( | ||||||
|  | 					working_fdt, nextNodeOffset, &curDepth); | ||||||
|  | 				if (nextNodeOffset < 0) | ||||||
|  | 					break; | ||||||
|  | 			} | ||||||
|  | 			if (subcmd[0] == 's') { | ||||||
|  | 				/* get the num nodes at this level */ | ||||||
|  | 				char buf[11]; | ||||||
|  | 
 | ||||||
|  | 				sprintf(buf, "%d", curIndex + 1); | ||||||
|  | 				setenv(var, buf); | ||||||
|  | 			} else { | ||||||
|  | 				/* node index not found */ | ||||||
|  | 				printf("libfdt node not found\n"); | ||||||
|  | 				return 1; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			nodep = fdt_getprop( | ||||||
|  | 				working_fdt, nodeoffset, prop, &len); | ||||||
|  | 			if (len == 0) { | ||||||
|  | 				/* no property value */ | ||||||
|  | 				setenv(var, ""); | ||||||
|  | 				return 0; | ||||||
|  | 			} else if (len > 0) { | ||||||
|  | 				if (subcmd[0] == 'v') { | ||||||
|  | 					int ret; | ||||||
|  | 
 | ||||||
|  | 					ret = fdt_value_setenv(nodep, len, var); | ||||||
|  | 					if (ret != 0) | ||||||
|  | 						return ret; | ||||||
|  | 				} else if (subcmd[0] == 'a') { | ||||||
|  | 					/* Get address */ | ||||||
|  | 					char buf[11]; | ||||||
|  | 
 | ||||||
|  | 					sprintf(buf, "0x%08X", (uint32_t)nodep); | ||||||
|  | 					setenv(var, buf); | ||||||
|  | 				} else if (subcmd[0] == 's') { | ||||||
|  | 					/* Get size */ | ||||||
|  | 					char buf[11]; | ||||||
|  | 
 | ||||||
|  | 					sprintf(buf, "0x%08X", len); | ||||||
|  | 					setenv(var, buf); | ||||||
|  | 				} else | ||||||
|  | 					return CMD_RET_USAGE; | ||||||
|  | 				return 0; | ||||||
|  | 			} else { | ||||||
|  | 				printf("libfdt fdt_getprop(): %s\n", | ||||||
|  | 					fdt_strerror(len)); | ||||||
|  | 				return 1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Print (recursive) / List (single level) | 	 * Print (recursive) / List (single level) | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -836,6 +976,10 @@ U_BOOT_CMD( | ||||||
| 	"fdt resize                          - Resize fdt to size + padding to 4k addr\n" | 	"fdt resize                          - Resize fdt to size + padding to 4k addr\n" | ||||||
| 	"fdt print  <path> [<prop>]          - Recursive print starting at <path>\n" | 	"fdt print  <path> [<prop>]          - Recursive print starting at <path>\n" | ||||||
| 	"fdt list   <path> [<prop>]          - Print one level starting at <path>\n" | 	"fdt list   <path> [<prop>]          - Print one level starting at <path>\n" | ||||||
|  | 	"fdt get value <var> <path> <prop>   - Get <property> and store in <var>\n" | ||||||
|  | 	"fdt get name <var> <path> <index>   - Get name of node <index> and store in <var>\n" | ||||||
|  | 	"fdt get addr <var> <path> <prop>    - Get start address of <property> and store in <var>\n" | ||||||
|  | 	"fdt get size <var> <path> [<prop>]  - Get size of [<property>] or num nodes and store in <var>\n" | ||||||
| 	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n" | 	"fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n" | ||||||
| 	"fdt mknode <path> <node>            - Create a new node after <path>\n" | 	"fdt mknode <path> <node>            - Create a new node after <path>\n" | ||||||
| 	"fdt rm     <path> [<prop>]          - Delete the node or <property>\n" | 	"fdt rm     <path> [<prop>]          - Delete the node or <property>\n" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue