diff options
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r-- | arch/powerpc/boot/devtree.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index ae8b886f5a1..129e6d9b8d4 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c @@ -218,7 +218,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, u32 this_addr[MAX_ADDR_CELLS]; void *parent; u64 ret_addr, ret_size; - u32 naddr, nsize, prev_naddr; + u32 naddr, nsize, prev_naddr, prev_nsize; int buflen, offset; parent = get_parent(node); @@ -233,7 +233,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, offset = (naddr + nsize) * res; if (reglen < offset + naddr + nsize || - sizeof(dt_xlate_buf) < offset + naddr + nsize) + sizeof(dt_xlate_buf) < (offset + naddr + nsize) * 4) return 0; 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, ret_size |= dt_xlate_buf[offset + naddr + 1]; } - while ((node = get_parent(node))) { + for (;;) { 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, sizeof(dt_xlate_buf)); - if (buflen < 0) + if (buflen == 0) continue; - if (buflen > sizeof(dt_xlate_buf)) + if (buflen < 0 || buflen > sizeof(dt_xlate_buf)) return 0; offset = find_range(last_addr, dt_xlate_buf, prev_naddr, - naddr, nsize, buflen / 4); + naddr, prev_nsize, buflen / 4); if (offset < 0) return 0; |