diff options
| author | Andy Fleming <afleming@freescale.com> | 2008-06-16 13:58:55 -0500 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2008-06-28 22:22:05 +0200 | 
| commit | 7570a9941fc565922078679a72d246fe208d696d (patch) | |
| tree | 91ed5c3837bb2c491fb4ef101c3371c5f58fb79a | |
| parent | 63796c4e61b207d2e635729d41b7a7f7d188b03c (diff) | |
| download | olio-uboot-2014.01-7570a9941fc565922078679a72d246fe208d696d.tar.xz olio-uboot-2014.01-7570a9941fc565922078679a72d246fe208d696d.zip  | |
Fix an underflow bug in __lmb_alloc_base
__lmb_alloc_base can underflow if it fails to find free space.  This was fixed
in linux with commit d9024df02ffe74d723d97d552f86de3b34beb8cc.  This patch
merely updates __lmb_alloc_base to resemble the current version in Linux.
Signed-off-by: Andy Fleming <afleming@freescale.com>
| -rw-r--r-- | lib_generic/lmb.c | 34 | 
1 files changed, 19 insertions, 15 deletions
diff --git a/lib_generic/lmb.c b/lib_generic/lmb.c index 3240f66bf..93264c15e 100644 --- a/lib_generic/lmb.c +++ b/lib_generic/lmb.c @@ -285,11 +285,14 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy  {  	long i, j;  	phys_addr_t base = 0; +	phys_addr_t res_base;  	for (i = lmb->memory.cnt-1; i >= 0; i--) {  		phys_addr_t lmbbase = lmb->memory.region[i].base;  		phys_size_t lmbsize = lmb->memory.region[i].size; +		if (lmbsize < size) +			continue;  		if (max_addr == LMB_ALLOC_ANYWHERE)  			base = lmb_align_down(lmbbase + lmbsize - size, align);  		else if (lmbbase < max_addr) { @@ -298,22 +301,23 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy  		} else  			continue; -		while ((lmbbase <= base) && -		       ((j = lmb_overlaps_region(&(lmb->reserved), base, size)) >= 0) ) -			base = lmb_align_down(lmb->reserved.region[j].base - size, -					      align); - -		if ((base != 0) && (lmbbase <= base)) -			break; +		while (base && lmbbase <= base) { +			j = lmb_overlaps_region(&lmb->reserved, base, size); +			if (j < 0) { +				/* This area isn't reserved, take it */ +				if (lmb_add_region(&lmb->reserved, base, +							lmb_align_up(size, +								align)) < 0) +					return 0; +				return base; +			} +			res_base = lmb->reserved.region[j].base; +			if (res_base < size) +				break; +			base = lmb_align_down(res_base - size, align); +		}  	} - -	if (i < 0) -		return 0; - -	if (lmb_add_region(&(lmb->reserved), base, lmb_align_up(size, align)) < 0) -		return 0; - -	return base; +	return 0;  }  int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr)  |