Uyuşturucu ticareti örgütlerini optimize edin

Bu sayfada, cihaz ağacı yerleşimi (DTO) uygulamanızda yapabileceğiniz optimizasyonlar, kök düğümün yerleştirilmesine yönelik kısıtlamalar ve DTBO görüntüsünde sıkıştırılmış yerleşimlerin nasıl yapılandırılacağı açıklanmaktadır. Ayrıca örnek uygulama talimatları ve kodu da sağlar.

Çekirdek komut satırı

Cihaz ağacındaki (DT) orijinal çekirdek komut satırı chosen/bootargs düğümünde bulunur. Önyükleyici, bu konumu çekirdek komut satırının diğer kaynaklarıyla birleştirmelidir:

/dts-v1/;

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

DTO, ana DT ve yer paylaşımı DT'sindeki değerleri birleştiremez. Bu nedenle, ana DT'nin çekirdek komut satırını chosen/bootargs, yer paylaşımı DT'sinin çekirdek komut satırını ise chosen/bootargs_ext içine yerleştirmeniz gerekir. Önyükleyici daha sonra bu konumları birleştirip sonucu çekirdeğe iletebilir.

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

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

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

libufdt

En son libfdt, DTO'yu desteklese de DTO'yu uygulamak için libufdt kullanılması önerilir (AOSP kaynağı: platform/system/libufdt). libufdt, düzleştirilmiş cihaz ağacından (FDT) gerçek bir ağaç yapısı (düzleştirilmemiş cihaz ağacı veya ufdt) oluşturur. Bu nedenle, ağaçtaki düğüm sayısı N olmak üzere iki .dtb dosyasının birleştirilmesini O(N2) yerine O(N) olacak şekilde iyileştirebilir.

Performans testi

Google'ın dahili testinde, 2405 libufdt .dtb ve 283 .dtbo DT düğümünde libufdt kullanıldığında derleme sonrası dosya boyutları 70.618 ve 8.566 bayt olur. FreeBSD'den taşınan bir DTO uygulaması (124 ms çalışma zamanı) ile karşılaştırıldığında, libufdt DTO çalışma zamanı 10 ms'dir.

Pixel cihazlarda libufdt ve libfdt ile karşılaştırılan performans testi. Temel düğüm sayısı etkisi benzerdir ancak aşağıdaki farklılıkları içerir:

  • 500 yerleştirme (ekleme veya geçersiz kılma) işleminde 6-8 kat zaman farkı vardır.
  • 1.000 yerleştirme (ekleme veya geçersiz kılma) işlemi, 8 ila 10 kat zaman farkına sahiptir.

Ekleme sayısı X olarak ayarlanmış örnek:

1. şekil. Ekleme sayısı X.

Geçersiz kılma sayısı X olarak ayarlanmış örnek:

Şekil 2. Geçersiz kılma sayısı X.

libufdt, bazı libfdt API'leri ve veri yapılarıyla geliştirilmiştir. libufdt kullanırken libfdt eklemeniz ve bağlamanız gerekir (ancak kodunuzda DTB veya DTBO'yu çalıştırmak için libfdt API'sini kullanabilirsiniz).

libufdt DTO API

libufdt'daki ana API'den DTO'ya şöyledir:

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 parametresi ana DT'dir ve overlay_fdt, .dtbo dosyasının içeriğini içeren arabellektir. Döndürülen değer, birleştirilmiş DT'yi (veya hata durumunda null) içeren yeni bir arabellektir. Birleştirilmiş DT, FDT biçimindedir. Bu biçimi, çekirdeği başlatırken çekirdeğe iletebilirsiniz.

Dönüş değerinden elde edilen yeni arabellek, dto_malloc() tarafından oluşturulur. libufdt öğesini önyükleyiciye aktarırken bu arabelleği uygulamanız gerekir. Referans uygulamalar için sysdeps/libufdt_sysdeps_*.c başlıklı makaleyi inceleyin.

Kök düğüm kısıtlamaları

Yer paylaşımı işlemleri etiketlere dayandığından, ana DT'nin kök düğümüne yeni bir düğüm veya mülk yer paylaşımı yapamazsınız. Ana DT'nin bir etiket tanımlaması ve yer paylaşımı DT'sinin, yer paylaşımı yapılacak düğümleri etiketlerle ataması gerektiğinden kök düğüme etiket veremezsiniz (bu nedenle kök düğüme yer paylaşımı yapamazsınız).

SoC tedarikçileri, ana DT'nin yerleştirme özelliğini tanımlamalıdır. ODM/OEM'ler yalnızca SoC tedarikçisi tarafından tanımlanan etiketlere sahip düğümleri ekleyebilir veya bu düğümleri geçersiz kılabilir. Geçici çözüm olarak, temel DT'deki kök düğümün altında bir odm düğümü tanımlayabilirsiniz. Bu sayede, yer paylaşımı DT'sindeki tüm ODM düğümleri yeni düğümler ekleyebilir. Alternatif olarak, SoC ile ilgili tüm düğümleri temel DT'deki kök düğümün altına aşağıdaki gibi bir soc düğümü olarak da yerleştirebilirsiniz:

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

Sıkıştırılmış yer paylaşımlarını kullanma

Android 9, DT tablosu başlığının 1. sürümü kullanılırken DTBO görüntüsünde sıkıştırılmış yerleşimlerin kullanılmasına destek ekler. DTBO başlığı v1 kullanılırken dt_table_entry içindeki flags alanının en az önemli dört biti, DT girişinin sıkıştırma biçimini gösterir.

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 */
};

Şu anda zlib ve gzip sıkıştırmaları desteklenmektedir.

enum dt_compression_info {
    NO_COMPRESSION,
    ZLIB_COMPRESSION,
    GZIP_COMPRESSION
};

Android 9, VtsFirmwareDtboVerification testine sıkıştırılmış yer paylaşımlarını test etme desteği ekleyerek yer paylaşımı uygulamasının doğruluğunu doğrulamanıza yardımcı olur.

Örnek DTO uygulaması

Aşağıdaki talimatlarda, libufdt ile DTO'nun örnek bir uygulaması adım adım açıklanmaktadır (örnek kod aşağıda verilmiştir).

Örnek DTO talimatları

  1. Kitaplıkları dahil edin. libufdt kullanmak için veri yapıları ve API'ler için libfdt ekleyin:
    #include <libfdt.h>
    #include <ufdt_overlay.h>
  2. Ana DT'yi ve yer paylaşımı DT'yi yükleyin. Depolama alanından belleğe .dtb ve .dtbo yükleyin (uygulanacak adımlar tasarımınıza bağlıdır). Bu noktada, .dtb/.dtbo arabelleği ve boyutu olmalıdır:
    main_size = my_load_main_dtb(main_buf, main_buf_size)
    overlay_size = my_load_overlay_dtb(overlay_buf, overlay_buf_size);
  3. DT'leri yerleştirin:
    1. Ana DT için FDT üstbilgisini almak üzere ufdt_install_blob() kullanın:
      main_fdt_header = ufdt_install_blob(main_buf, main_size);
      main_fdt_size = main_size;
    2. FDT biçiminde birleştirilmiş DT almak için DTO'yu ufdt_apply_overlay() numaralı telefondan arayın:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
    3. merged_fdt kullanarak dtc_totalsize() boyutunu alın:
      merged_fdt_size = dtc_totalsize(merged_fdt);
    4. Birleştirilmiş DT'yi çekirdeği başlatmak için iletin:
      my_kernel_entry(0, machine_type, merged_fdt);

Örnek DTO kodu

#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);
}