Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
カーネルVM関西 7回目 発表資料
Search
orumin
December 06, 2014
Technology
0
360
カーネルVM関西 7回目 発表資料
忙しい(言い訳)という事でした.カーネルVM関西 7回目の発表資料です. 発表で口頭だった部分をちゃんと書きました.
orumin
December 06, 2014
Tweet
Share
More Decks by orumin
See All by orumin
ヴィンテージマシンと付き合う - kernel/vm online 5
orumin
0
1.1k
むかしの RISC、むかしの Unix
orumin
7
3.5k
Fundamental of architecture to implementing OS on AArch64
orumin
3
4.8k
Kernel/VM Kansai #9
orumin
0
920
Kernel/VM #14 発表資料
orumin
1
570
Unikernels report
orumin
2
460
第13回Kernel/VM勉強会発表資料
orumin
1
1.6k
第12回カーネル/VM探検隊
orumin
0
360
第11回 Kernel/VM探検隊 発表資料
orumin
1
560
Other Decks in Technology
See All in Technology
【2025 Japan AWS Jr. Champions Ignition】点から線、線から面へ〜僕たちが起こすコラボレーション・ムーブメント〜
amixedcolor
1
120
Claude Codeは仕様駆動の夢を見ない
gotalab555
7
1.5k
GMOペパボのデータ基盤とデータ活用の現在地 / Current State of GMO Pepabo's Data Infrastructure and Data Utilization
zaimy
3
200
Claude Codeから我々が学ぶべきこと
s4yuba
7
1.9k
AIに目を奪われすぎて、周りの困っている人間が見えなくなっていませんか?
cap120
1
430
Segment Anything Modelの最新動向:SAM2とその発展系
tenten0727
0
390
僕たちが「開発しやすさ」を求め 模索し続けたアーキテクチャ #アーキテクチャ勉強会_findy
bengo4com
0
2k
Strands Agents & Bedrock AgentCoreを1分でおさらい
minorun365
PRO
6
230
隙間時間で爆速開発! Claude Code × Vibe Coding で作るマニュアル自動生成サービス
akitomonam
3
250
AIエージェントを現場で使う / 2025.08.07 著者陣に聞く!現場で活用するためのAIエージェント実践入門(Findyランチセッション)
smiyawaki0820
6
620
Google Cloud で学ぶデータエンジニアリング入門 2025年版 #GoogleCloudNext / 20250805
kazaneya
PRO
11
2.8k
MCP認可の現在地と自律型エージェント対応に向けた課題 / MCP Authorization Today and Challenges to Support Autonomous Agents
yokawasa
5
1.7k
Featured
See All Featured
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
The Invisible Side of Design
smashingmag
301
51k
Code Review Best Practice
trishagee
69
19k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
229
22k
Building Adaptive Systems
keathley
43
2.7k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Statistics for Hackers
jakevdp
799
220k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.9k
The Art of Programming - Codeland 2020
erikaheidi
54
13k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Transcript
忙しくて時間がなくなったので 10 分でブートローダーをつくっ た話で茶濁す
• orumin (@kotatsu_mi) • Google Summer of Code 2014 で
OSv に Ruby を移植してました. • 以前 UEFI 遊びしてた
• UEFI! • BIOS もう捨てよう • GRUB も要らない (UEFI のブートセレクタで良
い )
• UEFI とは ? • UEFI Advent Calender 2014 参照
! • http://qiita.com/advent-calendar/2014/uefi • 質問でも BIOS なブートローダーでも u-boot で も良いのでそれっぽいネタ大募集中
• 本題,ブートローダー
• UEFI の基本スペック • C 言語な SDK , EDK(NTDDK 風味
) • FAT32 なシステムパーティションを高レイヤに 読み書きできる • stdio.h もつかえるぜ !
• でも今回は EDK つかいません
• 表題通り時間がなかったので
• 表題通り時間がなかったので • gnu-efi でお茶を濁す
• gnu-efi: • 名前が GNU なのに License は BSDL •
なぜ ???
• Binutils とこれをビルドする必要…… • 今はなくなってる (?) • apt-get install gnu-efi
• pacman -S gnu-efi-libs
• #include<efi.h> • #include<efilib.h> • リンカオプションに -lefi -lgnuefi • あとはコード書くだけ
!
• https://github.com/orumin/SimpleMyLoader
Makefile • ARCH = x86_64 • EFIROOT = /usr •
HDDRROOT = $(EFIROOT)/include/efi • INCLUDES = -I. -I$(HDDRROOT) -I$(HDDRROOT)/ $(ARCH) -I$(HDDRROOT)/protocol • EFIROOT は configure で /usr/local とかにインスト ール先指定してたらそこに変更
Makefile • CFLAGS = -O2 -fPIC -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants
-mno- red-zone • ifeq ($(ARCH),x86_64) • CFLAGS += -DEFI_FUNCTION_WRAPPER • endif • • CPPFLAGS = -DCONFIG_$(ARCH)
Makefile • CFLAGS は -fPIC と -fshort-wchar ,あと x86_64 ならば
-DEFI_FUNCTION_WRAPPER を忘れなけ ればあとは好きなようにして大丈夫 • CPP にも FLAG を設定する必要アリ
Makefile • CRTOBJS= $(EFIROOT)/lib/crt0-efi-$(ARCH).o • FORMAT = efi-app-$(ARCH) • INSTALL
= install • LDFLAGS = -nostdlib • LDSCRIPT = $(EFIROOT)/lib/elf_$(ARCH)_efi.lds • LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic -L$(EFIROOT)/lib $(CRTOBJS) • LOADLIBS = -lefi -lgnuefi $(shell $(CC) -print- libgcc-file-name)
Makefile • リンカスクリプト,スタートアップルーチン, 共に gnu-efi のものを使うようにする • -nostdlib -shared •
先にも書いたように -lefi と -lgnuefi で gnu-efi をリンク
Makefile • prefix = • CC = $(prefix)gcc • AS
= $(prefix)as • LD = $(prefix)ld • AR = $(prefix)ar • RANLIB = $(prefix)ranlib • OBJCOPY = $(prefix)objcopy
Makefile • もし binutils や gcc を UEFI アプリケーションの ためにビルドしてどこか特定のディレクトリに
入れたなら prefix を指定.
Makefile • %.efi: %.so • $(OBJCOPY) -j .text -j .sdata
-j .data -j .dynamic -j .dynsym -j .rel \ • -j .rela -j .reloc --target=$(FORMAT) $*.so $@ • • %.so: %.o • $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBS) • • %.o: %.c • $(CC) $(INCLUDES) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
Makefile • C のソースをオブジェクトファイルにするとこ ろ,オブジェクトファイルを so なリロケータ ブルバイナリにするのには先に指定したフラグ を使う. •
とりたてて変わったことはしない.
Makefile • 最後 *.efi を作る時はちょっと特殊 • so なファイルから objcopy で,
ELF のセクショ ンの内必要な部分だけを取り出す
ソースコード ( 前知識 ) • efi.h , gnuefi.h をインクルード •
エントリポイントは efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE) • UEFI は Protocol という API を使う • 基本, OpenProtocol で Protocol の Handle を開いて,必 要な Protocol の関数ポインタ群を対応する Protocol 構造 体に詰めて,そこから Protocol の関数を呼ぶ •
ソースコード ( 前知識 ) • 本来は,たとえば BS->OpenProtocol() みたいに Protocol から直接関数呼び出し
• しかし Microsoft な ABI……
ソースコード ( 前知識 ) • gnu-efi の場合 uefi_call_wrapper() で第一引数に UEFI
の Protocol の関数ポインタ指定してつかう • なお,ソースコード中の BS は BootServices で, EFI_BOOT_SERVICES というブートローダーに 必要なプロトコルのハンドラ.これは OpenProtocol とかしなくても最初からグローバルの BS という変 数に詰めてある ( でないと OpenProtocol が呼べな い )
ソースコード ( 前知識 ) • なお EDK での前準備については 過去発表を参照されたし •
https://speakerdeck.com/orumin/driver
ソースコード • efi_main の引数の ImageHandle , SystemTable • 前者は自分自身のハンドル,後者はデバイスへ のハンドルやパスを手繰るための親のハンドル
や関数が入ってる
ソースコード • uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &LoadedImageProtocol, &LoadedImageParent, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
• まず自分自身のハンドルから,既に読み込まれ てるメモリイメージ ( 実行バイナリイメージ ) についての Protocol を取得
ソースコード • Path = FileDevicePath(LoadedImageParent- >DeviceHandle, L"\\vmlinuz"); • 先ほど取得した Protocol
ハンドルにあるデバイ スへのハンドルと, Linux カーネルへのパスを 引数に,カーネルのファイルへのデバイスパス を取得
ソースコード • この時指定するパスは, EFI のシステムパーテ ィションのパス. • カーネルもそこに置かないといけない • もし普通に
ext4 とかに置かれたものを読みた ければ, ext4 について EFI_SIMPLE_FILESYSTEM プロトコルを提供でき るように EFI Driver を書くしかない
ソースコード • rEFInd のコードがファイルシステムドライバの 参考になります • https://github.com/falstaff84/rEFInd/tree/master /filesystems
ソースコード • uefi_call_wrapper(BS->LoadImage, 6, FALSE, ImageHandle, Path, NULL, 0, &Image);
• 取得したデバイスパスをつかって,新たにメモ リイメージ ( 実行バイナリイメージ ) をメモリ にロード
ソースコード • uefi_call_wrapper(BS->StartImage, 3, Image, NULL, NULL); • そして読み込んだイメージを起動 !
完了 !
ソースコード • というわけにいかない. • Linux の起動に root のパーティションとか指定 するカーネルコマンドライン (
起動オプショ ン ) を指定したい
ソースコード • StartImage を実行する前に……
ソースコード • uefi_call_wrapper(BS->OpenProtocol, 6, Image, &LoadedImageProtocol, &LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
• また LoadedImage の Protocol • 今度は自分自身のイメージではなく先ほど読み込 んだカーネルのイメージについて Protocol を取得
ソースコード • LoadedImage->LoadOptions = Options; • LoadedImage->LoadOptionsSize = (StrLen(LoadedImage->LoadOptions)+1) *
sizeof(CHAR16); • この Protocol のメンバに起動オプションのため のフィールドがあるので指定するだけ
ソースコード • LoadOptions に渡してる Options • CHAR16 *Options = L"root=/dev/sda2
rootfstype=btrfs rw quiet splash"; • こんな感じで CHAR16 型の文字列を指定すれば 良い • CHAR16 型なので文字列リテラルのプレフィク スに L を付けておく ← 大事
ソースコード • 今度こそブートローダーとしての仕事完了 ! • LoadOptions を指定してから, StartImage! • その後の
2,3 行は後処理コード
ブートローダー • initrd 対応サボってるのでファイルシステムのドラ イバが組み込みじゃなくてモジュールになっちゃっ てる ( よくあるディストリビューション標準の ) カ
ーネルは起動時に root mount でカーネルパニックし ます. • ハードコードしてるカーネルのファイルパスと起動 オプションは環境に合わせると誰でも使えると思 う.
ブートローダー • 自作 OS でブートローダー書く時点で満足とい う話はおおかった. • UEFI ではもはやそんな事はないよ !
• 自作 OS のカーネルも生バイナリつくって EFI システムパーティションに配置するだけで良い • とってもラク !
• ちなみにこの発表は先ほどコーディングしたブ ートローダーを用いて起動した ArchLinux で行 ないました. • CHAR16 の変数を作るのに L
を付けわすれてハ マった以外はバグが出ず,実行は一発で成功 • なんて簡単なんだ
• さいごに : • みんなもスライドはちゃんと用意しましょう