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
350
カーネルVM関西 7回目 発表資料
忙しい(言い訳)という事でした.カーネルVM関西 7回目の発表資料です. 発表で口頭だった部分をちゃんと書きました.
orumin
December 06, 2014
Tweet
Share
More Decks by orumin
See All by orumin
ヴィンテージマシンと付き合う - kernel/vm online 5
orumin
0
1k
むかしの RISC、むかしの Unix
orumin
7
3.4k
Fundamental of architecture to implementing OS on AArch64
orumin
3
4.7k
Kernel/VM Kansai #9
orumin
0
900
Kernel/VM #14 発表資料
orumin
1
540
Unikernels report
orumin
2
440
第13回Kernel/VM勉強会発表資料
orumin
1
1.6k
第12回カーネル/VM探検隊
orumin
0
350
第11回 Kernel/VM探検隊 発表資料
orumin
1
530
Other Decks in Technology
See All in Technology
デザインから逆算して難易度を見積もるための観点
fumiyasac0921
0
120
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
350
Developer Summit 2025 [14-D-1] Yuki Hattori
yuhattor
18
4.5k
5分で紹介する生成AIエージェントとAmazon Bedrock Agents / 5-minutes introduction to generative AI agents and Amazon Bedrock Agents
hideakiaoyagi
0
210
目の前の仕事と向き合うことで成長できる - 仕事とスキルを広げる / Every little bit counts
soudai
21
4.6k
生成AIの利活用を加速させるための取り組み「prAIrie-dog」/ Shibuya_AI_1
visional_engineering_and_design
1
140
自動テストの世界に、この5年間で起きたこと
autifyhq
7
6.3k
30分でわかる『アジャイルデータモデリング』
hanon52_
9
2k
『AWS Distinguished Engineerに学ぶ リトライの技術』 #ARC403/Marc Brooker on Try again: The tools and techniques behind resilient systems
quiver
0
130
開発スピードは上がっている…品質はどうする? スピードと品質を両立させるためのプロダクト開発の進め方とは #DevSumi #DevSumiB / Agile And Quality
nihonbuson
1
790
CZII - CryoET Object Identification 参加振り返り・解法共有
tattaka
0
190
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
6
1.5k
Featured
See All Featured
Bash Introduction
62gerente
610
210k
Thoughts on Productivity
jonyablonski
69
4.4k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
It's Worth the Effort
3n
184
28k
Producing Creativity
orderedlist
PRO
343
39k
What's in a price? How to price your products and services
michaelherold
244
12k
Visualization
eitanlees
146
15k
Testing 201, or: Great Expectations
jmmastey
41
7.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
29
2.2k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
99
18k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
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
を付けわすれてハ マった以外はバグが出ず,実行は一発で成功 • なんて簡単なんだ
• さいごに : • みんなもスライドはちゃんと用意しましょう