Skip to content

Commit 704033c

Browse files
labbottglikely
authored andcommitted
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 <[email protected]> Tested-by: Andreas Färber <[email protected]> Signed-off-by: Grant Likely <[email protected]>
1 parent 4972a74 commit 704033c

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

drivers/of/fdt.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,54 @@
2626
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
2727
#include <asm/page.h>
2828

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+
2977
/**
3078
* of_fdt_is_compatible - Return true if given node from the given blob has
3179
* compat in its compatible list

include/linux/of_fdt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern void unflatten_and_copy_device_tree(void);
8686
extern void early_init_devtree(void *);
8787
extern void early_get_first_memblock_info(void *, phys_addr_t *);
8888
extern u64 fdt_translate_address(const void *blob, int node_offset);
89+
extern void of_fdt_limit_memory(int limit);
8990
#else /* CONFIG_OF_FLATTREE */
9091
static inline void early_init_fdt_scan_reserved_mem(void) {}
9192
static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }

0 commit comments

Comments
 (0)