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
現場で役立つAPIデザイン
nagix
33
12k
なぜ私は自分が使わないサービスを作るのか? / Why would I create a service that I would not use?
aiandrox
0
760
偶然 × 行動で人生の可能性を広げよう / Serendipity × Action: Discover Your Possibilities
ar_tama
1
1.1k
スタートアップ1人目QAエンジニアが QAチームを立ち上げ、“個”からチーム、 そして“組織”に成長するまで / How to set up QA team at reiwatravel
mii3king
2
1.5k
Amazon S3 Tablesと外部分析基盤連携について / Amazon S3 Tables and External Data Analytics Platform
nttcom
0
140
Developers Summit 2025 浅野卓也(13-B-7 LegalOn Technologies)
legalontechnologies
PRO
0
740
30分でわかる『アジャイルデータモデリング』
hanon52_
9
2.7k
飲食店予約台帳を支えるインタラクティブ UI 設計と実装
siropaca
7
1.8k
データ資産をシームレスに伝達するためのイベント駆動型アーキテクチャ
kakehashi
PRO
2
550
君も受託系GISエンジニアにならないか
sudataka
2
440
N=1から解き明かすAWS ソリューションアーキテクトの魅力
kiiwami
0
130
転生CISOサバイバル・ガイド / CISO Career Transition Survival Guide
kanny
3
1k
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
40
2.5k
Building an army of robots
kneath
303
45k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
A designer walks into a library…
pauljervisheath
205
24k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.2k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.4k
Rails Girls Zürich Keynote
gr2m
94
13k
Writing Fast Ruby
sferik
628
61k
Designing for humans not robots
tammielis
250
25k
Done Done
chrislema
182
16k
VelocityConf: Rendering Performance Case Studies
addyosmani
328
24k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
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
を付けわすれてハ マった以外はバグが出ず,実行は一発で成功 • なんて簡単なんだ
• さいごに : • みんなもスライドはちゃんと用意しましょう