Uyuşturucu ticareti örgütlerini optimize edin

Bu sayfada, cihaz ağacı yer paylaşımı (DTO) uygulamanızda yapabileceğiniz optimizasyonlar ele alınmakta, kök düğümün yer paylaşımına yönelik kısıtlamalar açıklanmakta ve DTBO resminde sıkıştırılmış yer paylaşımlarının nasıl yapılandırılacağı ayrıntılı olarak açıklanmaktadır. Ayrıca örnek uygulama talimatları ve kod da sağlanır.

Çekirdek komut satırı

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

/dts-v1/;

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

DTO, ana DT ve yer paylaşımlı DT'deki değerleri birleştiremez. Bu nedenle, ana DT'nin çekirdek komut satırını chosen/bootargs, yer paylaşımlı DT'nin çekirdek komut satırını ise chosen/bootargs_ext içine koymanız gerekir. Ardından önyükleme programı 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 yeni libfdt, DTO'yu desteklese de DTO'yu (platform/system/libufdt adresindeki AOSP kaynağı) uygulamak için libufdt kullanılması önerilir. 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. Böylece, iki .dtb düğümünün N(N2) numarasından O(N) numaraya doğru bir şekilde birleştirilmesini iyileştirebilir.

Performans testi

Google'ın dahili testine göre, 2405 .dtb ve 283 .dtbo DT düğümlerinde libufdt kullanıldığında, derleme sonrasında dosya boyutları 70.618 ve 8.566 bayttır. FreeBSD'ten (124 ms çalışma süresi) ported bir DTO uygulamasına kıyasla libufdt DTO çalışma süresi 10 ms'dir.

libufdt ve libfdt ile karşılaştırıldığında Pixel cihazlar için performans testi. Temel düğüm sayısı etkisi benzer olsa da aşağıdaki farklılıkları içerir:

  • 500 yer paylaşımı (ekleme veya geçersiz kılma) işleminin süresi 6 ila 8 kat daha uzundur
  • 1.000 yer paylaşımı (ekleme veya geçersiz kılma) işleminin süresi 8 ila 10 kat daha uzundur

Ekleme sayısının X olarak ayarlandığı örnek:

Şekil 1. Ekleme sayısı X.

Geçersiz kılma sayısının X olarak ayarlandığı ö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'sı

libufdt bölgesinde DTO'ya gönderilen ana API aşağıdaki gibidir:

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ştirilen DT, FDT biçimindedir. Bu dosyayı, çekirdeği başlatırken çekirdeğe iletebilirsiniz.

Döndürülen değerdeki yeni arabellek, libufdt'u önyükleyiciye taşırken uygulamanız gereken dto_malloc() tarafından oluşturulur. 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 bağlı olduğundan 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ı gerektiğinden ve bindirme DT'si etiketlerle yerleştirilecek düğümleri atadığından kök düğüm için etiket veremezsiniz (dolayısıyla kök düğümün üzerine yerleştiremezsiniz).

SoC tedarikçileri, ana DT'nin yer paylaşımı özelliğini tanımlamalıdır. ODM/OEM'ler yalnızca SoC tedarikçisi tarafından tanımlanan etiketlere sahip düğümleri ekleyebilir veya geçersiz kılabilir. Geçici bir çö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, temel DT'deki SoC ile ilgili tüm düğümleri aşağıda açıklandığı gibi kök düğümün altındaki bir soc düğümüne de yerleştirebilirsiniz:

main.dts yer paylaşımlı.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ı kullanın

Android 9, DT tablo başlığının 1. sürümünü kullanırken DTBO resminde sıkıştırılmış yer paylaşımları kullanma desteği ekler. DTBO başlığı v1 kullanıldığında, dt_table_entry içindeki flags alanının en az anlamlı dört biti DT girişinin sıkıştırma biçimini belirtir.

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, yer paylaşımı uygulamasının doğruluğunu doğrulamanıza yardımcı olmak için VtsFirmwareDtboVerification testine sıkıştırılmış yer paylaşımlarını test etme desteği ekler.

Örnek DTO uygulaması

Aşağıdaki talimatlarda, libufdt ile DTO'nun örnek uygulamasında size yol gösterilmektedir (aşağıdaki örnek kod).

Örnek DTO talimatları

  1. Kitaplıkları dahil et. 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şımlı DT'yi yükleyin. .dtb ve .dtbo'ı depolama alanından belleğe yükleyin (uygulanacak adımlar tasarımınıza bağlıdır). Bu noktada, .dtb/.dtbo arabellek ve boyutuna sahip olmalısınız:
    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 yer paylaşımı olarak ekleme:
    1. Ana DT için FDT üst bilgisini 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ş bir DT almak için ufdt_apply_overlay()'ü DTO'ya çağırın:
      merged_fdt = ufdt_apply_overlay(main_fdt_header, main_fdt_size,
                                      overlay_buf, overlay_size);
      
    3. dtc_totalsize() boyutunu almak için merged_fdt kullanın:
      merged_fdt_size = dtc_totalsize(merged_fdt);
      
    4. Çekirdeği başlatmak için birleştirilmiş DT'yi 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);
}