diff options
Diffstat (limited to 'arch/powerpc/boot/devtree.c')
-rw-r--r-- | arch/powerpc/boot/devtree.c | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index 23492d7fb556..ac4b5ee92d58 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c | |||
@@ -123,15 +123,17 @@ static void get_reg_format(void *node, u32 *naddr, u32 *nsize) | |||
123 | 123 | ||
124 | static void copy_val(u32 *dest, u32 *src, int naddr) | 124 | static void copy_val(u32 *dest, u32 *src, int naddr) |
125 | { | 125 | { |
126 | memset(dest, 0, (MAX_ADDR_CELLS - naddr) * 4); | 126 | int pad = MAX_ADDR_CELLS - naddr; |
127 | memcpy(dest, src, naddr * 4); | 127 | |
128 | memset(dest, 0, pad * 4); | ||
129 | memcpy(dest + pad, src, naddr * 4); | ||
128 | } | 130 | } |
129 | 131 | ||
130 | static int sub_reg(u32 *reg, u32 *sub) | 132 | static int sub_reg(u32 *reg, u32 *sub) |
131 | { | 133 | { |
132 | int i, borrow = 0; | 134 | int i, borrow = 0; |
133 | 135 | ||
134 | for (i = 0; i < MAX_ADDR_CELLS; i++) { | 136 | for (i = MAX_ADDR_CELLS - 1; i >= 0; i--) { |
135 | int prev_borrow = borrow; | 137 | int prev_borrow = borrow; |
136 | borrow = reg[i] < sub[i] + prev_borrow; | 138 | borrow = reg[i] < sub[i] + prev_borrow; |
137 | reg[i] -= sub[i] + prev_borrow; | 139 | reg[i] -= sub[i] + prev_borrow; |
@@ -140,11 +142,11 @@ static int sub_reg(u32 *reg, u32 *sub) | |||
140 | return !borrow; | 142 | return !borrow; |
141 | } | 143 | } |
142 | 144 | ||
143 | static int add_reg(u32 *reg, u32 *add) | 145 | static int add_reg(u32 *reg, u32 *add, int naddr) |
144 | { | 146 | { |
145 | int i, carry = 0; | 147 | int i, carry = 0; |
146 | 148 | ||
147 | for (i = 0; i < MAX_ADDR_CELLS; i++) { | 149 | for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) { |
148 | u64 tmp = (u64)reg[i] + add[i] + carry; | 150 | u64 tmp = (u64)reg[i] + add[i] + carry; |
149 | carry = tmp >> 32; | 151 | carry = tmp >> 32; |
150 | reg[i] = (u32)tmp; | 152 | reg[i] = (u32)tmp; |
@@ -228,7 +230,8 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, | |||
228 | buflen = getprop(node, "reg", buf, sizeof(buf)) / 4; | 230 | buflen = getprop(node, "reg", buf, sizeof(buf)) / 4; |
229 | offset = (naddr + nsize) * res; | 231 | offset = (naddr + nsize) * res; |
230 | 232 | ||
231 | if (buflen < offset + naddr + nsize) | 233 | if (buflen < offset + naddr + nsize || |
234 | sizeof(buf) < offset + naddr + nsize) | ||
232 | return 0; | 235 | return 0; |
233 | 236 | ||
234 | copy_val(last_addr, buf + offset, naddr); | 237 | copy_val(last_addr, buf + offset, naddr); |
@@ -263,18 +266,14 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, | |||
263 | 266 | ||
264 | copy_val(this_addr, buf + offset + prev_naddr, naddr); | 267 | copy_val(this_addr, buf + offset + prev_naddr, naddr); |
265 | 268 | ||
266 | if (!add_reg(last_addr, this_addr)) | 269 | if (!add_reg(last_addr, this_addr, naddr)) |
267 | return 0; | 270 | return 0; |
268 | } | 271 | } |
269 | 272 | ||
270 | if (naddr > 2) | 273 | if (naddr > 2) |
271 | return 0; | 274 | return 0; |
272 | 275 | ||
273 | ret_addr = last_addr[0]; | 276 | ret_addr = ((u64)last_addr[2] << 32) | last_addr[3]; |
274 | if (naddr == 2) { | ||
275 | ret_addr <<= 32; | ||
276 | ret_addr |= last_addr[1]; | ||
277 | } | ||
278 | 277 | ||
279 | if (sizeof(void *) == 4 && | 278 | if (sizeof(void *) == 4 && |
280 | (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL || | 279 | (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL || |