Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: u-boot places device-tree in bss



On 14/12/2025 18:56, Yuri Honegger wrote:
Hello,
When the memory address for the device tree isn't provided to u-boot, u-boot
decides where to place the device tree by itself. For me, it chooses to place it
right after the code, overlapping the bss section. This means the device tree
gets overwritten when clearing the bss and a bit later, NetBSD rightfully panics
because of a corrupt device tree.

Since u-boot leaves some space between the code and the device tree, it works
with a small kernel, but as soon as I enable more features and bss grows, I run
into this issue.

I'm a little surprised that NetBSD's GENERIC_V5 is bloated compared to your u-boot's idea of how big the kernel is, but not completely.


I can work around this by giving u-boot a boot.scr that manually places the
device tree, but I'm wondering if this could be fixed in NetBSD.

We could add a panic if we encounter this situation. That would be a bit more
helpful than the current error:
[ 1.0000000] panic: fdt_check_header failed: FDT_ERR_BADMAGIC

Sure... something like the attached. Oh, looking at arm32_bootmem_init it's a bit more complicated, but you get the idea.



Another option would be to add some logic that preserves the device tree in this
scenario. For example, we could move the device tree out of the way of the bss
if they overlap. The question is where would we move it though? Perhaps
beyond the end of the bss section?

This isn't possible. the fdt needs to be loaded outside of the kernel text, data and bss.

diff --git a/sys/arch/evbarm/fdt/fdt_machdep.c b/sys/arch/evbarm/fdt/fdt_machdep.c
index 89a1d4a06f5e..576f432982d6 100644
--- a/sys/arch/evbarm/fdt/fdt_machdep.c
+++ b/sys/arch/evbarm/fdt/fdt_machdep.c
@@ -257,10 +257,16 @@ initarm(void *arg)
 {
 	const struct fdt_platform *plat;
 	uint64_t memory_start, memory_end;
+	extern char etext[];
+	extern char _end[];
 
 	/* set temporally to work printf()/panic() even before consinit() */
 	cn_tab = &earlycons;
 
+	vaddr_t fdt_va = (vaddr_t)fdt_addr_r;
+	if ((vaddr_t)etext < fdt_va && fdt_va < (vaddr_t)_end)
+		panic("FDT placed within loaded kernel");
+
 	/* Load FDT */
 	int error = fdt_check_header(fdt_addr_r);
 	if (error != 0)


Home | Main Index | Thread Index | Old Index