cmd_fdt.c

来自「uboot详细解读可用启动引导LINUX2.6内核」· C语言 代码 · 共 805 行 · 第 1/2 页

C
805
字号
				printf("libfdt fdt_del_mem_rsv():  %s\n",					fdt_strerror(err));				return err;			}		} else {			/* Unrecognized command */			printf ("Usage:\n%s\n", cmdtp->usage);			return 1;		}	}#ifdef CONFIG_OF_BOARD_SETUP	/* Call the board-specific fixup routine */	else if (strncmp(argv[1], "boa", 3) == 0)		ft_board_setup(working_fdt, gd->bd);#endif	/* Create a chosen node */	else if (argv[1][0] == 'c')		fdt_chosen(working_fdt, 0, 0, 1);	else {		/* Unrecognized command */		printf ("Usage:\n%s\n", cmdtp->usage);		return 1;	}	return 0;}/****************************************************************************/static int fdt_valid(void){	int  err;	if (working_fdt == NULL) {		printf ("The address of the fdt is invalid (NULL).\n");		return 0;	}	err = fdt_check_header(working_fdt);	if (err == 0)		return 1;	/* valid */	if (err < 0) {		printf("libfdt fdt_check_header(): %s", fdt_strerror(err));		/*		 * Be more informative on bad version.		 */		if (err == -FDT_ERR_BADVERSION) {			if (fdt_version(working_fdt) <			    FDT_FIRST_SUPPORTED_VERSION) {				printf (" - too old, fdt %d < %d",					fdt_version(working_fdt),					FDT_FIRST_SUPPORTED_VERSION);				working_fdt = NULL;			}			if (fdt_last_comp_version(working_fdt) >			    FDT_LAST_SUPPORTED_VERSION) {				printf (" - too new, fdt %d > %d",					fdt_version(working_fdt),					FDT_LAST_SUPPORTED_VERSION);				working_fdt = NULL;			}			return 0;		}		printf("\n");		return 0;	}	return 1;}/****************************************************************************//* * Parse the user's input, partially heuristic.  Valid formats: * <0x00112233 4 05>	- an array of cells.  Numbers follow standard *			C conventions. * [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. * newval: An array of strings containing the new property as specified *	on the command line * count: The number of strings in the array * data: A bytestream to be placed in the property * len: The length of the resulting bytestream */static int fdt_parse_prop(char **newval, int count, char *data, int *len){	char *cp;		/* temporary char pointer */	char *newp;		/* temporary newval char pointer */	unsigned long tmp;	/* holds converted values */	int stridx = 0;	*len = 0;	newp = newval[0];	/* An array of cells */	if (*newp == '<') {		newp++;		while ((*newp != '>') && (stridx < count)) {			/*			 * Keep searching until we find that last ">"			 * That way users don't have to escape the spaces			 */			if (*newp == '\0') {				newp = newval[++stridx];				continue;			}			cp = newp;			tmp = simple_strtoul(cp, &newp, 0);			*(uint32_t *)data = __cpu_to_be32(tmp);			data  += 4;			*len += 4;			/* If the ptr didn't advance, something went wrong */			if ((newp - cp) <= 0) {				printf("Sorry, I could not convert \"%s\"\n",					cp);				return 1;			}			while (*newp == ' ')				newp++;		}		if (*newp != '>') {			printf("Unexpected character '%c'\n", *newp);			return 1;		}	} else if (*newp == '[') {		/*		 * Byte stream.  Convert the values.		 */		newp++;		while ((*newp != ']') && (stridx < count)) {			tmp = simple_strtoul(newp, &newp, 16);			*data++ = tmp & 0xFF;			*len    = *len + 1;			while (*newp == ' ')				newp++;			if (*newp != '\0')				newp = newval[++stridx];		}		if (*newp != ']') {			printf("Unexpected character '%c'\n", *newp);			return 1;		}	} else {		/*		 * Assume it is a string.  Copy it into our data area for		 * convenience (including the terminating '\0').		 */		while (stridx < count) {			*len = strlen(newp) + 1;			strcpy(data, newp);			newp = newval[++stridx];		}	}	return 0;}/****************************************************************************//* * Heuristic to guess if this is a string or concatenated strings. */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;}/* * 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;	/* 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;	}	if ((len %4) == 0) {		const u32 *p;		printf("<");		for (j = 0, p = data; j < len/4; j ++)			printf("0x%x%s", p[j], j < (len/4 - 1) ? " " : "");		printf(">");	} else { /* anything else... hexdump */		const u8 *s;		printf("[");		for (j = 0, s = data; j < len; j++)			printf("%02x%s", s[j], j < len - 1 ? " " : "");		printf("]");	}}/****************************************************************************//* * Recursively print (a portion of) the working_fdt.  The depth parameter * determines how deeply nested the fdt is printed. */static int fdt_print(const char *pathp, char *prop, int depth){	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";	const 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 */	const struct fdt_property *fdt_prop;	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;	}	/*	 * The user passed in a property as well as node path.	 * Print only the given property and then return.	 */	if (prop) {		nodep = fdt_getprop (working_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.	 */	while(level >= 0) {		tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);		switch(tag) {		case FDT_BEGIN_NODE:			pathp = fdt_get_name(working_fdt, nodeoffset, NULL);			if (level <= depth) {				if (pathp == NULL)					pathp = "/* NULL pointer error */";				if (*pathp == '\0')					pathp = "/";	/* root is nameless */				printf("%s%s {\n",					&tabs[MAX_LEVEL - level], pathp);			}			level++;			if (level >= MAX_LEVEL) {				printf("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:			fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,					sizeof(*fdt_prop));			pathp    = fdt_string(working_fdt,					fdt32_to_cpu(fdt_prop->nameoff));			len      = fdt32_to_cpu(fdt_prop->len);			nodep    = fdt_prop->data;			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:			printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);			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,	255,	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> and make it active\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 header                          - Display header info\n"	"fdt bootcpu <id>                    - Set boot cpuid\n"	"fdt memory <addr> <size>            - Add/Update memory node\n"	"fdt rsvmem print                    - Show current mem reserves\n"	"fdt rsvmem add <addr> <size>        - Add a mem reserve\n"	"fdt rsvmem delete <index>           - Delete a mem reserves\n"	"fdt chosen - Add/update the /chosen branch in the tree\n"	"NOTE: If the path or property you are setting/printing has a '#' character\n"	"     or spaces, you MUST escape it with a \\ character or quote it with \".\n");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?