cmd_fdt.c

来自「U-boot源码 ARM7启动代码」· C语言 代码 · 共 704 行 · 第 1/2 页

C
704
字号
			if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) {				printf (" - too new, fdt $d > %d",					fdt_version(fdt),					FDT_LAST_SUPPORTED_VERSION);				fdt = NULL;			}			return 0;		}		printf("\n");		return 0;	}	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;}/****************************************************************************//* * 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;	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("<0x%02x>", (*(u8 *) data) & 0xff);		break;	case 2:	 /* half-word */		printf("<0x%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);		break;	case 4:	 /* word */		printf("<0x%08x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);		break;	case 8:	 /* double-word */#if __WORDSIZE == 64		printf("<0x%016llx>", be64_to_cpu(*(uint64_t *) data));#else		printf("<0x%08x ", be32_to_cpu(*(u32 *) data) & 0xffffffffU);		data += 4;		printf("0x%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;	}}/****************************************************************************//* * Recursively print (a portion of) the 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 (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 (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(fdt, nodeoffset, &nextoffset);		switch(tag) {		case FDT_BEGIN_NODE:			pathp = fdt_get_name(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(fdt, nodeoffset,					sizeof(*fdt_prop));			pathp    = fdt_string(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("/* 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,	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"#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"	" 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");

⌨️ 快捷键说明

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