fdt: Sync up to the latest libfdt
Bring over the fdt from this commit: 430419c (origin/master) tests: fix some python warnings adding in the 'assumptions' series designed to reduce code size. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									e9bae5c534
								
							
						
					
					
						commit
						f0921f5098
					
				|  | @ -14,12 +14,13 @@ | |||
| 
 | ||||
| #include "libfdt_internal.h" | ||||
| 
 | ||||
| static int _fdt_nodename_eq(const void *fdt, int offset, | ||||
| 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); | ||||
| 	int olen; | ||||
| 	const char *p = fdt_get_name(fdt, offset, &olen); | ||||
| 
 | ||||
| 	if (!p) | ||||
| 	if (!p || (fdt_chk_extra() && olen < len)) | ||||
| 		/* short match */ | ||||
| 		return 0; | ||||
| 
 | ||||
|  | @ -34,46 +35,85 @@ static int _fdt_nodename_eq(const void *fdt, int offset, | |||
| 		return 0; | ||||
| } | ||||
| 
 | ||||
| const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) | ||||
| { | ||||
| 	int32_t totalsize; | ||||
| 	uint32_t absoffset; | ||||
| 	size_t len; | ||||
| 	int err; | ||||
| 	const char *s, *n; | ||||
| 
 | ||||
| 	if (!fdt_chk_extra()) { | ||||
| 		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | ||||
| 
 | ||||
| 		if (lenp) | ||||
| 			*lenp = strlen(s); | ||||
| 		return s; | ||||
| 	} | ||||
| 	totalsize = fdt_ro_probe_(fdt); | ||||
| 	err = totalsize; | ||||
| 	if (totalsize < 0) | ||||
| 		goto fail; | ||||
| 
 | ||||
| 	err = -FDT_ERR_BADOFFSET; | ||||
| 	absoffset = stroffset + fdt_off_dt_strings(fdt); | ||||
| 	if (absoffset >= totalsize) | ||||
| 		goto fail; | ||||
| 	len = totalsize - absoffset; | ||||
| 
 | ||||
| 	if (fdt_magic(fdt) == FDT_MAGIC) { | ||||
| 		if (stroffset < 0) | ||||
| 			goto fail; | ||||
| 		if (!fdt_chk_version() || fdt_version(fdt) >= 17) { | ||||
| 			if (stroffset >= fdt_size_dt_strings(fdt)) | ||||
| 				goto fail; | ||||
| 			if ((fdt_size_dt_strings(fdt) - stroffset) < len) | ||||
| 				len = fdt_size_dt_strings(fdt) - stroffset; | ||||
| 		} | ||||
| 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | ||||
| 		if ((stroffset >= 0) | ||||
| 		    || (stroffset < -fdt_size_dt_strings(fdt))) | ||||
| 			goto fail; | ||||
| 		if ((-stroffset) < len) | ||||
| 			len = -stroffset; | ||||
| 	} else { | ||||
| 		err = -FDT_ERR_INTERNAL; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	s = (const char *)fdt + absoffset; | ||||
| 	n = memchr(s, '\0', len); | ||||
| 	if (!n) { | ||||
| 		/* missing terminating NULL */ | ||||
| 		err = -FDT_ERR_TRUNCATED; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	if (lenp) | ||||
| 		*lenp = n - s; | ||||
| 	return s; | ||||
| 
 | ||||
| fail: | ||||
| 	if (lenp) | ||||
| 		*lenp = err; | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| const char *fdt_string(const void *fdt, int stroffset) | ||||
| { | ||||
| 	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | ||||
| 	return fdt_get_string(fdt, stroffset, NULL); | ||||
| } | ||||
| 
 | ||||
| static int _fdt_string_eq(const void *fdt, int stroffset, | ||||
| static int fdt_string_eq_(const void *fdt, int stroffset, | ||||
| 			  const char *s, int len) | ||||
| { | ||||
| 	const char *p = fdt_string(fdt, stroffset); | ||||
| 	int slen; | ||||
| 	const char *p = fdt_get_string(fdt, stroffset, &slen); | ||||
| 
 | ||||
| 	return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0); | ||||
| 	return p && (slen == len) && (memcmp(p, s, len) == 0); | ||||
| } | ||||
| 
 | ||||
| uint32_t fdt_get_max_phandle(const void *fdt) | ||||
| { | ||||
| 	uint32_t max_phandle = 0; | ||||
| 	int offset; | ||||
| 
 | ||||
| 	for (offset = fdt_next_node(fdt, -1, NULL);; | ||||
| 	     offset = fdt_next_node(fdt, offset, NULL)) { | ||||
| 		uint32_t phandle; | ||||
| 
 | ||||
| 		if (offset == -FDT_ERR_NOTFOUND) | ||||
| 			return max_phandle; | ||||
| 
 | ||||
| 		if (offset < 0) | ||||
| 			return (uint32_t)-1; | ||||
| 
 | ||||
| 		phandle = fdt_get_phandle(fdt, offset); | ||||
| 		if (phandle == (uint32_t)-1) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (phandle > max_phandle) | ||||
| 			max_phandle = phandle; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | ||||
| int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) | ||||
| { | ||||
| 	uint32_t max = 0; | ||||
| 	int offset = -1; | ||||
|  | @ -95,6 +135,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | |||
| 			max = value; | ||||
| 	} | ||||
| 
 | ||||
| 	if (phandle) | ||||
| 		*phandle = max; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | ||||
| { | ||||
| 	uint32_t max; | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = fdt_find_max_phandle(fdt, &max); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (max == FDT_MAX_PHANDLE) | ||||
| 		return -FDT_ERR_NOPHANDLES; | ||||
| 
 | ||||
|  | @ -104,24 +159,48 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) | ||||
| { | ||||
| 	int offset = n * sizeof(struct fdt_reserve_entry); | ||||
| 	int absoffset = fdt_off_mem_rsvmap(fdt) + offset; | ||||
| 
 | ||||
| 	if (fdt_chk_extra()) { | ||||
| 		if (absoffset < fdt_off_mem_rsvmap(fdt)) | ||||
| 			return NULL; | ||||
| 		if (absoffset > fdt_totalsize(fdt) - | ||||
| 		    sizeof(struct fdt_reserve_entry)) | ||||
| 			return NULL; | ||||
| 	} | ||||
| 	return fdt_mem_rsv_(fdt, n); | ||||
| } | ||||
| 
 | ||||
| int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | ||||
| { | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); | ||||
| 	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); | ||||
| 	const struct fdt_reserve_entry *re; | ||||
| 
 | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 	re = fdt_mem_rsv(fdt, n); | ||||
| 	if (fdt_chk_extra() && !re) | ||||
| 		return -FDT_ERR_BADOFFSET; | ||||
| 
 | ||||
| 	*address = fdt64_ld(&re->address); | ||||
| 	*size = fdt64_ld(&re->size); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_num_mem_rsv(const void *fdt) | ||||
| { | ||||
| 	int i = 0; | ||||
| 	int i; | ||||
| 	const struct fdt_reserve_entry *re; | ||||
| 
 | ||||
| 	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) | ||||
| 		i++; | ||||
| 	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { | ||||
| 		if (fdt64_ld(&re->size) == 0) | ||||
| 			return i; | ||||
| 	} | ||||
| 	return -FDT_ERR_TRUNCATED; | ||||
| } | ||||
| 
 | ||||
| static int _nextprop(const void *fdt, int offset) | ||||
| static int nextprop_(const void *fdt, int offset) | ||||
| { | ||||
| 	uint32_t tag; | ||||
| 	int nextoffset; | ||||
|  | @ -150,13 +229,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, | |||
| { | ||||
| 	int depth; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	for (depth = 0; | ||||
| 	     (offset >= 0) && (depth >= 0); | ||||
| 	     offset = fdt_next_node(fdt, offset, &depth)) | ||||
| 		if ((depth == 1) | ||||
| 		    && _fdt_nodename_eq(fdt, offset, name, namelen)) | ||||
| 		    && fdt_nodename_eq_(fdt, offset, name, namelen)) | ||||
| 			return offset; | ||||
| 
 | ||||
| 	if (depth < 0) | ||||
|  | @ -170,36 +249,17 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, | |||
| 	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Find the next of path separator, note we need to search for both '/' and ':' | ||||
|  * and then take the first one so that we do the right thing for e.g. | ||||
|  * "foo/bar:option" and "bar:option/otheroption", both of which happen, so | ||||
|  * first searching for either ':' or '/' does not work. | ||||
|  */ | ||||
| static const char *fdt_path_next_separator(const char *path, int len) | ||||
| { | ||||
| 	const void *sep1 = memchr(path, '/', len); | ||||
| 	const void *sep2 = memchr(path, ':', len); | ||||
| 
 | ||||
| 	if (sep1 && sep2) | ||||
| 		return (sep1 < sep2) ? sep1 : sep2; | ||||
| 	else if (sep1) | ||||
| 		return sep1; | ||||
| 	else | ||||
| 		return sep2; | ||||
| } | ||||
| 
 | ||||
| int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) | ||||
| { | ||||
| 	const char *end = path + namelen; | ||||
| 	const char *p = path; | ||||
| 	int offset = 0; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* see if we have an alias */ | ||||
| 	if (*path != '/') { | ||||
| 		const char *q = fdt_path_next_separator(path, namelen); | ||||
| 		const char *q = memchr(path, '/', end - p); | ||||
| 
 | ||||
| 		if (!q) | ||||
| 			q = end; | ||||
|  | @ -212,16 +272,15 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) | |||
| 		p = q; | ||||
| 	} | ||||
| 
 | ||||
| 	while (*p && (p < end)) { | ||||
| 	while (p < end) { | ||||
| 		const char *q; | ||||
| 
 | ||||
| 		while (*p == '/') | ||||
| 		while (*p == '/') { | ||||
| 			p++; | ||||
| 
 | ||||
| 		if (*p == '\0' || *p == ':') | ||||
| 			if (p == end) | ||||
| 				return offset; | ||||
| 
 | ||||
| 		q = fdt_path_next_separator(p, end - p); | ||||
| 		} | ||||
| 		q = memchr(p, '/', end - p); | ||||
| 		if (! q) | ||||
| 			q = end; | ||||
| 
 | ||||
|  | @ -243,16 +302,35 @@ int fdt_path_offset(const void *fdt, const char *path) | |||
| const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | ||||
| { | ||||
| 	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); | ||||
| 	const char *nameptr; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (((err = fdt_check_header(fdt)) != 0) | ||||
| 	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) | ||||
| 	if (fdt_chk_extra() && | ||||
| 	    (((err = fdt_ro_probe_(fdt)) < 0) | ||||
| 	     || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))) | ||||
| 		goto fail; | ||||
| 
 | ||||
| 	if (len) | ||||
| 		*len = strlen(nh->name); | ||||
| 	nameptr = nh->name; | ||||
| 
 | ||||
| 	return nh->name; | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		/*
 | ||||
| 		 * For old FDT versions, match the naming conventions of V16: | ||||
| 		 * give only the leaf name (after all /). The actual tree | ||||
| 		 * contents are loosely checked. | ||||
| 		 */ | ||||
| 		const char *leaf; | ||||
| 		leaf = strrchr(nameptr, '/'); | ||||
| 		if (leaf == NULL) { | ||||
| 			err = -FDT_ERR_BADSTRUCTURE; | ||||
| 			goto fail; | ||||
| 		} | ||||
| 		nameptr = leaf+1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (len) | ||||
| 		*len = strlen(nameptr); | ||||
| 
 | ||||
| 	return nameptr; | ||||
| 
 | ||||
|  fail: | ||||
| 	if (len) | ||||
|  | @ -267,7 +345,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset) | |||
| 	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) | ||||
| 		return offset; | ||||
| 
 | ||||
| 	return _nextprop(fdt, offset); | ||||
| 	return nextprop_(fdt, offset); | ||||
| } | ||||
| 
 | ||||
| int fdt_next_property_offset(const void *fdt, int offset) | ||||
|  | @ -275,17 +353,17 @@ int fdt_next_property_offset(const void *fdt, int offset) | |||
| 	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) | ||||
| 		return offset; | ||||
| 
 | ||||
| 	return _nextprop(fdt, offset); | ||||
| 	return nextprop_(fdt, offset); | ||||
| } | ||||
| 
 | ||||
| const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | ||||
| static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, | ||||
| 						              int offset, | ||||
| 						              int *lenp) | ||||
| { | ||||
| 	int err; | ||||
| 	const struct fdt_property *prop; | ||||
| 
 | ||||
| 	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { | ||||
| 	if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) { | ||||
| 		if (lenp) | ||||
| 			*lenp = err; | ||||
| 		return NULL; | ||||
|  | @ -294,35 +372,76 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | |||
| 	prop = fdt_offset_ptr_(fdt, offset); | ||||
| 
 | ||||
| 	if (lenp) | ||||
| 		*lenp = fdt32_to_cpu(prop->len); | ||||
| 		*lenp = fdt32_ld(&prop->len); | ||||
| 
 | ||||
| 	return prop; | ||||
| } | ||||
| 
 | ||||
| const struct fdt_property *fdt_get_property_namelen(const void *fdt, | ||||
| const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | ||||
| 						      int offset, | ||||
| 						      int *lenp) | ||||
| { | ||||
| 	/* Prior to version 16, properties may need realignment
 | ||||
| 	 * and this API does not work. fdt_getprop_*() will, however. */ | ||||
| 
 | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		if (lenp) | ||||
| 			*lenp = -FDT_ERR_BADVERSION; | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return fdt_get_property_by_offset_(fdt, offset, lenp); | ||||
| } | ||||
| 
 | ||||
| static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, | ||||
| 						            int offset, | ||||
| 						            const char *name, | ||||
| 						    int namelen, int *lenp) | ||||
| 						            int namelen, | ||||
| 							    int *lenp, | ||||
| 							    int *poffset) | ||||
| { | ||||
| 	for (offset = fdt_first_property_offset(fdt, offset); | ||||
| 	     (offset >= 0); | ||||
| 	     (offset = fdt_next_property_offset(fdt, offset))) { | ||||
| 		const struct fdt_property *prop; | ||||
| 
 | ||||
| 		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { | ||||
| 		prop = fdt_get_property_by_offset_(fdt, offset, lenp); | ||||
| 		if (fdt_chk_extra() && !prop) { | ||||
| 			offset = -FDT_ERR_INTERNAL; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), | ||||
| 				   name, namelen)) | ||||
| 		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), | ||||
| 				   name, namelen)) { | ||||
| 			if (poffset) | ||||
| 				*poffset = offset; | ||||
| 			return prop; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (lenp) | ||||
| 		*lenp = offset; | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const struct fdt_property *fdt_get_property_namelen(const void *fdt, | ||||
| 						    int offset, | ||||
| 						    const char *name, | ||||
| 						    int namelen, int *lenp) | ||||
| { | ||||
| 	/* Prior to version 16, properties may need realignment
 | ||||
| 	 * and this API does not work. fdt_getprop_*() will, however. */ | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		if (lenp) | ||||
| 			*lenp = -FDT_ERR_BADVERSION; | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, | ||||
| 					 NULL); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const struct fdt_property *fdt_get_property(const void *fdt, | ||||
| 					    int nodeoffset, | ||||
| 					    const char *name, int *lenp) | ||||
|  | @ -334,12 +453,18 @@ const struct fdt_property *fdt_get_property(const void *fdt, | |||
| const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | ||||
| 				const char *name, int namelen, int *lenp) | ||||
| { | ||||
| 	int poffset; | ||||
| 	const struct fdt_property *prop; | ||||
| 
 | ||||
| 	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); | ||||
| 	prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, | ||||
| 					 &poffset); | ||||
| 	if (!prop) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	/* Handle realignment */ | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10 && | ||||
| 	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | ||||
| 		return prop->data + 4; | ||||
| 	return prop->data; | ||||
| } | ||||
| 
 | ||||
|  | @ -348,11 +473,31 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, | |||
| { | ||||
| 	const struct fdt_property *prop; | ||||
| 
 | ||||
| 	prop = fdt_get_property_by_offset(fdt, offset, lenp); | ||||
| 	prop = fdt_get_property_by_offset_(fdt, offset, lenp); | ||||
| 	if (!prop) | ||||
| 		return NULL; | ||||
| 	if (namep) | ||||
| 		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); | ||||
| 	if (namep) { | ||||
| 		const char *name; | ||||
| 		int namelen; | ||||
| 
 | ||||
| 		if (fdt_chk_extra()) { | ||||
| 			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), | ||||
| 					      &namelen); | ||||
| 			if (!name) { | ||||
| 				if (lenp) | ||||
| 					*lenp = namelen; | ||||
| 				return NULL; | ||||
| 			} | ||||
| 			*namep = name; | ||||
| 		} else { | ||||
| 			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Handle realignment */ | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10 && | ||||
| 	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | ||||
| 		return prop->data + 4; | ||||
| 	return prop->data; | ||||
| } | ||||
| 
 | ||||
|  | @ -376,7 +521,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | |||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return fdt32_to_cpu(*php); | ||||
| 	return fdt32_ld(php); | ||||
| } | ||||
| 
 | ||||
| const char *fdt_get_alias_namelen(const void *fdt, | ||||
|  | @ -402,7 +547,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |||
| 	int offset, depth, namelen; | ||||
| 	const char *name; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (buflen < 2) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
|  | @ -454,7 +599,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |||
| 	int offset, depth; | ||||
| 	int supernodeoffset = -FDT_ERR_INTERNAL; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (supernodedepth < 0) | ||||
| 		return -FDT_ERR_NOTFOUND; | ||||
|  | @ -476,10 +621,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (fdt_chk_extra()) { | ||||
| 		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | ||||
| 			return -FDT_ERR_BADOFFSET; | ||||
| 		else if (offset == -FDT_ERR_BADOFFSET) | ||||
| 			return -FDT_ERR_BADSTRUCTURE; | ||||
| 	} | ||||
| 
 | ||||
| 	return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | @ -491,7 +638,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset) | |||
| 
 | ||||
| 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | ||||
| 	if (err) | ||||
| 		return (err < 0) ? err : -FDT_ERR_INTERNAL; | ||||
| 		return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL; | ||||
| 	return nodedepth; | ||||
| } | ||||
| 
 | ||||
|  | @ -513,7 +660,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | |||
| 	const void *val; | ||||
| 	int len; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we scan each
 | ||||
| 	 * property of a node in fdt_getprop(), then if that didn't | ||||
|  | @ -539,7 +686,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | |||
| 	if ((phandle == 0) || (phandle == -1)) | ||||
| 		return -FDT_ERR_BADPHANDLE; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we
 | ||||
| 	 * potentially scan each property of a node in | ||||
|  | @ -692,7 +839,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |||
| { | ||||
| 	int offset, err; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we scan each
 | ||||
| 	 * property of a node in fdt_node_check_compatible(), then if | ||||
|  | @ -711,3 +858,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |||
| 
 | ||||
| 	return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
| 
 | ||||
| #if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0 | ||||
| int fdt_check_full(const void *fdt, size_t bufsize) | ||||
| { | ||||
| 	int err; | ||||
| 	int num_memrsv; | ||||
| 	int offset, nextoffset = 0; | ||||
| 	uint32_t tag; | ||||
| 	unsigned depth = 0; | ||||
| 	const void *prop; | ||||
| 	const char *propname; | ||||
| 
 | ||||
| 	if (bufsize < FDT_V1_SIZE) | ||||
| 		return -FDT_ERR_TRUNCATED; | ||||
| 	err = fdt_check_header(fdt); | ||||
| 	if (err != 0) | ||||
| 		return err; | ||||
| 	if (bufsize < fdt_totalsize(fdt)) | ||||
| 		return -FDT_ERR_TRUNCATED; | ||||
| 
 | ||||
| 	num_memrsv = fdt_num_mem_rsv(fdt); | ||||
| 	if (num_memrsv < 0) | ||||
| 		return num_memrsv; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		offset = nextoffset; | ||||
| 		tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||
| 
 | ||||
| 		if (nextoffset < 0) | ||||
| 			return nextoffset; | ||||
| 
 | ||||
| 		switch (tag) { | ||||
| 		case FDT_NOP: | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_END: | ||||
| 			if (depth != 0) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			return 0; | ||||
| 
 | ||||
| 		case FDT_BEGIN_NODE: | ||||
| 			depth++; | ||||
| 			if (depth > INT_MAX) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_END_NODE: | ||||
| 			if (depth == 0) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			depth--; | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_PROP: | ||||
| 			prop = fdt_getprop_by_offset(fdt, offset, &propname, | ||||
| 						     &err); | ||||
| 			if (!prop) | ||||
| 				return err; | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			return -FDT_ERR_INTERNAL; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| # Makefile.libfdt
 | ||||
| #
 | ||||
| # This is not a complete Makefile of itself.  Instead, it is designed to
 | ||||
|  | @ -9,3 +10,9 @@ LIBFDT_VERSION = version.lds | |||
| LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
 | ||||
| 	fdt_addresses.c fdt_overlay.c | ||||
| LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) | ||||
| LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) | ||||
| 
 | ||||
| libfdt_clean: | ||||
| 	@$(VECHO) CLEAN "(libfdt)" | ||||
| 	rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) | ||||
| 	rm -f $(LIBFDT_dir)/$(LIBFDT_soname) | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -55,14 +10,24 @@ | |||
| 
 | ||||
| #include "libfdt_internal.h" | ||||
| 
 | ||||
| int fdt_check_header(const void *fdt) | ||||
| /*
 | ||||
|  * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks | ||||
|  * that the given buffer contains what appears to be a flattened | ||||
|  * device tree with sane information in its header. | ||||
|  */ | ||||
| int32_t fdt_ro_probe_(const void *fdt) | ||||
| { | ||||
| 	uint32_t totalsize = fdt_totalsize(fdt); | ||||
| 
 | ||||
| 	if (fdt_magic(fdt) == FDT_MAGIC) { | ||||
| 		/* Complete tree */ | ||||
| 		if (fdt_chk_version()) { | ||||
| 			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | ||||
| 				return -FDT_ERR_BADVERSION; | ||||
| 		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) | ||||
| 			if (fdt_last_comp_version(fdt) > | ||||
| 					FDT_LAST_SUPPORTED_VERSION) | ||||
| 				return -FDT_ERR_BADVERSION; | ||||
| 		} | ||||
| 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | ||||
| 		/* Unfinished sequential-write blob */ | ||||
| 		if (fdt_size_dt_struct(fdt) == 0) | ||||
|  | @ -71,6 +36,96 @@ int fdt_check_header(const void *fdt) | |||
| 		return -FDT_ERR_BADMAGIC; | ||||
| 	} | ||||
| 
 | ||||
| 	if (totalsize < INT32_MAX) | ||||
| 		return totalsize; | ||||
| 	else | ||||
| 		return -FDT_ERR_TRUNCATED; | ||||
| } | ||||
| 
 | ||||
| static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) | ||||
| { | ||||
| 	return (off >= hdrsize) && (off <= totalsize); | ||||
| } | ||||
| 
 | ||||
| static int check_block_(uint32_t hdrsize, uint32_t totalsize, | ||||
| 			uint32_t base, uint32_t size) | ||||
| { | ||||
| 	if (!check_off_(hdrsize, totalsize, base)) | ||||
| 		return 0; /* block start out of bounds */ | ||||
| 	if ((base + size) < base) | ||||
| 		return 0; /* overflow */ | ||||
| 	if (!check_off_(hdrsize, totalsize, base + size)) | ||||
| 		return 0; /* block end out of bounds */ | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| size_t fdt_header_size_(uint32_t version) | ||||
| { | ||||
| 	if (version <= 1) | ||||
| 		return FDT_V1_SIZE; | ||||
| 	else if (version <= 2) | ||||
| 		return FDT_V2_SIZE; | ||||
| 	else if (version <= 3) | ||||
| 		return FDT_V3_SIZE; | ||||
| 	else if (version <= 16) | ||||
| 		return FDT_V16_SIZE; | ||||
| 	else | ||||
| 		return FDT_V17_SIZE; | ||||
| } | ||||
| 
 | ||||
| size_t fdt_header_size(const void *fdt) | ||||
| { | ||||
| 	return fdt_chk_version() ? fdt_header_size_(fdt_version(fdt)) : | ||||
| 		FDT_V17_SIZE; | ||||
| } | ||||
| 
 | ||||
| int fdt_check_header(const void *fdt) | ||||
| { | ||||
| 	size_t hdrsize; | ||||
| 
 | ||||
| 	if (fdt_magic(fdt) != FDT_MAGIC) | ||||
| 		return -FDT_ERR_BADMAGIC; | ||||
| 	if (fdt_chk_version()) { | ||||
| 		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) | ||||
| 		    || (fdt_last_comp_version(fdt) > | ||||
| 			FDT_LAST_SUPPORTED_VERSION)) | ||||
| 			return -FDT_ERR_BADVERSION; | ||||
| 		if (fdt_version(fdt) < fdt_last_comp_version(fdt)) | ||||
| 			return -FDT_ERR_BADVERSION; | ||||
| 	} | ||||
| 	hdrsize = fdt_header_size(fdt); | ||||
| 	if (fdt_chk_basic()) { | ||||
| 
 | ||||
| 		if ((fdt_totalsize(fdt) < hdrsize) | ||||
| 		    || (fdt_totalsize(fdt) > INT_MAX)) | ||||
| 			return -FDT_ERR_TRUNCATED; | ||||
| 
 | ||||
| 		/* Bounds check memrsv block */ | ||||
| 		if (!check_off_(hdrsize, fdt_totalsize(fdt), | ||||
| 				fdt_off_mem_rsvmap(fdt))) | ||||
| 			return -FDT_ERR_TRUNCATED; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fdt_chk_extra()) { | ||||
| 		/* Bounds check structure block */ | ||||
| 		if (fdt_chk_version() && fdt_version(fdt) < 17) { | ||||
| 			if (!check_off_(hdrsize, fdt_totalsize(fdt), | ||||
| 					fdt_off_dt_struct(fdt))) | ||||
| 				return -FDT_ERR_TRUNCATED; | ||||
| 		} else { | ||||
| 			if (!check_block_(hdrsize, fdt_totalsize(fdt), | ||||
| 					  fdt_off_dt_struct(fdt), | ||||
| 					  fdt_size_dt_struct(fdt))) | ||||
| 				return -FDT_ERR_TRUNCATED; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Bounds check strings block */ | ||||
| 		if (!check_block_(hdrsize, fdt_totalsize(fdt), | ||||
| 				  fdt_off_dt_strings(fdt), | ||||
| 				  fdt_size_dt_strings(fdt))) | ||||
| 			return -FDT_ERR_TRUNCATED; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -78,12 +133,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) | |||
| { | ||||
| 	unsigned absoffset = offset + fdt_off_dt_struct(fdt); | ||||
| 
 | ||||
| 	if (fdt_chk_basic()) | ||||
| 		if ((absoffset < offset) | ||||
| 		    || ((absoffset + len) < absoffset) | ||||
| 		    || (absoffset + len) > fdt_totalsize(fdt)) | ||||
| 			return NULL; | ||||
| 
 | ||||
| 	if (fdt_version(fdt) >= 0x11) | ||||
| 	if (!fdt_chk_version() || fdt_version(fdt) >= 0x11) | ||||
| 		if (((offset + len) < offset) | ||||
| 		    || ((offset + len) > fdt_size_dt_struct(fdt))) | ||||
| 			return NULL; | ||||
|  | @ -100,7 +156,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | |||
| 
 | ||||
| 	*nextoffset = -FDT_ERR_TRUNCATED; | ||||
| 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); | ||||
| 	if (!tagp) | ||||
| 	if (fdt_chk_basic() && !tagp) | ||||
| 		return FDT_END; /* premature end */ | ||||
| 	tag = fdt32_to_cpu(*tagp); | ||||
| 	offset += FDT_TAGSIZE; | ||||
|  | @ -112,18 +168,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | |||
| 		do { | ||||
| 			p = fdt_offset_ptr(fdt, offset++, 1); | ||||
| 		} while (p && (*p != '\0')); | ||||
| 		if (!p) | ||||
| 		if (fdt_chk_basic() && !p) | ||||
| 			return FDT_END; /* premature end */ | ||||
| 		break; | ||||
| 
 | ||||
| 	case FDT_PROP: | ||||
| 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); | ||||
| 		if (!lenp) | ||||
| 		if (fdt_chk_basic() && !lenp) | ||||
| 			return FDT_END; /* premature end */ | ||||
| 		/* skip-name offset, length and value */ | ||||
| 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE | ||||
| 			+ fdt32_to_cpu(*lenp); | ||||
| 		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && | ||||
| 		if (fdt_chk_version() && | ||||
| 		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && | ||||
| 		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) | ||||
| 			offset += 4; | ||||
| 		break; | ||||
|  | @ -137,7 +194,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) | |||
| 		return FDT_END; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) | ||||
| 	if (fdt_chk_basic() && | ||||
| 	    !fdt_offset_ptr(fdt, startoffset, offset - startoffset)) | ||||
| 		return FDT_END; /* premature end */ | ||||
| 
 | ||||
| 	*nextoffset = FDT_TAGALIGN(offset); | ||||
|  | @ -244,7 +302,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) | |||
| 
 | ||||
| int fdt_move(const void *fdt, void *buf, int bufsize) | ||||
| { | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (fdt_totalsize(fdt) > bufsize) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
|  |  | |||
|  | @ -1,55 +1,10 @@ | |||
| /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ | ||||
| #ifndef FDT_H | ||||
| #define FDT_H | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * Copyright 2012 Kim Phillips, Freescale Semiconductor. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
|  |  | |||
|  | @ -1,53 +1,8 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> | ||||
|  * Copyright (C) 2018 embedded brains GmbH | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -97,3 +52,50 @@ int fdt_size_cells(const void *fdt, int nodeoffset) | |||
| 		return 1; | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| /* This function assumes that [address|size]_cells is 1 or 2 */ | ||||
| int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, | ||||
| 			     const char *name, uint64_t addr, uint64_t size) | ||||
| { | ||||
| 	int addr_cells, size_cells, ret; | ||||
| 	uint8_t data[sizeof(fdt64_t) * 2], *prop; | ||||
| 
 | ||||
| 	ret = fdt_address_cells(fdt, parent); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	addr_cells = ret; | ||||
| 
 | ||||
| 	ret = fdt_size_cells(fdt, parent); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	size_cells = ret; | ||||
| 
 | ||||
| 	/* check validity of address */ | ||||
| 	prop = data; | ||||
| 	if (addr_cells == 1) { | ||||
| 		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) | ||||
| 			return -FDT_ERR_BADVALUE; | ||||
| 
 | ||||
| 		fdt32_st(prop, (uint32_t)addr); | ||||
| 	} else if (addr_cells == 2) { | ||||
| 		fdt64_st(prop, addr); | ||||
| 	} else { | ||||
| 		return -FDT_ERR_BADNCELLS; | ||||
| 	} | ||||
| 
 | ||||
| 	/* check validity of size */ | ||||
| 	prop += addr_cells * sizeof(fdt32_t); | ||||
| 	if (size_cells == 1) { | ||||
| 		if (size > UINT32_MAX) | ||||
| 			return -FDT_ERR_BADVALUE; | ||||
| 
 | ||||
| 		fdt32_st(prop, (uint32_t)size); | ||||
| 	} else if (size_cells == 2) { | ||||
| 		fdt64_st(prop, size); | ||||
| 	} else { | ||||
| 		return -FDT_ERR_BADNCELLS; | ||||
| 	} | ||||
| 
 | ||||
