aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaura Abbott <lauraa@codeaurora.org>2014-07-15 13:03:35 -0400
committerGrant Likely <grant.likely@linaro.org>2014-07-29 23:26:45 -0400
commit704033cee2e5b3c1c6eaf5bb398e465a9c3667b5 (patch)
tree4b6e7a5ca961e3b8c82fd82295b53cca550a332a
parent4972a74b888c6b52ca41fae6076786dbbeb746d5 (diff)
of: Add memory limiting function for flattened devicetrees
Buggy bootloaders may pass bogus memory entries in the devicetree. Add of_fdt_limit_memory to add an upper bound on the number of entries that can be present in the devicetree. Signed-off-by: Laura Abbott <lauraa@codeaurora.org> Tested-by: Andreas Färber <afaerber@suse.de> Signed-off-by: Grant Likely <grant.likely@linaro.org>
-rw-r--r--drivers/of/fdt.c48
-rw-r--r--include/linux/of_fdt.h1
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ecc7a02d868e..9aa012e6ea0a 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -26,6 +26,54 @@
26#include <asm/setup.h> /* for COMMAND_LINE_SIZE */ 26#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
27#include <asm/page.h> 27#include <asm/page.h>
28 28
29/*
30 * of_fdt_limit_memory - limit the number of regions in the /memory node
31 * @limit: maximum entries
32 *
33 * Adjust the flattened device tree to have at most 'limit' number of
34 * memory entries in the /memory node. This function may be called
35 * any time after initial_boot_param is set.
36 */
37void of_fdt_limit_memory(int limit)
38{
39 int memory;
40 int len;
41 const void *val;
42 int nr_address_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
43 int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
44 const uint32_t *addr_prop;
45 const uint32_t *size_prop;
46 int root_offset;
47 int cell_size;
48
49 root_offset = fdt_path_offset(initial_boot_params, "/");
50 if (root_offset < 0)
51 return;
52
53 addr_prop = fdt_getprop(initial_boot_params, root_offset,
54 "#address-cells", NULL);
55 if (addr_prop)
56 nr_address_cells = fdt32_to_cpu(*addr_prop);
57
58 size_prop = fdt_getprop(initial_boot_params, root_offset,
59 "#size-cells", NULL);
60 if (size_prop)
61 nr_size_cells = fdt32_to_cpu(*size_prop);
62
63 cell_size = sizeof(uint32_t)*(nr_address_cells + nr_size_cells);
64
65 memory = fdt_path_offset(initial_boot_params, "/memory");
66 if (memory > 0) {
67 val = fdt_getprop(initial_boot_params, memory, "reg", &len);
68 if (len > limit*cell_size) {
69 len = limit*cell_size;
70 pr_debug("Limiting number of entries to %d\n", limit);
71 fdt_setprop(initial_boot_params, memory, "reg", val,
72 len);
73 }
74 }
75}
76
29/** 77/**
30 * of_fdt_is_compatible - Return true if given node from the given blob has 78 * of_fdt_is_compatible - Return true if given node from the given blob has
31 * compat in its compatible list 79 * compat in its compatible list
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index ebb2449082fb..0ff360d5b3b3 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -86,6 +86,7 @@ extern void unflatten_and_copy_device_tree(void);
86extern void early_init_devtree(void *); 86extern void early_init_devtree(void *);
87extern void early_get_first_memblock_info(void *, phys_addr_t *); 87extern void early_get_first_memblock_info(void *, phys_addr_t *);
88extern u64 fdt_translate_address(const void *blob, int node_offset); 88extern u64 fdt_translate_address(const void *blob, int node_offset);
89extern void of_fdt_limit_memory(int limit);
89#else /* CONFIG_OF_FLATTREE */ 90#else /* CONFIG_OF_FLATTREE */
90static inline void early_init_fdt_scan_reserved_mem(void) {} 91static inline void early_init_fdt_scan_reserved_mem(void) {}
91static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } 92static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }