Esempio n. 1
0
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
	const fdt32_t *tagp, *lenp;
	uint32_t tag;
	int offset = startoffset;
	const char *p;

	*nextoffset = -FDT_ERR_TRUNCATED;
	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
	if (!tagp)
		return FDT_END; /* premature end */
	tag = fdt32_to_cpu(*tagp);
	offset += FDT_TAGSIZE;

	*nextoffset = -FDT_ERR_BADSTRUCTURE;
	switch (tag) {
	case FDT_BEGIN_NODE:
		/* skip name */
		do {
			p = fdt_offset_ptr(fdt, offset++, 1);
		} while (p && (*p != '\0'));
		if (!p)
			return FDT_END; /* premature end */
		break;

	case FDT_PROP:
		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
		if (!lenp)
			return FDT_END; /* premature end */
		/* skip-name offset, length and value */
		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
			+ fdt32_to_cpu(*lenp);
		break;

	case FDT_END:
	case FDT_END_NODE:
	case FDT_NOP:
		break;

	default:
		return FDT_END;
	}

	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
		return FDT_END; /* premature end */

	*nextoffset = FDT_TAGALIGN(offset);
	return tag;
}
Esempio n. 2
0
static int check_subnode(struct fdt_header *fdt, int parent, const char *name)
{
	int offset;
	const struct fdt_node_header *nh;
	uint32_t tag;

	verbose_printf("Checking subnode \"%s\" of %d...", name, parent);
	offset = fdt_subnode_offset(fdt, parent, name);
	verbose_printf("offset %d...", offset);
	if (offset < 0)
		FAIL("fdt_subnode_offset(\"%s\"): %s", name, fdt_strerror(offset));
	nh = fdt_offset_ptr(fdt, offset, sizeof(*nh));
	verbose_printf("pointer %p\n", nh);
	if (! nh)
		FAIL("NULL retrieving subnode \"%s\"", name);

	tag = fdt32_to_cpu(nh->tag);

	if (tag != FDT_BEGIN_NODE)
		FAIL("Incorrect tag 0x%08x on property \"%s\"", tag, name);
	if (!nodename_eq(nh->name, name))
		FAIL("Subnode name mismatch \"%s\" instead of \"%s\"",
		     nh->name, name);

	return offset;
}
Esempio n. 3
0
static int
fdt_nextprop(int offset, char *buf, size_t size)
{
	const struct fdt_property *prop;
	const char *name;
	uint32_t tag;
	int nextoffset, depth;

	depth = 0;
	tag = fdt_next_tag(fdtp, offset, &nextoffset);

	/* Find the next prop */
	do {
		offset = nextoffset;
		tag = fdt_next_tag(fdtp, offset, &nextoffset);

		if (tag == FDT_BEGIN_NODE)
			depth++;
		else if (tag == FDT_END_NODE)
			depth--;
		else if ((tag == FDT_PROP) && (depth == 0)) {
			prop =
			    (const struct fdt_property *)fdt_offset_ptr(fdtp,
			    offset, sizeof(*prop));
			name = fdt_string(fdtp,
			    fdt32_to_cpu(prop->nameoff));
			strncpy(buf, name, size);
			return (strlen(name));
		} else
			depth = -1;
	} while (depth >= 0);

	return (-1);
}
Esempio n. 4
0
static int _fdt_nodename_eq(const void *fdt, int offset,
			    const char *s, int len)
{
	/*
	 * struct fdt_node_header {
	 * uint32_t tag;
	 * char name[0];
	 * };

	 * fdt_node_header의 name을 가져옴
	 * (len+1)만큼 가져오는 것은 밑에서 '@'을 체크하기 위해?
	*/
	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);

	if (! p)
		/* short match */
		return 0;

	if (memcmp(p, s, len) != 0)
		return 0;

	if (p[len] == '\0')
		return 1;
	else if (!memchr(s, '@', len) && (p[len] == '@'))
		return 1;
	else
		return 0;
}
Esempio n. 5
0
int fdt_nop_node(void *fdt, int nodeoffset)
{
	int endoffset;

	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
	if (endoffset < 0)
		return endoffset;

	nop_region(fdt_offset_ptr(fdt, nodeoffset, 0), endoffset - nodeoffset);
	return 0;
}
Esempio n. 6
0
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
{
	const uint32_t *tagp, *lenp;
	uint32_t tag;
	const char *p;

	if (offset % FDT_TAGSIZE)
		return -1;

	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
	if (! tagp)
		return FDT_END; /* premature end */
	tag = fdt32_to_cpu(*tagp);
	offset += FDT_TAGSIZE;

	switch (tag) {
	case FDT_BEGIN_NODE:
		/* skip name */
		do {
			p = fdt_offset_ptr(fdt, offset++, 1);
		} while (p && (*p != '\0'));
		if (! p)
			return FDT_END;
		break;
	case FDT_PROP:
		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
		if (! lenp)
			return FDT_END;
		/* skip name offset, length and value */
		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
		break;
	}

	if (nextoffset)
		*nextoffset = FDT_TAGALIGN(offset);

	return tag;
}
Esempio n. 7
0
static int _fdt_nodename_eq(const void *fdt, int offset, const char *s, int len)
{
	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len + 1);

	if (!p)
		/* short match */
		return 0;

	if (memcmp(p, s, len) != 0)
		return 0;

	if (p[len] == '\0')
		return 1;
	else if (!memchr(s, '@', len) && (p[len] == '@'))
		return 1;
	else
		return 0;
}
Esempio n. 8
0
int main(int argc, char *argv[])
{
	void *fdt;
	const struct fdt_node_header *nh;

	test_init(argc, argv);
	fdt = load_blob_arg(argc, argv);

	nh = fdt_offset_ptr(fdt, 0, sizeof(*nh));

	if (! nh)
		FAIL("NULL retrieving root node");

	if (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE)
		FAIL("Wrong tag on root node");

	if (strlen(nh->name) != 0)
		FAIL("Wrong name for root node, \"%s\" instead of empty",
		     nh->name);

	PASS();
}
Esempio n. 9
0
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
	const struct fdt_node_header *nh;
	int err;

	if ((err = fdt_check_header(fdt)) != 0)
		goto fail;

	err = -FDT_ERR_BADOFFSET;
	nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
	if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
		goto fail;

	if (len)
		*len = strlen(nh->name);

	return nh->name;

 fail:
	if (len)
		*len = err;
	return NULL;
}
Esempio n. 10
0
const struct fdt_property *fdt_get_property(const void *fdt,
					    int nodeoffset,
					    const char *name, int *lenp)
{
	uint32_t tag;
	const struct fdt_property *prop;
	int namestroff;
	int offset, nextoffset;
	int err;

	if ((err = fdt_check_header(fdt)) != 0)
		goto fail;

	err = -FDT_ERR_BADOFFSET;
	if (nodeoffset % FDT_TAGSIZE)
		goto fail;

	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
	if (tag != FDT_BEGIN_NODE)
		goto fail;

	do {
		offset = nextoffset;

		tag = fdt_next_tag(fdt, offset, &nextoffset);
		switch (tag) {
		case FDT_END:
			err = -FDT_ERR_TRUNCATED;
			goto fail;

		case FDT_BEGIN_NODE:
		case FDT_END_NODE:
		case FDT_NOP:
			break;

		case FDT_PROP:
			err = -FDT_ERR_BADSTRUCTURE;
			prop = fdt_offset_ptr(fdt, offset, sizeof(*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;

				return prop;
			}
			break;

		default:
			err = -FDT_ERR_BADSTRUCTURE;
			goto fail;
		}
	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));

	err = -FDT_ERR_NOTFOUND;
 fail:
	if (lenp)
		*lenp = err;
	return NULL;
}
Esempio n. 11
0
File: fdt.c Progetto: 95strat/linux
/*
 * 다음 tag의 Offset를 찾는다.(nextoffset갱신) 
 * in	startoffset	현재 시작 offset
 * out	nextoffset	다음 시작 offset
 * return FDT_END	에러 혹은 현재의 tag값
 * 	tag 구분값
 *		define FDT_BEGIN_NODE	0x1		
 *		#define FDT_END_NODE	0x2
 *		#define FDT_PROP	0x3
 */
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
	const uint32_t *tagp, *lenp;
	uint32_t tag;
	int offset = startoffset;
	const char *p;

	*nextoffset = -FDT_ERR_TRUNCATED;
	/* FDT_TAGSIZE: sizeof(uint32_t) word사이즈 */
	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
	if (!tagp)
		return FDT_END; /* premature end */
	tag = fdt32_to_cpu(*tagp);
	offset += FDT_TAGSIZE;

	*nextoffset = -FDT_ERR_BADSTRUCTURE;
	switch (tag) {
	    /*
		#define FDT_BEGIN_NODE	0x1		
		#define FDT_END_NODE	0x2
		#define FDT_PROP	0x3

		[2015-11-07 여기까지 함]
	    */
	case FDT_BEGIN_NODE:
		/* skip name */
		/*
		   struct fdt_node_header {
			   uint32_t tag;
			   char name[0];
		   };
		 */
		do {
			p = fdt_offset_ptr(fdt, offset++, 1);
		} while (p && (*p != '\0'));
		if (!p)
			return FDT_END; /* premature end */
		break;

	case FDT_PROP:
		/*
		   struct fdt_property {
			   uint32_t tag;
			   uint32_t len;
			   uint32_t nameoff;
			   char data[0];
		   };
		 */
		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
		if (!lenp)
			return FDT_END; /* premature end */
		/* skip-name offset, length and value */
		/* offset += 12 - 4 + (*lenp)
		sizeof(struct fdt_property) 는 12이다.
		*/
		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
			+ fdt32_to_cpu(*lenp);
		break;

	case FDT_END:
	case FDT_END_NODE:
	case FDT_NOP:
		break;

	default:
		return FDT_END;
	}

	// offset값 범위체크
	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
		return FDT_END; /* premature end */
	/*
	   4 byte align을 맞추기위해
	#define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
	#define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))

	ex) FDT_TAGALIGN(10)
		FDT_ALIGN(10, 4)
		((10 + 4 - 1) & ~(4 - 1)) = 12
		(13 & ~3) = 0b1101 & ~0b0011 = 0b1100 = 12
	*/
	*nextoffset = FDT_TAGALIGN(offset);
	return tag;
}
static int nlm_fdt_read(char *page, char **start, off_t off,
			     int count, int *eof, void *data)
{
	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;
	int plen = 0;
	const char *pathp = "/";
	int depth = MAX_LEVEL;
	off_t begin = 0;

	working_fdt = (struct fdt_header *)fdt;

	nodeoffset = fdt_path_offset (working_fdt, pathp);
	if (nodeoffset < 0) {
		/*
		 * Not found or something else bad happened.
		 */
		plen += sprintf(page + plen, 
			"libfdt fdt_path_offset() returned %s\n",
			fdt_strerror(nodeoffset));
		goto out;
	}

	/*
	 * The user passed in a node path and no property,
	 * print the node and all subnodes.
	 */
	while(level >= 0) {
		if (!proc_pos_check(&begin, &plen, off, count)) goto out;
		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 */
				plen += sprintf(page + plen, "%s%s {\n",
					&tabs[MAX_LEVEL - level], pathp);
			}
			level++;
			if (level >= MAX_LEVEL) {
				plen += sprintf(page + plen, "Nested too deep, aborting.\n");
				goto out;
			}
			break;
		case FDT_END_NODE:
			level--;
			if (level <= depth)
				plen += sprintf(page + plen, "%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) {
				plen += sprintf (page + plen, "libfdt fdt_getprop(): %s\n",
					fdt_strerror(len));
				goto out;
			} else if (len == 0) {
				/* the property has no value */
				if (level <= depth)
					plen += sprintf(page + plen, "%s%s;\n",
						&tabs[MAX_LEVEL - level],
						pathp);
			} else {
				if (level <= depth) {
					plen += sprintf(page + plen, "%s%s = ",
						&tabs[MAX_LEVEL - level],
						pathp);
					plen += print_data (page + plen, nodep, len);
					plen += sprintf(page + plen, ";\n");
				}
			}
			break;
		case FDT_NOP:
			plen += sprintf(page + plen, "%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
			break;
		case FDT_END:
			goto good_out;
		default:
			if (level <= depth)
				plen += sprintf(page + plen, "Unknown tag 0x%08X\n", tag);
			goto out;
		}
		nodeoffset = nextoffset;
	}

	good_out:
	*eof = 1;

	out:
	*start = page + (off - begin);
	plen -= (off - begin);
	if (plen > count)
		plen = count;
	if (plen < 0)
		plen = 0;

	return plen;
}
Esempio n. 13
0
static void compare_structure(const void *fdt1, const void *fdt2)
{
	int nextoffset1 = 0, nextoffset2 = 0;
	int offset1, offset2;
	uint32_t tag1, tag2;
	const char *name1, *name2;
	int err;
	const struct fdt_property *prop1, *prop2;
	int len1, len2;

	while (1) {
		do {
			offset1 = nextoffset1;
			tag1 = fdt_next_tag(fdt1, offset1, &nextoffset1);
		} while (tag1 == FDT_NOP);
		do {
			offset2 = nextoffset2;
			tag2 = fdt_next_tag(fdt2, offset2, &nextoffset2);
		} while (tag2 == FDT_NOP);

		if (tag1 != tag2)
			MISMATCH("Tag mismatch (%d != %d) at (%d, %d)",
			     tag1, tag2, offset1, offset2);

		switch (tag1) {
		case FDT_BEGIN_NODE:
			name1 = fdt_get_name(fdt1, offset1, &err);
			if (!name1)
				FAIL("fdt_get_name(fdt1, %d, ..): %s",
				     offset1, fdt_strerror(err));
			name2 = fdt_get_name(fdt2, offset2, NULL);
			if (!name2)
				FAIL("fdt_get_name(fdt2, %d, ..): %s",
				     offset2, fdt_strerror(err));

			if (!streq(name1, name2))
			    MISMATCH("Name mismatch (\"%s\" != \"%s\") at (%d, %d)",
				     name1, name2, offset1, offset2);
			break;

		case FDT_PROP:
			prop1 = fdt_offset_ptr(fdt1, offset1, sizeof(*prop1));
			if (!prop1)
				FAIL("Could get fdt1 property at %d", offset1);
			prop2 = fdt_offset_ptr(fdt2, offset2, sizeof(*prop2));
			if (!prop2)
				FAIL("Could get fdt2 property at %d", offset2);

			name1 = fdt_string(fdt1, fdt32_to_cpu(prop1->nameoff));
			name2 = fdt_string(fdt2, fdt32_to_cpu(prop2->nameoff));
			if (!streq(name1, name2))
				MISMATCH("Property name mismatch \"%s\" != \"%s\" "
					 "at (%d, %d)", name1, name2, offset1, offset2);
			len1 = fdt32_to_cpu(prop1->len);
			len2 = fdt32_to_cpu(prop2->len);
			if (len1 != len2)
				MISMATCH("Property length mismatch %u != %u "
					 "at (%d, %d)", len1, len2, offset1, offset2);

			if (memcmp(prop1->data, prop2->data, len1) != 0)
				MISMATCH("Property value mismatch at (%d, %d)",
					 offset1, offset2);
			break;

		case FDT_END:
			return;
		}
	}
}
/*
 * 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;
}