Bir BSP Ne Zaman "Teslim Edilebilir" Sayılır?

"BSP hazır" cümlesi, gömülü projelerde en çok anlam kayması yaşayan cümledir. Geliştirici için genellikle "kart açılıyor, kamera görüntü veriyor, uygulama koşuyor" demektir. Üretim planlamacısı için "bu görüntüyü on bin karta basabilirim, ikinci parti de aynı davranır" demektir. Saha servisi için "bozulan cihazı geri getirebilirim" demektir. Hukuk ve satın alma için "bu kutunun içindeki üçüncü taraf kodun envanteri elimde" demektir. Dördü aynı anda doğru değilse BSP hazır değildir; yalnızca demo hazırdır.

Bu yazı, bir kart görüntüsünü demo halinden teslim edilebilir hale getiren kapıları tarif eder. Kapı (gate) burada gevşek bir kontrol listesi maddesi değil; iki şeyin birleşimi: cevabı yanlışlanabilir bir soru ve o cevabı üreten saklanabilir bir çıktı. "Lisanslara baktık" bir kapı değildir. "Şu görüntü için üretilmiş license.manifest dosyası şu dizinde duruyor, içinde şu paketler var ve kopyaları kutuyla birlikte gidiyor" bir kapıdır. Fark, ikincisinin altı ay sonra bir başkası tarafından tekrar sorgulanabilmesidir.

Kapıların Sırası Tesadüf Değil

Kapılar bağımsız değildir; her birinin çıktısı bir sonrakinin girdisidir. Tekrar üretilemeyen bir görüntü üzerinde yapılan lisans envanteri, envanteri çıkarılan görüntüyle sahaya gidenin aynı olduğunu kanıtlayamaz. Sıcaklık köşelerinde açılmayan bir görüntünün kurtarma yolunu test etmenin anlamı yoktur, çünkü kurtarma yolu da aynı görüntüyü açmaya çalışacaktır. Bu yüzden sıra şudur: önce görüntünün kimliği (kaynak, tekrar üretilebilirlik, envanter), sonra görüntünün içeriği (konfigürasyon), sonra fiziksel koşullar (sıcaklık, güç), en sonda bozulma senaryoları (kurtarma, saha teşhisi).

Ters sırada ilerleyen projelerde tanıdık bir sahne yaşanır: iklim kabininde üç hafta test edilen görüntü, teslimden önce "küçük bir düzeltme" ile yeniden derlenir ve elde kalan bütün test kayıtları artık başka bir ikili dosya kümesine aittir.

Kapı 1 — Kaynak: Görüntüdeki Her Bit'in Bir Adresi Var mı?

Sorunun kanıtı tek bir denemeyle alınır: ağ kapalıyken temiz bir dizinde derleme. Bütün kaynaklar önceden çekilmiş bir aynadan geliyorsa ve derleme BB_NO_NETWORK = "1" ile tamamlanıyorsa, görüntüdeki hiçbir bileşen "o gün GitHub'da ne varsa" değildir.

Pratikte üç şey gerekir. Birincisi, her SRCREV değerinin bir commit hash'ine sabitlenmesi; AUTOREV bir sürüm dalında bulunmamalıdır. İkincisi, bitbake --runall=fetch ile doldurulmuş ve BB_GENERATE_MIRROR_TARBALLS = "1" ile arşivlenmiş bir kaynak aynası. Üçüncüsü, katman revizyonlarının kendisinin sabitlenmesi — bitbake-layers show-layers çıktısı ile katman deposu commit'lerinin birlikte kaydı. Yocto katman mimarisi doğru kurulduğunda bu kayıt zaten tek bir manifest dosyasına düşer.

Kapının çıktısı: ağsız derlemenin logu, katman/commit manifesti ve kaynak aynasının kendisi.

Kapı 2 — Tekrar Üretilebilirlik: Aynı Girdi, Aynı Görüntü

Bu kapı, bütün doğrulama zincirinin taşıyıcısıdır. Tekrar üretilemeyen bir görüntüde, sahadaki bir hatayı yeniden canlandırmak için elinizde yalnızca ikili dosya kalır; kaynağa dönüş yolu yoktur.

Yocto Project tarafında altyapı hazırdır: BUILD_REPRODUCIBLE_BINARIES, SOURCE_DATE_EPOCH ve REPRODUCIBLE_TIMESTAMP_ROOTFS mekanizmaları zaman damgalarını sabitler, reproducible sınıfı derleme yolu ve host bilgisi sızıntılarını temizler. Doğru test şudur: aynı kaynaklardan, farklı bir derleme dizininde, farklı bir makinede ve farklı bir tarihte ikinci bir derleme alıp iki çıktıyı diffoscope ile karşılaştırmak. Yocto'nun kendi oe-selftest -r reproducible koşusu bu senaryoyu poky ağacı için otomatikleştirir; proje katmanları için aynı deseni tekrarlamak gerekir.

