#include <linux/kernel.h>
#include <linux/initrd.h>
#include <linux/memblock.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
* unflatten_dt_node - Alloc and populate a device_node from the flat tree
* @blob: The parent device tree blob
* @mem: Memory chunk to use for allocating device nodes and properties
- * @p: pointer to node in flat tree
+ * @poffset: pointer to node in flat tree
* @dad: Parent struct device_node
+ * @nodepp: The device_node tree created by the call
* @fpsize: Size of the node path up at the current depth.
+ * @dryrun: If true, do not allocate device nodes but still calculate needed
+ * memory size
*/
-static void * unflatten_dt_node(void *blob,
+static void * unflatten_dt_node(const void *blob,
void *mem,
int *poffset,
struct device_node *dad,
struct property *pp, **prev_pp = NULL;
const char *pathp;
unsigned int l, allocl;
- static int depth = 0;
+ static int depth;
int old_depth;
int offset;
int has_name = 0;
* @dt_alloc: An allocator that provides a virtual address to memory
* for the resulting tree
*/
-static void __unflatten_device_tree(void *blob,
+static void __unflatten_device_tree(const void *blob,
struct device_node **mynodes,
void * (*dt_alloc)(u64 size, u64 align))
{
return kzalloc(size, GFP_KERNEL);
}
+static DEFINE_MUTEX(of_fdt_unflatten_mutex);
+
/**
* of_fdt_unflatten_tree - create tree of device_nodes from flat blob
*
* pointers of the nodes so the normal device-tree walking functions
* can be used.
*/
-void of_fdt_unflatten_tree(unsigned long *blob,
+void of_fdt_unflatten_tree(const unsigned long *blob,
struct device_node **mynodes)
{
+ mutex_lock(&of_fdt_unflatten_mutex);
__unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
+ mutex_unlock(&of_fdt_unflatten_mutex);
}
EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
if (!initial_boot_params)
return;
- /* Reserve the dtb region */
- early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
- fdt_totalsize(initial_boot_params),
- 0);
-
/* Process header /memreserve/ fields */
for (n = 0; ; n++) {
fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
fdt_init_reserved_mem();
}
+/**
+ * early_init_fdt_reserve_self() - reserve the memory used by the FDT blob
+ */
+void __init early_init_fdt_reserve_self(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ /* Reserve the dtb region */
+ early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
+ fdt_totalsize(initial_boot_params),
+ 0);
+}
+
/**
* of_scan_flat_dt - scan flattened tree blob and call callback on each.
* @it: callback function
if (!p || !l)
return -ENOENT;
+ /* Remove console options if present */
+ l = strchrnul(p, ':') - p;
+
/* Get the node specified by stdout-path */
- offset = fdt_path_offset(fdt, p);
+ offset = fdt_path_offset_namelen(fdt, p, l);
if (offset < 0)
return -ENODEV;
while (match->compatible[0]) {
- unsigned long addr;
+ u64 addr;
+
if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
match++;
continue;
}
addr = fdt_translate_address(fdt, offset);
- if (!addr)
+ if (addr == OF_BAD_ADDR)
return -ENXIO;
of_setup_earlycon(addr, match->data);
return __va(memblock_alloc(size, align));
}
#else
+void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+ WARN_ON(1);
+}
+
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
phys_addr_t size, bool nomap)
{
- pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
+ pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n",
&base, &size, nomap ? " (nomap)" : "");
return -ENOSYS;
}
+
+void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+ WARN_ON(1);
+ return NULL;
+}
#endif
bool __init early_init_dt_verify(void *params)