Slide 1

Slide 1 text

Raspberry Pi 5の起動プロセスについて Kernel/VM つくば 2026/3/20 ほたるいか

Slide 2

Slide 2 text

自己紹介 ほたるいか 詳細なプロフィール 東京科学大学 学士2年 SecHack365 '25 坂井ゼミ サイボウズ・ラボユース ‘25 セキュリティキャンプ 2024 全国大会 ハイパーバイザゼミ OS/ハイパーバイザ作成から基板作成まで 低レイヤーが好きです

Slide 3

Slide 3 text

背景 ベアメタルプログラムをRaspberry Pi 5で起動するまでの障害 Raspberry Pi 5でもベアメタル開発がしたいが、Raspberry Pi 5では起動のも難しい Uefi非対応 U-Boot非対応 独自のfirmwareに よりlinuxを起動

Slide 4

Slide 4 text

Raspberry Pi 5での起動プロセスの概要 Soc(BCM2712)内蔵のBoot ROMから 1st Stage BootLoaderが起動 SPI EEPROM上の 2nd Stage BootLoaderが起動 SPI EEPROMにある BOOT_ORDERに従ってBoot パーティションを探索 Bootパーティションの config.txtを読む initramfsをメモリ上にロード dtbをメモリ上にロードしてdtb overlayを適用 trusted firmwareをメモリ上にロード kernelをロード + 展開 trusted firmwareを実行 kernelを実行 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

Slide 5

Slide 5 text

1.Soc(BCM2712)内蔵のBoot ROMから1st Stage BootLoaderが起動 Raspberry Pi 5のSocであるBCM2712内部のROMから読み出されて実行される最初のBootlLoader 変更が不可能なので、セキュアブートの際のtrusted rootとして利用されていそう SDカードのboot partitionにrecovery.binが配置されている場合は、それを読み出してEEPROMをそのデータで初期化する EEPROMの2nd Stage BootLoaderのアップデートに利用できる 2.SPI EEPROM上の2nd Stage BootLoaderが起動 Raspberry Pi 5に乗っているEEPROMから読み出されるSecond Stage BootLoader このBootLoaderがメモリの初期化やRP1のfirmware転送などのほとんどの初期化を担当する config.txtで挙動を変更できる 3.SPI EEPROMにあるBOOT_ORDERに従ってBootパーティションを探索 EEPROMに保存されているBOOT ORDERに沿って、デバイスのBootを試みる EEPROMで設定できる内容は以下のページにまとまっている https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#configuration-properties

Slide 6

Slide 6 text

4.Bootパーティションのconfig.txtを読む Bootパーティションがあるデバイスが見つかった場合、Firmwareはまずconfig.txtを読み、 その内容に従ってデバイスを起動する config.txtの設定できる内容は以下の通り https://www.raspberrypi.com/documentation/computers/config_txt.html 5.initramfsをメモリ上にロード initramfsをメモリ上にロードする config.txtのinitramfs で明示指定できる 複数fileを指定できるらしい addrのところにfollowkernelとするとカーネル直後に auto_initramfs=1ならkernel_2712.img → initramfs_2712、kernel8.img → initramfs8になる 6.dtbをメモリ上にロードしてdtb overlayを適用 dtbをメモリ上にロードして、config.txtのdtoverlayで指示されているdtb overlayを適用する ロード位置は、device_tree_address=で変更できる

Slide 7

Slide 7 text

7.trusted firmwareをメモリ上にロード メモリ上にtrusted firmwareをロードする armstub=でロードするfirmwareを変更できる(メモリ上の0番地からにロードされてアドレスの変更は出来ない?) 8.kernelをロード + 展開 kernelをメモリ上にロードして(gzipで圧縮されている場合は)展開する デフォルトではRaspberry Pi 5用のkernel_2712.imgをロードしようとするが、無かった場合はkernel8.imgにフォールバック kernel=で指定可能 kernel_address=でロードするアドレスは指定できるが、それを展開する/relocateするアドレスは固定で baremetal binaryの場合: 0x80000固定 linux binaryの場合:   0x200000固定 になっていそう 9.trusted firmwareを実行 10.kernelを実行 trusted firmwareを実行する このとき、権限レベルはEL3で実行されて、この実行が終了するときにEL2に下げられてからkernelが起動される

Slide 8

Slide 8 text

Raspberry Pi 5でベアメタルプログラミングをする際の注意点 elfのロードは出来ない stripされた生binary or linuxのヘッダ形式のbinaryのみ起動可能 kernelのアドレスは生binaryの場合はロード先が0x80000固定 config.txtのkernel_addressで指定できるように見えるが嘘 kernel_addressは一時ロード先の指定で、その後relocateされてしまう アドレスの指定をミスると簡単に上書きされうる

Slide 9

Slide 9 text

Raspberry Pi 5でHelloWorldをRP1からしてみる RP1とはRaspberry Pi 5のGPIO等外部ペリフェラルコントローラー BCM2712(Soc)とPcie 2.0 x4で繋がっている firmwareがRP1の初期化を行ったあとリセットせずにkernelに渡してくれる オプションがある pciex4_reset=0 # RP1をリセットせずにkernelに渡す enable_rp1_gpio=1 # RP1のGPIO 14/15から出ているuart0をGPIO含め てセットアップしてから渡すオプション enable_rp1_gpio=1があれば、何も初期化せずともRP1のuart0から文字を 出力できる 0x1c_0003_0000にあるpl011にアクセスして文字表示

Slide 10

Slide 10 text

Raspberry Pi 5でRP1のUARTからの割込みを受け取ってみる Cortex A76 ✕ 4 GIC-400 (Gic v2) ④:IRQ/FIQ MSI-X Interrupt Peripheral ③:SPI RP1 割込みコントローラ ②:MSI/X PL011 UARTコントローラ ①: SPI RP1(GPIOコントローラ) BCM2712(Soc) PL011 UARTコントローラ ①: SPI GIC-400 (Gic v2) Raspberry Pi 5 Raspberry Pi 4 GIC-400 (Gic v2) Cortex A72 ✕ 4 ②:IRQ/FIQ

Slide 11

Slide 11 text

Raspberry Pi 5でRP1のUARTからの割込みを受け取ってみる Cortex A76 ✕ 4 GIC-400 (Gic v2) ④:IRQ/FIQ MSI-X Interrupt Peripheral ③:SPI RP1 割込みコントローラ ②:MSI/X PL011 UARTコントローラ ①: SPI RP1(GPIOコントローラ) BCM2712(Soc) PL011 UARTコントローラ ①: SPI GIC-400 (Gic v2) Raspberry Pi 5 Raspberry Pi 4 GIC-400 (Gic v2) Cortex A72 ✕ 4 ②:IRQ/FIQ ここを頑張って設定

Slide 12

Slide 12 text

Raspberry Pi 5でRP1のUARTからの割込みを受け取ってみる 動いた! をしたかった図(なにも変えてないのに壊れた) GitHub