00 Boot sırası ve U-Boot'un yeri
Güç geldiği andan Linux çekirdeğinin kontrolü devralmasına kadar birden fazla yazılım katmanı sırayla çalışır.
Modern gömülü sistemlerde bootloader tek bir binary değildir. SoC'ların dahili SRAM'ı genellikle 256 KB ile birkaç MB arasında olduğundan, her şeyi ilk anda yüklemek mümkün değildir. Bu nedenle önyükleme birden fazla aşamaya bölünür.
ROM Bootrom SoC içi, değiştirilemez, üreticide yazılmış │ SRAM'ı hazırlar, boot medyasını tarar ▼ SPL (MLO / spl.bin) Secondary Program Loader — SRAM'da çalışır │ DDR'yi başlatır (training dahil) │ Gerçek U-Boot'u DDR'ye yükler ▼ U-Boot DDR'de çalışır, tam özellikli bootloader │ Ortam değişkenlerini okur │ Kernel, DTB, initrd yükler ▼ Linux Kernel DTB ile donanımı tanır, driver'ları probe eder ▼ init / systemd User-space ilk süreci
Neden birden fazla stage?
AM335x gibi bir SoC'da dahili SRAM genellikle 64 KB civarındadır. U-Boot'un tam binary'si ise 400–600 KB'a ulaşabilir. SPL bu engeli aşmak için vardır: minimal bir loader olarak SRAM'a sığar, DDR controller'ı başlatır ve sonra gerçek U-Boot'u büyük belleğe yükler. SPL kendi başına dosya sistemi, ağ veya USB gibi özelliklere ihtiyaç duymaz.
Bazı platformlarda SPL'nin önünde bir de FSBL (First Stage Boot Loader) yer alır. Xilinx Zynq'de FSBL, PL (FPGA) tarafını yapılandırır ve ardından SPL'yi başlatır. Katman sayısı platforma göre 2 ile 4 arasında değişebilir.
U-Boot vs diğer bootloader'lar
| Bootloader | Hedef Platform | Özellik |
|---|---|---|
| U-Boot | ARM, RISC-V, x86, MIPS, PowerPC | Gömülü Linux'ta fiili standart; geniş board desteği |
| GRUB 2 | x86 / x86-64 (EFI dahil) | PC/sunucu; çoklu OS seçimi; UEFI Secure Boot |
| Barebox | ARM ağırlıklı | Daha temiz kod tabanı; U-Boot'tan etkilenmiş; endüstriyel |
| Coreboot | x86 (Chromebook, sunucu) | Donanım başlatmaya odaklı; payload olarak GRUB/SeaBIOS çalıştırır |
U-Boot çıktı dosyaları
Bu bölümde
- ROM → SPL → U-Boot → Kernel → init zincirinin her halkasının görevi
- SRAM kısıtının SPL ihtiyacını nasıl doğurduğu
- U-Boot, GRUB, Barebox ve Coreboot arasındaki farklar
- Derleme çıktılarının (.bin, .img, MLO) platform bazındaki anlamı
01 U-Boot derleme
Kaynak koddan hedef board için binary üretmek; cross-compiler, defconfig ve Kconfig seçenekleri.
Kaynak kodu edinme
# Resmi U-Boot deposu (DENX)
git clone https://source.denx.de/u-boot/u-boot.git
cd u-boot
# Kararlı bir etiket seç
git checkout v2024.10
Cross-compiler kurulumu
# ARM 32-bit (gnueabihf = hard-float ABI)
sudo apt install gcc-arm-linux-gnueabihf
# Build ortamı için zorunlu değişkenler
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# ARM64 (Raspberry Pi 4, i.MX8 vb.)
sudo apt install gcc-aarch64-linux-gnu
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
ARCH değişkeni ayarlanmazsa make, host mimarisini kullanır ve yanlış araç zincirine yönlenir. Her oturumda ya da Makefile içinde açıkça tanımla.
defconfig ve derleme
# Raspberry Pi 4 için hazır konfigürasyon
make rpi_4_defconfig
# BeagleBone Black (TI AM335x)
make am335x_boneblack_defconfig
# Allwinner H3 (Orange Pi PC)
make orangepi_pc_defconfig
# Paralel derleme (nproc = CPU çekirdek sayısı)
make -j$(nproc)
# Çıktıları temizle
make distclean
Derleme çıktıları
| Dosya | Platform | Açıklama |
|---|---|---|
| u-boot.bin | Genel | Ham ELF-strip edilmiş binary |
| MLO | TI AM335x | SPL; FAT'a kopyalanır, ROM tarafından yüklenir |
| u-boot-sunxi-with-spl.bin | Allwinner | SPL + U-Boot birleşik; dd bs=1024 seek=8 ile SD'ye yazılır |
| u-boot.img | TI AM335x | mkimage header'lı; MLO bu dosyayı yükler |
| u-boot-dtb.img | Çeşitli | DT gömülü binary; CONFIG_OF_EMBED=y ile |
Kconfig ile özellik seçimi
# Etkileşimli menü (ncurses gerektirir)
make menuconfig
# Komut satırından tek seçenek değiştirme
./scripts/config --enable CONFIG_CMD_DHCP
./scripts/config --enable CONFIG_FIT
./scripts/config --set-val CONFIG_BOOTDELAY 3
# Mevcut konfigürasyonu doğrula
grep CONFIG_FIT .config
board'a özgü seçenekler genellikle configs/<board>_defconfig içinde önceden tanımlıdır. menuconfig sonrası make savedefconfig ile değişiklikleri minimal formatta geri kaydedebilirsin.
Bu bölümde
- DENX deposundan kaynak edinme ve stabil etiket seçimi
- ARCH ve CROSS_COMPILE zorunluluğu
- defconfig → make -j$(nproc) derleme akışı
- Platform bazında çıktı dosyası farklılıkları
- menuconfig ve scripts/config ile feature toggle
02 U-Boot shell ve temel komutlar
UART konsolundan U-Boot prompt'una ulaşmak ve sık kullanılan komutları öğrenmek.
U-Boot başladığında bootdelay süresinde herhangi bir tuşa basılırsa otomatik boot durur ve interaktif shell açılır. Varsayılan UART ayarı 115200 baud, 8N1'dir.
Konsol bağlantısı
# minicom ile bağlan
minicom -D /dev/ttyUSB0 -b 115200
# picocom (daha hafif)
picocom -b 115200 /dev/ttyUSB0
# screen
screen /dev/ttyUSB0 115200
Ortam değişkeni komutları
# Tüm environment değişkenlerini listele
printenv
# Tek değişken
printenv bootargs
# Değişken tanımla (sadece RAM'de)
setenv myvar "hello world"
# Değişkeni kalıcı kaydet (flash/eMMC'ye)
saveenv
# Değişkeni sil
setenv myvar
Bellek komutları
# Belleği hex dump et (md = memory display)
# md.b = byte, md.w = word(16), md.l = long(32)
md.l 0x80000000 0x20 # 0x80000000'dan 32 long göster
# Belleğe yaz (mw = memory write)
mw.l 0x80000000 0xdeadbeef 1
# Board bilgisi (CPU, DRAM, clock)
bdinfo
Dosya yükleme komutları
# FAT partition'dan yükle (mmc 0:1 = ilk MMC, ilk partition)
fatload mmc 0:1 0x80000000 zImage
# ext4 partition'dan yükle
ext4load mmc 0:2 0x80000000 /boot/zImage
# TFTP ile ağdan yükle
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.1
tftp 0x80000000 zImage
# DHCP + TFTP tek adımda
dhcp 0x80000000 zImage
Yardım ve otomatik tamamlama
# Tüm komutları listele
help
# Komut için ayrıntılı yardım
help fatload
fatload ? # alternatif sözdizimi
# Tab tuşu ile otomatik tamamlama
fat[TAB] # → fatload, fatls, fatsize...
setenv boot[TAB] # → bootcmd, bootargs, bootdelay...
U-Boot prompt'unda yukarı ok tuşu ile komut geçmişine erişilebilir. Bazı eski U-Boot sürümlerinde bu özellik CONFIG_CMDLINE_EDITING=y ile etkinleştirilmesi gerekir.
Bu bölümde
- UART konsol bağlantısı: 115200 8N1, minicom / picocom
- printenv, setenv, saveenv ile ortam değişkeni yönetimi
- md / mw ile bellek erişimi
- fatload, ext4load, tftp ile farklı kaynaklardan yükleme
- help komutu ve Tab ile otomatik tamamlama
03 Environment değişkenleri ve bootargs
U-Boot'un davranışını yönlendiren değişkenler ve kernel'a aktarılan komut satırı parametreleri.
U-Boot environment'ı, power-on'dan boot'un sonuna kadar tüm davranışı yöneten anahtar-değer çiftleri topluluğudur. Bazı değişkenler özel anlam taşır ve U-Boot tarafından otomatik yorumlanır.
Temel özel değişkenler
bootargs örnekleri
# Temel: seri konsol + eMMC rootfs
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw"
# NFS rootfs ile ağdan boot
setenv bootargs "console=ttyS0,115200 root=/dev/nfs \
nfsroot=192.168.1.1:/srv/nfs/rootfs,v3 \
ip=192.168.1.100:192.168.1.1:192.168.1.1:255.255.255.0::eth0:off \
rw"
# initramfs ile (rootfs adres gömülü)
setenv bootargs "console=ttyAMA0,115200 rootfstype=tmpfs"
# Kernel debug modu
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait \
loglevel=8 ignore_loglevel debug earlyprintk"
Environment depolama seçenekleri
| Depolama | Kconfig | Açıklama |
|---|---|---|
| eMMC / SD (FAT) | CONFIG_ENV_IS_IN_FAT | uboot.env dosyası olarak boot partition'da saklanır |
| eMMC / SD (raw) | CONFIG_ENV_IS_IN_MMC | Belirlenen offset'e raw yazılır; CONFIG_ENV_OFFSET ile ayarlanır |
| SPI NOR Flash | CONFIG_ENV_IS_IN_SPI_FLASH | Flash'ta sabit offset; CONFIG_ENV_SECT_SIZE dikkat |
| NAND Flash | CONFIG_ENV_IS_IN_NAND | Bad-block aware; yedek kopya desteği mevcut |
| Yok (sadece derleme) | CONFIG_ENV_IS_NOWHERE | saveenv çalışmaz; her boot varsayılan değerler |
Geliştirme sırasında saveenv'yi dikkatli kullan. Yanlış bootargs kaydedilirse cihaz her açılışta boot edemez hale gelebilir. Üretim ortamında environment'ı read-only bir bölümden yükleyip RAM'de değiştirmek daha güvenlidir.
Bu bölümde
- bootcmd, bootargs, bootdelay — özel değişkenlerin işlevleri
- loadaddr ve fdtaddr adres çakışması riski
- Farklı rootfs senaryoları için bootargs örnekleri
- FAT, raw MMC, SPI Flash, NAND depolama seçenekleri
04 Boot script (.cmd → .scr)
Karmaşık boot mantığını tekrar kullanılabilir bir script dosyasına taşı; koşullu dal ve değişken kontrolü.
bootcmd içine uzun komut zincirleri yazmak hem okunaksız hem de kırılgandır. Boot script yöntemi, boot.cmd metin dosyasını mkimage ile binary boot.scr'ye dönüştürür ve U-Boot bu dosyayı doğrudan çalıştırır.
Script derleme
# boot.cmd → boot.scr dönüşümü
mkimage -C none -A arm -T script -d boot.cmd boot.scr
# ARM64 için
mkimage -C none -A arm64 -T script -d boot.cmd boot.scr
# boot.scr'yi FAT partition'a kopyala
cp boot.scr /media/boot/
U-Boot'ta script çalıştırma
# boot.scr'yi yükle ve çalıştır
fatload mmc 0:1 ${loadaddr} boot.scr
source ${loadaddr}
# bootcmd olarak otomatikleştir
setenv bootcmd "fatload mmc 0:1 ${loadaddr} boot.scr; source ${loadaddr}"
saveenv
Tam boot script örneği
# ── Adres tanımları ──────────────────────────────────
setenv kernel_addr 0x80008000
setenv dtb_addr 0x83000000
setenv initrd_addr 0x84000000
# ── Kernel komut satırı ──────────────────────────────
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw"
# ── Koşullu boot: önce TFTP dene, sonra MMC ──────────
if test -n ${serverip}; then
echo "Network boot deneniyor..."
if tftp ${kernel_addr} zImage; then
tftp ${dtb_addr} my-board.dtb
bootz ${kernel_addr} - ${dtb_addr}
fi
fi
# ── MMC boot ─────────────────────────────────────────
echo "MMC boot..."
fatload mmc 0:1 ${kernel_addr} zImage
fatload mmc 0:1 ${dtb_addr} my-board.dtb
fatload mmc 0:1 ${initrd_addr} initrd.img
# bootz: zImage (ARM32) + DTB + initrd
bootz ${kernel_addr} ${initrd_addr} ${dtb_addr}
Script'te dosya varlığı kontrolü
# FAT'ta dosya var mı?
if test -e mmc 0:1 /boot.scr; then
fatload mmc 0:1 ${loadaddr} boot.scr
source ${loadaddr}
fi
# env değişkeni boş mu?
if test -z ${fdt_file}; then
setenv fdt_file my-board.dtb
fi
U-Boot script değişkenleri ${} sözdizimi kullanır. run <varname> komutu ise değişken içindeki komut dizisini çalıştırır — bu şekilde bootcmd içinde alt rutinler tanımlanabilir.
Bu bölümde
- mkimage ile .cmd → .scr dönüşümü
- source komutu ile script çalıştırma
- Koşullu boot: TFTP önce, MMC yedek
- test -e ile dosya varlığı, test -n/-z ile değişken kontrolü
- bootz (ARM32 zImage) ile kernel başlatma
05 Network boot (TFTP + NFS)
Geliştirme sırasında her değişiklik için reflash gerekmez — kernel ve rootfs'i doğrudan ağdan yükle.
Network boot, gömülü Linux geliştirmenin en hızlı döngüsüdür. Kernel veya rootfs değiştiğinde yalnızca sunucu tarafı güncellenir; hedef cihaz yeniden başlatılınca yeni imajı ağdan çeker. Donanıma hiç dokunulmaz.
Host: TFTP sunucu kurulumu
# tftpd-hpa kur
sudo apt install tftpd-hpa
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
# Servisi başlat
sudo systemctl enable --now tftpd-hpa
# Kernel ve DTB'yi TFTP dizinine kopyala
cp arch/arm/boot/zImage /srv/tftp/
cp arch/arm/boot/dts/my-board.dtb /srv/tftp/
U-Boot'ta network boot
# Statik IP ayarla
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.1
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
# Alternatif: DHCP ile otomatik IP
dhcp
# Kernel indir
tftp ${loadaddr} zImage
# DTB indir
tftp ${fdt_addr} my-board.dtb
# NFS rootfs ile boot
setenv bootargs "console=ttyS0,115200 root=/dev/nfs \
nfsroot=192.168.1.1:/srv/nfs/rootfs,v3,tcp \
ip=dhcp rw"
bootz ${loadaddr} - ${fdt_addr}
Host: NFS sunucu kurulumu
# NFS sunucu kur
sudo apt install nfs-kernel-server
# /etc/exports dosyasına ekle
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
# Rootfs'i oluştur (Buildroot çıktısı gibi)
sudo tar xf rootfs.tar -C /srv/nfs/rootfs/
# Dışa aktar
sudo exportfs -ra
sudo systemctl enable --now nfs-kernel-server
netboot değişkeni ile tek komut
setenv netboot "dhcp; \
tftp ${loadaddr} zImage; \
tftp ${fdt_addr} my-board.dtb; \
setenv bootargs console=ttyS0,115200 root=/dev/nfs \
nfsroot=${serverip}:/srv/nfs/rootfs,v3 ip=dhcp rw; \
bootz ${loadaddr} - ${fdt_addr}"
# Tek komutla network boot
run netboot
# Kalıcı kaydet
saveenv
NFS v3 ile no_root_squash seçeneği geliştirme ortamında gereklidir; üretimde kullanma. Ayrıca host güvenlik duvarının 69/UDP (TFTP) ve 2049/TCP (NFS) portlarına izin verdiğinden emin ol.
Bu bölümde
- tftpd-hpa kurulumu ve yapılandırması
- dhcp / statik IP + tftp ile kernel ve DTB yükleme
- NFS rootfs: /etc/exports, no_root_squash
- netboot değişkeni ile tek adımlı geliştirme döngüsü
06 FIT image (Flattened Image Tree)
Kernel, DTB ve initrd'yi tek imzalanabilir dosyada birleştir; güvenli boot'un temel taşı.
FIT (Flattened Image Tree), mkimage tarafından oluşturulan ve içinde birden fazla alt imaj barındırabilen kapsayıcı bir formattır. Yapısı DTS/DTB formatına benzer; bir .its (Image Tree Source) dosyası ile tanımlanır ve dtc'ye benzer biçimde derlenir.
Tam .its dosyası örneği
/dts-v1/;
/ {
description = "ARM Kernel + DTB + Ramdisk";
#address-cells = <1>;
images {
kernel {
description = "Linux Kernel";
data = /incbin/("arch/arm/boot/zImage");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
load = <0x80008000>;
entry = <0x80008000>;
};
fdt {
description = "Device Tree";
data = /incbin/("my-board.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
};
ramdisk {
description = "Initial Ramdisk";
data = /incbin/("initrd.img");
type = "ramdisk";
arch = "arm";
os = "linux";
compression = "gzip";
};
};
configurations {
default = "conf-1";
conf-1 {
description = "Boot config 1";
kernel = "kernel";
fdt = "fdt";
ramdisk = "ramdisk";
};
};
};
FIT image derleme ve yükleme
# .its → .fit binary oluştur
mkimage -f my.its my.fit
# İçeriği doğrula
mkimage -l my.fit
# FIT image'ı FAT'tan yükle ve boot et
fatload mmc 0:1 ${loadaddr} my.fit
bootm ${loadaddr}
# Belirli bir konfigürasyonu seç
bootm ${loadaddr}#conf-1
# TFTP ile FIT yükle
tftp ${loadaddr} my.fit
bootm ${loadaddr}
FIT ile imzalama
# RSA anahtar üret
mkdir keys
openssl genrsa -out keys/dev.key 2048
# X.509 sertifikası üret
openssl req -new -x509 -key keys/dev.key -out keys/dev.crt \
-subj "/CN=Embedded Dev Key"
# FIT'i imzala ve public key'i U-Boot DTB'ye göm
mkimage -f my.its -K u-boot.dtb -k keys/ -F -r my.fit
# Public key gömülü U-Boot DTB ile yeniden derle
make EXT_DTB=u-boot.dtb
FIT imzalama için CONFIG_FIT_SIGNATURE=y ve CONFIG_RSA=y Kconfig seçenekleri etkin olmalıdır. Public key U-Boot DTB'sine gömüldükten sonra imzasız FIT image'lar reddedilir — bu güvenli boot zincirinin temel adımıdır.
Bu bölümde
- FIT formatı: .its kaynak, mkimage ile derleme
- Kernel + DTB + ramdisk tek dosyada; configurations bloğu
- bootm ile FIT yükleme ve yapılandırma seçimi
- RSA anahtar üretimi ve FIT imzalama süreci
- CONFIG_FIT_SIGNATURE ve güvenli boot temeli
07 MMC / SD kart operasyonları
U-Boot'ta MMC/SD aygıtlarını listele, bölümleri incele ve doğrudan ham yazma yap.
U-Boot MMC subsystem'i hem SD kartları hem eMMC'yi destekler. Komutlarda mmc <dev>:<part> biçiminde device:partition çifti kullanılır. Device numaraları mmc list ile öğrenilir.
Cihaz yönetimi
# Tüm MMC/SD cihazlarını listele
mmc list
# Örnek çıktı:
mmc@fe320000: 0 (SD)
mmc@fe330000: 1 (eMMC)
# Aktif cihazı değiştir
mmc dev 0 # SD kart
mmc dev 1 # eMMC
# Cihaz bilgisi (kapasite, hız, bus genişliği)
mmc info
# Cihazı yeniden tara
mmc rescan
Partition listeleme
# FAT partition içeriğini listele (mmc 0, partition 1)
fatls mmc 0:1
# FAT'ta alt dizin
fatls mmc 0:1 /boot
# ext4 partition içeriğini listele
ext4ls mmc 0:2 /
# ext4'te /boot dizini
ext4ls mmc 0:2 /boot
# Partition tablosunu göster (MBR/GPT)
part list mmc 0
Dosya boyutu sorgulama
# Dosya boyutunu filesize değişkenine yaz
fatsize mmc 0:1 zImage
echo ${filesize} # bayt cinsinden onaltılık
ext4size mmc 0:2 /boot/zImage
Ham sektör erişimi
# Ham okuma: sektör 0'dan 8 sektör oku (MBR kontrolü)
mmc read ${loadaddr} 0x0 0x8
# Bellekten MMC'ye ham yaz (DİKKATLİ!)
# mmc write
mmc write ${loadaddr} 0x0 0x800 # 0x800 blok = 1 MB
mmc write komutu doğrudan ham sektörlere yazar. Yanlış blok adresi veya sayımı partition tablosunu, dosya sistemini veya boot bölümünü kalıcı olarak bozabilir. Adres ve blok sayısını iki kez kontrol et.
Partition düzeni
| Partition | Tür | İçerik | Tipik boyut |
|---|---|---|---|
| p1 | FAT32 (0xC) | MLO, u-boot.img, boot.scr, zImage, *.dtb | 64–256 MB |
| p2 | ext4 (0x83) | Linux rootfs | Kalan alan |
| Sektör 0 | MBR/raw | Allwinner: u-boot-sunxi-with-spl.bin (offset 8 KB) | 8–1024 KB |
Bu bölümde
- mmc list / dev / info / rescan komutları
- fatls, ext4ls ile partition içeriğini inceleme
- part list ile MBR/GPT partition tablosu
- mmc read / write ile ham sektör erişimi ve dikkat edilecekler
- Tipik gömülü Linux SD kart partition düzeni
08 Güvenli boot ve imzalama
İmzasız kernel'ın çalışmasını engelle — RSA anahtarları, FIT imzalama ve U-Boot'a public key gömme.
Güvenli boot, bootloader'ın yalnızca belirli bir anahtarla imzalanmış imajları kabul etmesini sağlar. Amaç, yetkisiz veya değiştirilmiş kernel/initrd'nin yüklenmesinin önüne geçmektir. U-Boot'ta bu FIT imzalama mekanizması üzerine inşa edilir.
Gerekli Kconfig seçenekleri
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_RSA=y
CONFIG_RSA_SOFTWARE_EXP=y
CONFIG_FIT_VERBOSE=y # hata mesajları için yararlı
CONFIG_OF_CONTROL=y
CONFIG_SPL_FIT_SIGNATURE=y # SPL de imzalama yapacaksa
Anahtar üretimi
# Anahtar dizini oluştur
mkdir -p keys
# RSA-2048 private key
openssl genrsa -out keys/dev.key 2048
# Self-signed sertifika (U-Boot public key için)
openssl req -batch -new -x509 \
-key keys/dev.key \
-out keys/dev.crt \
-days 7300 \
-subj "/CN=Embedded Secure Boot Key"
# Anahtar çiftini doğrula
openssl x509 -in keys/dev.crt -noout -text | grep Subject
İmzalı FIT image oluşturma
/dts-v1/;
/ {
description = "Signed Kernel Image";
#address-cells = <1>;
images {
kernel {
data = /incbin/("arch/arm/boot/zImage");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
load = <0x80008000>;
entry = <0x80008000>;
signature {
algo = "sha256,rsa2048";
key-name-hint = "dev";
};
};
fdt {
data = /incbin/("my-board.dtb");
type = "flat_dt";
arch = "arm";
compression = "none";
};
};
configurations {
default = "conf-1";
conf-1 {
kernel = "kernel";
fdt = "fdt";
signature {
algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "fdt", "kernel";
};
};
};
};
# FIT oluştur ve imzala; public key'i u-boot.dtb'ye göm
mkimage -f my-signed.its \
-K u-boot.dtb \
-k keys/ \
-F -r my-signed.fit
# U-Boot'u public key gömülü DTB ile yeniden derle
make EXT_DTB=u-boot.dtb
# İmzayı doğrula
mkimage -l my-signed.fit
Güvenli boot zinciri
ROM SoC'a gömülü hash ile SPL'yi doğrular (OTP fuse) │ ▼ SPL ROM tarafından doğrulanmış │ U-Boot FIT'ini yükler ve imzasını kontrol eder ▼ U-Boot Public key DTB'ye gömülü │ Kernel FIT imzasını RSA ile doğrular │ İmza hatalıysa → boot reddedilir ▼ Kernel Doğrulanmış imaj çalışır │ ▼ rootfs dm-verity ile blok katmanında bütünlük
Tam güvenli boot için SoC'un OTP (One Time Programmable) fuse'larına SPL hash'ini yakmak gerekir. Bu adım platform bağımlıdır ve geri alınamaz. Geliştirme aşamasında fuse yakmadan FIT imzalama mekanizmasını test edebilirsin.
Bu bölümde
- CONFIG_FIT_SIGNATURE, CONFIG_RSA — gerekli Kconfig seçenekleri
- openssl ile RSA-2048 anahtar ve sertifika üretimi
- signature node içeren .its dosyası yapısı
- mkimage -K ile public key'i U-Boot DTB'ye gömme
- ROM → SPL → U-Boot → Kernel güvenli boot zinciri
09 Pratik: QEMU ile test
Gerçek donanım olmadan U-Boot'u çalıştır, TFTP boot ve GDB ile debug yap.
QEMU, gerçek board'a ihtiyaç duymadan U-Boot'u test etmek için ideal ortamdır. Boot script geliştirme, FIT imzalama testi ve GDB ile adım adım hata ayıklama için kullanılır.
Kurulum
# ARM 32-bit ve 64-bit QEMU emülatörleri
sudo apt install qemu-system-arm qemu-system-aarch64
ARM32: vexpress-a9
# U-Boot'u vexpress-a9 defconfig ile derle
make vexpress_ca9x4_defconfig
make -j$(nproc)
# QEMU'da çalıştır (stdio üzerinden UART)
qemu-system-arm \
-M vexpress-a9 \
-kernel u-boot.bin \
-serial stdio \
-nographic
SD kart emülasyonu
# 1 GB SD imajı oluştur
dd if=/dev/zero of=sd.img bs=1M count=1024
# Partition tablosu oluştur
parted sd.img mklabel msdos
parted sd.img mkpart primary fat32 1MiB 64MiB
parted sd.img mkpart primary ext4 64MiB 100%
# Loop device üzerinden formatla
sudo losetup -f --show --partscan sd.img
# → /dev/loop0
sudo mkfs.fat -F32 /dev/loop0p1
sudo mkfs.ext4 /dev/loop0p2
# SD imajı ile QEMU
qemu-system-arm \
-M vexpress-a9 \
-kernel u-boot.bin \
-drive file=sd.img,format=raw,if=sd \
-serial stdio \
-nographic
TFTP ağ emülasyonu
# QEMU user-mode networking + TFTP
# QEMU host = 10.0.2.2, guest = 10.0.2.15
qemu-system-arm \
-M vexpress-a9 \
-kernel u-boot.bin \
-netdev user,id=net0,tftp=/srv/tftp \
-device virtio-net,netdev=net0 \
-serial stdio \
-nographic
# U-Boot'ta (QEMU içinde):
setenv ipaddr 10.0.2.15
setenv serverip 10.0.2.2
tftp 0x60000000 zImage
ARM64: Raspberry Pi 3
# ARM64 U-Boot derle
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make rpi_3_defconfig
make -j$(nproc)
# QEMU aarch64 raspi3b emülasyonu
qemu-system-aarch64 \
-M raspi3b \
-kernel u-boot.bin \
-serial stdio \
-nographic
GDB ile debug
# Terminal 1: QEMU'yu GDB stub ile başlat
# -s → GDB stub port 1234, -S → başlangıçta bekle
qemu-system-arm \
-M vexpress-a9 \
-kernel u-boot.bin \
-serial stdio \
-nographic \
-s -S
# Terminal 2: GDB ile bağlan
arm-linux-gnueabihf-gdb u-boot
# GDB komutları:
(gdb) target remote :1234
(gdb) break board_init_f
(gdb) continue
(gdb) info registers
(gdb) x/10i $pc # PC konumundan 10 instruction
QEMU'da -nographic kullanılınca Ctrl+A X ile çıkılır (Ctrl+C değil). UART çıktısı stdio'ya yönlendirilir; ayrı bir pencere açmak için -serial telnet:localhost:5555,server ve başka bir terminalde telnet localhost 5555 kullanılabilir.
Bu bölümde
- qemu-system-arm ile vexpress-a9 ve ARM64 raspi3b emülasyonu
- dd + parted + losetup ile SD kart imajı hazırlama
- QEMU user-mode networking ile TFTP boot (10.0.2.2)
- -s -S ile GDB stub başlatma ve remote debugging
- arm-linux-gnueabihf-gdb ile U-Boot'a breakpoint koyma