Commit 7b937cc2 authored by Frank Rowand's avatar Frank Rowand Committed by Rob Herring
Browse files

of: Create of_root if no dtb provided by firmware



When enabling CONFIG_OF on a platform where 'of_root' is not populated
by firmware, we end up without a root node. In order to apply overlays
and create subnodes of the root node, we need one. Create this root node
by unflattening an empty builtin dtb.

If firmware provides a flattened device tree (FDT) then the FDT is
unflattened via setup_arch(). Otherwise, the call to
unflatten(_and_copy)?_device_tree() will create an empty root node.

We make of_have_populated_dt() return true only if the DTB was loaded by
firmware so that existing callers don't change behavior after this
patch. The call in the of platform code is removed because it prevents
overlays from creating platform devices when the empty root node is
used.

[sboyd@kernel.org: Update of_have_populated_dt() to treat this empty dtb
as not populated. Drop setup_of() initcall]

Signed-off-by: default avatarFrank Rowand <frowand.list@gmail.com>
Link: https://lore.kernel.org/r/20230317053415.2254616-2-frowand.list@gmail.com


Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
Link: https://lore.kernel.org/r/20240217010557.2381548-3-sboyd@kernel.org


Signed-off-by: default avatarRob Herring <robh@kernel.org>
parent dc1460fe
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -14,9 +14,8 @@ if OF

config OF_UNITTEST
	bool "Device Tree runtime unit tests"
	depends on !SPARC
	depends on OF_EARLY_FLATTREE
	select IRQ_DOMAIN
	select OF_EARLY_FLATTREE
	select OF_RESOLVE
	help
	  This option builds in test cases for the device tree infrastructure
@@ -54,7 +53,7 @@ config OF_FLATTREE
	select CRC32

config OF_EARLY_FLATTREE
	bool
	def_bool OF && !(SPARC || ALPHA || HEXAGON || M68K || PARISC || S390)
	select DMA_DECLARE_COHERENT if HAS_DMA && HAS_IOMEM
	select OF_FLATTREE

+1 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
obj-y = base.o cpu.o device.o module.o platform.o property.o
obj-$(CONFIG_OF_KOBJ) += kobj.o
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o empty_root.dtb.o
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
obj-$(CONFIG_OF_PROMTREE) += pdt.o
obj-$(CONFIG_OF_ADDRESS)  += address.o
+6 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/dts-v1/;

/ {

};
+31 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#define pr_fmt(fmt)	"OF: fdt: " fmt

#include <linux/acpi.h>
#include <linux/crash_dump.h>
#include <linux/crc32.h>
#include <linux/kernel.h>
@@ -32,6 +33,13 @@

#include "of_private.h"

/*
 * __dtb_empty_root_begin[] and __dtb_empty_root_end[] magically created by
 * cmd_dt_S_dtb in scripts/Makefile.lib
 */
extern uint8_t __dtb_empty_root_begin[];
extern uint8_t __dtb_empty_root_end[];

/*
 * of_fdt_limit_memory - limit the number of regions in the /memory node
 * @limit: maximum entries
@@ -1343,7 +1351,29 @@ static void *__init copy_device_tree(void *fdt)
 */
void __init unflatten_device_tree(void)
{
	__unflatten_device_tree(initial_boot_params, NULL, &of_root,
	void *fdt = initial_boot_params;

	/* Don't use the bootloader provided DTB if ACPI is enabled */
	if (!acpi_disabled)
		fdt = NULL;

	/*
	 * Populate an empty root node when ACPI is enabled or bootloader
	 * doesn't provide one.
	 */
	if (!fdt) {
		fdt = (void *) __dtb_empty_root_begin;
		/* fdt_totalsize() will be used for copy size */
		if (fdt_totalsize(fdt) >
		    __dtb_empty_root_end - __dtb_empty_root_begin) {
			pr_err("invalid size in dtb_empty_root\n");
			return;
		}
		of_fdt_crc32 = crc32_be(~0, fdt, fdt_totalsize(fdt));
		fdt = copy_device_tree(fdt);
	}

	__unflatten_device_tree(fdt, NULL, &of_root,
				early_init_dt_alloc_memory_arch, false);

	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
+0 −3
Original line number Diff line number Diff line
@@ -512,9 +512,6 @@ static int __init of_platform_default_populate_init(void)

	device_links_supplier_sync_state_pause();

	if (!of_have_populated_dt())
		return -ENODEV;

	if (IS_ENABLED(CONFIG_PPC)) {
		struct device_node *boot_display = NULL;
		struct platform_device *dev;
Loading