Skip to content

Commit

Permalink
of/fdt: Clean up casting in unflattening path
Browse files Browse the repository at this point in the history
The flat tree unflatting path is using unsigned longs to carry around
virtual address pointers to the device tree and the allocated memory
used to unpack it. This is a little insane since every access to them
needs to be cast to a pointer type before using it. This patch changes
the data type to void* for the 'start' and 'mem' pointers and reworks
the unflattening functions to use those values directly which results in
slightly simpler code.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
  • Loading branch information
Grant Likely committed Aug 30, 2013
1 parent 92d3161 commit 4485681
Showing 1 changed file with 30 additions and 33 deletions.
63 changes: 30 additions & 33 deletions drivers/of/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,13 @@ int of_fdt_match(struct boot_param_header *blob, unsigned long node,
return score;
}

static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
static void *unflatten_dt_alloc(void **mem, unsigned long size,
unsigned long align)
{
void *res;

*mem = ALIGN(*mem, align);
res = (void *)*mem;
*mem = PTR_ALIGN(*mem, align);
res = *mem;
*mem += size;

return res;
Expand All @@ -147,9 +147,9 @@ static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
* @allnextpp: pointer to ->allnext from last allocated device_node
* @fpsize: Size of the node path up at the current depth.
*/
static unsigned long unflatten_dt_node(struct boot_param_header *blob,
unsigned long mem,
unsigned long *p,
static void * unflatten_dt_node(struct boot_param_header *blob,
void *mem,
void **p,
struct device_node *dad,
struct device_node ***allnextpp,
unsigned long fpsize)
Expand All @@ -162,15 +162,15 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
int has_name = 0;
int new_format = 0;

tag = be32_to_cpup((__be32 *)(*p));
tag = be32_to_cpup(*p);
if (tag != OF_DT_BEGIN_NODE) {
pr_err("Weird tag at start of node: %x\n", tag);
return mem;
}
*p += 4;
pathp = (char *)*p;
pathp = *p;
l = allocl = strlen(pathp) + 1;
*p = ALIGN(*p + l, 4);
*p = PTR_ALIGN(*p + l, 4);

/* version 0x10 has a more compact unit name here instead of the full
* path. we accumulate the full path size using "fpsize", we'll rebuild
Expand Down Expand Up @@ -239,19 +239,19 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
u32 sz, noff;
char *pname;

tag = be32_to_cpup((__be32 *)(*p));
tag = be32_to_cpup(*p);
if (tag == OF_DT_NOP) {
*p += 4;
continue;
}
if (tag != OF_DT_PROP)
break;
*p += 4;
sz = be32_to_cpup((__be32 *)(*p));
noff = be32_to_cpup((__be32 *)((*p) + 4));
sz = be32_to_cpup(*p);
noff = be32_to_cpup(*p + 4);
*p += 8;
if (be32_to_cpu(blob->version) < 0x10)
*p = ALIGN(*p, sz >= 8 ? 8 : 4);
*p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4);

pname = of_fdt_get_string(blob, noff);
if (pname == NULL) {
Expand Down Expand Up @@ -281,11 +281,11 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
np->phandle = be32_to_cpup((__be32 *)*p);
pp->name = pname;
pp->length = sz;
pp->value = (void *)*p;
pp->value = *p;
*prev_pp = pp;
prev_pp = &pp->next;
}
*p = ALIGN((*p) + sz, 4);
*p = PTR_ALIGN((*p) + sz, 4);
}
/* with version 0x10 we may not have the name property, recreate
* it here from the unit name if absent
Expand Down Expand Up @@ -334,7 +334,7 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
else
mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
fpsize);
tag = be32_to_cpup((__be32 *)(*p));
tag = be32_to_cpup(*p);
}
if (tag != OF_DT_END_NODE) {
pr_err("Weird tag at end of node: %x\n", tag);
Expand All @@ -360,7 +360,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
struct device_node **mynodes,
void * (*dt_alloc)(u64 size, u64 align))
{
unsigned long start, mem, size;
unsigned long size;
void *start, *mem;
struct device_node **allnextp = mynodes;

pr_debug(" -> unflatten_device_tree()\n");
Expand All @@ -381,32 +382,28 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
}

/* First pass, scan for size */
start = ((unsigned long)blob) +
be32_to_cpu(blob->off_dt_struct);
size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
size = (size | 3) + 1;
start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
size = ALIGN(size, 4);

pr_debug(" size is %lx, allocating...\n", size);

/* Allocate memory for the expanded device tree */
mem = (unsigned long)
dt_alloc(size + 4, __alignof__(struct device_node));
mem = dt_alloc(size + 4, __alignof__(struct device_node));
memset(mem, 0, size);

memset((void *)mem, 0, size);
*(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);

((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);

pr_debug(" unflattening %lx...\n", mem);
pr_debug(" unflattening %p...\n", mem);

/* Second pass, do actual unflattening */
start = ((unsigned long)blob) +
be32_to_cpu(blob->off_dt_struct);
start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
if (be32_to_cpup((__be32 *)start) != OF_DT_END)
pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
if (be32_to_cpup(start) != OF_DT_END)
pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start));
if (be32_to_cpup(mem + size) != 0xdeadbeef)
pr_warning("End of tree marker overwritten: %08x\n",
be32_to_cpu(((__be32 *)mem)[size / 4]));
be32_to_cpup(mem + size));
*allnextp = NULL;

pr_debug(" <- unflatten_device_tree()\n");
Expand Down

0 comments on commit 4485681

Please sign in to comment.