diff options
Diffstat (limited to 'scripts/dtc/libfdt/fdt.c')
| -rw-r--r-- | scripts/dtc/libfdt/fdt.c | 99 | 
1 files changed, 62 insertions, 37 deletions
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index d6ce7c052dc8..c28fcc115771 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -19,15 +19,21 @@ int32_t fdt_ro_probe_(const void *fdt)  {  	uint32_t totalsize = fdt_totalsize(fdt); +	if (can_assume(VALID_DTB)) +		return totalsize; +  	if (fdt_magic(fdt) == FDT_MAGIC) {  		/* Complete tree */ -		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) -			return -FDT_ERR_BADVERSION; -		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) -			return -FDT_ERR_BADVERSION; +		if (!can_assume(LATEST)) { +			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) +				return -FDT_ERR_BADVERSION; +			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) +		if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)  			return -FDT_ERR_BADSTATE;  	} else {  		return -FDT_ERR_BADMAGIC; @@ -70,44 +76,59 @@ size_t fdt_header_size_(uint32_t version)  		return FDT_V17_SIZE;  } +size_t fdt_header_size(const void *fdt) +{ +	return can_assume(LATEST) ? FDT_V17_SIZE : +		fdt_header_size_(fdt_version(fdt)); +} +  int fdt_check_header(const void *fdt)  {  	size_t hdrsize;  	if (fdt_magic(fdt) != FDT_MAGIC)  		return -FDT_ERR_BADMAGIC; +	if (!can_assume(LATEST)) { +		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_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; - -	if ((fdt_totalsize(fdt) < hdrsize) -	    || (fdt_totalsize(fdt) > INT_MAX)) -		return -FDT_ERR_TRUNCATED; +	if (!can_assume(VALID_DTB)) { -	/* Bounds check memrsv block */ -	if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) -		return -FDT_ERR_TRUNCATED; +		if ((fdt_totalsize(fdt) < hdrsize) +		    || (fdt_totalsize(fdt) > INT_MAX)) +			return -FDT_ERR_TRUNCATED; -	/* Bounds check structure block */ -	if (fdt_version(fdt) < 17) { +		/* Bounds check memrsv block */  		if (!check_off_(hdrsize, fdt_totalsize(fdt), -				fdt_off_dt_struct(fdt))) +				fdt_off_mem_rsvmap(fdt)))  			return -FDT_ERR_TRUNCATED; -	} else { +	} + +	if (!can_assume(VALID_DTB)) { +		/* Bounds check structure block */ +		if (!can_assume(LATEST) && 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_struct(fdt), -				  fdt_size_dt_struct(fdt))) +				  fdt_off_dt_strings(fdt), +				  fdt_size_dt_strings(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;  } @@ -115,12 +136,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)  {  	unsigned absoffset = offset + fdt_off_dt_struct(fdt); -	if ((absoffset < offset) -	    || ((absoffset + len) < absoffset) -	    || (absoffset + len) > fdt_totalsize(fdt)) -		return NULL; +	if (!can_assume(VALID_INPUT)) +		if ((absoffset < offset) +		    || ((absoffset + len) < absoffset) +		    || (absoffset + len) > fdt_totalsize(fdt)) +			return NULL; -	if (fdt_version(fdt) >= 0x11) +	if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)  		if (((offset + len) < offset)  		    || ((offset + len) > fdt_size_dt_struct(fdt)))  			return NULL; @@ -137,7 +159,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 (!can_assume(VALID_DTB) && !tagp)  		return FDT_END; /* premature end */  	tag = fdt32_to_cpu(*tagp);  	offset += FDT_TAGSIZE; @@ -149,18 +171,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 (!can_assume(VALID_DTB) && !p)  			return FDT_END; /* premature end */  		break;  	case FDT_PROP:  		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); -		if (!lenp) +		if (!can_assume(VALID_DTB) && !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 (!can_assume(LATEST) && +		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&  		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)  			offset += 4;  		break; @@ -183,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)  int fdt_check_node_offset_(const void *fdt, int offset)  { +	if (can_assume(VALID_INPUT)) +		return offset;  	if ((offset < 0) || (offset % FDT_TAGSIZE)  	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))  		return -FDT_ERR_BADOFFSET;  |