Fuchsia の ZBI データ構造
Fuchsia の起動時に使用する ZBI(Zircon Boot Image)のデータ構造を紹介します。
ZBI とは
-
Zircon Boot Image には、ドライバーが動作する前のブートプロセスに必要なものがすべて含まれています。
カーネルイメージとブートファイルシステム用の RAM ディスクが含まれています。 -
ZBI に含まれるもの(Boot Item と呼ぶ)
- ブートローダ
- 圧縮カーネルイメージ
- カーネル起動オプション
- ブートファイルシステム
など
Linux の vmlinuz + initrd
に近いです。
ZBI データ構造
- Container Header
ZBI の先頭ヘッダー - Boot Item
- Boot Item Header
データ(Payload)を説明するヘッダー - Payload
データ本体
- Boot Item Header
Container Header と Boot Item Header の実体は zbi_header_t 構造体です。
- zbi_header_t
- type: Payload の種別
- length: Header を除いたデータ(Payload)サイズ
- extra: type によって用途が異なる
- flags: 次のフラグの論理和
- 必須:0x00010000 (ZBI_FLAG_VERSION)
- 圧縮されたペイロードの場合:0x00000001 (ZBI_FLAG_STORAGE_COMPRESSED)
- CRC32 を持つ場合:0x00020000 (ZBI_FLAG_CRC32)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32:
- CRC32 を持つ場合:CRC32 の値
- CRC32 を持たない場合:0x4a87e8d6 (ZBI_ITEM_NO_CRC32)
ソースコード:zircon/system/public/zircon/boot/image.h
Container Header
- zbi_header_t
- type: 0x544f4f42 (ZBI_TYPE_CONTAINER)。Conteiner Header を示す
- length: Conteiner Header を除いたデータサイズ
- extra: 0x868cf7e6 (ZBI_CONTAINER_MAGIC)
- flags: 0x00010000 (ZBI_FLAG_VERSION)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0x4a87e8d6 (ZBI_ITEM_NO_CRC32)。CRC32 を持たない
Boot Item Header
- zbi_header_t
- type:
- ブートローダの場合:0x4c4e524b (ZBI_TYPE_KERNEL_X64)
- 圧縮カーネルの場合:0x5254534b (ZBI_TYPE_STORAGE_KERNEL)
- 起動オプションの場合:0x4c444d43 (ZBI_TYPE_CMDLINE)
- bootfs の場合:0x42534642 (ZBI_TYPE_STORAGE_BOOTFS)
- エントロピーの場合:0x444e4152 (ZBI_TYPE_SECURE_ENTROPY)
- length: Boot Item Header を除いたデータサイズ(ペイロードのサイズ)
- extra: type によって用途が異なる
- flags: Boot Item による
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: Boot Item による
- type:
Boot Item Payload
データ本体です。
- 8 バイト境界にパディング
- Boot Item Header の length は、パディング無しのサイズ
ZBI のヘッダー具体例
次の環境で生成される ZBI(fuchsia-ssh.zbi)について紹介します。
fx set bringup.x64
fx build
fx qemu
bringup.x64 は、x86-64 アーキテクチャで動作する最小のブート環境です。
fx qemu で実行する qemu の引数を簡単に示します。
qemu -kernel multiboot.bin -initrd fuchsia-ssh.zbi
-kernel
でブートローダ(multiboot.bin)を、-initrd
で ZBI(fuchsia-ssh.zbi)を指定します。
- qemu は、ブートローダと ZBI の両方をメモリにロードし、ブートローダを実行します
- ブートローダは ZBI から physboot ブートローダを見つけ、実行します
- physboot は ZBI から圧縮された zircon カーネルを見つけ、展開し、実行します
ブートローダについて
Fuchsia は複数のブートローダを使用します。
Qemu で Fuchsia を動かす場合、multiboot ブートローダと physboot ブートローダを使用します。
multiboot → physboot → zircon
fuchsia-ssh.zbi の中身
Container Header
$ hexdump -C -s 0 -n 32 fuchsia-ssh.zbi
00000000 42 4f 4f 54 d8 b8 aa 01 e6 f7 8c 86 00 00 01 00 |BOOT............|
00000010 00 00 00 00 00 00 00 00 29 17 78 b5 d6 e8 87 4a |........).x....J|
-s 0 -n 32
で先頭から 32 バイト表示します。
リトルエンディアンなので、42 4f 4f 54
が 0x544f4f42
となります。
- zbi_header_t
- type: 0x544f4f42 (ZBI_TYPE_CONTAINER)
- length: 0x01aab8d8 (27,965,656 bytes)
- extra: 0x868cf7e6 (ZBI_CONTAINER_MAGIC)
- flags: 0x00010000 (ZBI_FLAG_VERSION)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0x4a87e8d6 (ZBI_ITEM_NO_CRC32)
physboot Boot Item Header
Zircon 互換ブートローダのヘッダーです。
$ hexdump -C -s 32 -n 32 fuchsia-ssh.zbi
00000020 4b 52 4e 4c 78 7c 0a 00 00 00 00 00 00 00 01 00 |KRNLx|..........|
00000030 00 00 00 00 00 00 00 00 29 17 78 b5 d6 e8 87 4a |........).x....J|
-s 32 -n 32
で先頭 32 バイト目から 32 バイト表示します。
- zbi_header_t
- type: 0x4c4e524b (ZBI_TYPE_KERNEL_X64)
- length: 0x000a7c78 (687,224 bytes)
- extra: 0x0
- flags: 0x00010000 (ZBI_FLAG_VERSION)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0x4a87e8d6 (ZBI_ITEM_NO_CRC32)
compressed zircon Boot Item Header
圧縮された Zircon カーネルイメージのヘッダーです。
$ hexdump -C -s 687288 -n 32 fuchsia-ssh.zbi
000a7cb8 4b 53 54 52 d6 bd 0e 00 88 c9 29 00 01 00 03 00 |KSTR......).....|
000a7cc8 00 00 00 00 00 00 00 00 29 17 78 b5 fd 06 d8 1a |........).x.....|
-s 687288 -n 32
で先頭 687,288 バイト目から 32 バイト表示します。
Container Header 32 bytes +
physboot Boot Item Header 32 bytes + payload 687,224 bytes
= 687,288 bytes
- zbi_header_t
- type: 0x5254534b (ZBI_TYPE_STORAGE_KERNEL)
- length: 0x000ebdd6 (966,102 bytes)
- extra: 0x0029c988 展開後のサイズ 2,738,568 bytes
- flags: 0x00030001 (ZBI_FLAG_VERSION | ZBI_FLAG_CRC32 | ZBI_FLAG_STORAGE_COMPRESSED)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0x1ad806fd
entropy Boot Item Header
エントロピーのヘッダーです。疑似乱数生成のシードに利用します。
$ hexdump -C -s 1653424 -n 32 fuchsia-ssh.zbi
00193ab0 52 41 4e 44 40 00 00 00 00 00 00 00 00 00 03 00 |RAND@...........|
00193ac0 00 00 00 00 00 00 00 00 29 17 78 b5 ae 6a 58 a5 |........).x..jX.|
-s 1653424 -n 32
で先頭 1,653,424 バイト目から 32 バイト表示します。
Container Header 32 bytes +
physboot Boot Item Header 32 bytes + payload 687,224 bytes
compressed zircon Boot Item Header 32 bytes + payload 966,102 bytes + padding 2 bytes
= 1,653,424 bytes
- zbi_header_t
- type: 0x444e4152 (ZBI_TYPE_SECURE_ENTROPY)
- length: 0x00000040 (64 bytes)
- extra: 0x0
- flags: 0x00030000 (ZBI_FLAG_VERSION | ZBI_FLAG_CRC32)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0xa5586aae
cmdline Boot Item Header
カーネル起動オプションのヘッダーです。
$ hexdump -C -s 1653520 -n 32 fuchsia-ssh.zbi
00193b10 43 4d 44 4c e4 00 00 00 00 00 00 00 00 00 03 00 |CMDL............|
00193b20 00 00 00 00 00 00 00 00 29 17 78 b5 03 da 17 a9 |........).x.....|
-s 1653520 -n 32
で先頭 1,653,520 バイト目から 32 バイト表示します。
Container Header 32 bytes +
physboot Boot Item Header 32 bytes + payload 687,224 bytes
compressed zircon Boot Item Header 32 bytes + payload 966,102 bytes + padding 2 bytes
entropy Boot Item Header 32 bytes + payload 64 bytes
= 1,653,520 bytes
- zbi_header_t
- type: 0x4c444d43 (ZBI_TYPE_CMDLINE)
- length: 0x000000e4 (228 bytes)
- extra: 0x0
- flags: 0x00030000 (ZBI_FLAG_VERSION | ZBI_FLAG_CRC32)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0xa917da03
bootfs Boot Item Header
ブートファイルシステムのヘッダーです。
$ hexdump -C -s 1653784 -n 32 fuchsia-ssh.zbi
00193c18 42 46 53 42 bc 7c 91 01 00 70 a8 06 01 00 03 00 |BFSB.|...p......|
00193c28 00 00 00 00 00 00 00 00 29 17 78 b5 bb ed 4f 06 |........).x...O.|
-s 1653784 -n 32
で先頭 1,653,784 バイト目から 32 バイト表示します。
Container Header 32 bytes +
physboot Boot Item Header 32 bytes + payload 687,224 bytes
compressed zircon Boot Item Header 32 bytes + payload 966,102 bytes + padding 2 bytes
entropy Boot Item Header 32 bytes + payload 64 bytes
cmdline Boot Item Header 32 bytes + payload 228 bytes + padding 4 bytes
= 1,653,784 bytes
- zbi_header_t
- type: 0x42534642 (ZBI_TYPE_STORAGE_BOOTFS)
- length: 0x01917cbc (26,311,868 bytes)
- extra:
- flags: 0x00030000 (ZBI_FLAG_VERSION | ZBI_FLAG_CRC32)
- reserved0: 0x0
- reserved1: 0x0
- magic: 0xb5781729 (ZBI_ITEM_MAGIC)
- crc32: 0xa917da03
合計サイズ
Container Header 32 bytes +
physboot Boot Item Header 32 bytes + payload 687,224 bytes
compressed zircon Boot Item Header 32 bytes + payload 966,102 bytes + padding 2 bytes
entropy Boot Item Header 32 bytes + payload 64 bytes
cmdline Boot Item Header 32 bytes + payload 228 bytes + padding 4 bytes
bootfs Boot Item Header 32 bytes + payload 26,311,868 bytes + padding 4 bytes
= 27,965,688 bytes
これは、Container Header size 32 bytes
+ Container Header length 27,965,656 bytes
に一致します。
ZBI のデータ具体例
fx build
時に実行されるコマンドは out/default/*/toolchain.ninja
に記載。
*.ninja
についてはこちらの記事を参照。
fuchsia-ssh.zbi
bringup.zbi
に SSH 公開鍵 data/ssh/authorized_keys
とエントロピーを追加したものです。
fucnshia-ssh.zbi = bringup.zbi + data/ssh/authorized_keys + entropy
生成方法
fx qemu
時に zbi
コマンドで fuchsia-ssh.zbi
を生成します。
-
zbi \ --compressed="zstd" \ -o "fuchsia-ssh.zbi" \ "bringup.zbi" \ --entry "data/ssh/authorized_keys=${HOME}/.ssh/fuchsia_authorized_keys" \ --type=entropy:64 /dev/urandom
-
bringup.zbi
のbootfs
に SSH 公開鍵を追加- SSH 公開鍵の実体は、
${HOME}/.ssh/fuchsia_authorized_keys
- SSH 公開鍵の実体は、
- (SSH 公開鍵追加後に)
bootfs
をzstd
で圧縮 - エントロピーは、
/dev/urandom
から 64 バイト読み出した値
-
関連するソースコード
-
tools/devshell/qemu
fx-zbi
の呼び出し -
tools/devshell/lib/vars.sh
fx-zbi
の定義。zbi
の実行 -
zircon/tools/zbi/zbi.cc
zbi
の実体
bringup.zbi
fuchsia-ssh.zbi
のベースとなる ZBI です。
physzircon.zbi
と cmdline
起動オプションと bootfs
ブートファイルシステムから構成されます。
-
ブートファイルシステムは、ブートプロセスの初期に必要なファイルを格納しています。
bootfs RAM ディスクには、ブートプロセスの初期段階で、他のファイルシステムが利用できない場合に必要なファイルが格納されています。これは zircon ブートイメージの一部であり、 bootsvc によって解凍されて提供されます。初期のブートプロセスが完了すると、bootfs は
/boot
にマウントされます。
bringup.zbi = physzircon.zbi + cmdline + bootfs
生成方法
fx build
時に ffx
コマンドで bringup.zbi
を生成します。
-
out/default/toolchain.ninja より抜粋
ffx \ --env .ffx.env \ --config assembly_enabled=true \ assembly image \ --product obj/build/images/bringup/bringup_product_config.json \ --board obj/build/images/bringup/bringup_board_config.json \ --gendir obj/build/images/bringup/bringup/gen \ --outdir obj/build/images/bringup/bringup
construct_zbi()@src/developer/ffx/plugins/assembly/src/zbi.rs に関係する部分のみ紹介。
-
assembly image
カーネルイメージ、起動オプション、ブートファイルシステムを結合して ZBI イメージファイルを生成 -
--product bringup_product_config.json
カーネルイメージphyszircon.zbi
、起動オプションcmdline
、ブートファイルシステムbootfs
を指定 -
--board bringup_board_config.json
出力ファイル名、圧縮方式などを指定
-
-
bringup_product_config.json
generate_product_config()@build/images/assemble_system.gniで生成
bringup_product_config.json 抜粋{ "base_packages": [], "cache_packages": [], "extra_packages_for_base_package": [], "version_file": "latest-commit-date.txt", "epoch_file": "obj/src/sys/pkg/bin/system-updater/epoch.json", "kernel_image": "kernel_x64/physzircon.zbi", "kernel_cmdline": [ "kernel.serial=legacy", "blobfs.cache-eviction-policy=NEVER_EVICT", "console.shell=true", "kernel.enable-debugging-syscalls=true", "kernel.enable-serial-syscalls=true", "kernel.oom.behavior=jobkill", "netsvc.all-features=true", "netsvc.disable=false" ], "boot_args": [], "bootfs_files": [ { "destination": "bin/acpidump", "label": "//src/devices/bin/acpidump:acpidump(//build/toolchain/fuchsia:x64)", "source": "zircon-migrated/acpidump" }, ... { "destination": "config/archivist/archivist_config.json", "label": "//src/diagnostics/archivist:root-config(//build/toolchain/fuchsia:x64)", "source": "../../src/diagnostics/archivist/configs/root-config.json" }, ... { "destination": "data/lspci/pci.ids", "label": "//src/devices/pci/bin/lspci:database(//build/toolchain/fuchsia:x64)", "source": "../../third_party/pciids/pci.ids" }, { "destination": "driver/ahci.so", "label": "//src/devices/block/drivers/ahci:ahci-driver(//build/toolchain/fuchsia:x64-shared)", "source": "x64-shared/ahci.so" }, ... { "destination": "lib/ld.so.1", "label": "//zircon/system/ulib/c:c(//zircon/system/ulib/c:user.libc_x64)", "source": "user.libc_x64/libc.so" }, ... { "destination": "meta/ahci.cm", "label": "//src/devices/block/drivers/ahci:ahci_manifest_resource(//build/toolchain/fuchsia:x64)", "source": "obj/src/devices/block/drivers/ahci/cml/ahci/ahci.cm" }, ... ], "update_package_name": "update", "base_package_name": "system_image" }
-
kernel_image
カーネルイメージを指定 -
kernel_cmdline
起動オプションを指定 -
bootfs_files
ブートファイルシステムの中身を指定
-
-
bringup_board_config.json
generate_board_config()@build/images/assemble_system.gniで生成
bringup_board_config.json{ "arch": "x64", "blobfs": { "compress": true, "layout": "compact" }, "board_name": "x64", "bootloaders": [ { "name": "bootloader", "partition": "bootloader", "source": "fuchsia.esp.blk", "type": "esp" } ], "recovery": { "name": "zedboot", "vbmeta": "zedboot.vbmeta", "zbi": "zedboot.zbi" }, "vbmeta": { "additional_descriptor_files": [ ], "kernel_partition": "zircon", "key": "../../third_party/android/platform/external/avb/test/data/testkey_atx_psk.pem", "key_metadata": "../../third_party/android/platform/external/avb/test/data/atx_metadata.bin", "partition": "vbmeta_a" }, "zbi": { "backstop_file": "minimum-utc-stamp.txt", "compression": "zstd", "embed_fvm_in_zbi": false, "max_size": 0, "name": "bringup", "partition": "zircon-a" } }
-
zbi.compression
Boot Item の圧縮方法 -
zbi.name
出力する ZBI ファイルの名前 -
recovoery
、bootloaders
、vbmeta
(verified boot metadata)などは更新パッケージに必要
-
関連するソースコード
-
build/images/bringup/BUILD.gn
assemble_system("bringup")
の呼び出し -
build/images/assemble_system.gni
assemble_system
の定義。ffx_action
の呼び出し -
src/developer/ffx/build/ffx_action.gni
ffx_action
の定義。ffx
の実行 -
src/developer/ffx
ffx
の実体
ドキュメント
physzircon.zbi
physboot.zbi
ブートローダと、"kernel.zbi
カーネルイメージを圧縮した"データ。
physzircon.zbi = physboot.zbi + kernel.zbi自体(ZBIヘッダ込)を圧縮したもの
生成方法
fx build
時に zbi
コマンドで physzircon.zbi
を生成します。
-
out/default/kernel_x64/toolchain.ninja
../../build/zbi/run_zbi.py \ --zbi host_x64/zbi \ --depfile kernel_x64/physzircon.zbi.d \ --rspfile kernel_x64/gen/zircon/kernel/physzircon.zbi.rsp \ --output kernel_x64/physzircon.zbi \ --json-output kernel_x64/physzircon.zbi.json \ --bootable=x64 \ --compressed=zstd ↓ になります。 zbi \ --depfile kernel_x64/physzircon.zbi.d.intermediate \ --prefix= --files --compressed --type=kernel --compressed=max kernel_x64/kernel.zbi \ --files kernel_x64/gen/zircon/kernel/vmzircon.fini \ --type=container kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi \ --prefix= --compressed --files kernel_x64/gen/zircon/kernel/physzircon_input.fini \ --output kernel_x64/physzircon.zbi \ --json-output kernel_x64/physzircon.zbi.json \ --bootable=x64 \ --compressed=zstd
physboot.zbi と圧縮した kernel.zbi を結合します。
-
入力オプション
-
--prefix= --files --type=kernel --compressed=max kernel_x64/kernel.zbi
-
kernel.zbi
をカーネルイメージファイル(ZBI_TYPE_STORAGE_KERNEL
)として扱う - ペイロードは
zstd
・圧縮率最大でkernel.zbi
を圧縮したデータ - Item::CreateFromFile()、Item::WriteZBI()
-
-
--files kernel_x64/gen/zircon/kernel/vmzircon.fini
今回は空ファイル
-
--type=container kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi
-
physboot.zbi
を ZBI ファイル(ZBI_TYPE_CONTAINER
)として扱う-
physboot.zbi
中のBootItem
をそのまま出力ファイルにコピーする
-
- ImportFile()
-
-
--prefix= --compressed --files kernel_x64/gen/zircon/kernel/physzircon_input.fini
今回は空ファイル
-
-
出力オプション
-
--output kernel_x64/physzircon.zbi
出力 ZBI ファイル名 -
--json-output kernel_x64/physzircon.zbi.json
ZBI 中の BootItem を記載した JSON ファイル -
--depfile kernel_x64/physzircon.zbi.d.intermediate
依存関係を記載したファイル。自動で削除される
-
-
フォーマットオプション
-
--bootable=x64
bootable image であるか検証する。
bootable image とは、physboot
(ZBI_TYPE_KERNEL_{X64,ARM64}
)が BootItem の先頭である ZBI のこと -
--compressed=zstd
bootfs
をzstd
で圧縮する。今回はbootfs
がないので無効
-
-
関連するソースコード
-
zircon/kernel/BUILD.gn
zbi("physzircon")
zbi_input("vmzircon")
-
build/zbi/zbi_input.gni
zbi_input()
の定義 -
build/zbi/zbi.gni
zbi()
の定義。run_zbi.py の実行 -
build/zbi/run_zbi.py
zbi
コマンドの実行 -
zircon/tools/zbi/zbi.cc
zbi
の実体
physboot.zbi
physboot
ブートローダのみを含む ZBI。
physboot.zbi = Container Header + BootItem Header + physboot
ペイロードは objcopy -O binary physboot
で ELF ヘッダーを除去されたバイナリファイルです。
生成方法
../../build/zircon/toolchain_utils_action.sh \
kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi \
kernel.phys_x64/obj/zircon/kernel/phys/_host_tool_action.physboot.d \
../../prebuilt/third_party/clang/linux-x64/bin/llvm-objcopy \
-O binary \
@kernel.phys_x64/gen/zircon/kernel/phys/physboot.image.rsp \
kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi
↓ になります。
llvm-objcopy \
-O binary \
kernel.phys_x64/physboot
kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi
physboot
のコンパイル、リンクは out/default/kernel.phys_x64/obj/zircon/kernel/phys/_phys_executable.physboot.executable.ninja
に記載。
zircon/kernel/phys/zbi-header.S
、zircon/kernel/phys/zbi-header.ld
でリンクすることで、ELF ファイルの段階ですでに ZBI ヘッダーが含まれています。
objcopy
で ELF ヘッダーを除去すると、ZBI ファイルが出来上がります。
-
zircon/kernel/phys/zbi-header.S 抜粋
.section .boot.header, "a", %progbits ZBI_CONTAINER_HEADER(kZbiContainerHeader, PHYS_LOAD_END - kZbiItemHeader) // zbi_header_t .object kZbiItemHeader, rodata, nosection=nosection #ifdef __aarch64__ .int ZBI_TYPE_KERNEL_ARM64 // type #elif defined(__x86_64__) .int ZBI_TYPE_KERNEL_X64 // type #else #error "what machine?" #endif .int PHYS_LOAD_END - kZbiKernelHeader // length .int 0 // extra .int ZBI_FLAG_VERSION // flags .int 0, 0 // reserved0, reserved1 .int ZBI_ITEM_MAGIC // magic .int ZBI_ITEM_NO_CRC32 // crc32 .end_object
関連するソースコード
- zircon/kernel/phys/BUILD.gn
-
zircon/kernel/phys/zbi_executable.gni
physboot
バイナリにContainer Header、BootItem Header
をつける指定。phys_executable
を呼ぶ。
(リンカスクリプトzbi-header.ld
で) -
zircon/kernel/phys/phys_executable.gni
physboot
ELF ファイルビルド。physboot
バイナリ生成
kernel.zbi
(非圧縮)カーネルイメージのみを含む ZBI。
kernel.zbi = Container Header + BootItem Header + image
ペイロードはカーネルイメージファイル image
から objcopy -O binary
で ELF ヘッダーを除去したバイナリファイルです。
生成方法
../../build/zircon/toolchain_utils_action.sh \
kernel_x64/kernel.zbi \
kernel_x64/obj/zircon/kernel/_host_tool_action.kernel.d \
../../prebuilt/third_party/clang/linux-x64/bin/llvm-objcopy \
-O binary \
@kernel_x64/gen/zircon/kernel/kernel.image.rsp \
kernel_x64/kernel.zbi
↓ になります。
llvm-objcopy \
-O binary \
kernel_x64/image \
kernel_x64/kernel.zbi
image
から ELF ヘッダーを除去します。
image
は、zircon/kernel/arch/x86/image.S
、zircon/kernel/image.ld
でリンクすることで、ELF ファイルの段階ですでに ZBI ヘッダーが含まれています。
objcopy
で ELF ヘッダーを除去すると、ZBI ファイルが出来上がります。
kernel_x64/image ができるまで
-
zircon ELF ファイルをビルド(out/default/kernel_x64/zircon.elf)
カーネル本体。
リンカスクリプトは zircon/kernel/kernel.ld。
zircon
のコンパイル、リンクはout/default/kernel.phys_x64/obj/zircon/kernel/zircon.ninja
に記載。 -
objcopy -O binary
で zircon から ELF ヘッダーを除去 -
image ELF ファイルをビルド(out/default/kernel_x64/image)
リンカスクリプトは zircon/kernel/image.ld。
ヘッダーは zircon/kernel/arch/x86/image.S で指定。
image
のコンパイル、リンクはout/default/kernel.phys_x64/obj/zircon/kernel/image.ninja
に記載。image = ELF Header + Container Header + BootItem Header + ZBI kernel header + zircon + fixupコード
-
ZBI kernel header
は、ZBI_TYPE が KERNEL の時に使われるヘッダー
実体は、zbi_kernel_t 構造体 -
fixup コードは、
KASLR(Kernel Address Space Layout Randomization)
を実現するためのコードリンク時に決まった zircon 中の(絶対)アドレスを、実際にロードされたアドレスに書き換えるコード。
実体は、zircon
ビルド後に生成されるout/default/kernel_x64/gen/zircon/kernel/kernel-fixups.inc
-
-
zircon/kernel/arch/x86/image.S 抜粋
// ZBI file header (zbi_header_t) ZBI_CONTAINER_HEADER(_zbi_file_header, boot_load_end - _zbi_kernel_header) // ZBI kernel header (zbi_header_t) DATA(_zbi_kernel_header) .int ZBI_TYPE_KERNEL_X64 .int boot_load_end - _zbi_kernel_payload .int 0 .int ZBI_FLAG_VERSION .int 0 .int 0 .int ZBI_ITEM_MAGIC .int ZBI_ITEM_NO_CRC32 END_DATA(_zbi_kernel_header) // ZBI_TYPE_KERNEL payload (zbi_kernel_t) DATA(_zbi_kernel_payload) .quad PHYS(IMAGE_ELF_ENTRY) .quad boot_bss_end - boot_load_end END_DATA(_zbi_kernel_payload)
関連するソースコード
成果物一覧
-
ZBI ファイル
$ rg --files | rg ".zbi$" | rg -v test host_arm64/zbi fuchsia_prime.zbi fuchsia.zbi netboot.zbi zedboot.zbi bringup.zbi host_x64/zbi kernel_x64/kernel.zbi kernel_x64/physzircon.zbi host_arm64/exe.unstripped/zbi host_x64/exe.unstripped/zbi obj/build/images/fuchsia/fuchsia/fuchsia.zbi obj/build/images/fuchsia/fuchsia_prime/fuchsia_prime.zbi obj/build/images/fuchsia/netboot/netboot.zbi obj/build/images/bringup/bringup/bringup.zbi kernel.phys_x64/obj/zircon/kernel/phys/physboot.zbi kernel.phys_x64/obj/zircon/kernel/arch/x86/phys/boot-shim/phys-1mb-hello-world.zbi kernel.phys_x64/obj/zircon/kernel/arch/x86/phys/boot-shim/pic-1mb-boot-shim.zbi kernel.phys_x64/obj/zircon/kernel/arch/x86/phys/boot-shim/x86-legacy-zbi-boot-shim.zbi
-
ZBI JSON ファイル
*.zbi.json
で ZBI ファイルの中身を知ることができます。$ rg --files | rg ".zbi.json$" | rg -v test zedboot.zbi.json fuchsia_prime.zbi.json fuchsia.zbi.json netboot.zbi.json bringup.zbi.json kernel_x64/physzircon.zbi.json obj/build/images/sizes/fuchsia.zbi.json obj/build/images/fuchsia/fuchsia/gen/zbi.json obj/build/images/fuchsia/fuchsia_prime/gen/zbi.json obj/build/images/fuchsia/netboot/gen/zbi.json obj/build/images/bringup/bringup/gen/zbi.json
Discussion