Page 1 of 2

device tree overlays and U-Boot

Posted: Mon Jan 25, 2016 10:59 pm
by jampy81
AFAIK U-Boot does not support device tree overlays.

So, is it possible to merge the main device tree dtb and desired overlays to a single .dtb so that U-Boot can use it? If yes, how is it done?

I'm trying to get a I2C RTC working and need to boot via U-Boot.

see also my related Stackexchange question: http://unix.stackexchange.com/q/256264

Thanks!

Re: device tree overlays and U-Boot

Posted: Tue Jan 26, 2016 8:40 am
by PhilE
I have written a utility that can do that - I used it to test the overlay mechanism during its development. It needs a bit of polishing before the source code is released, time I don't have at the moment, but I'm happy to make a Pi binary available in the meantime if that helps.

Re: device tree overlays and U-Boot

Posted: Wed Jan 27, 2016 7:33 pm
by chaosjug
If you just want to enable I2C RTC you could also just write a small dts-file and compile it:

Code: Select all

#include "bcm2708-rpi-b-plus.dts"

&i2c1 {
	status = "okay";
	pcf8563: [email protected] {
		compatible = "nxp,pcf8563";
		reg = <0x51>;
		status = "okay";
	};
};
You'll obviously have to pick the correct RTC part from i2c-rtc-overlay.dts (and change disable to okay).
And at least I found no way to use the i2c_arm alias, so you might need to change i2c0 to i2c1 depending on your device.

Edit: As PhilE noted below, i2c1 is the right i2c for a b+

Re: device tree overlays and U-Boot

Posted: Wed Jan 27, 2016 8:12 pm
by PhilE
The aliases are created by the firmware, which is too late in this case. Only early Model Bs used i2c0 for user I2C, so your example using the b-plus dts should definitely say &i2c1.

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 10:36 am
by samskiter
While u-boot doesn't directly support overlays - start.elf still does and you can have u-boot effectively 'pass through' the flattened device tree that start.elf creates. I've just managed to get this working (last night) I have a little detail here that you might find useful: viewtopic.php?f=29&t=137599 and perhaps a blog post on the way once I get all my ducks in a row.

This was also pretty useful: http://dius.com.au/2015/08/19/raspberry-pi-uboot/

I would appreciate if anyone could help me work out why start.elf was loading the FDT to somewhere other that 0x100 (in my case to: 0x17fed200)

Thanks,

Sam

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 10:45 am
by PhilE
The slot at 0x100 is limited to just under 16KB (0x3f00), and there have been situations where the fully resolved DTB exceeds that. I modified the loader to remove that limit by putting the DTB at the end of memory, in the same way that the initramfs followkernel option does. You can force a specific location using the device_tree_address config.txt setting.

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 11:07 am
by samskiter
Thanks for your reply PhilE - I've since been using device_tree_address to correct the location...

I'm still a bit confused though because a) my resolved device tree is reported as "size 2d35" which is under the 16KB limit and b) inspecting the memory at 0x17fed200 shows as completely empty - so my device tree seems to vanish...

edit: re: a) I just reread your post and realised you mean that the device tree is now ALWAYS placed at the end of memory, regardless of size.

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 11:24 am
by PhilE
The code to load the DTB high is not conditional on its size. Making it so is possible, but it would mean that some problems would only be detected when the DTB reaches the threshold, and I much prefer systems to fail consistently.

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 1:16 pm
by samskiter
Thanks again, inspecting 0x000, I see that the device tree should be loaded at 0x17fed200 but that appears to be empty. Seems that U-boot is being relocated pretty close to that (0x17F4B000) so potentially stomping over the device tree.

So that I can adjust U-boot, could you give me any more information about the rules used to locate the device tree? will it always be at 0x17fed200 or is it size dependent??

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 1:58 pm
by PhilE
The DTB start address is size dependent. The aim is to copy the DTB as high as possible. Once the kernel starts it will "unflatten" the DTB into allocated memory and then re-use the space.
1
ARM memory starts at 0 in the VPU physical address space. The GPU memory sits at the top. This is how it works:

Code: Select all

ARMMEM_END = MEM_SIZE - GPU_MEM

// Leave 64KB for GRUB
free_end = ALIGN_DOWN(ARMMEM_END - 0x10000, 0x1000)

// Leave space for initramfs, if there is one
free_end = ALIGN_DOWN(free_end - initramfs_size, 0x1000)

device_tree_address = ALIGN_DOWN(free_end - device_tree_size, 0x100)
Don't forget that the address of the DTB is passed in register r2 to the kernel/U-boot entry point, with r0 holding 0 and r1 being 3138 (the BCM2708 machine id).

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 8:47 pm
by swarren
Has this feature been tested on a system with 1GB RAM and a config.txt setting the VC memory size as small as possible (e.g. 32M) and no initrd?

The Linux kernel splits RAM into two sections; lowmem that is 1:1 mapped in kernel VA space and highmem that is not. The DT must reside in lowmem, since the early kernel boot code can only access lowmem, yet needs to access the DT. On a system with only 512M or less, everything is lowmem. In a 1GB system, a good chunk of RAM is highmem so can't contain the DT.

