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)

  • None

Tools Required

  • None

Input Files Required

  • Boot Image
  • Linux FIT Image

Output Files Produced

  • None

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.
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.
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.
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.
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

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

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.
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 ...
 

Related Links

© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy