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