Re: device tree overlays and U-Boot

Posted: Thu Mar 03, 2016 9:55 pm
by PhilE
That would be true on a system with a 1/3 kernel/user split, but we use a 2/2 split so it's all low mem.

Re: device tree overlays and U-Boot

Posted: Fri Mar 11, 2016 9:09 pm
by TheDJVG
Has anyone found a way to view the u-boot output and kernel boot output over pins 14/15? I'm able to start u-boot without any problems but I can't see the kernel booting process over serial.

I've tried merging the device tree files (bcm2710-rpi-3-b.dts and pi3-disable-bt-overlay.dts) and started the kernel with "console=serial0 or serial1 or ttyAMA0 or ttyS0" but no luck. I might be doing something wrong but I don't know what.

Re: device tree overlays and U-Boot

Posted: Thu Apr 07, 2016 4:58 am
by swarren
PhilE wrote:That would be true on a system with a 1/3 kernel/user split, but we use a 2/2 split so it's all low mem.
That's presumably a configuration quirk specific to the Pi Foundation's kernel, and is not true for mainline Linux?

Sorry for the late reply; I guess I wasn't subscribed to this thread.

Re: device tree overlays and U-Boot

Posted: Mon Sep 12, 2016 8:46 pm
by Synoia
How would u-boot discover the length of the device tree?

Re: device tree overlays and U-Boot

Posted: Mon Sep 12, 2016 8:48 pm
by Synoia
TheDJVG wrote:Has anyone found a way to view the u-boot output and kernel boot output over pins 14/15? I'm able to start u-boot without any problems but I can't see the kernel booting process over serial.

I've tried merging the device tree files (bcm2710-rpi-3-b.dts and pi3-disable-bt-overlay.dts) and started the kernel with "console=serial0 or serial1 or ttyAMA0 or ttyS0" but no luck. I might be doing something wrong but I don't know what.
You need one of the USB to R Pi pin-to-serial devices. The PI pin voltage swing is too low for a serial port.

Re: device tree overlays and U-Boot

Posted: Mon Sep 12, 2016 8:49 pm
by Synoia
PhilE wrote:The DTB start address is size dependent. The aim is to copy the DTB as high as possible. Once the kernel starts it will "unflatten" the DTB into allocated memory and then re-use the space.
1
ARM memory starts at 0 in the VPU physical address space. The GPU memory sits at the top. This is how it works:

Code: Select all

ARMMEM_END = MEM_SIZE - GPU_MEM

// Leave 64KB for GRUB
free_end = ALIGN_DOWN(ARMMEM_END - 0x10000, 0x1000)

// Leave space for initramfs, if there is one
free_end = ALIGN_DOWN(free_end - initramfs_size, 0x1000)

device_tree_address = ALIGN_DOWN(free_end - device_tree_size, 0x100)
Don't forget that the address of the DTB is passed in register r2 to the kernel/U-boot entry point, with r0 holding 0 and r1 being 3138 (the BCM2708 machine id).

How would u-boot find the length of the DTB?

Re: device tree overlays and U-Boot

Posted: Mon Sep 12, 2016 8:53 pm
by PhilE
The Flattened Device Tree format, which is what is generated by dtc and stored in DTB files and overlays, starts with a header including the length:

Code: Select all

struct boot_param_header {
        u32     magic;                  /* magic word 0xd00dfeed */
        u32     totalsize;              /* total size of DT block */
        u32     off_dt_struct;          /* offset to structure */
        u32     off_dt_strings;         /* offset to strings */
        u32     off_mem_rsvmap;         /* offset to memory reserve map
                                           */
        u32     version;                /* format version */
        u32     last_comp_version;      /* last compatible version */

        /* version 2 fields below */
        u32     boot_cpuid_phys;        /* Which physical CPU id we're
                                           booting on */
        /* version 3 fields below */
        u32     size_dt_strings;        /* size of the strings block */

        /* version 17 fields below */
        u32	size_dt_struct;		/* size of the DT structure block */
};
i.e. you just need to check the magic, then read the second word to get the length.

Re: device tree overlays and U-Boot

Posted: Mon Sep 19, 2016 6:14 pm
by Synoia
PhilE wrote:The Flattened Device Tree format, which is what is generated by dtc and stored in DTB files and overlays, starts with a header including the length:

Code: Select all

struct boot_param_header {
        u32     magic;                  /* magic word 0xd00dfeed */
        u32     totalsize;              /* total size of DT block */
        u32     off_dt_struct;          /* offset to structure */
        u32     off_dt_strings;         /* offset to strings */
        u32     off_mem_rsvmap;         /* offset to memory reserve map
                                           */
        u32     version;                /* format version */
        u32     last_comp_version;      /* last compatible version */

        /* version 2 fields below */
        u32     boot_cpuid_phys;        /* Which physical CPU id we're
                                           booting on */
        /* version 3 fields below */
        u32     size_dt_strings;        /* size of the strings block */

        /* version 17 fields below */
        u32	size_dt_struct;		/* size of the DT structure block */
};
i.e. you just need to check the magic, then read the second word to get the length.
Can you post the definitions of the structures referenced in this header, or a github (or similar) repository?

Thx

Re: device tree overlays and U-Boot

Posted: Mon Sep 19, 2016 8:36 pm
by PhilE

Re: device tree overlays and U-Boot

Posted: Wed May 24, 2017 2:35 pm
by ahmedawad
Please can you summarize how to get U-boot to work correctly fine with RPI3, I mean by correctly is " Having the device tree in the config.txt read by U-boot" ?

For a noob like me, I did the following steps:

1- I downloaded the last Jessie image.
2- git clone -b v2017.05-rc1 git://git.denx.de/u-boot.git
3- cd u-boot , make rpi_3_32b_defconfig , make -j4
4- I get the u-boot.bin , then copy it to /boot
5- add kernel=u-boot.bin to config.txt
6- prepare boot.txt with the following:

Code: Select all

fatload mmc 0:1 ${kernel_addr_r} kernel7.img
fatload mmc 0:1 ${fdt_addr_r} bcm2710-rpi-3-b.dtb
setenv bootargs earlyprintk dwc_otg.lpm_enable=0 console=serial0,115200 root=/dev/mmcblk0p3 rootfstype=ext4 rootwait
bootz ${kernel_addr_r} - ${fdt_addr_r}
7- execute

Code: Select all

mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "rpi3 boot script" -d boot.txt boot.scr
8- cp boot.scr /boot
when reboot, the image and kernel starts, but none of the dtoverlay in my config.txt get read by the kernel, even the hdmi resolution is not set correctly.

Please help and thanks in advance.

Re: device tree overlays and U-Boot

Posted: Wed May 24, 2017 2:48 pm
by PhilE
The way I would expect it to work now is using a feature of the new stub files to store the DTB address where u-boot can read it; that feature was developed in a collaboration with swarren. Having said that, I've not used u-boot and we don't provide support for it.

Re: device tree overlays and U-Boot

Posted: Thu May 25, 2017 1:41 pm
by swarren
@ahmedawad,

U-Boot sets environment variable $fdt_addr to the address of the DTB provided by the firmware. If you want to pass that to the kernel, you need to (a) pass that value to bootz rather than the address of any DTB that U-Boot loaded, (b) not load a DTB from U-Boot. For example, your boot script might be (untested):

Code: Select all

fatload mmc 0:1 ${kernel_addr_r} kernel7.img
setenv bootargs earlyprintk dwc_otg.lpm_enable=0 console=serial0,115200 root=/dev/mmcblk0p3 rootfstype=ext4 rootwait
bootz ${kernel_addr_r} - ${fdt_addr}
Reference: http://git.denx.de/?p=u-boot.git;a=blob ... aster#l257

One other comment: With the boot script you described, U-Boot isn't really doing anything useful; it's just passing through the existing DTB and loading a kernel that the firmware could load directly itself. All this can be configured from config.txt more easily than via a U-Boot script (i.e. just editing the .txt file rather than having to run mkimage on an edited script file). It would be simplest not to use U-Boot in this case. Of course, perhaps you're just working on getting baseline U-Boot functionality working so you can later make use of its other features; if so, ignore this paragraph.

Re: device tree overlays and U-Boot

Posted: Fri May 26, 2017 7:39 am
by ahmedawad
swarren wrote:@ahmedawad,
For example, your boot script might be (untested):

Code: Select all

fatload mmc 0:1 ${kernel_addr_r} kernel7.img
setenv bootargs earlyprintk dwc_otg.lpm_enable=0 console=serial0,115200 root=/dev/mmcblk0p3 rootfstype=ext4 rootwait
bootz ${kernel_addr_r} - ${fdt_addr}
Reference: http://git.denx.de/?p=u-boot.git;a=blob ... aster#l257
Thanks @PhilE and @swarren for your replies. However, I tried your script and not to load bcm2710-rpi-3-b.dtb in boot.scr but when Uboot starts, still the dtoverlays are not detected. In /u-boot/include/configs/rpi.h --> the fdt_addr_r is set to 0x100. I am confused, could it be memory overlap?. I am trying to inspect U-boot just it would be useful as many applications can use it.

Many thanks in advance!

Re: device tree overlays and U-Boot

Posted: Fri May 26, 2017 8:00 am
by PhilE
Reading the link swarren sent, u-boot sets "fdt_addr" to the DT address passed to the kernel. "fdt_addr_r" is the old constant value of 0x100, which is where the kernel used to put its ATAGs or DTB. Unfortunately the gap from 0x100 to where the kernel starts is only 32KB, and the decompressor seems to use memory starting at 0x4000, leaving only 16KB for the DTB - not enough in many cases, so the RPi firmware switched to loading the DTB high above the kernel and the u-boot startup code now stores the value passed to the "kernel" in the variable "fdt_addr".

Does u-boot let you print output from your script? I would suggest displaying "fdt_addr" and "fdt_addr_r" to see if they are sensible.