diff options
| -rw-r--r-- | include/libfdt.h | 3 | ||||
| -rw-r--r-- | libfdt/fdt.c | 39 | ||||
| -rw-r--r-- | libfdt/fdt_ro.c | 116 | ||||
| -rw-r--r-- | libfdt/fdt_rw.c | 6 | ||||
| -rw-r--r-- | libfdt/fdt_sw.c | 2 | ||||
| -rw-r--r-- | libfdt/fdt_wip.c | 4 | ||||
| -rw-r--r-- | libfdt/libfdt_internal.h | 1 | 
7 files changed, 119 insertions, 52 deletions
| diff --git a/include/libfdt.h b/include/libfdt.h index acdc72eac..c4b3c249b 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -81,6 +81,9 @@ struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,  void *fdt_getprop(const void *fdt, int nodeoffset,  		  const char *name, int *lenp); +uint32_t fdt_next_tag(const void *fdt, int offset, +                      int *nextoffset, char **namep); +  /* Write-in-place functions */  int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,  			const void *val, int len); diff --git a/libfdt/fdt.c b/libfdt/fdt.c index 772da46a7..4b1c8abf9 100644 --- a/libfdt/fdt.c +++ b/libfdt/fdt.c @@ -58,45 +58,6 @@ void *fdt_offset_ptr(const void *fdt, int offset, int len)  	return p;  } -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 = ALIGN(offset, FDT_TAGSIZE); - -	return tag; -} -  const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)  {  	int len = strlen(s) + 1; diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c index 9112c6a63..f88408395 100644 --- a/libfdt/fdt_ro.c +++ b/libfdt/fdt_ro.c @@ -48,11 +48,24 @@ static int offset_streq(const void *fdt, int offset,  	return 1;  } +/* + * Return a pointer to the string at the given string offset. + */  char *fdt_string(const void *fdt, int stroffset)  {  	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;  } +/* + * Return the node offset of the node specified by: + *   parentoffset - starting place (0 to start at the root) + *   name         - name being searched for + *   namelen      - length of the name: typically strlen(name) + * + * Notes: + *   If the start node has subnodes, the subnodes are _not_ searched for the + *     requested name. + */  int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  			       const char *name, int namelen)  { @@ -62,13 +75,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  	CHECK_HEADER(fdt); -	tag = _fdt_next_tag(fdt, parentoffset, &nextoffset); +	tag = fdt_next_tag(fdt, parentoffset, &nextoffset, NULL);  	if (tag != FDT_BEGIN_NODE)  		return -FDT_ERR_BADOFFSET;  	do {  		offset = nextoffset; -		tag = _fdt_next_tag(fdt, offset, &nextoffset); +		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);  		switch (tag) {  		case FDT_END: @@ -76,10 +89,15 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  		case FDT_BEGIN_NODE:  			level++; +			/* +			 * If we are nested down levels, ignore the strings +			 * until we get back to the proper level. +			 */  			if (level != 1)  				continue; + +			/* Return the offset if this is "our" string. */  			if (offset_streq(fdt, offset+FDT_TAGSIZE, name, namelen)) -				/* Found it! */  				return offset;  			break; @@ -99,12 +117,19 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,  	return -FDT_ERR_NOTFOUND;  } +/* + * See fdt_subnode_offset_namelen() + */  int fdt_subnode_offset(const void *fdt, int parentoffset,  		       const char *name)  {  	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));  } +/* + * 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)  {  	const char *end = path + strlen(path); @@ -113,21 +138,33 @@ int fdt_path_offset(const void *fdt, const char *path)  	CHECK_HEADER(fdt); +	/* Paths must be absolute */  	if (*path != '/')  		return -FDT_ERR_BADPATH;  	while (*p) {  		const char *q; +		/* Skip path separator(s) */  		while (*p == '/')  			p++;  		if (! *p)  			return -FDT_ERR_BADPATH; + +		/* +		 * Find the next path separator.  The characters between +		 * p and q are the next segment of the the path to find. +		 */  		q = strchr(p, '/');  		if (! q)  			q = end; +		/* +		 * Find the offset corresponding to the this path segment. +		 */  		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + +		/* Oops, error, abort abort abort */  		if (offset < 0)  			return offset; @@ -137,6 +174,10 @@ int fdt_path_offset(const void *fdt, const char *path)  	return offset;	  } +/* + * Given the offset of a node and a name of a property in that node, return + * a pointer to the property struct. + */  struct fdt_property *fdt_get_property(const void *fdt,  				      int nodeoffset,  				      const char *name, int *lenp) @@ -155,14 +196,14 @@ struct fdt_property *fdt_get_property(const void *fdt,  	if (nodeoffset % FDT_TAGSIZE)  		goto fail; -	tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); +	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);  	if (tag != FDT_BEGIN_NODE)  		goto fail;  	do {  		offset = nextoffset; -		tag = _fdt_next_tag(fdt, offset, &nextoffset); +		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);  		switch (tag) {  		case FDT_END:  			err = -FDT_ERR_TRUNCATED; @@ -177,6 +218,10 @@ struct fdt_property *fdt_get_property(const void *fdt,  			break;  		case FDT_PROP: +			/* +			 * If we are nested down levels, ignore the strings +			 * until we get back to the proper level. +			 */  			if (level != 0)  				continue; @@ -216,6 +261,10 @@ struct fdt_property *fdt_get_property(const void *fdt,  	return NULL;  } +/* + * Given the offset of a node and a name of a property in that node, return + * a pointer to the property data (ONLY). + */  void *fdt_getprop(const void *fdt, int nodeoffset,  		  const char *name, int *lenp)  { @@ -225,5 +274,60 @@ void *fdt_getprop(const void *fdt, int nodeoffset,  	if (! prop)  		return NULL; -	return prop->data; +	return (void *)prop->data;  } + + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset, char **namep) +{ +	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: +		if(namep) +			*namep = fdt_offset_ptr(fdt, offset, 1); + +		/* 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; +		/* +		 * Get the property and set the namep to the name. +		 */ +		if(namep) { +			struct fdt_property *prop; + +			prop = fdt_offset_ptr_typed(fdt, offset - FDT_TAGSIZE, prop); +			if (! prop) +				return -FDT_ERR_BADSTRUCTURE; +			*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); +		} +		/* skip name offset, length and value */ +		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp); +		break; +	} + +	if (nextoffset) +		*nextoffset = ALIGN(offset, FDT_TAGSIZE); + +	return tag; +} + diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c index 7396645a6..b33fbf45d 100644 --- a/libfdt/fdt_rw.c +++ b/libfdt/fdt_rw.c @@ -145,7 +145,7 @@ static int _add_property(void *fdt, int nodeoffset, const char *name, int len,  	int namestroff;  	int err; -	tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); +	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);  	if (tag != FDT_BEGIN_NODE)  		return -FDT_ERR_BADOFFSET; @@ -219,10 +219,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,  		return offset;  	/* Try to place the new node after the parent's properties */ -	_fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ +	fdt_next_tag(fdt, parentoffset, &nextoffset, NULL); /* skip the BEGIN_NODE */  	do {  		offset = nextoffset; -		tag = _fdt_next_tag(fdt, offset, &nextoffset); +		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);  	} while (tag == FDT_PROP);  	nh = _fdt_offset_ptr(fdt, offset); diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c index 41d4891bb..672f4ddd9 100644 --- a/libfdt/fdt_sw.c +++ b/libfdt/fdt_sw.c @@ -203,7 +203,7 @@ int fdt_finish(void *fdt)  	/* Walk the structure, correcting string offsets */  	offset = 0; -	while ((tag = _fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { +	while ((tag = fdt_next_tag(fdt, offset, &nextoffset, NULL)) != FDT_END) {  		if (tag == FDT_PROP) {  			struct fdt_property *prop = fdt_offset_ptr(fdt, offset,  								   sizeof(*prop)); diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c index 0db7d259f..261b9b0dc 100644 --- a/libfdt/fdt_wip.c +++ b/libfdt/fdt_wip.c @@ -68,12 +68,12 @@ int _fdt_node_end_offset(void *fdt, int nodeoffset)  	uint32_t tag;  	int offset, nextoffset; -	tag = _fdt_next_tag(fdt, nodeoffset, &nextoffset); +	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset, NULL);  	if (tag != FDT_BEGIN_NODE)  		return -FDT_ERR_BADOFFSET;  	do {  		offset = nextoffset; -		tag = _fdt_next_tag(fdt, offset, &nextoffset); +		tag = fdt_next_tag(fdt, offset, &nextoffset, NULL);  		switch (tag) {  		case FDT_END: diff --git a/libfdt/libfdt_internal.h b/libfdt/libfdt_internal.h index 124bef78e..cc9633c9e 100644 --- a/libfdt/libfdt_internal.h +++ b/libfdt/libfdt_internal.h @@ -27,7 +27,6 @@  #define streq(p, q)	(strcmp((p), (q)) == 0)  int _fdt_check_header(const void *fdt); -uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);  const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);  int _fdt_node_end_offset(void *fdt, int nodeoffset); |