| 	return fdt_appendprop(fdt, nodeoffset, name, data, | ||||
| 			      (addr_cells + size_cells) * sizeof(fdt32_t)); | ||||
| } | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2012 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,53 +1,8 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2016 Free Electrons | ||||
|  * Copyright (C) 2016 NextThing Co. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -93,11 +48,11 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) | |||
|  * @pathp: pointer which receives the path of the target (or NULL) | ||||
|  * | ||||
|  * overlay_get_target() retrieves the target offset in the base | ||||
|  * device tree of a fragment, no matter how the actual targetting is | ||||
|  * device tree of a fragment, no matter how the actual targeting is | ||||
|  * done (through a phandle or a path) | ||||
|  * | ||||
|  * returns: | ||||
|  *      the targetted node offset in the base device tree | ||||
|  *      the targeted node offset in the base device tree | ||||
|  *      Negative error code on error | ||||
|  */ | ||||
| static int overlay_get_target(const void *fdt, const void *fdto, | ||||
|  | @ -697,7 +652,7 @@ static int get_path_len(const void *fdt, int nodeoffset) | |||
| 	int len = 0, namelen; | ||||
| 	const char *name; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	for (;;) { | ||||
| 		name = fdt_get_name(fdt, nodeoffset, &namelen); | ||||
|  | @ -778,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto) | |||
| 		/* keep end marker to avoid strlen() */ | ||||
| 		e = path + path_len; | ||||
| 
 | ||||
| 		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ | ||||
| 
 | ||||
| 		if (*path != '/') | ||||
| 			return -FDT_ERR_BADVALUE; | ||||
| 
 | ||||
| 		/* get fragment name first */ | ||||
| 		s = strchr(path + 1, '/'); | ||||
| 		if (!s) | ||||
| 			return -FDT_ERR_BADOVERLAY; | ||||
| 		if (!s) { | ||||
| 			/* Symbol refers to something that won't end
 | ||||
| 			 * up in the target tree */ | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		frag_name = path + 1; | ||||
| 		frag_name_len = s - path - 1; | ||||
| 
 | ||||
| 		/* verify format; safe since "s" lies in \0 terminated prop */ | ||||
| 		len = sizeof("/__overlay__/") - 1; | ||||
| 		if ((e - s) < len || memcmp(s, "/__overlay__/", len)) | ||||
| 			return -FDT_ERR_BADOVERLAY; | ||||
| 
 | ||||
| 		if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { | ||||
| 			/* /<fragment-name>/__overlay__/<relative-subnode-path> */ | ||||
| 			rel_path = s + len; | ||||
| 			rel_path_len = e - rel_path; | ||||
| 		} else if ((e - s) == len | ||||
| 			   && (memcmp(s, "/__overlay__", len - 1) == 0)) { | ||||
| 			/* /<fragment-name>/__overlay__ */ | ||||
| 			rel_path = ""; | ||||
| 			rel_path_len = 0; | ||||
| 		} else { | ||||
| 			/* Symbol refers to something that won't end
 | ||||
| 			 * up in the target tree */ | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* find the fragment index in which the symbol lies */ | ||||
| 		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, | ||||
|  | @ -863,11 +828,15 @@ static int overlay_symbol_update(void *fdt, void *fdto) | |||
| 
 | ||||
| int fdt_overlay_apply(void *fdt, void *fdto) | ||||
| { | ||||
| 	uint32_t delta = fdt_get_max_phandle(fdt); | ||||
| 	uint32_t delta; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_CHECK_HEADER(fdto); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 	FDT_RO_PROBE(fdto); | ||||
| 
 | ||||
| 	ret = fdt_find_max_phandle(fdt, &delta); | ||||
| 	if (ret) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	ret = overlay_adjust_local_phandles(fdto, delta); | ||||
| 	if (ret) | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -61,7 +16,7 @@ static int fdt_nodename_eq_(const void *fdt, int offset, | |||
| 	int olen; | ||||
| 	const char *p = fdt_get_name(fdt, offset, &olen); | ||||
| 
 | ||||
| 	if (!p || olen < len) | ||||
| 	if (!p || (fdt_chk_extra() && olen < len)) | ||||
| 		/* short match */ | ||||
| 		return 0; | ||||
| 
 | ||||
|  | @ -76,46 +31,85 @@ static int fdt_nodename_eq_(const void *fdt, int offset, | |||
| 		return 0; | ||||
| } | ||||
| 
 | ||||
| const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) | ||||
| { | ||||
| 	int32_t totalsize; | ||||
| 	uint32_t absoffset; | ||||
| 	size_t len; | ||||
| 	int err; | ||||
| 	const char *s, *n; | ||||
| 
 | ||||
| 	if (!fdt_chk_extra()) { | ||||
| 		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | ||||
| 
 | ||||
| 		if (lenp) | ||||
| 			*lenp = strlen(s); | ||||
| 		return s; | ||||
| 	} | ||||
| 	totalsize = fdt_ro_probe_(fdt); | ||||
| 	err = totalsize; | ||||
| 	if (totalsize < 0) | ||||
| 		goto fail; | ||||
| 
 | ||||
| 	err = -FDT_ERR_BADOFFSET; | ||||
| 	absoffset = stroffset + fdt_off_dt_strings(fdt); | ||||
| 	if (absoffset >= totalsize) | ||||
| 		goto fail; | ||||
| 	len = totalsize - absoffset; | ||||
| 
 | ||||
| 	if (fdt_magic(fdt) == FDT_MAGIC) { | ||||
| 		if (stroffset < 0) | ||||
| 			goto fail; | ||||
| 		if (!fdt_chk_version() || fdt_version(fdt) >= 17) { | ||||
| 			if (stroffset >= fdt_size_dt_strings(fdt)) | ||||
| 				goto fail; | ||||
| 			if ((fdt_size_dt_strings(fdt) - stroffset) < len) | ||||
| 				len = fdt_size_dt_strings(fdt) - stroffset; | ||||
| 		} | ||||
| 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) { | ||||
| 		if ((stroffset >= 0) | ||||
| 		    || (stroffset < -fdt_size_dt_strings(fdt))) | ||||
| 			goto fail; | ||||
| 		if ((-stroffset) < len) | ||||
| 			len = -stroffset; | ||||
| 	} else { | ||||
| 		err = -FDT_ERR_INTERNAL; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	s = (const char *)fdt + absoffset; | ||||
| 	n = memchr(s, '\0', len); | ||||
| 	if (!n) { | ||||
| 		/* missing terminating NULL */ | ||||
| 		err = -FDT_ERR_TRUNCATED; | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	if (lenp) | ||||
| 		*lenp = n - s; | ||||
| 	return s; | ||||
| 
 | ||||
| fail: | ||||
| 	if (lenp) | ||||
| 		*lenp = err; | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| const char *fdt_string(const void *fdt, int stroffset) | ||||
| { | ||||
| 	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; | ||||
| 	return fdt_get_string(fdt, stroffset, NULL); | ||||
| } | ||||
| 
 | ||||
| static int fdt_string_eq_(const void *fdt, int stroffset, | ||||
| 			  const char *s, int len) | ||||
| { | ||||
| 	const char *p = fdt_string(fdt, stroffset); | ||||
| 	int slen; | ||||
| 	const char *p = fdt_get_string(fdt, stroffset, &slen); | ||||
| 
 | ||||
| 	return (strlen(p) == len) && (memcmp(p, s, len) == 0); | ||||
| 	return p && (slen == len) && (memcmp(p, s, len) == 0); | ||||
| } | ||||
| 
 | ||||
| uint32_t fdt_get_max_phandle(const void *fdt) | ||||
| { | ||||
| 	uint32_t max_phandle = 0; | ||||
| 	int offset; | ||||
| 
 | ||||
| 	for (offset = fdt_next_node(fdt, -1, NULL);; | ||||
| 	     offset = fdt_next_node(fdt, offset, NULL)) { | ||||
| 		uint32_t phandle; | ||||
| 
 | ||||
| 		if (offset == -FDT_ERR_NOTFOUND) | ||||
| 			return max_phandle; | ||||
| 
 | ||||
| 		if (offset < 0) | ||||
| 			return (uint32_t)-1; | ||||
| 
 | ||||
| 		phandle = fdt_get_phandle(fdt, offset); | ||||
| 		if (phandle == (uint32_t)-1) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (phandle > max_phandle) | ||||
| 			max_phandle = phandle; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | ||||
| int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) | ||||
| { | ||||
| 	uint32_t max = 0; | ||||
| 	int offset = -1; | ||||
|  | @ -137,6 +131,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | |||
| 			max = value; | ||||
| 	} | ||||
| 
 | ||||
| 	if (phandle) | ||||
| 		*phandle = max; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | ||||
| { | ||||
| 	uint32_t max; | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = fdt_find_max_phandle(fdt, &max); | ||||
| 	if (err < 0) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (max == FDT_MAX_PHANDLE) | ||||
| 		return -FDT_ERR_NOPHANDLES; | ||||
| 
 | ||||
|  | @ -146,22 +155,46 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) | ||||
| { | ||||
| 	int offset = n * sizeof(struct fdt_reserve_entry); | ||||
| 	int absoffset = fdt_off_mem_rsvmap(fdt) + offset; | ||||
| 
 | ||||
| 	if (fdt_chk_extra()) { | ||||
| 		if (absoffset < fdt_off_mem_rsvmap(fdt)) | ||||
| 			return NULL; | ||||
| 		if (absoffset > fdt_totalsize(fdt) - | ||||
| 		    sizeof(struct fdt_reserve_entry)) | ||||
| 			return NULL; | ||||
| 	} | ||||
| 	return fdt_mem_rsv_(fdt, n); | ||||
| } | ||||
| 
 | ||||
| int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) | ||||
| { | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); | ||||
| 	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); | ||||
| 	const struct fdt_reserve_entry *re; | ||||
| 
 | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 	re = fdt_mem_rsv(fdt, n); | ||||
| 	if (fdt_chk_extra() && !re) | ||||
| 		return -FDT_ERR_BADOFFSET; | ||||
| 
 | ||||
| 	*address = fdt64_ld(&re->address); | ||||
| 	*size = fdt64_ld(&re->size); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_num_mem_rsv(const void *fdt) | ||||
| { | ||||
| 	int i = 0; | ||||
| 	int i; | ||||
| 	const struct fdt_reserve_entry *re; | ||||
| 
 | ||||
| 	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) | ||||
| 		i++; | ||||
| 	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { | ||||
| 		if (fdt64_ld(&re->size) == 0) | ||||
| 			return i; | ||||
| 	} | ||||
| 	return -FDT_ERR_TRUNCATED; | ||||
| } | ||||
| 
 | ||||
| static int nextprop_(const void *fdt, int offset) | ||||
| { | ||||
|  | @ -192,7 +225,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, | |||
| { | ||||
| 	int depth; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	for (depth = 0; | ||||
| 	     (offset >= 0) && (depth >= 0); | ||||
|  | @ -218,7 +251,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) | |||
| 	const char *p = path; | ||||
| 	int offset = 0; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* see if we have an alias */ | ||||
| 	if (*path != '/') { | ||||
|  | @ -268,13 +301,14 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) | |||
| 	const char *nameptr; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (((err = fdt_check_header(fdt)) != 0) | ||||
| 	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) | ||||
| 	if (fdt_chk_extra() && | ||||
| 	    (((err = fdt_ro_probe_(fdt)) < 0) | ||||
| 	     || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))) | ||||
| 		goto fail; | ||||
| 
 | ||||
| 	nameptr = nh->name; | ||||
| 
 | ||||
| 	if (fdt_version(fdt) < 0x10) { | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		/*
 | ||||
| 		 * For old FDT versions, match the naming conventions of V16: | ||||
| 		 * give only the leaf name (after all /). The actual tree | ||||
|  | @ -325,7 +359,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, | |||
| 	int err; | ||||
| 	const struct fdt_property *prop; | ||||
| 
 | ||||
| 	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { | ||||
| 	if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) { | ||||
| 		if (lenp) | ||||
| 			*lenp = err; | ||||
| 		return NULL; | ||||
|  | @ -334,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, | |||
| 	prop = fdt_offset_ptr_(fdt, offset); | ||||
| 
 | ||||
| 	if (lenp) | ||||
| 		*lenp = fdt32_to_cpu(prop->len); | ||||
| 		*lenp = fdt32_ld(&prop->len); | ||||
| 
 | ||||
| 	return prop; | ||||
| } | ||||
|  | @ -346,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, | |||
| 	/* Prior to version 16, properties may need realignment
 | ||||
| 	 * and this API does not work. fdt_getprop_*() will, however. */ | ||||
| 
 | ||||
| 	if (fdt_version(fdt) < 0x10) { | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		if (lenp) | ||||
| 			*lenp = -FDT_ERR_BADVERSION; | ||||
| 		return NULL; | ||||
|  | @ -367,11 +401,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, | |||
| 	     (offset = fdt_next_property_offset(fdt, offset))) { | ||||
| 		const struct fdt_property *prop; | ||||
| 
 | ||||
| 		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { | ||||
| 		prop = fdt_get_property_by_offset_(fdt, offset, lenp); | ||||
| 		if (fdt_chk_extra() && !prop) { | ||||
| 			offset = -FDT_ERR_INTERNAL; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff), | ||||
| 		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), | ||||
| 				   name, namelen)) { | ||||
| 			if (poffset) | ||||
| 				*poffset = offset; | ||||
|  | @ -392,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, | |||
| { | ||||
| 	/* Prior to version 16, properties may need realignment
 | ||||
| 	 * and this API does not work. fdt_getprop_*() will, however. */ | ||||
| 	if (fdt_version(fdt) < 0x10) { | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10) { | ||||
| 		if (lenp) | ||||
| 			*lenp = -FDT_ERR_BADVERSION; | ||||
| 		return NULL; | ||||
|  | @ -423,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, | |||
| 		return NULL; | ||||
| 
 | ||||
| 	/* Handle realignment */ | ||||
| 	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && | ||||
| 	    fdt32_to_cpu(prop->len) >= 8) | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10 && | ||||
| 	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | ||||
| 		return prop->data + 4; | ||||
| 	return prop->data; | ||||
| } | ||||
|  | @ -437,12 +472,27 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, | |||
| 	prop = fdt_get_property_by_offset_(fdt, offset, lenp); | ||||
| 	if (!prop) | ||||
| 		return NULL; | ||||
| 	if (namep) | ||||
| 		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); | ||||
| 	if (namep) { | ||||
| 		const char *name; | ||||
| 		int namelen; | ||||
| 
 | ||||
| 		if (fdt_chk_extra()) { | ||||
| 			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), | ||||
| 					      &namelen); | ||||
| 			if (!name) { | ||||
| 				if (lenp) | ||||
| 					*lenp = namelen; | ||||
| 				return NULL; | ||||
| 			} | ||||
| 			*namep = name; | ||||
| 		} else { | ||||
| 			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* Handle realignment */ | ||||
| 	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && | ||||
| 	    fdt32_to_cpu(prop->len) >= 8) | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 0x10 && | ||||
| 	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) | ||||
| 		return prop->data + 4; | ||||
| 	return prop->data; | ||||
| } | ||||
|  | @ -467,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) | |||
| 			return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	return fdt32_to_cpu(*php); | ||||
| 	return fdt32_ld(php); | ||||
| } | ||||
| 
 | ||||
| const char *fdt_get_alias_namelen(const void *fdt, | ||||
|  | @ -493,7 +543,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) | |||
| 	int offset, depth, namelen; | ||||
| 	const char *name; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (buflen < 2) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
|  | @ -545,7 +595,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |||
| 	int offset, depth; | ||||
| 	int supernodeoffset = -FDT_ERR_INTERNAL; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (supernodedepth < 0) | ||||
| 		return -FDT_ERR_NOTFOUND; | ||||
|  | @ -567,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (fdt_chk_extra()) { | ||||
| 		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) | ||||
| 			return -FDT_ERR_BADOFFSET; | ||||
| 		else if (offset == -FDT_ERR_BADOFFSET) | ||||
| 			return -FDT_ERR_BADSTRUCTURE; | ||||
| 	} | ||||
| 
 | ||||
