summaryrefslogtreecommitdiffstats
path: root/drivers/of/fdt.c
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2016-05-11 19:36:57 +0200
committerRob Herring <robh@kernel.org>2016-05-19 16:15:14 +0200
commit78c44d910d3e5f96dc6b3695fc1e4efd7c46a455 (patch)
tree5d9a0e4a54adc0efcbe4319801707be6e2037458 /drivers/of/fdt.c
parentof: dynamic: changeset prop-update revert fix (diff)
downloadlinux-78c44d910d3e5f96dc6b3695fc1e4efd7c46a455.tar.xz
linux-78c44d910d3e5f96dc6b3695fc1e4efd7c46a455.zip
drivers/of: Fix depth when unflattening devicetree
When the implementation for unflatten_dt_node() changed from being recursive to being non-recursive, it had a side effect of increasing the depth passed to fdt_next_node() by 1. This is fine most of the time, but it seems that when the end of the dtb is being parsed, it will cause the FDT_END condition in fdt_next_node() to return a different value (returning nextoffset instead of -FDT_ERR_NOTFOUND). This ends up passing an FDT_ERR_TRUNCATED error back to the unflatten_dt_node() which then sees that and complains "Error -8 processing FDT" causing boot to fail. This patch simply avoids incrementing depth and uses modified accesses for local array indices so that the depth is the same as it was before the change as far as fdt_next_node() is concerned. This problem was discovered trying to boot Tegra210-Smaug platforms. Fixes: 50800082f176 ("drivers/of: Avoid recursively calling unflatten_dt_node()") Signed-off-by: Rhyland Klein <rklein@nvidia.com> [robh: squashed in KASAN fix from Rhyland] Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r--drivers/of/fdt.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ef1ccee51af8..b352f67d710b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -407,24 +407,24 @@ static int unflatten_dt_nodes(const void *blob,
root = dad;
fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
- nps[depth++] = dad;
+ nps[depth] = dad;
for (offset = 0;
- offset >= 0;
+ offset >= 0 && depth >= 0;
offset = fdt_next_node(blob, offset, &depth)) {
if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
continue;
- fpsizes[depth] = populate_node(blob, offset, &mem,
- nps[depth - 1],
- fpsizes[depth - 1],
- &nps[depth], dryrun);
- if (!fpsizes[depth])
+ fpsizes[depth+1] = populate_node(blob, offset, &mem,
+ nps[depth],
+ fpsizes[depth],
+ &nps[depth+1], dryrun);
+ if (!fpsizes[depth+1])
return mem - base;
if (!dryrun && nodepp && !*nodepp)
- *nodepp = nps[depth];
+ *nodepp = nps[depth+1];
if (!dryrun && !root)
- root = nps[depth];
+ root = nps[depth+1];
}
if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {