Upgrade to Pro — share decks privately, control downloads, hide ads and more …

カーネルVM関西 7回目 発表資料

orumin
December 06, 2014

カーネルVM関西 7回目 発表資料

忙しい(言い訳)という事でした.カーネルVM関西 7回目の発表資料です. 発表で口頭だった部分をちゃんと書きました.

orumin

December 06, 2014
Tweet

More Decks by orumin

Other Decks in Technology

Transcript

  1. • orumin (@kotatsu_mi) • Google Summer of Code 2014 で

    OSv に Ruby を移植してました. • 以前 UEFI 遊びしてた
  2. • UEFI とは ? • UEFI Advent Calender 2014 参照

    ! • http://qiita.com/advent-calendar/2014/uefi • 質問でも BIOS なブートローダーでも u-boot で も良いのでそれっぽいネタ大募集中
  3. • UEFI の基本スペック • C 言語な SDK , EDK(NTDDK 風味

    ) • FAT32 なシステムパーティションを高レイヤに 読み書きできる • stdio.h もつかえるぜ !
  4. Makefile • ARCH = x86_64 • EFIROOT = /usr •

    HDDRROOT = $(EFIROOT)/include/efi • INCLUDES = -I. -I$(HDDRROOT) -I$(HDDRROOT)/ $(ARCH) -I$(HDDRROOT)/protocol • EFIROOT は configure で /usr/local とかにインスト ール先指定してたらそこに変更
  5. 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)
  6. Makefile • CFLAGS は -fPIC と -fshort-wchar ,あと x86_64 ならば

    -DEFI_FUNCTION_WRAPPER を忘れなけ ればあとは好きなようにして大丈夫 • CPP にも FLAG を設定する必要アリ
  7. 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)
  8. Makefile • prefix = • CC = $(prefix)gcc • AS

    = $(prefix)as • LD = $(prefix)ld • AR = $(prefix)ar • RANLIB = $(prefix)ranlib • OBJCOPY = $(prefix)objcopy
  9. 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 $@
  10. ソースコード ( 前知識 ) • efi.h , gnuefi.h をインクルード •

    エントリポイントは efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE) • UEFI は Protocol という API を使う • 基本, OpenProtocol で Protocol の Handle を開いて,必 要な Protocol の関数ポインタ群を対応する Protocol 構造 体に詰めて,そこから Protocol の関数を呼ぶ •
  11. ソースコード ( 前知識 ) • gnu-efi の場合 uefi_call_wrapper() で第一引数に UEFI

    の Protocol の関数ポインタ指定してつかう • なお,ソースコード中の BS は BootServices で, EFI_BOOT_SERVICES というブートローダーに 必要なプロトコルのハンドラ.これは OpenProtocol とかしなくても最初からグローバルの BS という変 数に詰めてある ( でないと OpenProtocol が呼べな い )
  12. ソースコード • uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &LoadedImageProtocol, &LoadedImageParent, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);

    • まず自分自身のハンドルから,既に読み込まれ てるメモリイメージ ( 実行バイナリイメージ ) についての Protocol を取得
  13. ソースコード • Path = FileDevicePath(LoadedImageParent- >DeviceHandle, L"\\vmlinuz"); • 先ほど取得した Protocol

    ハンドルにあるデバイ スへのハンドルと, Linux カーネルへのパスを 引数に,カーネルのファイルへのデバイスパス を取得
  14. ソースコード • この時指定するパスは, EFI のシステムパーテ ィションのパス. • カーネルもそこに置かないといけない • もし普通に

    ext4 とかに置かれたものを読みた ければ, ext4 について EFI_SIMPLE_FILESYSTEM プロトコルを提供でき るように EFI Driver を書くしかない
  15. ソースコード • uefi_call_wrapper(BS->LoadImage, 6, FALSE, ImageHandle, Path, NULL, 0, &Image);

    • 取得したデバイスパスをつかって,新たにメモ リイメージ ( 実行バイナリイメージ ) をメモリ にロード
  16. ソースコード • uefi_call_wrapper(BS->OpenProtocol, 6, Image, &LoadedImageProtocol, &LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);

    • また LoadedImage の Protocol • 今度は自分自身のイメージではなく先ほど読み込 んだカーネルのイメージについて Protocol を取得
  17. ソースコード • LoadedImage->LoadOptions = Options; • LoadedImage->LoadOptionsSize = (StrLen(LoadedImage->LoadOptions)+1) *

    sizeof(CHAR16); • この Protocol のメンバに起動オプションのため のフィールドがあるので指定するだけ
  18. ソースコード • LoadOptions に渡してる Options • CHAR16 *Options = L"root=/dev/sda2

    rootfstype=btrfs rw quiet splash"; • こんな感じで CHAR16 型の文字列を指定すれば 良い • CHAR16 型なので文字列リテラルのプレフィク スに L を付けておく ← 大事
  19. ブートローダー • initrd 対応サボってるのでファイルシステムのドラ イバが組み込みじゃなくてモジュールになっちゃっ てる ( よくあるディストリビューション標準の ) カ

    ーネルは起動時に root mount でカーネルパニックし ます. • ハードコードしてるカーネルのファイルパスと起動 オプションは環境に合わせると誰でも使えると思 う.
  20. ブートローダー • 自作 OS でブートローダー書く時点で満足とい う話はおおかった. • UEFI ではもはやそんな事はないよ !

    • 自作 OS のカーネルも生バイナリつくって EFI システムパーティションに配置するだけで良い • とってもラク !