diff options
author | Laura Abbott <lauraa@codeaurora.org> | 2014-07-15 13:03:35 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-07-29 23:26:45 -0400 |
commit | 704033cee2e5b3c1c6eaf5bb398e465a9c3667b5 (patch) | |
tree | 4b6e7a5ca961e3b8c82fd82295b53cca550a332a | |
parent | 4972a74b888c6b52ca41fae6076786dbbeb746d5 (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.c | 48 | ||||
-rw-r--r-- | include/linux/of_fdt.h | 1 |
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 | */ | ||
37 | void 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); | |||
86 | extern void early_init_devtree(void *); | 86 | extern void early_init_devtree(void *); |
87 | extern void early_get_first_memblock_info(void *, phys_addr_t *); | 87 | extern void early_get_first_memblock_info(void *, phys_addr_t *); |
88 | extern u64 fdt_translate_address(const void *blob, int node_offset); | 88 | extern u64 fdt_translate_address(const void *blob, int node_offset); |
89 | extern void of_fdt_limit_memory(int limit); | ||
89 | #else /* CONFIG_OF_FLATTREE */ | 90 | #else /* CONFIG_OF_FLATTREE */ |
90 | static inline void early_init_fdt_scan_reserved_mem(void) {} | 91 | static inline void early_init_fdt_scan_reserved_mem(void) {} |
91 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } | 92 | static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } |