Commit 0602801c authored by Scott Wood's avatar Scott Wood Committed by Paul Mackerras

[POWERPC] bootwrapper: dt_xlate_range() bugfixes

1. The check whether ranges fits in the buffer was using elements rather
than bytes.
2. Empty ranges were not properly treated as transparent, and missing
ranges were treated as transparent.
3. The loop terminated when translating from the root rather than to.  Once
bug #2 was fixed, it failed due to a missing ranges in the root node.
4. In decoding the ranges property, the #size-cells used was that of
the parent, not the child.
Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
Acked-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 643d3c13
...@@ -218,7 +218,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, ...@@ -218,7 +218,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
u32 this_addr[MAX_ADDR_CELLS]; u32 this_addr[MAX_ADDR_CELLS];
void *parent; void *parent;
u64 ret_addr, ret_size; u64 ret_addr, ret_size;
u32 naddr, nsize, prev_naddr; u32 naddr, nsize, prev_naddr, prev_nsize;
int buflen, offset; int buflen, offset;
parent = get_parent(node); parent = get_parent(node);
...@@ -233,7 +233,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, ...@@ -233,7 +233,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
offset = (naddr + nsize) * res; offset = (naddr + nsize) * res;
if (reglen < offset + naddr + nsize || if (reglen < offset + naddr + nsize ||
sizeof(dt_xlate_buf) < offset + naddr + nsize) sizeof(dt_xlate_buf) < (offset + naddr + nsize) * 4)
return 0; return 0;
copy_val(last_addr, dt_xlate_buf + offset, naddr); copy_val(last_addr, dt_xlate_buf + offset, naddr);
...@@ -244,20 +244,26 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, ...@@ -244,20 +244,26 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
ret_size |= dt_xlate_buf[offset + naddr + 1]; ret_size |= dt_xlate_buf[offset + naddr + 1];
} }
while ((node = get_parent(node))) { for (;;) {
prev_naddr = naddr; prev_naddr = naddr;
prev_nsize = nsize;
node = parent;
get_reg_format(node, &naddr, &nsize); parent = get_parent(node);
if (!parent)
break;
get_reg_format(parent, &naddr, &nsize);
buflen = getprop(node, "ranges", dt_xlate_buf, buflen = getprop(node, "ranges", dt_xlate_buf,
sizeof(dt_xlate_buf)); sizeof(dt_xlate_buf));
if (buflen < 0) if (buflen == 0)
continue; continue;
if (buflen > sizeof(dt_xlate_buf)) if (buflen < 0 || buflen > sizeof(dt_xlate_buf))
return 0; return 0;
offset = find_range(last_addr, dt_xlate_buf, prev_naddr, offset = find_range(last_addr, dt_xlate_buf, prev_naddr,
naddr, nsize, buflen / 4); naddr, prev_nsize, buflen / 4);
if (offset < 0) if (offset < 0)
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment