Google is committed to advancing racial equity for Black communities. See how.
Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Mengoptimalkan DTO

Halaman ini membahas pengoptimalan yang dapat Anda lakukan untuk implementasi DTO Anda, menjelaskan batasan terhadap overlay node root, dan detail cara mengkonfigurasi overlay terkompresi pada image DTBO. Ini juga memberikan contoh instruksi dan kode implementasi.

Baris perintah kernel

Baris perintah kernel asli di pohon perangkat terletak di simpul chosen/bootargs . Bootloader harus menggabungkan lokasi ini dengan sumber baris perintah kernel lainnya:

/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};

DTO tidak dapat menggabungkan nilai dari DT utama dan DT overlay, jadi Anda harus meletakkan baris perintah kernel dari DT utama di chosen/bootargs dan baris perintah kernel dari DT overlay di chosen/bootargs_ext . Bootloader kemudian dapat menggabungkan lokasi-lokasi ini dan meneruskan hasilnya ke kernel.

main.dts overlay.dts
/dts-v1/;

/ {
  chosen: chosen {
    bootargs = "...";
  };
};
/dts-v1/;
/plugin/;

&chosen {
  bootargs_ext = "...";
};

libufdt

Meskipun libfdt terbaru mendukung DTO, direkomendasikan untuk menggunakan libufdt untuk mengimplementasikan DTO (sumber AOSP di platform/system/libufdt ). libufdt membangun struktur pohon nyata (pohon perangkat yang tidak diratakan, atau ufdt ) dari pohon perangkat yang diratakan (FDT), sehingga dapat meningkatkan penggabungan dua file .dtb dari O (N 2 ) ke O (N), di mana N adalah jumlah node di pohon.

Pengujian kinerja

Dalam pengujian internal Google, menggunakan libufdt pada 2405 .dtb dan 283 .dtbo DT node menghasilkan ukuran file 70.618 dan 8.566 byte setelah kompilasi. Dibandingkan dengan implementasi DTO yang di- porting dari FreeBSD (124 ms runtime), runtime DTO libufdt adalah 10 ms.

Pengujian kinerja untuk perangkat Pixel membandingkan libufdt dan libfdt . Efek jumlah node dasar serupa, tetapi mencakup perbedaan berikut:

  • 500 operasi overlay (tambahkan atau timpa) memiliki perbedaan waktu 6x hingga 8x
  • 1000 operasi overlay (tambahkan atau timpa) memiliki perbedaan waktu 8x hingga 10x

Contoh dengan menambahkan set hitungan ke X:

Gambar 1. Jumlah yang ditambahkan adalah X

Contoh dengan override count diatur ke X:

Gambar 2. Hitungan utama adalah X

libufdt dikembangkan dengan beberapa API libfdt dan struktur data. Saat menggunakan libufdt , Anda harus menyertakan dan menautkan libfdt (namun, dalam kode Anda, Anda dapat menggunakan API libfdt untuk mengoperasikan DTB atau DTBO).

libufdt DTO API

API utama ke DTO di libufdt adalah sebagai berikut:

struct fdt_header *ufdt_apply_overlay(
        struct fdt_header *main_fdt_header,
        size_t main_fdt_size,
        void *overlay_fdt,
        size_t overlay_size);

Parameter main_fdt_header adalah DT utama dan overlay_fdt adalah buffer yang berisi konten file .dtbo . Nilai yang dikembalikan adalah buffer baru yang berisi DT gabungan (atau null jika terjadi error). DT gabungan diformat dalam FDT, yang dapat Anda berikan ke kernel saat memulai kernel.

Buffer baru dari nilai kembalian dibuat oleh dto_malloc() , yang harus Anda implementasikan saat mem-port libufdt ke bootloader. Untuk implementasi referensi, lihat sysdeps/libufdt_sysdeps_*.c

Pembatasan node root

Anda tidak dapat melapisi node atau properti baru ke dalam node root DT utama karena operasi overlay bergantung pada label. Karena DT utama harus menentukan label dan DT overlay menetapkan node untuk dilapisi dengan label, Anda tidak dapat memberikan label untuk node root (dan karena itu tidak dapat melapisi node root).

Vendor SoC harus menentukan kemampuan overlay dari DT utama; ODM / OEM hanya dapat menambahkan atau mengganti node dengan label yang ditentukan oleh vendor SoC. Sebagai solusinya, Anda dapat menentukan node odm bawah node root di DT dasar, memungkinkan semua node ODM di DT overlay untuk menambahkan node baru. Alternatifnya, Anda bisa meletakkan semua node yang berhubungan dengan SoC di DT dasar menjadi node soc bawah node root seperti yang dijelaskan di bawah ini:

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 {
        ...
    };
    ...
};

Menggunakan hamparan terkompresi

Android 9 menambahkan dukungan untuk menggunakan overlay terkompresi dalam gambar DTBO saat menggunakan versi 1 dari header tabel pohon perangkat. Saat menggunakan DTBO header v1, empat bit paling signifikan dari bidang bendera di dt_table_entry menunjukkan format kompresi entri 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 */
};

Saat ini, kompresi zlib dan gzip didukung.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9 menambahkan dukungan untuk menguji hamparan terkompresi ke uji VtsFirmwareDtboVerification untuk membantu Anda memverifikasi kebenaran aplikasi hamparan.

Contoh implementasi DTO

Petunjuk berikut memandu Anda melalui contoh implementasi DTO dengan libufdt (contoh kode di bawah).

Contoh instruksi DTO

  1. Sertakan perpustakaan. Untuk menggunakan libufdt , sertakan libfdt untuk struktur data dan API:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
    
  2. Muat DT utama dan DT overlay. Muat .dtb dan .dtbo dari penyimpanan ke dalam memori (langkah persisnya bergantung pada desain Anda). Pada titik ini, Anda harus memiliki buffer dan ukuran .dtb / .dtbo :
    main_size = my_load_main_dtb(main_buf, main_buf_size)
    
    overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
    
  3. Overlay DT:
    1. Gunakan ufdt_install_blob() untuk mendapatkan header FDT untuk DT utama:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
      
    2. Panggil ufdt_apply_overlay() ke DTO untuk mendapatkan DT gabungan dalam format FDT:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. Gunakan merged_fdt untuk mendapatkan ukuran dtc_totalsize() :
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. Lulus DT gabungan untuk memulai kernel:
      my_kernel_entry(0, machine_type, merged_fdt);
      

Contoh kode 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);
}