דף זה דן באופטימיזציות שאתה יכול לבצע למימוש ה-DTO שלך, מתאר הגבלות נגד שכבת-על של צומת השורש, ומפרט כיצד להגדיר שכבות-על דחוסות בתמונת DTBO. הוא גם מספק הוראות יישום וקוד לדוגמה.
שורת הפקודה של ליבה
שורת הפקודה המקורית של הליבה בעץ המכשיר ממוקמת בצומת chosen/bootargs
. טוען האתחול חייב לשרשר מיקום זה עם מקורות אחרים של שורת הפקודה של הליבה:
/dts-v1/; / { chosen: chosen { bootargs = "..."; }; };
DTO אינו יכול לשרשר ערכים מה-DT הראשי ומ-Overlay 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 (מקור AOSP platform/system/libufdt
). libufdt
בונה מבנה עץ אמיתי (עץ מכשיר לא שטוח, או ufdt ) מעץ המכשירים השטוח (FDT), כך שהוא יכול לשפר את המיזוג של שני קובצי .dtb
מ-O(N 2 ) ל-O(N), כאשר N הוא מספר הצמתים בעץ.
בדיקת ביצועים
בבדיקה הפנימית של גוגל, שימוש libufdt
על 2405 .dtb
ו-283 .dtbo
DT צמתים מביא לגדלים של קבצים של 70,618 ו-8,566 בתים לאחר הידור. בהשוואה למימוש DTO שמועבר מ-FreeBSD (זמן ריצה של 124 אלפיות השנייה), זמן הריצה של libufdt
DTO הוא 10 אלפיות השנייה.
בדיקות ביצועים עבור מכשירי Pixel השוו בין libufdt
ו- libfdt
. השפעת מספר צמתי הבסיס דומה, אך כוללת את ההבדלים הבאים:
- ל-500 פעולות שכבת-על (הוספה או ביטול) יש הפרש זמן של פי 6 עד פי 8
- ל-1000 פעולות שכבת-על (הוספה או ביטול) יש הפרש זמן של פי 8 עד פי 10
דוגמה עם ספירת הוספות מוגדרת ל-X:
דוגמה עם ספירת עוקפת מוגדרת ל-X:
libufdt
פותח עם כמה ממשקי API ומבני נתונים libfdt
. בעת שימוש libufdt
, עליך לכלול ולקשר libfdt
(עם זאת, בקוד שלך תוכל להשתמש ב- libfdt
API כדי להפעיל DTB או DTBO).
libufdt DTO API
ה-API הראשי ל-DTO ב- libufdt
הוא כדלקמן:
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 הממוזג מעוצב ב-FDT, אותו תוכל להעביר לקרנל בעת הפעלת הקרנל.
המאגר החדש מערך ההחזרה נוצר על ידי dto_malloc()
, אותו עליך ליישם בעת העברת libufdt
ל-bootloader. ליישומי עזר, עיין ב- sysdeps/libufdt_sysdeps_*.c
.
הגבלות על צומת שורש
אינך יכול לכסות צומת או תכונה חדשים לצומת הבסיס של DT הראשי מכיוון שפעולות שכבת-על מסתמכות על תוויות. מכיוון שה-DT הראשי חייב להגדיר תווית וה-Overlay DT מקצה את הצמתים שיוצפו עם תוויות, לא ניתן לתת תווית לצומת השורש (ולכן לא ניתן לכסות את צומת השורש).
ספקי SoC חייבים להגדיר את יכולת שכבת העל של DT ראשי; ODM/OEMs יכולים רק לצרף או לעקוף צמתים עם תוויות שהוגדרו על ידי ספק ה-SoC. כדרך לעקיפת הבעיה, אתה יכול להגדיר צומת odm
מתחת לצומת השורש בבסיס DT, מה שמאפשר לכל צמתי ODM ב-Overlay DT להוסיף צמתים חדשים. לחלופין, אתה יכול לשים את כל הצמתים הקשורים ל-SoC בבסיס DT לתוך צומת 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 { ... }; ... }; |
שימוש בשכבות על דחוסות
אנדרואיד 9 מוסיפה תמיכה בשימוש בשכבות-על דחוסות בתמונת DTBO בעת שימוש בגרסה 1 של כותרת טבלת עץ המכשיר. בעת שימוש בכותרת 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' will be 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 };
אנדרואיד 9 מוסיפה תמיכה בבדיקת שכבות-על דחוסות למבחן VtsFirmwareDtboVerification
כדי לעזור לך לאמת את נכונות אפליקציית שכבת-העל.
יישום DTO לדוגמה
ההוראות הבאות מובילות אותך דרך יישום לדוגמה של DTO עם libufdt
(קוד לדוגמה למטה).
הוראות DTO לדוגמה
- כלול ספריות. כדי להשתמש
libufdt
, כלול אתlibfdt
עבור מבני נתונים וממשקי API:#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);
- שכבה על ה-DTs:
- השתמש
ufdt_install_blob()
כדי לקבל את הכותרת FDT עבור DT הראשי:main_fdt_header = ufdt_install_blob(main_buf, main_size); main_fdt_size = main_size;
- התקשר ל-
ufdt_apply_overlay()
ל-DTO כדי לקבל DT ממוזג בפורמט FDT: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); }