本頁說明如何最佳化裝置樹狀結構重疊 (DTO) 實作。 說明瞭疊加根節點的限制,並詳細說明 在 DTBO 圖像中設定壓縮的疊加層。並提供範例 導入操作說明和程式碼
核心指令列
裝置樹狀結構的原始核心指令列 (DT) 位於
chosen/bootargs
個節點。系統啟動載入程式必須將這項資訊串連
與核心指令列其他來源有關的位置:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO 無法串連主要 DT 中的值,以及重疊 DT 的值,因此
您必須將主要 DT 的核心指令列
chosen/bootargs
和疊加層 DT 的核心指令列
chosen/bootargs_ext
。如此一來,系統啟動載入程式就能將這些
並將結果傳送至核心。
main.dts | Overlay.dts |
---|---|
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; }; |
/dts-v1/; /plugin/; &chosen { bootargs_ext = "..."; }; |
libufdt
最新資訊
libfdt
支援 DTO,建議您使用 libufdt
實作 DTO
(Android 開放原始碼計畫原始碼,網址為
platform/system/libufdt
)。
libufdt
會建構真實的樹狀結構 (整併裝置樹狀結構、
或 ufdt)。這樣一來,您就能改善
將兩個 .dtb
檔案從 O(N2) 合併到 O(N),其中 N 是
樹狀結構中的節點數量
效能測試
在 Google 的內部測試中,於 2405 使用 libufdt
.dtb
和 283 .dtbo
DT 節點會導致檔案大小:
編譯後 70,618 和 8,566 個位元組。與
DTO
從 FreeBSD (124 毫秒的執行階段) 移植的實作,libufdt
DTO 執行階段為 10 毫秒。
Pixel 裝置效能測試比較:libufdt
與
libfdt
。基本節點數量大致相同,但包含
其差異如下:
- 500 次重疊 (附加或覆寫) 作業的時間為 6 至 8 倍 差異
- 1000 次重疊 (附加或覆寫) 作業的時間可達 8 至 10 倍 差異
附加計數設為 X 的範例:
圖 1. 附加次數為 X。
將覆寫計數設為 X 的範例:
圖 2. 覆寫計數為 X。
libufdt
是使用某些 libfdt
API 和資料開發而成
成本中心的架構使用 libufdt
時,您必須加入
libfdt
(不過,在程式碼中,您可以使用 libfdt
執行 DTB 或 DTBO 的 API)。
Libufdt DTO API
libufdt
中的主要 API 至 DTO 如下:
struct fdt_header *ufdt_apply_overlay( struct fdt_header *main_fdt_header, size_t main_fdt_size, void *overlay_fdt, size_t overlay_size);
main_fdt_header
參數是主要 DT,
overlay_fdt
是包含
.dtbo
檔案。傳回值是新的緩衝區,其中包含
合併的 DT (如果發生錯誤,則為 null
)。已合併 DT 的格式
,可在啟動核心時傳遞至核心。
來自傳回值的新緩衝區是由 dto_malloc()
建立,
將 libufdt
移植至系統啟動載入程式時,應實作這種方式。
如需參考實作,請參閱
sysdeps/libufdt_sysdeps_*.c
。
根節點限制
你無法將新的節點或屬性重疊至主要 DT 的根節點 因為疊加層作業必須仰賴標籤由於主要 DT 必須定義 標籤,而覆蓋 DT 會指派要與標籤重疊的節點 無法為根節點加上標籤 (因此也無法疊加根節點) 節點)。
SoC 供應商必須定義主要 DT 的重疊功能。ODM/原始設備製造商 (OEM) 只能
以 SoC 供應商定義的標籤附加或覆寫節點。身為
您可以在odm
根節點,啟用重疊 DT 中的所有 ODM 節點以新增節點。
您也可以在基本 DT 中將所有 SoC 相關節點放入
根節點下的 soc
節點,如下所述:
main.dts | Overlay.dts |
---|---|
/dts-v1/; / { compatible = "corp,bar"; ... chosen: chosen { bootargs = "..."; }; /* nodes for all soc nodes */ soc { ... soc_device@0: soc_device@0 { compatible = "corp,bar"; ... }; ... }; odm: odm { /* reserved for overlay by odm */ }; }; |
/dts-v1/; /plugin/; / { }; &chosen { bootargs_ex = "..."; }; &odm { odm_device@0 { ... }; ... }; |
使用壓縮的疊加層
Android 9 開始支援使用壓縮疊加層 顯示在 DTBO 圖片中的樣子。 使用 DTBO 標頭 v1 時,標記欄位的四個最差部分 dt_table_entry 表示 DT 項目的壓縮格式。
struct dt_table_entry_v1 { 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 flags; /* For version 1 of dt_table_header, the 4 least significant bits of 'flags' are used to indicate the compression format of the DT entry as per the enum 'dt_compression_info' */ uint32_t custom[3]; /* optional, must be zero if unused */ };
目前支援 zlib
和 gzip
壓縮。
enum dt_compression_info { NO_COMPRESSION, ZLIB_COMPRESSION, GZIP_COMPRESSION };
Android 9 新增對壓縮測試的支援
是疊加在 VtsFirmwareDtboVerification
測試中
並驗證疊加應用程式的正確性。
DTO 實作範例
以下操作說明會引導您完成 DTO 實作範例
來呼叫 libufdt
(請見下方的程式碼範例)。
DTO 範例操作說明
- 包含程式庫。如要使用「
libufdt
」,請加入 適用於資料結構和 API 的libfdt
:#include <libfdt.h> #include <ufdt_overlay.h>
- 載入主要 DT 和重疊 DT。載入
.dtb
和.dtbo
從儲存空間轉換為記憶體 (具體步驟取決於您的設計)。到目前為止 您應該擁有.dtb
/.dtbo
的緩衝區和大小:main_size = my_load_main_dtb(main_buf, main_buf_size)
overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
- 疊加 DT:
- 使用
ufdt_install_blob()
取得主要 DT 的 FDT 標頭:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- 呼叫
ufdt_apply_overlay()
給 DTO,即可取得 FDT 中的合併 DT 格式:merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size);
- 使用
merged_fdt
來取得dtc_totalsize()
:merged_fdt_size = dtc_totalsize(merged_fdt);
- 傳遞合併的 DT 以啟動核心:
my_kernel_entry(0, machine_type, merged_fdt);
- 使用
DTO 程式碼範例
#include <libfdt.h> #include <ufdt_overlay.h> … { struct fdt_header *main_fdt_header; struct fdt_header *merged_fdt; /* load main dtb into memory and get the size */ main_size = my_load_main_dtb(main_buf, main_buf_size); /* load overlay dtb into memory and get the size */ overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size); /* overlay */ main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size; merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size, overlay_buf, overlay_size); merged_fdt_size = dtc_totalsize(merged_fdt); /* pass to kernel */ my_kernel_entry(0, machine_type, merged_fdt); }