U-Boot Flattened Device Tree
This article describes the features supported by U-Boot related to Flattened Device Tree (DTB).
Table of Contents
Task Dependencies (Pre-requisites)
- Boot Image
- Linux FIT Image
Output Files Produced
Task Description
Locate the device-tree
In order to be able to use the FDT commands in U-Boot, the first step is to configure the address where the DTB file is stored. As the common use case for Xilinx Linux Images is the usage of Flattened Image Trees, all the Linux images components (Kernel, Ramdisk and DTB) file are contained in a single file (i.e. image.ub for Petalinux images). So first load the Linux image in the memory and get the address where the DTB file is located using iminfo command. Code Block |
---|
|
ZynqMP> fatload mmc 0 0x1000000 image.ub
reading image.ub
24222740 bytes read in 3131 ms (7.4 MiB/s)
ZynqMP> iminfo 0x1000000
## Checking Image at 01000000 ...
FIT image found
FIT description: U-Boot fitImage for plnx_aarch64 kernel
....
Image 1 (fdt@0)
Description: Flattened Device Tree blob
Type: Flat Device Tree
Compression: uncompressed
Data Start: 0x01c6dbd0
Data Size: 41389 Bytes = 40.4 KiB
Architecture: AArch64
Hash algo: sha1
Hash value: 90651e85c42e7316fc710b9d7dc23f66fbf055d3
.... |
Once is placed in the memory inform to fdt the address of its location to be able to use all the comands associated with this feature. Code Block |
---|
|
ZynqMP> fdt addr 0x01c6dbd0
ZynqMP> fdt
fdt - flattened device tree utility commands
Usage:
fdt addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>
fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active
fdt resize [<extrasize>] - Resize fdt to size + padding to 4k addr + some optional <extrasize> if needed
fdt print <path> [<prop>] - Recursive print starting at <path>
fdt list <path> [<prop>] - Print one level starting at <path>
fdt get value <var> <path> <prop> - Get <property> and store in <var>
fdt get name <var> <path> <index> - Get name of node <index> and store in <var>
fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>
fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>
fdt set <path> <prop> [<val>] - Set <property> [to <val>]
fdt mknode <path> <node> - Create a new node after <path>
fdt rm <path> [<prop>] - Delete the node or <property>
fdt header - Display header info
fdt bootcpu <id> - Set boot cpuid
fdt memory <addr> <size> - Add/Update memory node
fdt rsvmem print - Show current mem reserves
fdt rsvmem add <addr> <size> - Add a mem reserve
fdt rsvmem delete <index> - Delete a mem reserves
fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree
<start>/<end> - initrd start/end addr
NOTE: Dereference aliases by omitting the leading '/', e.g. fdt print ethernet0. |
Get the device-tree
There are two ways to get the nodes within the device-tree, fdt list (one level) and fdt print (recursive). Both commands also provide the option to specify a certin path in order to get and specific node rather the entire device-tree node. Following some examples of the usage of the mentioned commands. Code Block |
---|
|
ZynqMP> fdt list /amba/usb0
usb0 {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
status = "okay";
compatible = "xlnx,zynqmp-dwc3";
reg = <0x00000000 0xff9d0000 0x00000000 0x00000100>;
clock-names = "bus_clk", "ref_clk";
#stream-id-cells = <0x00000001>;
iommus = <0x00000008 0x00000860>;
power-domains = <0x00000031>;
ranges;
nvmem-cells = <0x00000020>;
nvmem-cell-names = "soc_revision";
clocks = <0x00000003 0x00000020 0x00000003 0x00000022>;
pinctrl-names = "default";
pinctrl-0 = <0x00000032>;
dwc3@fe200000 {
};
};
ZynqMP> fdt print /amba/usb0
usb0 {
#address-cells = <0x00000002>;
#size-cells = <0x00000002>;
status = "okay";
compatible = "xlnx,zynqmp-dwc3";
reg = <0x00000000 0xff9d0000 0x00000000 0x00000100>;
clock-names = "bus_clk", "ref_clk";
#stream-id-cells = <0x00000001>;
iommus = <0x00000008 0x00000860>;
power-domains = <0x00000031>;
ranges;
nvmem-cells = <0x00000020>;
nvmem-cell-names = "soc_revision";
clocks = <0x00000003 0x00000020 0x00000003 0x00000022>;
pinctrl-names = "default";
pinctrl-0 = <0x00000032>;
dwc3@fe200000 {
compatible = "snps,dwc3";
status = "okay";
reg = <0x00000000 0xfe200000 0x00000000 0x00040000>;
interrupt-parent = <0x00000004>;
interrupts = <0x00000000 0x00000041 0x00000004 0x00000000 0x00000045 0x00000004>;
snps,quirk-frame-length-adjustment = <0x00000020>;
snps,refclk_fladj;
dr_mode = "host";
snps,usb3_lpm_capable;
phy-names = "usb3-phy";
phys = <0x00000033 0x00000004 0x00000000 0x00000002 0x018cba80>;
};
}; |
Relocate the device-tree
Xilinx Release Images are build as a Flattened Image Trees with verified boot enabled so the content of those images cannot be modified on runtime and be used for booting purposes. This statement also applies to the pre-build petalinux images or the default images generated by Petalinux. In order to be able to use the fdt features with the verified FIT images, the DTB is relocated (copied) into a different memory address so we can modify it and use for the booting process in a later stage.There are different ways to copy or relocate the device-tree but but in this case fdt move command is used. Code Block |
---|
|
ZynqMP> fdt move 0x01c6dbd0 0x07000000
ZynqMP> fdt addr 0x07000000 |
Modify the device-tree
Properites within the nodes can be modified through fdt set command. This command can be used for example to disable specific nodes within the device tree blob in order to isolate an issue.
Modify node properties
Code Block |
---|
|
ZynqMP> fdt print /amba/usb0 status
status = "okay"
ZynqMP> fdt set /amba/usb0 status "disabled"
ZynqMP> fdt print /amba/usb0 status
status = "disabled"
|
Remove node properties
Code Block |
---|
|
ZynqMP> fdt rm /amba/usb0/dwc3 snps,usb3_lpm_capable
ZynqMP> fdt print /amba/usb0/dwc3
dwc3@fe200000 {
compatible = "snps,dwc3";
status = "okay";
reg = <0x00000000 0xfe200000 0x00000000 0x00040000>;
interrupt-parent = <0x00000004>;
interrupts = <0x00000000 0x00000041 0x00000004 0x00000000 0x00000045 0x00000004>;
snps,quirk-frame-length-adjustment = <0x00000020>;
snps,refclk_fladj;
dr_mode = "host";
phy-names = "usb3-phy";
phys = <0x00000033 0x00000004 0x00000000 0x00000002 0x018cba80>;
}; |
Boot with modified device-tree
Once the device-tree is modified,
bootm sub-commands can be used to specify the device-tree location, rather than using the one contained in the FIT image.
Code Block |
---|
|
ZynqMP> bootm 0x1000000 0x1000000 0x7000000
## Loading kernel from FIT Image at 01000000 ...
Using 'conf@1' configuration
Trying 'kernel@0' kernel subimage
Description: Linux Kernel
Type: Kernel Image
Compression: uncompressed
Data Start: 0x010000d8
Data Size: 13031936 Bytes = 12.4 MiB
Architecture: AArch64
OS: Linux
Load Address: 0x00080000
Entry Point: 0x00080000
Hash algo: sha1
Hash value: ebcadc7d72382ab50509ffb36dc24e4ac6a0a87b
Verifying Hash Integrity ... sha1+ OK
## Loading ramdisk from FIT Image at 01000000 ...
Using 'conf@1' configuration
Trying 'ramdisk@0' ramdisk subimage
Description: ramdisk
Type: RAMDisk Image
Compression: uncompressed
Data Start: 0x01c77e34
Data Size: 11147755 Bytes = 10.6 MiB
Architecture: AArch64
OS: Linux
Load Address: unavailable
Entry Point: unavailable
Hash algo: sha1
Hash value: 7566bdc0eebfa6472df07b478040f22d02404f8a
Verifying Hash Integrity ... sha1+ OK
## Flattened Device Tree blob at 07000000
Booting using the fdt blob at 0x7000000
Loading Kernel Image ... OK
reserving fdt memory region: addr=7000000 size=a000
Loading Ramdisk to 0755e000, end 07fff9eb ... OK
Loading Device Tree to 0000000007551000, end 000000000755dfff ... OK
Starting kernel ...
|