| 	return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
|  | @ -582,7 +634,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset) | |||
| 
 | ||||
| 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); | ||||
| 	if (err) | ||||
| 		return (err < 0) ? err : -FDT_ERR_INTERNAL; | ||||
| 		return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL; | ||||
| 	return nodedepth; | ||||
| } | ||||
| 
 | ||||
|  | @ -604,7 +656,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, | |||
| 	const void *val; | ||||
| 	int len; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we scan each
 | ||||
| 	 * property of a node in fdt_getprop(), then if that didn't | ||||
|  | @ -630,7 +682,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) | |||
| 	if ((phandle == 0) || (phandle == -1)) | ||||
| 		return -FDT_ERR_BADPHANDLE; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we
 | ||||
| 	 * potentially scan each property of a node in | ||||
|  | @ -783,7 +835,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |||
| { | ||||
| 	int offset, err; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	/* FIXME: The algorithm here is pretty horrible: we scan each
 | ||||
| 	 * property of a node in fdt_node_check_compatible(), then if | ||||
|  | @ -802,3 +854,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, | |||
| 
 | ||||
| 	return offset; /* error from fdt_next_node() */ | ||||
| } | ||||
| 
 | ||||
| #if !defined(FDT_ASSUME_MASK) || FDT_ASSUME_MASK != 0xff | ||||
| int fdt_check_full(const void *fdt, size_t bufsize) | ||||
| { | ||||
| 	int err; | ||||
| 	int num_memrsv; | ||||
| 	int offset, nextoffset = 0; | ||||
| 	uint32_t tag; | ||||
| 	unsigned depth = 0; | ||||
| 	const void *prop; | ||||
| 	const char *propname; | ||||
| 
 | ||||
| 	if (bufsize < FDT_V1_SIZE) | ||||
| 		return -FDT_ERR_TRUNCATED; | ||||
| 	err = fdt_check_header(fdt); | ||||
| 	if (err != 0) | ||||
| 		return err; | ||||
| 	if (bufsize < fdt_totalsize(fdt)) | ||||
| 		return -FDT_ERR_TRUNCATED; | ||||
| 
 | ||||
| 	num_memrsv = fdt_num_mem_rsv(fdt); | ||||
| 	if (num_memrsv < 0) | ||||
| 		return num_memrsv; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		offset = nextoffset; | ||||
| 		tag = fdt_next_tag(fdt, offset, &nextoffset); | ||||
| 
 | ||||
| 		if (nextoffset < 0) | ||||
| 			return nextoffset; | ||||
| 
 | ||||
| 		switch (tag) { | ||||
| 		case FDT_NOP: | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_END: | ||||
| 			if (depth != 0) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			return 0; | ||||
| 
 | ||||
| 		case FDT_BEGIN_NODE: | ||||
| 			depth++; | ||||
| 			if (depth > INT_MAX) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_END_NODE: | ||||
| 			if (depth == 0) | ||||
| 				return -FDT_ERR_BADSTRUCTURE; | ||||
| 			depth--; | ||||
| 			break; | ||||
| 
 | ||||
| 		case FDT_PROP: | ||||
| 			prop = fdt_getprop_by_offset(fdt, offset, &propname, | ||||
| 						     &err); | ||||
| 			if (!prop) | ||||
| 				return err; | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			return -FDT_ERR_INTERNAL; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -58,6 +13,8 @@ | |||
| static int fdt_blocks_misordered_(const void *fdt, | ||||
| 				  int mem_rsv_size, int struct_size) | ||||
| { | ||||
| 	if (!fdt_chk_basic()) | ||||
| 		return false; | ||||
| 	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) | ||||
| 		|| (fdt_off_dt_struct(fdt) < | ||||
| 		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) | ||||
|  | @ -67,25 +24,27 @@ static int fdt_blocks_misordered_(const void *fdt, | |||
| 		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); | ||||
| } | ||||
| 
 | ||||
| static int fdt_rw_check_header_(void *fdt) | ||||
| static int fdt_rw_probe_(void *fdt) | ||||
| { | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	if (!fdt_chk_basic()) | ||||
| 		return 0; | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	if (fdt_version(fdt) < 17) | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) < 17) | ||||
| 		return -FDT_ERR_BADVERSION; | ||||
| 	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), | ||||
| 				   fdt_size_dt_struct(fdt))) | ||||
| 		return -FDT_ERR_BADLAYOUT; | ||||
| 	if (fdt_version(fdt) > 17) | ||||
| 	if (fdt_chk_version() && fdt_version(fdt) > 17) | ||||
| 		fdt_set_version(fdt, 17); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define FDT_RW_CHECK_HEADER(fdt) \ | ||||
| #define FDT_RW_PROBE(fdt) \ | ||||
| 	{ \ | ||||
| 		int err_; \ | ||||
| 		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ | ||||
| 		if (fdt_chk_extra() && (err_ = fdt_rw_probe_(fdt)) != 0) \ | ||||
| 			return err_; \ | ||||
| 	} | ||||
| 
 | ||||
|  | @ -136,6 +95,14 @@ static int fdt_splice_struct_(void *fdt, void *p, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* Must only be used to roll back in case of error */ | ||||
| static void fdt_del_last_string_(void *fdt, const char *s) | ||||
| { | ||||
| 	int newlen = strlen(s) + 1; | ||||
| 
 | ||||
| 	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); | ||||
| } | ||||
| 
 | ||||
| static int fdt_splice_string_(void *fdt, int newlen) | ||||
| { | ||||
| 	void *p = (char *)fdt | ||||
|  | @ -149,7 +116,16 @@ static int fdt_splice_string_(void *fdt, int newlen) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int fdt_find_add_string_(void *fdt, const char *s) | ||||
| /**
 | ||||
|  * fdt_find_add_string_() - Find or allocate a string | ||||
|  * | ||||
|  * @fdt: pointer to the device tree to check/adjust | ||||
|  * @s: string to find/add | ||||
|  * @allocated: Set to 0 if the string was found, 1 if not found and so | ||||
|  *	allocated. Ignored if !fdt_chk_basic() | ||||
|  * @return offset of string in the string table (whether found or added) | ||||
|  */ | ||||
| static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) | ||||
| { | ||||
| 	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); | ||||
| 	const char *p; | ||||
|  | @ -157,6 +133,9 @@ static int fdt_find_add_string_(void *fdt, const char *s) | |||
| 	int len = strlen(s) + 1; | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (fdt_chk_basic()) | ||||
| 		*allocated = 0; | ||||
| 
 | ||||
| 	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); | ||||
| 	if (p) | ||||
| 		/* found it */ | ||||
|  | @ -167,6 +146,9 @@ static int fdt_find_add_string_(void *fdt, const char *s) | |||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (fdt_chk_basic()) | ||||
| 		*allocated = 1; | ||||
| 
 | ||||
| 	memcpy(new, s, len); | ||||
| 	return (new - strtab); | ||||
| } | ||||
|  | @ -176,7 +158,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) | |||
| 	struct fdt_reserve_entry *re; | ||||
| 	int err; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); | ||||
| 	err = fdt_splice_mem_rsv_(fdt, re, 0, 1); | ||||
|  | @ -192,7 +174,7 @@ int fdt_del_mem_rsv(void *fdt, int n) | |||
| { | ||||
| 	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	if (n >= fdt_num_mem_rsv(fdt)) | ||||
| 		return -FDT_ERR_NOTFOUND; | ||||
|  | @ -225,11 +207,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, | |||
| 	int nextoffset; | ||||
| 	int namestroff; | ||||
| 	int err; | ||||
| 	int allocated; | ||||
| 
 | ||||
| 	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) | ||||
| 		return nextoffset; | ||||
| 
 | ||||
| 	namestroff = fdt_find_add_string_(fdt, name); | ||||
| 	namestroff = fdt_find_add_string_(fdt, name, &allocated); | ||||
| 	if (namestroff < 0) | ||||
| 		return namestroff; | ||||
| 
 | ||||
|  | @ -237,8 +220,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, | |||
| 	proplen = sizeof(**prop) + FDT_TAGALIGN(len); | ||||
| 
 | ||||
| 	err = fdt_splice_struct_(fdt, *prop, 0, proplen); | ||||
| 	if (err) | ||||
| 	if (err) { | ||||
| 		/* Delete the string if we failed to add it */ | ||||
| 		if (fdt_chk_basic() && allocated) | ||||
| 			fdt_del_last_string_(fdt, name); | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	(*prop)->tag = cpu_to_fdt32(FDT_PROP); | ||||
| 	(*prop)->nameoff = cpu_to_fdt32(namestroff); | ||||
|  | @ -252,7 +239,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) | |||
| 	int oldlen, newlen; | ||||
| 	int err; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); | ||||
| 	if (!namep) | ||||
|  | @ -275,7 +262,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, | |||
| 	struct fdt_property *prop; | ||||
| 	int err; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); | ||||
| 	if (err == -FDT_ERR_NOTFOUND) | ||||
|  | @ -308,7 +295,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, | |||
| 	struct fdt_property *prop; | ||||
| 	int err, oldlen, newlen; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); | ||||
| 	if (prop) { | ||||
|  | @ -334,7 +321,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) | |||
| 	struct fdt_property *prop; | ||||
| 	int len, proplen; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len); | ||||
| 	if (!prop) | ||||
|  | @ -354,7 +341,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, | |||
| 	uint32_t tag; | ||||
| 	fdt32_t *endtag; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); | ||||
| 	if (offset >= 0) | ||||
|  | @ -394,7 +381,7 @@ int fdt_del_node(void *fdt, int nodeoffset) | |||
| { | ||||
| 	int endoffset; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	endoffset = fdt_node_end_offset_(fdt, nodeoffset); | ||||
| 	if (endoffset < 0) | ||||
|  | @ -435,12 +422,12 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) | |||
| 	const char *fdtend = fdtstart + fdt_totalsize(fdt); | ||||
| 	char *tmp; | ||||
| 
 | ||||
| 	FDT_CHECK_HEADER(fdt); | ||||
| 	FDT_RO_PROBE(fdt); | ||||
| 
 | ||||
| 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | ||||
| 		* sizeof(struct fdt_reserve_entry); | ||||
| 
 | ||||
| 	if (fdt_version(fdt) >= 17) { | ||||
| 	if (!fdt_chk_version() || fdt_version(fdt) >= 17) { | ||||
| 		struct_size = fdt_size_dt_struct(fdt); | ||||
| 	} else { | ||||
| 		struct_size = 0; | ||||
|  | @ -494,7 +481,7 @@ int fdt_pack(void *fdt) | |||
| { | ||||
| 	int mem_rsv_size; | ||||
| 
 | ||||
| 	FDT_RW_CHECK_HEADER(fdt); | ||||
| 	FDT_RW_PROBE(fdt); | ||||
| 
 | ||||
| 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) | ||||
| 		* sizeof(struct fdt_reserve_entry); | ||||
|  |  | |||
|  | @ -1,51 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
|  | @ -82,6 +38,7 @@ static struct fdt_errtabent fdt_errtable[] = { | |||
| 	FDT_ERRTABENT(FDT_ERR_BADVALUE), | ||||
| 	FDT_ERRTABENT(FDT_ERR_BADOVERLAY), | ||||
| 	FDT_ERRTABENT(FDT_ERR_NOPHANDLES), | ||||
| 	FDT_ERRTABENT(FDT_ERR_BADFLAGS), | ||||
| }; | ||||
| #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  | @ -55,21 +10,90 @@ | |||
| 
 | ||||
| #include "libfdt_internal.h" | ||||
| 
 | ||||
| static int fdt_sw_check_header_(void *fdt) | ||||
| static int fdt_sw_probe_(void *fdt) | ||||
| { | ||||
| 	if (fdt_magic(fdt) != FDT_SW_MAGIC) | ||||
| 	if (fdt_chk_basic()) { | ||||
| 		if (fdt_magic(fdt) == FDT_MAGIC) | ||||
| 			return -FDT_ERR_BADSTATE; | ||||
| 		else if (fdt_magic(fdt) != FDT_SW_MAGIC) | ||||
| 			return -FDT_ERR_BADMAGIC; | ||||
| 	/* FIXME: should check more details about the header state */ | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define FDT_SW_CHECK_HEADER(fdt) \ | ||||
| #define FDT_SW_PROBE(fdt) \ | ||||
| 	{ \ | ||||
| 		int err; \ | ||||
| 		if ((err = fdt_sw_check_header_(fdt)) != 0) \ | ||||
| 		if (fdt_chk_basic() && (err = fdt_sw_probe_(fdt)) != 0) \ | ||||
| 			return err; \ | ||||
| 	} | ||||
| 
 | ||||
| /* 'memrsv' state:	Initial state after fdt_create()
 | ||||
|  * | ||||
|  * Allowed functions: | ||||
|  *	fdt_add_reservmap_entry() | ||||
|  *	fdt_finish_reservemap()		[moves to 'struct' state] | ||||
|  */ | ||||
| static int fdt_sw_probe_memrsv_(void *fdt) | ||||
| { | ||||
| 	int err = fdt_sw_probe_(fdt); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (fdt_chk_extra() && fdt_off_dt_strings(fdt) != 0) | ||||
| 		return -FDT_ERR_BADSTATE; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define FDT_SW_PROBE_MEMRSV(fdt) \ | ||||
| 	{ \ | ||||
| 		int err; \ | ||||
| 		if (fdt_chk_extra() && (err = fdt_sw_probe_memrsv_(fdt)) != 0) \ | ||||
| 			return err; \ | ||||
| 	} | ||||
| 
 | ||||
| /* 'struct' state:	Enter this state after fdt_finish_reservemap()
 | ||||
|  * | ||||
|  * Allowed functions: | ||||
|  *	fdt_begin_node() | ||||
|  *	fdt_end_node() | ||||
|  *	fdt_property*() | ||||
|  *	fdt_finish()			[moves to 'complete' state] | ||||
|  */ | ||||
| static int fdt_sw_probe_struct_(void *fdt) | ||||
| { | ||||
| 	int err; | ||||
| 
 | ||||
| 	if (!fdt_chk_extra()) | ||||
| 		return 0; | ||||
| 	err = fdt_sw_probe_(fdt); | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) | ||||
| 		return -FDT_ERR_BADSTATE; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #define FDT_SW_PROBE_STRUCT(fdt) \ | ||||
| 	{ \ | ||||
| 		int err; \ | ||||
| 		if (fdt_chk_extra() && (err = fdt_sw_probe_struct_(fdt)) != 0) \ | ||||
| 			return err; \ | ||||
| 	} | ||||
| 
 | ||||
| static inline uint32_t sw_flags(void *fdt) | ||||
| { | ||||
| 	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ | ||||
| 	return fdt_last_comp_version(fdt); | ||||
| } | ||||
| 
 | ||||
| /* 'complete' state:	Enter this state after fdt_finish()
 | ||||
|  * | ||||
|  * Allowed functions: none | ||||
|  */ | ||||
| 
 | ||||
| static void *fdt_grab_space_(void *fdt, size_t len) | ||||
| { | ||||
| 	int offset = fdt_size_dt_struct(fdt); | ||||
|  | @ -85,38 +109,58 @@ static void *fdt_grab_space_(void *fdt, size_t len) | |||
| 	return fdt_offset_ptr_w_(fdt, offset); | ||||
| } | ||||
| 
 | ||||
| int fdt_create(void *buf, int bufsize) | ||||
| int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) | ||||
| { | ||||
| 	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), | ||||
| 					 sizeof(struct fdt_reserve_entry)); | ||||
| 	void *fdt = buf; | ||||
| 
 | ||||
| 	if (bufsize < sizeof(struct fdt_header)) | ||||
| 	if (bufsize < hdrsize) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
| 
 | ||||
| 	if (flags & ~FDT_CREATE_FLAGS_ALL) | ||||
| 		return -FDT_ERR_BADFLAGS; | ||||
| 
 | ||||
| 	memset(buf, 0, bufsize); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * magic and last_comp_version keep intermediate state during the fdt | ||||
| 	 * creation process, which is replaced with the proper FDT format by | ||||
| 	 * fdt_finish(). | ||||
| 	 * | ||||
| 	 * flags should be accessed with sw_flags(). | ||||
| 	 */ | ||||
| 	fdt_set_magic(fdt, FDT_SW_MAGIC); | ||||
| 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); | ||||
| 	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); | ||||
| 	fdt_set_last_comp_version(fdt, flags); | ||||
| 
 | ||||
| 	fdt_set_totalsize(fdt,  bufsize); | ||||
| 
 | ||||
| 	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), | ||||
| 					      sizeof(struct fdt_reserve_entry))); | ||||
| 	fdt_set_off_mem_rsvmap(fdt, hdrsize); | ||||
| 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); | ||||
| 	fdt_set_off_dt_strings(fdt, bufsize); | ||||
| 	fdt_set_off_dt_strings(fdt, 0); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_create(void *buf, int bufsize) | ||||
| { | ||||
| 	return fdt_create_with_flags(buf, bufsize, 0); | ||||
| } | ||||
| 
 | ||||
| int fdt_resize(void *fdt, void *buf, int bufsize) | ||||
| { | ||||
| 	size_t headsize, tailsize; | ||||
| 	char *oldtail, *newtail; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 	FDT_SW_PROBE(fdt); | ||||
| 
 | ||||
| 	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); | ||||
| 	tailsize = fdt_size_dt_strings(fdt); | ||||
| 
 | ||||
| 	if (fdt_chk_extra() && (headsize + tailsize) > fdt_totalsize(fdt)) | ||||
| 		return -FDT_ERR_INTERNAL; | ||||
| 
 | ||||
| 	if ((headsize + tailsize) > bufsize) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
| 
 | ||||
|  | @ -133,8 +177,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize) | |||
| 		memmove(buf, fdt, headsize); | ||||
| 	} | ||||
| 
 | ||||
| 	fdt_set_off_dt_strings(buf, bufsize); | ||||
| 	fdt_set_totalsize(buf, bufsize); | ||||
| 	if (fdt_off_dt_strings(buf)) | ||||
| 		fdt_set_off_dt_strings(buf, bufsize); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -144,10 +189,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) | |||
| 	struct fdt_reserve_entry *re; | ||||
| 	int offset; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 
 | ||||
| 	if (fdt_size_dt_struct(fdt)) | ||||
| 		return -FDT_ERR_BADSTATE; | ||||
| 	FDT_SW_PROBE_MEMRSV(fdt); | ||||
| 
 | ||||
| 	offset = fdt_off_dt_struct(fdt); | ||||
| 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) | ||||
|  | @ -164,16 +206,23 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) | |||
| 
 | ||||
| int fdt_finish_reservemap(void *fdt) | ||||
| { | ||||
| 	return fdt_add_reservemap_entry(fdt, 0, 0); | ||||
| 	int err = fdt_add_reservemap_entry(fdt, 0, 0); | ||||
| 
 | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| 	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int fdt_begin_node(void *fdt, const char *name) | ||||
| { | ||||
| 	struct fdt_node_header *nh; | ||||
| 	int namelen = strlen(name) + 1; | ||||
| 	int namelen; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 	FDT_SW_PROBE_STRUCT(fdt); | ||||
| 
 | ||||
| 	namelen = strlen(name) + 1; | ||||
| 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); | ||||
| 	if (! nh) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
|  | @ -187,7 +236,7 @@ int fdt_end_node(void *fdt) | |||
| { | ||||
| 	fdt32_t *en; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 	FDT_SW_PROBE_STRUCT(fdt); | ||||
| 
 | ||||
| 	en = fdt_grab_space_(fdt, FDT_TAGSIZE); | ||||
| 	if (! en) | ||||
|  | @ -197,19 +246,13 @@ int fdt_end_node(void *fdt) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int fdt_find_add_string_(void *fdt, const char *s) | ||||
| static int fdt_add_string_(void *fdt, const char *s) | ||||
| { | ||||
| 	char *strtab = (char *)fdt + fdt_totalsize(fdt); | ||||
| 	const char *p; | ||||
| 	int strtabsize = fdt_size_dt_strings(fdt); | ||||
| 	int len = strlen(s) + 1; | ||||
| 	int struct_top, offset; | ||||
| 
 | ||||
| 	p = fdt_find_string_(strtab - strtabsize, strtabsize, s); | ||||
| 	if (p) | ||||
| 		return p - strtab; | ||||
| 
 | ||||
| 	/* Add it */ | ||||
| 	offset = -strtabsize - len; | ||||
| 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); | ||||
| 	if (fdt_totalsize(fdt) + offset < struct_top) | ||||
|  | @ -220,20 +263,56 @@ static int fdt_find_add_string_(void *fdt, const char *s) | |||
| 	return offset; | ||||
| } | ||||
| 
 | ||||
| /* Must only be used to roll back in case of error */ | ||||
| static void fdt_del_last_string_(void *fdt, const char *s) | ||||
| { | ||||
| 	int strtabsize = fdt_size_dt_strings(fdt); | ||||
| 	int len = strlen(s) + 1; | ||||
| 
 | ||||
| 	fdt_set_size_dt_strings(fdt, strtabsize - len); | ||||
| } | ||||
| 
 | ||||
| static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) | ||||
| { | ||||
| 	char *strtab = (char *)fdt + fdt_totalsize(fdt); | ||||
| 	int strtabsize = fdt_size_dt_strings(fdt); | ||||
| 	const char *p; | ||||
| 
 | ||||
| 	*allocated = 0; | ||||
| 
 | ||||
| 	p = fdt_find_string_(strtab - strtabsize, strtabsize, s); | ||||
| 	if (p) | ||||
| 		return p - strtab; | ||||
| 
 | ||||
| 	*allocated = 1; | ||||
| 
 | ||||
| 	return fdt_add_string_(fdt, s); | ||||
| } | ||||
| 
 | ||||
| int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) | ||||
| { | ||||
| 	struct fdt_property *prop; | ||||
| 	int nameoff; | ||||
| 	int allocated; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 	FDT_SW_PROBE_STRUCT(fdt); | ||||
| 
 | ||||
| 	nameoff = fdt_find_add_string_(fdt, name); | ||||
| 	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ | ||||
| 	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { | ||||
| 		allocated = 1; | ||||
| 		nameoff = fdt_add_string_(fdt, name); | ||||
| 	} else { | ||||
| 		nameoff = fdt_find_add_string_(fdt, name, &allocated); | ||||
| 	} | ||||
| 	if (nameoff == 0) | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
| 
 | ||||
| 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); | ||||
| 	if (! prop) | ||||
| 	if (! prop) { | ||||
| 		if (allocated) | ||||
| 			fdt_del_last_string_(fdt, name); | ||||
| 		return -FDT_ERR_NOSPACE; | ||||
| 	} | ||||
| 
 | ||||