INHERIT += "buildhistory create-spdx archiver cve-check"

BUILDHISTORY_COMMIT = "1"
BB_GENERATE_MIRROR_TARBALLS = "1"

COPY_LIC_MANIFEST = "1"
COPY_LIC_DIRS = "1"
LICENSE_CREATE_PACKAGE = "1"
INCOMPATIBLE_LICENSE = "GPL-3.0* LGPL-3.0* AGPL-3.0*"

ARCHIVER_MODE[src] = "original"
ARCHIVER_MODE[diff] = "1"

buildhistory burada sessiz ama kritik bir rol oynar: iki sürüm arasında paket listesi, paket boyutları, bağımlılıklar ve dosya sahiplikleri düzeyinde farkı buildhistory-diff ile gösterir. Bir sürümde açıklanamayan bir paketin görüntüye girdiğini en erken burada görürsünüz. İkili düzeyde bir fark açıklanamıyorsa bitbake -S printdiff ve bitbake-diffsigs, hangi görevin imzasının değiştiğini doğrudan söyler.

Kapının çıktısı: iki bağımsız derlemenin karşılaştırma raporu ve buildhistory deposunun commit'i.

Kapı 3 — Lisans Envanteri ve SBOM

Bu kapı hukuki bir formalite gibi görünür; gerçekte bir mühendislik kapısıdır, çünkü envanter çıkarmak çoğu zaman görüntüde ne olduğunu ilk kez öğrenmek anlamına gelir.

Yocto, görüntü başına license.manifest üretir; COPY_LIC_MANIFEST ve COPY_LIC_DIRS ile lisans metinleri cihazın kendi dosya sistemine de kopyalanır. create-spdx sınıfı (sürüme göre create-spdx-2.2 veya create-spdx-3.0) makine tarafından okunabilir bir SBOM üretir; SPDX 2.2.1, ISO/IEC 5962:2021 numarasıyla uluslararası standart olarak yayımlanmıştır ve müşteri sözleşmelerinde giderek daha sık bu formatla isteniyor. Copyleft yükümlülüğü için archiver sınıfı, dağıtılan ikili dosyalara karşılık gelen kaynak arşivlerini derleme anında ayırır — teslimden sonra "hangi sürümün kaynağıydı" sorusunu aramaya kalmazsınız.

INCOMPATIBLE_LICENSE ise bir envanter aracı değil, bir kapıdır: kabul edilmeyen bir lisans görüntüye girdiği anda derleme durur. Karar ürün stratejisine aittir; kapının işi, kararın sessizce ihlal edilmesini imkânsız kılmaktır. Aynı derlemeye cve-check eklendiğinde, teslim tarihindeki bilinen zafiyet listesi de bir çıktı haline gelir; CVE_STATUS alanları hangi kaydın neden kapsam dışı bırakıldığını yazılı olarak taşır.

Kapı 4 — Konfigürasyon: Çekirdekte Ne Var, Neden Var?

Bir BSP'nin en kolay çürüyen parçası çekirdek konfigürasyonudur. menuconfig ile açılıp kapatılan seçenekler bir defconfig dosyasına kaydedilir, sonra kimse hangi satırın neden orada olduğunu hatırlamaz.

Yocto tarafında doğru desen, tek bir dev defconfig yerine gerekçeleri ayrı ayrı taşıyan konfigürasyon parçacıklarıdır (SRC_URI += "file://watchdog.cfg" gibi). bitbake -c kernel_configcheck -f virtual/kernel görevi, istediğiniz ama nihai .config dosyasına giremeyen seçenekleri raporlar — bağımlılığı olmayan bir CONFIG_ satırının sessizce düşmesi, bu kapı olmadığında ancak sahada fark edilir.

Aynı kapı üretim/geliştirme ayrımını da kilitler. Geliştirme görüntüsünde makul olan CONFIG_MAGIC_SYSRQ, CONFIG_DEVMEM, CONFIG_DEBUG_FS, açık bir seri konsol kabuğu ve debug-tweaks özelliği, üretim görüntüsünde bilinçli birer karardır; kapı bu kararların listesini ve gerekçesini ister. Aynı yerde durulacak diğer soru güvenli açılıştır: imzalı açılış zinciri devrede mi, anahtarlar nerede tutuluyor, kart tek yönlü olarak kilitlendi mi (iMX HAB güvenli açılış notu bu zincirin tipik adımlarını ayrıntılandırır).

Kapı 5 — Çevre: Sıcaklık ve Güç Köşelerinde Aynı Davranış

Oda sıcaklığında ve laboratuvar güç kaynağıyla açılan her görüntü çalışır. Ürün, kabinin en sıcak noktasında ve kış sabahında soğuk marşta çalışmak zorundadır.

Sıcaklık tarafında kapının referansı tahmin değil, SoC ve bellek datasheet'lerinin "Recommended Operating Conditions" ve "Absolute Maximum Ratings" tabloları ile kartın termal tasarım hedefidir. Yazılım tarafında sorulacak somut sorular şunlardır: /sys/class/thermal/thermal_zone*/ altında tanımlı trip point'ler cihaz ağacındaki değerlerle örtüşüyor mu; passive ve critical tiplerinde soğutma haritaları gerçekten bağlı mı; kısıtlama (throttling) devreye girdiğinde uygulama bunu bir hata olarak mı yoksa beklenen bir durum olarak mı görüyor. Kabin testlerinin yöntem tarafı IEC 60068-2-1 (soğuk), IEC 60068-2-2 (kuru sıcak) ve IEC 60068-2-14 (sıcaklık değişimi) ile adlandırılır; kabul kriterinde hangi köşede kaç tekrar açılış isteneceği testten önce yazılır.

Güç tarafında iki senaryo ayrı ayrı denenir: yavaş yükselen besleme (ramp) ve düşük gerilimde takılıp kalan besleme (brownout). İkincisi, DDR eğitiminin veya eMMC başlatmasının yarım kalmasıyla cihazı açılış döngüsünde bırakabilir. Soğuk ortamda ilk açılışın sıcak ortamdakinden farklı davranması bu kapının en sık ürettiği bulgudur; açılış süresi bütçesi de bu köşede ölçülmelidir, oda sıcaklığında değil (açılış süresi mimarisi notu bunun yöntemini ayrıca ele alıyor).

Kapı 6 — Kurtarma: Bozulan Cihaz Geri Dönüyor mu?

Bu kapı, teslim öncesi listede en çok atlanandır ve saha maliyetini en çok belirleyendir. Soru "güncelleme çalışıyor mu" değil, "güncelleme yarıda kesilirse cihaz geri geliyor mu" sorusudur.

Kurtarma üç bağımsız katmanda kurulur. En üstte atomik güncelleme ve geri alma: A/B slot düzeni, güncellemenin tek bir işlemde geçerli hale gelmesi ve yeni slot kendini "iyi" olarak işaretleyene kadar eskisine dönebilme (SWUpdate ve Mender karşılaştırması bu düzenin seçeneklerini ayrıntılandırır). Ortada önyükleyici sayacı: U-Boot'ta CONFIG_BOOTCOUNT_LIMIT ile bootlimit aşıldığında altbootcmd devreye girer, yani karar donanıma en yakın katmanda verilir. En altta fiziksel son çare: ROM açılış modu, UART veya USB üzerinden yükleme, eMMC boot bölümlerinin ayrı tutulması.

setenv bootlimit 3
setenv altbootcmd 'run bootcmd_slot_b'
saveenv

fw_printenv bootcount
fw_setenv bootcount 0

Testin kendisi kaba ama tartışmasızdır: güncellemenin farklı anlarında beslemeyi kesip cihazı tekrar açmak, her turda hangi slotun açıldığını ve bootcount değerinin ne olduğunu kayda geçmek. Aynı disiplin watchdog için de geçerlidir. Linux tarafında CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED ve CONFIG_WATCHDOG_NOWAYOUT seçenekleri, açılış sırasında ve /dev/watchdog kapatıldığında ne olacağını belirler; systemd tarafında RuntimeWatchdogSec ve servis birimlerindeki WatchdogSec ile sd_notify(0, "WATCHDOG=1") çağrısı, besleme sorumluluğunu doğru katmana taşır.

Kapı 7 — Saha: Cihaz Kendini Anlatabiliyor mu?

Son kapı, teslim edilen cihazın kendi durumunu tek başına anlatabilmesidir. Uygulaması ucuz, yokluğu pahalıdır.

Cihazda okunabilir bir sürüm kimliği bulunmalı: /etc/os-release içindeki BUILD_ID ve VERSION_ID, görüntü adı ve katman manifestinin cihaz üzerindeki kopyası. Bu bilgi, Kapı 1 ve Kapı 2'nin çıktılarıyla aynı anahtarı paylaşmalıdır — saha telefonunda okunan sürüm dizesi, derleme sunucusundaki tam kaynak setini tek adımda bulmalıdır. Günlükler kalıcı olmalı ama sınırlı: journald için Storage=persistent ve SystemMaxUse birlikte ayarlanmazsa, ilk uzun kesinti dosya sistemini doldurur. Tek komutla üretilen bir teşhis paketi (dmesg, journal özeti, sürüm manifesti, termal ve güç kayıtları) sahadaki teknisyeni tahmin yürütmekten kurtarır.

Nerede Yanlış Gider

  • Kapı, sstate önbelleği sayesinde geçilir. Tekrar üretilebilirlik testi, aynı makinede aynı sstate-cache ile alınan ikinci derlemeyle yapılırsa hiçbir şey kanıtlanmaz. Test farklı dizin, farklı makine ve boş önbellek ister.
  • Tekrar üretilebilirlik zaman damgasına indirgenir. Zaman damgaları en kolay kaynaktır; asıl kaynaklar derleme yolunun ikili dosyaya sızması, host araç zinciri sürümü, locale ve TZ farkları, paralel derlemede oluşan sıralama farklarıdır. Bunların hepsi diffoscope çıktısında görünür, hiçbiri tek bir ayarla kapanmaz.
  • AUTOREV bir yardımcı katmanda unutulur. Ana katmanlar sabitlenmiş, üçüncü taraf bir meta-* katmanındaki tek bir tarif hâlâ dal ucunu takip ediyordur. Ağsız derleme bu tarifi ilk turda yakalar.
  • Lisans kararı üst katmanda ezilir. INCOMPATIBLE_LICENSE dağıtım katmanında konur, ürün katmanında bir :append ile gevşetilir. bitbake -e | grep ^INCOMPATIBLE_LICENSE çıktısı, dosyalarda okunan değerden daha güvenilirdir.
  • Termal test ısınma beklemeden yapılır. Kabin sıcaklığa ulaşır ulaşmaz alınan sonuç, kartın kendi ısınmasını içermez. Kapı, sıcaklık dengesine oturmuş durumda ve yük altında sorulmalıdır.
  • Kurtarma yalnızca temiz senaryoda denenir. Güncelleme başarıyla tamamlandığında geri alma yolu hiç çalıştırılmaz; yedek slot bir kez bile açılmamış olabilir. Yedek slotun kendisi de en az bir kez gerçekten açılmalıdır.
  • fw_setenv başka bir ortamı yazar. /etc/fw_env.config içindeki ofset ve boyut, U-Boot'un derlendiği ayarlarla birebir örtüşmezse userspace ile önyükleyici farklı ortamları okur. Sonuç, güncellemeden sonra "bootcount sıfırlanmıyor" şeklinde ortaya çıkar.
  • Watchdog'u yanlış katman besler. Uygulama kilitlenirken onu izlemesi gereken bir yardımcı süreç /dev/watchdog dosyasını beslemeye devam ediyorsa, watchdog yalnızca çekirdeğin canlı olduğunu doğrular; görevin yürüdüğünü değil.
  • Kapı bir belgede yaşar, CI'da değil. Tek kişinin elindeki kontrol listesi, o kişi izne çıktığında yok olur. Kapıların her biri bir iş adımı olarak koşmalı ve çıktısını bir dizine bırakmalıdır.

Karar Kriteri

Sıralama net: Kapı 1 ve 2 geçilmeden diğerlerine harcanan emek geçicidir, çünkü elinizdeki test kayıtları yeniden üretemediğiniz bir ikili dosyaya aittir. Hiçbiri kurulu değilse ilk hafta ağsız derleme ve katman manifestine, ikinci hafta ikinci makinede tekrar üretilebilirlik karşılaştırmasına gider; bu iki adım tek başına, sonraki her bulguyu tartışılabilir olmaktan çıkarır.

Teslim kararı için pratik eşik şudur: yedi kapının her biri için (a) sorunun yazılı hali, (b) o soruyu koşan komut, (c) son koşunun çıktısı ve tarihi bir arada duruyorsa BSP teslim edilebilir. Üçünden biri eksik olan kapı, geçilmiş değil ertelenmiş kapıdır — ve ertelenmiş kapılar sahada, en pahalı anda kendini gösterir.

Elinizde çalışan bir görüntü var ama bu kapıların hangisinin gerçekten kurulu olduğundan emin değilseniz, mevcut BSP'nizi ve derleme hattınızı gömülü sistem mimari denetimi kapsamında birlikte geçirebilir, eksik kapıları öncelik sırasına koyabiliriz.