Re: [PATCH] powerpc: Add dt_xlate_addr() to bootwrapper
From: Mark A. Greer <hidden>
Date: 2007-04-25 21:16:35
On Fri, Apr 13, 2007 at 05:25:51PM -0500, Scott Wood wrote:
On Fri, Apr 13, 2007 at 01:23:43PM -0700, Mark A. Greer wrote:
This causes it to use the caller-provided buffer to read the ranges property, which may not be large enough in the case of dt_xlate_addr(). ...
Scott, how about this? If you like it, please give me an "Acked-by:" line and I'll submit it with some other patches I'm prep'ing. Thanks, Mark --- [PATCH] powerpc: Add dt_xlate_addr() to bootwrapper From: "Mark A. Greer" <redacted> dt_xlate_reg() looks up the 'reg' property in the specified node to get the address and size to translate. Add dt_xlate_addr() which is passed in the address and size to translate. Signed-off-by: Mark A. Greer <redacted> --- devtree.c | 45 ++++++++++++++++++++++++++++++++------------- ops.h | 4 ++-- 2 files changed, 34 insertions(+), 15 deletions(-) Index: powerpc/arch/powerpc/boot/devtree.c ===================================================================
--- powerpc.orig/arch/powerpc/boot/devtree.c
+++ powerpc/arch/powerpc/boot/devtree.c@@ -205,16 +205,17 @@ static int find_range(u32 *reg, u32 *ran * In particular, PCI is not supported. Also, only the beginning of the * reg block is tracked; size is ignored except in ranges. */ -int dt_xlate_reg(void *node, int res, unsigned long *addr, - unsigned long *size) +static u32 dt_xlate_buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; + +static int dt_xlate(void *node, int res, int buflen, unsigned long *addr, + unsigned long *size) { u32 last_addr[MAX_ADDR_CELLS]; u32 this_addr[MAX_ADDR_CELLS]; - u32 buf[MAX_ADDR_CELLS * MAX_RANGES * 3]; void *parent; u64 ret_addr, ret_size; u32 naddr, nsize, prev_naddr; - int buflen, offset; + int offset; parent = get_parent(node); if (!parent)
@@ -225,18 +226,17 @@ int dt_xlate_reg(void *node, int res, un if (nsize > 2) return 0; - buflen = getprop(node, "reg", buf, sizeof(buf)) / 4; offset = (naddr + nsize) * res; if (buflen < offset + naddr + nsize) return 0; - copy_val(last_addr, buf + offset, naddr); + copy_val(last_addr, dt_xlate_buf + offset, naddr); - ret_size = buf[offset + naddr]; + ret_size = dt_xlate_buf[offset + naddr]; if (nsize == 2) { ret_size <<= 32; - ret_size |= buf[offset + naddr + 1]; + ret_size |= dt_xlate_buf[offset + naddr + 1]; } while ((node = get_parent(node))) {
@@ -244,24 +244,25 @@ int dt_xlate_reg(void *node, int res, un get_reg_format(node, &naddr, &nsize); - buflen = getprop(node, "ranges", buf, sizeof(buf)); + buflen = getprop(node, "ranges", dt_xlate_buf, + sizeof(dt_xlate_buf)); if (buflen < 0) continue; - if (buflen > sizeof(buf)) + if (buflen > sizeof(dt_xlate_buf)) return 0; - offset = find_range(last_addr, buf, prev_naddr, + offset = find_range(last_addr, dt_xlate_buf, prev_naddr, naddr, nsize, buflen / 4); if (offset < 0) return 0; - copy_val(this_addr, buf + offset, prev_naddr); + copy_val(this_addr, dt_xlate_buf + offset, prev_naddr); if (!sub_reg(last_addr, this_addr)) return 0; - copy_val(this_addr, buf + offset + prev_naddr, naddr); + copy_val(this_addr, dt_xlate_buf + offset + prev_naddr, naddr); if (!add_reg(last_addr, this_addr)) return 0;
@@ -287,3 +288,21 @@ int dt_xlate_reg(void *node, int res, un return 1; } + +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size) +{ + int buflen; + + buflen = getprop(node, "reg", dt_xlate_buf, sizeof(dt_xlate_buf)) / 4; + return dt_xlate(node, res, buflen, addr, size); +} + +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr) +{ + + if (buflen > sizeof(dt_xlate_buf)) + return 0; + + memcpy(dt_xlate_buf, buf, buflen); + return dt_xlate(node, 0, buflen / 4, xlated_addr, NULL); +}
Index: powerpc/arch/powerpc/boot/ops.h ===================================================================
--- powerpc.orig/arch/powerpc/boot/ops.h
+++ powerpc/arch/powerpc/boot/ops.h@@ -82,8 +82,8 @@ int ns16550_console_init(void *devp, str void *simple_alloc_init(char *base, unsigned long heap_size, unsigned long granularity, unsigned long max_allocs); extern void flush_cache(void *, unsigned long); -int dt_xlate_reg(void *node, int res, unsigned long *addr, - unsigned long *size); +int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size); +int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr); static inline void *finddevice(const char *name) {