| 	prop->tag = cpu_to_fdt32(FDT_PROP); | ||||
| 	prop->nameoff = cpu_to_fdt32(nameoff); | ||||
|  | @ -262,7 +341,7 @@ int fdt_finish(void *fdt) | |||
| 	uint32_t tag; | ||||
| 	int offset, nextoffset; | ||||
| 
 | ||||
| 	FDT_SW_CHECK_HEADER(fdt); | ||||
| 	FDT_SW_PROBE_STRUCT(fdt); | ||||
| 
 | ||||
| 	/* Add terminator */ | ||||
| 	end = fdt_grab_space_(fdt, sizeof(*end)); | ||||
|  | @ -295,6 +374,10 @@ int fdt_finish(void *fdt) | |||
| 
 | ||||
| 	/* Finally, adjust the header */ | ||||
| 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); | ||||
| 
 | ||||
| 	/* And fix up fields that were keeping intermediate state. */ | ||||
| 	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); | ||||
| 	fdt_set_magic(fdt, FDT_MAGIC); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1,52 +1,7 @@ | |||
| // SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include "libfdt_env.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,54 +1,9 @@ | |||
| /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ | ||||
| #ifndef LIBFDT_H | ||||
| #define LIBFDT_H | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #include "libfdt_env.h" | ||||
|  | @ -90,8 +45,9 @@ | |||
| 
 | ||||
| /* Error codes: codes for bad device tree blobs */ | ||||
| #define FDT_ERR_TRUNCATED	8 | ||||
| 	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
 | ||||
| 	 * ends without an FDT_END tag. */ | ||||
| 	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
 | ||||
| 	 * terminated (overflows, goes outside allowed bounds, or | ||||
| 	 * isn't properly terminated).  */ | ||||
| #define FDT_ERR_BADMAGIC	9 | ||||
| 	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
 | ||||
| 	 * device tree at all - it is missing the flattened device | ||||
|  | @ -137,7 +93,11 @@ | |||
| 	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
 | ||||
| 	 * phandle available anymore without causing an overflow */ | ||||
| 
 | ||||
| #define FDT_ERR_MAX		17 | ||||
| #define FDT_ERR_BADFLAGS	18 | ||||
| 	/* FDT_ERR_BADFLAGS: The function was passed a flags field that
 | ||||
| 	 * contains invalid flags or an invalid combination of flags. */ | ||||
| 
 | ||||
| #define FDT_ERR_MAX		18 | ||||
| 
 | ||||
| /* constants */ | ||||
| #define FDT_MAX_PHANDLE 0xfffffffe | ||||
|  | @ -157,6 +117,61 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) | |||
| 
 | ||||
| uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); | ||||
| 
 | ||||
| /*
 | ||||
|  * Alignment helpers: | ||||
|  *     These helpers access words from a device tree blob.  They're | ||||
|  *     built to work even with unaligned pointers on platforms (ike | ||||
|  *     ARM) that don't like unaligned loads and stores | ||||
|  */ | ||||
| 
 | ||||
| static inline uint32_t fdt32_ld(const fdt32_t *p) | ||||
| { | ||||
| 	const uint8_t *bp = (const uint8_t *)p; | ||||
| 
 | ||||
| 	return ((uint32_t)bp[0] << 24) | ||||
| 		| ((uint32_t)bp[1] << 16) | ||||
| 		| ((uint32_t)bp[2] << 8) | ||||
| 		| bp[3]; | ||||
| } | ||||
| 
 | ||||
| static inline void fdt32_st(void *property, uint32_t value) | ||||
| { | ||||
| 	uint8_t *bp = (uint8_t *)property; | ||||
| 
 | ||||
| 	bp[0] = value >> 24; | ||||
| 	bp[1] = (value >> 16) & 0xff; | ||||
| 	bp[2] = (value >> 8) & 0xff; | ||||
| 	bp[3] = value & 0xff; | ||||
| } | ||||
| 
 | ||||
| static inline uint64_t fdt64_ld(const fdt64_t *p) | ||||
| { | ||||
| 	const uint8_t *bp = (const uint8_t *)p; | ||||
| 
 | ||||
| 	return ((uint64_t)bp[0] << 56) | ||||
| 		| ((uint64_t)bp[1] << 48) | ||||
| 		| ((uint64_t)bp[2] << 40) | ||||
| 		| ((uint64_t)bp[3] << 32) | ||||
| 		| ((uint64_t)bp[4] << 24) | ||||
| 		| ((uint64_t)bp[5] << 16) | ||||
| 		| ((uint64_t)bp[6] << 8) | ||||
| 		| bp[7]; | ||||
| } | ||||
| 
 | ||||
| static inline void fdt64_st(void *property, uint64_t value) | ||||
| { | ||||
| 	uint8_t *bp = (uint8_t *)property; | ||||
| 
 | ||||
| 	bp[0] = value >> 56; | ||||
| 	bp[1] = (value >> 48) & 0xff; | ||||
| 	bp[2] = (value >> 40) & 0xff; | ||||
| 	bp[3] = (value >> 32) & 0xff; | ||||
| 	bp[4] = (value >> 24) & 0xff; | ||||
| 	bp[5] = (value >> 16) & 0xff; | ||||
| 	bp[6] = (value >> 8) & 0xff; | ||||
| 	bp[7] = value & 0xff; | ||||
| } | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| /* Traversal functions                                                */ | ||||
| /**********************************************************************/ | ||||
|  | @ -199,7 +214,7 @@ int fdt_next_subnode(const void *fdt, int offset); | |||
|  *		... | ||||
|  *	} | ||||
|  * | ||||
|  *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { | ||||
|  *	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { | ||||
|  *		Error handling | ||||
|  *	} | ||||
|  * | ||||
|  | @ -217,7 +232,7 @@ int fdt_next_subnode(const void *fdt, int offset); | |||
| /* General functions                                                  */ | ||||
| /**********************************************************************/ | ||||
| #define fdt_get_header(fdt, field) \ | ||||
| 	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) | ||||
| 	(fdt32_ld(&((const struct fdt_header *)(fdt))->field)) | ||||
| #define fdt_magic(fdt)			(fdt_get_header(fdt, magic)) | ||||
| #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize)) | ||||
| #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct)) | ||||
|  | @ -248,18 +263,32 @@ fdt_set_hdr_(size_dt_struct); | |||
| #undef fdt_set_hdr_ | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_check_header - sanity check a device tree or possible device tree | ||||
|  * fdt_header_size - return the size of the tree's header | ||||
|  * @fdt: pointer to a flattened device tree | ||||
|  */ | ||||
| size_t fdt_header_size(const void *fdt); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_header_size_ - internal function which takes a version number | ||||
|  */ | ||||
| size_t fdt_header_size_(uint32_t version); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_check_header - sanity check a device tree header | ||||
| 
 | ||||
|  * @fdt: pointer to data which might be a flattened device tree | ||||
|  * | ||||
|  * fdt_check_header() checks that the given buffer contains what | ||||
|  * appears to be a flattened device tree with sane information in its | ||||
|  * header. | ||||
|  * appears to be a flattened device tree, and that the header contains | ||||
|  * valid information (to the extent that can be determined from the | ||||
|  * header alone). | ||||
|  * | ||||
|  * returns: | ||||
|  *     0, if the buffer appears to contain a valid device tree | ||||
|  *     -FDT_ERR_BADMAGIC, | ||||
|  *     -FDT_ERR_BADVERSION, | ||||
|  *     -FDT_ERR_BADSTATE, standard meanings, as above | ||||
|  *     -FDT_ERR_BADSTATE, | ||||
|  *     -FDT_ERR_TRUNCATED, standard meanings, as above | ||||
|  */ | ||||
| int fdt_check_header(const void *fdt); | ||||
| 
 | ||||
|  | @ -288,6 +317,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize); | |||
| /* Read-only functions                                                */ | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| int fdt_check_full(const void *fdt, size_t bufsize); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_get_string - retrieve a string from the strings block of a device tree | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  * @stroffset: offset of the string within the strings block (native endian) | ||||
|  * @lenp: optional pointer to return the string's length | ||||
|  * | ||||
|  * fdt_get_string() retrieves a pointer to a single string from the | ||||
|  * strings block of the device tree blob at fdt, and optionally also | ||||
|  * returns the string's length in *lenp. | ||||
|  * | ||||
|  * returns: | ||||
|  *     a pointer to the string, on success | ||||
|  *     NULL, if stroffset is out of bounds, or doesn't point to a valid string | ||||
|  */ | ||||
| const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_string - retrieve a string from the strings block of a device tree | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  | @ -298,10 +345,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize); | |||
|  * | ||||
|  * returns: | ||||
|  *     a pointer to the string, on success | ||||
|  *     NULL, if stroffset is out of bounds | ||||
|  *     NULL, if stroffset is out of bounds, or doesn't point to a valid string | ||||
|  */ | ||||
| const char *fdt_string(const void *fdt, int stroffset); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_find_max_phandle - find and return the highest phandle in a tree | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  * @phandle: return location for the highest phandle value found in the tree | ||||
|  * | ||||
|  * fdt_find_max_phandle() finds the highest phandle value in the given device | ||||
|  * tree. The value returned in @phandle is only valid if the function returns | ||||
|  * success. | ||||
|  * | ||||
|  * returns: | ||||
|  *     0 on success or a negative error code on failure | ||||
|  */ | ||||
| int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_get_max_phandle - retrieves the highest phandle in a tree | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  | @ -310,12 +371,24 @@ const char *fdt_string(const void *fdt, int stroffset); | |||
|  * device tree. This will ignore badly formatted phandles, or phandles | ||||
|  * with a value of 0 or -1. | ||||
|  * | ||||
|  * This function is deprecated in favour of fdt_find_max_phandle(). | ||||
|  * | ||||
|  * returns: | ||||
|  *      the highest phandle on success | ||||
|  *      0, if no phandle was found in the device tree | ||||
|  *      -1, if an error occurred | ||||
|  */ | ||||
| uint32_t fdt_get_max_phandle(const void *fdt); | ||||
| static inline uint32_t fdt_get_max_phandle(const void *fdt) | ||||
| { | ||||
| 	uint32_t phandle; | ||||
| 	int err; | ||||
| 
 | ||||
| 	err = fdt_find_max_phandle(fdt, &phandle); | ||||
| 	if (err < 0) | ||||
| 		return (uint32_t)-1; | ||||
| 
 | ||||
| 	return phandle; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_generate_phandle - return a new, unused phandle for a device tree blob | ||||
|  | @ -522,7 +595,7 @@ int fdt_next_property_offset(const void *fdt, int offset); | |||
|  *		... | ||||
|  *	} | ||||
|  * | ||||
|  *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { | ||||
|  *	if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { | ||||
|  *		Error handling | ||||
|  *	} | ||||
|  * | ||||
|  | @ -625,7 +698,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, | |||
| /**
 | ||||
|  * fdt_getprop_by_offset - retrieve the value of a property at a given offset | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  * @ffset: offset of the property to read | ||||
|  * @offset: offset of the property to read | ||||
|  * @namep: pointer to a string variable (will be overwritten) or NULL | ||||
|  * @lenp: pointer to an integer variable (will be overwritten) or NULL | ||||
|  * | ||||
|  | @ -734,7 +807,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); | |||
| /**
 | ||||
|  * fdt_get_alias_namelen - get alias based on substring | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  * @name: name of the alias to look up | ||||
|  * @name: name of the alias th look up | ||||
|  * @namelen: number of characters of name to consider | ||||
|  * | ||||
|  * Identical to fdt_get_alias(), but only examine the first namelen | ||||
|  | @ -1316,7 +1389,45 @@ int fdt_nop_node(void *fdt, int nodeoffset); | |||
| /* Sequential write functions                                         */ | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| /* fdt_create_with_flags flags */ | ||||
| #define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 | ||||
| 	/* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
 | ||||
| 	 * names in the fdt. This can result in faster creation times, but | ||||
| 	 * a larger fdt. */ | ||||
| 
 | ||||
| #define FDT_CREATE_FLAGS_ALL	(FDT_CREATE_FLAG_NO_NAME_DEDUP) | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_create_with_flags - begin creation of a new fdt | ||||
|  * @fdt: pointer to memory allocated where fdt will be created | ||||
|  * @bufsize: size of the memory space at fdt | ||||
|  * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. | ||||
|  * | ||||
|  * fdt_create_with_flags() begins the process of creating a new fdt with | ||||
|  * the sequential write interface. | ||||
|  * | ||||
|  * fdt creation process must end with fdt_finished() to produce a valid fdt. | ||||
|  * | ||||
|  * returns: | ||||
|  *	0, on success | ||||
|  *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt | ||||
|  *	-FDT_ERR_BADFLAGS, flags is not valid | ||||
|  */ | ||||
| int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_create - begin creation of a new fdt | ||||
|  * @fdt: pointer to memory allocated where fdt will be created | ||||
|  * @bufsize: size of the memory space at fdt | ||||
|  * | ||||
|  * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. | ||||
|  * | ||||
|  * returns: | ||||
|  *	0, on success | ||||
|  *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt | ||||
|  */ | ||||
| int fdt_create(void *buf, int bufsize); | ||||
| 
 | ||||
| int fdt_resize(void *fdt, void *buf, int bufsize); | ||||
| int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); | ||||
| int fdt_finish_reservemap(void *fdt); | ||||
|  | @ -1787,6 +1898,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, | |||
| #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ | ||||
| 	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_appendprop_addrrange - append a address range property | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  * @parent: offset of the parent node | ||||
|  * @nodeoffset: offset of the node to add a property at | ||||
|  * @name: name of property | ||||
|  * @addr: start address of a given range | ||||
|  * @size: size of a given range | ||||
|  * | ||||
|  * fdt_appendprop_addrrange() appends an address range value (start | ||||
|  * address and size) to the value of the named property in the given | ||||
|  * node, or creates a new property with that value if it does not | ||||
|  * already exist. | ||||
|  * If "name" is not specified, a default "reg" is used. | ||||
|  * Cell sizes are determined by parent's #address-cells and #size-cells. | ||||
|  * | ||||
|  * This function may insert data into the blob, and will therefore | ||||
|  * change the offsets of some existing nodes. | ||||
|  * | ||||
|  * returns: | ||||
|  *	0, on success | ||||
|  *	-FDT_ERR_BADLAYOUT, | ||||
|  *	-FDT_ERR_BADMAGIC, | ||||
|  *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid | ||||
|  *		#address-cells property | ||||
|  *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag | ||||
|  *	-FDT_ERR_BADSTATE, | ||||
|  *	-FDT_ERR_BADSTRUCTURE, | ||||
|  *	-FDT_ERR_BADVERSION, | ||||
|  *	-FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size | ||||
|  *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to | ||||
|  *		contain a new property | ||||
|  *	-FDT_ERR_TRUNCATED, standard meanings | ||||
|  */ | ||||
| int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, | ||||
| 			     const char *name, uint64_t addr, uint64_t size); | ||||
| 
 | ||||
| /**
 | ||||
|  * fdt_delprop - delete a property | ||||
|  * @fdt: pointer to the device tree blob | ||||
|  |  | |||
|  | @ -1,55 +1,10 @@ | |||
| /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ | ||||
| #ifndef LIBFDT_ENV_H | ||||
| #define LIBFDT_ENV_H | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * Copyright 2012 Kim Phillips, Freescale Semiconductor. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
|  | @ -57,6 +12,7 @@ | |||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <limits.h> | ||||
| 
 | ||||
| #ifdef __CHECKER__ | ||||
| #define FDT_FORCE __attribute__((force)) | ||||
|  |  | |||
|  | @ -1,65 +1,24 @@ | |||
| /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ | ||||
| #ifndef LIBFDT_INTERNAL_H | ||||
| #define LIBFDT_INTERNAL_H | ||||
| /*
 | ||||
|  * libfdt - Flat Device Tree manipulation | ||||
|  * Copyright (C) 2006 David Gibson, IBM Corporation. | ||||
|  * | ||||
|  * libfdt is dual licensed: you can use it either under the terms of | ||||
|  * the GPL, or the BSD license, at your option. | ||||
|  * | ||||
|  *  a) This library is free software; you can redistribute it and/or | ||||
|  *     modify it under the terms of the GNU General Public License as | ||||
|  *     published by the Free Software Foundation; either version 2 of the | ||||
|  *     License, or (at your option) any later version. | ||||
|  * | ||||
|  *     This library is distributed in the hope that it will be useful, | ||||
|  *     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *     GNU General Public License for more details. | ||||
|  * | ||||
|  *     You should have received a copy of the GNU General Public | ||||
|  *     License along with this library; if not, write to the Free | ||||
|  *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | ||||
|  *     MA 02110-1301 USA | ||||
|  * | ||||
|  * Alternatively, | ||||
|  * | ||||
|  *  b) Redistribution and use in source and binary forms, with or | ||||
|  *     without modification, are permitted provided that the following | ||||
|  *     conditions are met: | ||||
|  * | ||||
|  *     1. Redistributions of source code must retain the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer. | ||||
|  *     2. Redistributions in binary form must reproduce the above | ||||
|  *        copyright notice, this list of conditions and the following | ||||
|  *        disclaimer in the documentation and/or other materials | ||||
|  *        provided with the distribution. | ||||
|  * | ||||
|  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||||
|  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||||
|  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||||
|  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
|  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||||
|  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
|  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
|  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||||
|  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
| #include <fdt.h> | ||||
| 
 | ||||
| #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1)) | ||||
| #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE)) | ||||
| 
 | ||||
| #define FDT_CHECK_HEADER(fdt) \ | ||||
| int fdt_ro_probe_(const void *fdt); | ||||
| #define FDT_RO_PROBE(fdt)					\ | ||||
| 	{							\ | ||||
| 		int err_; \ | ||||
| 		if ((err_ = fdt_check_header(fdt)) != 0) \ | ||||
| 			return err_; \ | ||||
| 		int totalsize_;					\ | ||||
| 		if (fdt_chk_basic()) {				\ | ||||
| 			totalsize_ = fdt_ro_probe_(fdt);	\ | ||||
| 			if (totalsize_ < 0)			\ | ||||
| 				return totalsize_;		\ | ||||
| 		}						\ | ||||
| 	} | ||||
| 
 | ||||
| int fdt_check_node_offset_(const void *fdt, int offset); | ||||
|  | @ -92,4 +51,87 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) | |||
| 
 | ||||
| #define FDT_SW_MAGIC		(~FDT_MAGIC) | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| /* Checking controls                                                  */ | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #ifndef FDT_ASSUME_MASK | ||||
| #define FDT_ASSUME_MASK 0 | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Defines assumptions which can be enabled. Each of these can be enabled | ||||
|  * individually. For maximum saftey, don't enable any assumptions! | ||||
|  * | ||||
|  * For minimal code size and no safety, use FDT_ASSUME_PERFECT at your own risk. | ||||
|  * You should have another method of validating the device tree, such as a | ||||
|  * signature or hash check before using libfdt. | ||||
|  * | ||||
|  * For situations where security is not a concern it may be safe to enable | ||||
|  * FDT_ASSUME_FRIENDLY. | ||||
|  */ | ||||
| enum { | ||||
| 	/*
 | ||||
| 	 * This does essentially no checks. Only the latest device-tree | ||||
| 	 * version is correctly handled. Incosistencies or errors in the device | ||||
| 	 * tree may cause undefined behaviour or crashes. | ||||
| 	 * | ||||
| 	 * If an error occurs when modifying the tree it may leave the tree in | ||||
| 	 * an intermediate (but valid) state. As an example, adding a property | ||||
| 	 * where there is insufficient space may result in the property name | ||||
| 	 * being added to the string table even though the property itself is | ||||
| 	 * not added to the struct section. | ||||
| 	 * | ||||
| 	 * Only use this if you have a fully validated device tree with | ||||
| 	 * the latest supported version and wish to minimise code size. | ||||
| 	 */ | ||||
| 	FDT_ASSUME_PERFECT	= 0xff, | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This assumes that the device tree is sane. i.e. header metadata | ||||
| 	 * and basic hierarchy are correct. | ||||
| 	 * | ||||
| 	 * These checks will be sufficient if you have a valid device tree with | ||||
| 	 * no internal inconsistencies. With this assumption, libfdt will | ||||
| 	 * generally not return -FDT_ERR_INTERNAL, -FDT_ERR_BADLAYOUT, etc. | ||||
| 	 */ | ||||
| 	FDT_ASSUME_SANE		= 1 << 0, | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This disables checks for device-tree version and removes all code | ||||
| 	 * which handles older versions. | ||||
| 	 * | ||||
| 	 * Only enable this if you know you have a device tree with the latest | ||||
| 	 * version. | ||||
| 	 */ | ||||
| 	FDT_ASSUME_LATEST	= 1 << 1, | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This disables any extensive checking of parameters and the device | ||||
| 	 * tree, making various assumptions about correctness. Normal device | ||||
| 	 * trees produced by libfdt and the compiler should be handled safely. | ||||
| 	 * Malicious device trees and complete garbage may cause libfdt to | ||||
| 	 * behave badly or crash. | ||||
| 	 */ | ||||
| 	FDT_ASSUME_FRIENDLY	= 1 << 2, | ||||
| }; | ||||
| 
 | ||||
| /** fdt_chk_basic() - see if basic checking of params and DT data is enabled */ | ||||
| static inline bool fdt_chk_basic(void) | ||||
| { | ||||
| 	return !(FDT_ASSUME_MASK & FDT_ASSUME_SANE); | ||||
| } | ||||
| 
 | ||||
| /** fdt_chk_version() - see if we need to handle old versions of the DT */ | ||||
| static inline bool fdt_chk_version(void) | ||||
| { | ||||
| 	return !(FDT_ASSUME_MASK & FDT_ASSUME_LATEST); | ||||
| } | ||||
| 
 | ||||
| /** fdt_chk_extra() - see if extra checking is enabled */ | ||||
| static inline bool fdt_chk_extra(void) | ||||
| { | ||||
| 	return !(FDT_ASSUME_MASK & FDT_ASSUME_FRIENDLY); | ||||
| } | ||||
| 
 | ||||
| #endif /* LIBFDT_INTERNAL_H */ | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ int fdt_remove_unused_strings(const void *old, void *new) | |||
| 	const char *str; | ||||
| 	int ret; | ||||
| 	int tag = FDT_PROP; | ||||
| 	int allocated; | ||||
| 
 | ||||
| 	/* Make a copy and remove the strings */ | ||||
| 	memcpy(new, old, size); | ||||
|  | @ -25,7 +26,7 @@ int fdt_remove_unused_strings(const void *old, void *new) | |||
| 		new_prop = (struct fdt_property *)(unsigned long) | ||||
| 			fdt_get_property_by_offset(new, offset, NULL); | ||||
| 		str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff)); | ||||
| 		ret = fdt_find_add_string_(new, str); | ||||
| 		ret = fdt_find_add_string_(new, str, &allocated); | ||||
| 		if (ret < 0) | ||||
| 			return ret; | ||||
| 		new_prop->nameoff = cpu_to_fdt32(ret); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue