DTBO功能介绍

1. DTB overlay介绍

1.1 DTB overlay作用介绍

DTB overlay是一种对设备树做叠加的功能,由libfdt中的fdt_overlay.c提供支持(https://github.com/dgibson/dtc),其核心功能函数:

// <U-boot>/scripts/dtc/libfdt/fdt_overlay.c
int fdt_overlay_apply(void *fdt, void *fdto)

目前dtb overlay功能在各个厂家基本都是用于对U-boot或者Kernel的设备树做叠加修改。

例如对于SigmaStar的pioneer5 SOC平台,有SSC028A-S01A-S、SSZ028A-S01A-M、SSC028B-S01A-S等多种开发板,在配置设备树过程中,可以:

  1. 将SOC相关的设备树配置集合在主设备树,编译出pioneer5.dtb
  2. 将不同开发板存在差异的的设备树配置集合到dtbo中编译出SSC028A-S01A-S.dtbo、SSZ028A-S01A-M.dtbo、SSC028B-S01A-S.dtbo
  3. 将这些dtbo按一定格式打包生成dtbo.img

在实际启动U-boot或者Kernel中,所有开发板都使用含SOC公共配置的设备树pioneer5.dtb,对于SSC028B-S01A-S会将dtbo.img中的SSC028B-S01A-S.dtbo取出执行:

fdt_overlay_apply(pioneer5.dtb, SSC028B-S01A-S.dtbo);

以得到支持开发板SSC028B-S01A-S的设备树。

1.2 dtbo的语法及编译介绍

FDT的相关语法请参考:https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.3

首先本质上dtbo其实也是一个dtb文件,都是通过dtc(device tree compiler)工具编译出来的,它们甚至使用的dtc编译命令都是一样的。

常见的dtc工具用法:

./dtc -@ -I <input format> -O <output format> -o <output file name>  <input file>

例如编译一个dtb:

./dtc -@ -I dts -O dtb -o pionner5.dtb pionner5.dts

编译一个dtbo

./dtc -@ -I dts -O dtb -o SSC028A-S01A-S.dtbo SSC028A-S01A-S.dts

可见在编译dtb和dtbo时的“input format”均是dts,”output format“均是dtb。

dtbo和dtb的主要差异在其dts的写法上,dtbo的dts需要添加/plugin/;以表示该文件在编译时允许对不存在的解决做未定义引用:

/dts-v1/;
/plugin/;

形如:

// my_main_dt.dts

/dts-v1/;

/ {
    my_node: node@0 {
        status = "disabled";

        my_child: child@0 {
            value = <0xffffffff>;
        };
    };
};
// my_overlay_dt.dts

/dts-v1/;
/plugin/;

&my_node {
    status = "okay";
};

&my_child {
    value = <0x1>;
};

DTB overlay是以node为单位的,并且需要被overlay的node需要在其node name前添加<label name>:,例如本例中的my_node。在dtbo中则是通过&<lable name>来引用要被overlay的节点,再去覆盖、新增property或者新增子节点。

其原理是:当调用dtc编译dtb时,如果额外地传入了"-@"参数,dtc会在最终的dtb中生成__symbols__节点,该节点中会收集所有带label的节点的在设备树中位置信息,格式<label name> = "<node path>";,形如:

__symbols__ {
    sound = "/soc/sound";
    bach1 = "/soc/bach1";
    bach2 = "/soc/bach2";
};

dtc也可以用来反编译,将dtb或者dtbo反编译为dts,形如:

./dtc -@ -I dtb -O dts -o pionner5.dts pionner5.dtb

1.3 DTB Overlay支持的行为

1.3.1 Overriding(覆盖)

// my_main_dt.dts

/dts-v1/;

/ {
    compatible = "corp,foo";

    my_node: node@0 {
        status = "disabled";
    };
};
// my_overlay_dt.dts

/dts-v1/;
/plugin/;

&my_node {
    status = "okay";
};

Merge Result:

/dts-v1/;

/ {
    compatible = "corp,foo";
      ......

      node@0 {
        linux,phandle = <0x1>;
        phandle = <0x1>;
        status = "okay";
      };
};

1.3.2 Appending(追加)

// my_main_dt.dts

/dts-v1/;

/ {
    compatible = "corp,foo";

    my_node: node@0 {
        status = "okay";
    };
};
// my_overlay_dt.dts

/dts-v1/;
/plugin/;

&my_node {
    new_prop = "bar";
};

Merge Result:

/dts-v1/;

/ {
    compatible = "corp,foo";

    ......

      node@0 {
        linux,phandle = <0x1>;
        phandle = <0x1>;
        status = "okay";
        new_prop = "bar";
      };
};

1.3.3 Child nodes(子节点的新增、追加、覆盖)

// my_main_dt.dts

/dts-v1/;

/ {
    compatible = "corp,foo";

    my_nodes: nodes {
        compatible = "corp,bar";

        node@0 {
              status = "disabled";
        };
      };
};
// my_overlay_dt.dts

/dts-v1/;
/plugin/;

&my_nodes {
     new_prop1 = "abc";

      node@0 {
        status = "okay";
        new_prop2 = "xyz";
      };
};

Merge Result:

/dts-v1/;

/ {
      compatible = "corp,foo";

      ......

      nodes {
        linux,phandle = <0x1>;
        phandle = <0x1>;
        compatible = "corp,bar";
        new_prop1 = "abc";

        node@0 {
              linux,phandle = <0x2>;
              phandle = <0x2>;
              status = "okay";
              new_prop2 = "xyz";
        };
      };
};

2. SigmaStar平台DTB overlay实现

2.1 DTB overlay相关的Kconfig

U-boot:

SigmaStar平台的DTB overlay都是在U-boot中完成的,所其开关以及相关的配置都是在U-boot的Kconfig中配置:

#arch/arm/mach-sstar/Kconfig

config SSTAR_BOOT_DEV
    string "boot device"
    default "mmc"
    help
      specify boot device type

config SSTAR_BOOT_DEV_ID
    int "boot device id"
    default 0
    help
      specify boot device id

config SSTAR_ENV_PART_NAME
    string "env patition name"
    default "env"
    help
      secify the real 'env' partition name in partition table

config SSTAR_DTBO_PART_NAME
    string "dtbo patition name"
    default "dtbo"
    help
      secify the real 'dtbo' partition name in partition table

config SSTAR_UBOOT_DTB_OVERLAY
    bool "Uboot DTB overlay"
    select SSTAR_DTB_OVERLAY_SUPPORT
    default n
    help
      Select this config to enable uboot dtb overlay feature, this feature
      will load fdt table from 'dtbo' partition. all dtbo specify in env
      'uboot_dtbo_list' will be overlay to uboot dtb. If your driver cares
      about the result of dtb overlay, please try to get property from
      the device node after 'board_init'.

config SSTAR_KERNEL_DTB_OVERLAY
    bool "Kernel DTB overlay"
    select SSTAR_DTB_OVERLAY_SUPPORT
    default n
    help
      Select this config to enable kernel dtb overlay feature, this feature
      will load fdt table from 'dtbo' partition. all dtbo specify in env
      'kernel_dtbo_list' will be overlay to kernel dtb.

config SSTAR_DTB_OVERLAY_SUPPORT
    bool
    select OF_LIBFDT_OVERLAY
    select CMD_ADTIMG
    default n

config SSTAR_BUILTIN_KERNEL_DTB
    bool "Built-in dtb support"
    default y
    help
      When Kernel use SigmaStar built-in dtb, uboot should pass
      atags instead fdt to kernel from x0.

每个Kconfig的作用请参考其help信息,其中CONFIG_SSTAR_BUILTIN_KERNEL_DTB这一项的作用是将对builtin DTB的支持关闭。

Kernel

Kernel涉及的Kconfig并不多,最主要的是将builtin DTB的功能关闭,使Kernel接收并使用由U-boot传递过来的设备树。

config SSTAR_BUILTIN_DTB
    bool "SigmaStar built-in DTB"
    default y

2.2 U-boot DTB overlay流程

U-boot中的 CONFIG_SSTAR_UBOOT_DTB_OVERLAY 用于使能U-boot DTB overlay功能,其在启动过程中的大致被调用的位置如下图:

如上图,SigmaStar平台的U-boot DTB overlay并非在前级loader做好dtb overlay再将merged dtb传给U-boot。而是在U-boot init早期,storage设备准备好之后(dm_init后)根据U-boot env "uboot_dtbo_list" 的设定立即执行U-boot DTB overlay,因为U-boot的dtb在overlay之后会发生变化,所以在U-boot DTB overlay之后会再做一次dm_init。

详细代码流程参考:

arch/arm/mach-sstar/board_common.c #board_uboot_dtb_overlay

2.3 Kernel DTB overlay流程

U-boot中的 CONFIG_SSTAR_KERNEL_DTB_OVERLAY 用于使能Kernel DTB overlay功能,其在启动过程中的大致被调用的位置如下图:

如上图,SigmaStar的Linux和Android平台在启动Kernel时,虽然入口不一样,但是在准备好Kernel、DTB、Rootfs之后,都会通过booti/bootm命令启动Kernel,最终都是走一下流程启动Kernel:

arch/arm/lib/bootm.c #do_bootm_linux
arch/arm/lib/bootm.c #boot_prep_linux
    -> arch/arm/mach-sstar/board_common.c #sstar_prep_linux
        -> arch/arm/mach-sstar/board_common.c #board_kernel_dtb_overlay
arch/arm/lib/bootm.c #boot_jump_linux

可以看到,在跳Kernel之前(boot_jump_linux),会在board_kernel_dtb_overlay中会根据U-boot env "kernel_dtbo_list" 的设定对即将传递给kernel的dtb做dtb overylay动作,详细流程请参考:

arch/arm/mach-sstar/board_common.c #board_kernel_dtb_overlay

2.4 uboot_dtbo_list和kernel_dtbo_list

前文有提到,这两个uboot的env是U-boot DTB Overlay和Kernel DTB overlay流程中用于列出有哪几个dtbo要从dtbo.img中取出来做Overlay。这里涉及到libfdt做DTB overlay过程中的一个特性:dtbo源文件中可以指定根节点"/"的"compatible"属性,但是实际做DTB overlay过程中,dtbo中的该属性不会覆盖掉主设备树的根节点"/"的"compatible"属性。

基于这个特性,我们可以根据每个dtbo的作用设定其根节点"/"的"compatible"属性,形如:

/ {
    compatible = "sstar_dtbo,ssz028a_s01a_m";
};

&padmux {
    schematic = <xxxxx>;
}

从dtbo.img找dtbo时通过该property进行查找就不需要担心诸如通过index取dtbo自己的dtbo放在dtbo.img中某个index,某一天index突然变化取出错误dtbo的问题。所以这两个env的写法形如:

sstar_dtbo,ssz028a_s01a_m;sstar_dtbo,panel-RM68200;...

2.5 dtbo.img介绍

在第1.1章中有提到SigmaStar平台会有一个dtbo.img用于包含支持各种规格板子的dtbo.img。通过1.2章的介绍已经了解到dtc编译出来的.dtb(.dtbo)文件其实就是单独的一个dtb文件,为了能够包含多个dtb文件到一个dtbo.img中,我们选择使用Android的mkdtimg工具来制作dtimg。dtimg的格式大致如下:

核心信息就在于位于镜像头的dt_table_header以及dt_table_entry,dt_table_header用于描述该镜像的基本信息,以及该镜像包含的dt_table_entry相关信息,dt_table_entry则是描述了每个包含在该镜像中的dtb的位置信息以及一些标记信息:

#define DT_TABLE_MAGIC 0xd7b7ab1e

struct dt_table_header {
  uint32_t magic;             // DT_TABLE_MAGIC
  uint32_t total_size;        // includes dt_table_header + all dt_table_entry
                              // and all dtb/dtbo
  uint32_t header_size;       // sizeof(dt_table_header)

  uint32_t dt_entry_size;     // sizeof(dt_table_entry)
  uint32_t dt_entry_count;    // number of dt_table_entry
  uint32_t dt_entries_offset; // offset to the first dt_table_entry
                              // from head of dt_table_header

  uint32_t page_size;         // flash page size we assume
  uint32_t version;       // DTBO image version, the current version is 0.
                          // The version will be incremented when the
                          // dt_table_header struct is updated.
};

struct dt_table_entry {
  uint32_t dt_size;
  uint32_t dt_offset;         // offset from head of dt_table_header

  uint32_t id;                // optional, must be zero if unused
  uint32_t rev;               // optional, must be zero if unused
  uint32_t custom[4];         // optional, must be zero if unused
};

制作dtbo.img的mkdtimg的用法如下:

mkdtimg create <image_filename> (<global-option>...) \
    <ftb1_filename> (<entry1_option>...) \
    <ftb2_filename> (<entry2_option>...) \
    ...

其中entryX_option的写法如下:

--id=<number|path>
--rev=<number|path>
--custom0=<number|path>
--custom1=<number|path>
--custom2=<number|path>
--custom3=<number|path>

2.6 dtbo以及dtbo.img制作

2.6.1 Linux

目前在我们SigmaStar的Kernel中已经将1.2章2.5章提到的dtbo、dtbo.img的制作整合成了一个kernel的build targe:dtbo_image,其定义位于Kernel根目录的Makefile。

# Makefile
ifeq ($(CONFIG_ARCH_SSTAR), y)
dtbo_image: FORCE
    @echo 'Generate sstar dtbo image'
    @PATH=$(PATH):/usr/bin $(srctree)/scripts/sstar/dtbo/sstar_mkdtboimage.py -c $(srctree)/dtbo/$(SSTAR_CHIP_NAME).json -o $(objtree)

PHONY += dtbo_image
endif

目前我们将dtbo的源文件以及不同的soc对应的配置文件放在了:

<kernel path>/dtbo

相关工具放在了:

<Kernel path>/scripts/sstar/dtbo/

不难发现,'make dtbo_image'时其实就是调用了一个python脚本,以make pioneer5相关的defconfig为例,其实就是执行命令:

./scripts/sstar/dtbo/sstar_mkdtboimage.py -c ./dtbo/pioneer5.json

以上命令就是调用sstar_mkdtboimage.py脚本根据配置文件./dtbo/pioneer5.json生成dtbo.img,

其中pionner5.json:

{
    "entries": {
        "dtbo_1": {
            "dts":"dtbo/pioneer5-ssz028a-s01a-m.dts"
        },
        "dtbo_2": {
            "dts":"dtbo/panel-SAT070AT50H18BH.dts"
        },
        "dtbo_3": {
            "dts":"dtbo/panel-BT601OUTPUT_720x480.dts"
        },
        "dtbo_4": {
            "dts":"dtbo/panel-BT656OUTPUT_800x480.dts"
        },
        "dtbo_5": {
            "dts":"dtbo/panel-RM68200.dts"
        },
        "dtbo_6": {
            "dts":"dtbo/panel-RM68200HDH.dts"
        },
        "dtbo_7": {
            "dts":"dtbo/panel-M270HVN02.dts"
        },
        "dtbo_8": {
            "dts":"dtbo/panel-DV150X0M.dts"
        }
    }
}

sstar_mkdtboimage.py脚本基本流程即遍历json中所有entries,调用dtc工具将dts指出的源文件编译成dtbo(这其中还涉及到dts中的一些C语言的宏展开,会涉及到使用dtx_diff工具,请自行参考sstar_mkdtboimage.py脚本实现),最后调用mkdtimg将所有的dtbo收集制作成dtbo.img。

注:sstar_mkdtboimage.py是可以单独执行的,当然直接make dtbo_image也不会有太多的额外的时间开销。

2.6.2 AOSP

AOSP中dtbo.img的生成最终也是通过在Kernel编译时执行"make sstar_dtboimg"生成的。可以看到,在引入dtbo后,在Kernel的build.config有如下改动:

diff --git a/build.config.pioneer5_android_gki b/build.config.pioneer5_android_gki
index 2a268b40de81..996c57e4e1b5 100644
--- a/build.config.pioneer5_android_gki
+++ b/build.config.pioneer5_android_gki
@@ -40,12 +40,14 @@ android/abi_gki_aarch64_xiaomi

 MAKE_GOALS="${MAKE_GOALS}
 Image.gz
+dtbo_image
 sstar/pioneer5-android.dtb
 sstar/pioneer5-android-nondynamic.dtb
 "

 FILES="${FILES}
 arch/arm64/boot/Image.gz
+dtbo.img
 arch/arm64/boot/dts/sstar/pioneer5-android.dtb
 arch/arm64/boot/dts/sstar/pioneer5-android-nondynamic.dtb
 "

和其他大部分AOSP镜像一样,dtbo.img也是预置在device目录中的,因为dtbo.img集合支持所有板级差异的dtbo,所以同一个soc平台的不同device公用一个即可。以pionner5为例,其位置:

<AOSP>/device/sigmastar/pioneer5/kernel/dtbo.img

由上面介绍可知:

sstar_make -k会一并生成dtbo.img到device目录,out目录下的dtbo.img需要sstar_make -a才能生成。

3 调试

3.1 一个帮助调试DTBO overlay的patch

因为libfdt中的fdt_overlay_apply_verbose原生代码不会打印太多信息,例如在label找不到overlay失败时只会打印一句"FDT_ERR_NOTFOUND"。不太利于调试,目前有根据实作时遇到的问题在原生代码添加了一些打印,pathc如下:

diff --git a/common/image-android-dt.c b/common/image-android-dt.c
index 12a6ea9c14..6f4857a832 100644
--- a/common/image-android-dt.c
+++ b/common/image-android-dt.c
@@ -388,7 +388,7 @@ int android_dt_overlay_apply_verbose(void *dtb_addr, char *dtbo_list, struct blk
         ret = fdt_overlay_apply_verbose(dtb_addr, dtbo_addr);
         if (ret < 0) {
             printf("Error: Apply dtbo with compatible(%s) fail\n", compatible);
-            free(dtbo_addr);
+            // free(dtbo_addr);
             goto out;
         }

@@ -397,7 +397,7 @@ int android_dt_overlay_apply_verbose(void *dtb_addr, char *dtbo_list, struct blk
 #endif
         // Next compatible
         compatible = strtok(NULL, delim);
-        free(dtbo_addr);
+        // free(dtbo_addr);
     }

     // Resize fdt to fixup size
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
index 7a65c35af6..0fc65b85e8 100644
--- a/scripts/dtc/libfdt/fdt_overlay.c
+++ b/scripts/dtc/libfdt/fdt_overlay.c
@@ -441,6 +441,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
         return len;
     }

+
     do {
         const char *path, *name, *fixup_end;
         const char *fixup_str = value;
@@ -483,10 +484,13 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
         ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
                         path, path_len, name, name_len,
                         poffset, label);
-        if (ret)
+        if (ret) {
+            printf("Error: overlay_fixup_phandle %s fail\n", label);
             return ret;
+        }
     } while (len > 0);

+    printf("Info: overlay_fixup_phandle %s success\n", label);
     return 0;
 }

@@ -560,6 +564,8 @@ static int overlay_apply_node(void *fdt, int target,
     int property;
     int subnode;

+    printf("Info: overlay_apply_node %s\n", fdt_get_name(fdt, target, NULL));
+
     fdt_for_each_property_offset(property, fdto, node) {
         const char *name;
         const void *prop;
@@ -636,6 +642,8 @@ static int overlay_merge(void *fdt, void *fdto)
         if (overlay < 0)
             return overlay;

+        printf("Info: overlay_merge overlay %s\n", fdt_get_name(fdto, fragment, NULL));
+
         target = overlay_get_target(fdt, fdto, fragment, NULL);
         if (target < 0)
             return target;
@@ -834,34 +842,48 @@ int fdt_overlay_apply(void *fdt, void *fdto)
     FDT_RO_PROBE(fdt);
     FDT_RO_PROBE(fdto);

+    printf("Info: fdt_overlay_apply %#x to %#x\n", fdto, fdt);
+
     ret = fdt_find_max_phandle(fdt, &delta);
-    if (ret)
+    if (ret) {
+        printf("Error: fdt_find_max_phandle fail\n");
         goto err;
+    }

     ret = overlay_adjust_local_phandles(fdto, delta);
-    if (ret)
+    if (ret) {
+        printf("Error: overlay_adjust_local_phandles fail\n");
         goto err;
+    }

     ret = overlay_update_local_references(fdto, delta);
-    if (ret)
+    if (ret) {
+        printf("Error: overlay_update_local_references fail\n");
         goto err;
+    }

     ret = overlay_fixup_phandles(fdt, fdto);
-    if (ret)
+    if (ret) {
+        printf("Error: overlay_fixup_phandles fail\n");
         goto err;
+    }

     ret = overlay_merge(fdt, fdto);
-    if (ret)
+    if (ret) {
+        printf("Error: overlay_merge fail\n");
         goto err;
+    }

     ret = overlay_symbol_update(fdt, fdto);
-    if (ret)
+    if (ret) {
+        printf("Error: overlay_symbol_update fail\n");
         goto err;
+    }

     /*
      * The overlay has been damaged, erase its magic.
      */
-    fdt_set_magic(fdto, ~0);
+    // fdt_set_magic(fdto, ~0);

     return 0;

该patch不仅会多输出一些调试信息,并且将free释放临时放置dtbo的操作注释掉了。这样就可以根据:

printf("Info: fdt_overlay_apply %#x to %#x\n", fdto, fdt);

的输出,结合uboot的"fdt"命令查看dtb以及dtbo的内容(当然,使用dtc反编译也是一样的,请参考1.2章)。

注:本章提供的diff修改没有完全覆盖到所有的情况下的log打印,仅作抛砖引玉,读者需要根据自己遇到的情况进行完善。

3.2 U-boot命令adt

adt命令可以直接执行不带任何参数获取帮助:

SigmaStar # adtimg
adtimg - manipulate dtb/dtbo Android image

Usage:
adtimg addr <addr> - Set image location to <addr>
adtimg dump        - Print out image contents
adtimg get dt --index=<index> [avar [svar]]         - Get DT address/size by index

Legend:
  - <addr>: DTB/DTBO image address (hex) in RAM
  - <index>: index (hex/dec) of desired DT in the image
  - <avar>: variable name to contain DT address (hex)
  - <svar>: variable name to contain DT size (hex)

根据帮助信息,可以执行如下操作:

SigmaStar # mmc read 0x21000000 0x0004602a 0x2000

MMC read: dev # 0, block # 286762, count 8192 ... 8192 blocks read: OK
SigmaStar # adt addr 0x21000000
SigmaStar # adt dump
dt_table_header:
               magic = d7b7ab1e
          total_size = 19853
         header_size = 32
       dt_entry_size = 32
      dt_entry_count = 10
   dt_entries_offset = 32
           page_size = 2048
             version = 0
dt_table_entry[0]:
             dt_size = 2707
           dt_offset = 352
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 2707
     (FDT)compatible = sstar_dtbo,ssz028a_s01a_m
dt_table_entry[1]:
             dt_size = 123
           dt_offset = 3059
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 123
     (FDT)compatible = sstar_dtbo,ssc028b_s01a_s
dt_table_entry[2]:
             dt_size = 3014
           dt_offset = 3182
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 3014
     (FDT)compatible = sstar_dtbo,ssz028b_s01a_s
dt_table_entry[3]:
             dt_size = 1467
           dt_offset = 6196
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 1467
     (FDT)compatible = sstar_dtbo,panel-SAT070AT50H18BH
dt_table_entry[4]:
             dt_size = 1480
           dt_offset = 7663
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 1480
     (FDT)compatible = sstar_dtbo,panel-BT601OUTPUT_720x480
.....
dt_table_entry[9]:
             dt_size = 1690
           dt_offset = 18163
                  id = 00000000
                 rev = 00000000
           custom[0] = 00000000
           custom[1] = 00000000
           custom[2] = 00000000
           custom[3] = 00000000
           (FDT)size = 1690
     (FDT)compatible = sstar_dtbo,panel-DV150X0M
SigmaStar #

3.3 U-boot命令fdt命令

fdt命令可以直接执行不带任何参数获取帮助:

fdt - flattened device tree utility commands

Usage:
fdt addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>
fdt apply <addr>                    - Apply overlay to the DT
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 [get <var> <member>]     - Display header info
                                      get - get header member <member> and store it in <var>
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.

结合前面adt命令,可以做如下操作查看dtbo.img中某个dtbo的内容:

SigmaStar # adtimg get dt --index=0
0x21000160, 0xa93 (2707)
SigmaStar # fdt list /
/ {
    compatible = "sstar_dtbo,ssz028a_s01a_m";
    __fixups__ {
    };
    fragment@0 {
    };
    fragment@1 {
    };
    fragment@2 {
    };
};

再例如需要看U-boot dtb时,可以通过U-boot环境变量fdtcontroladdr获取到U-boot dtb在内存中的位置后,使用fdt命令查看内容。