view slide/slide.md @ 21:1769ede4d434

fin
author okud
date Tue, 16 Feb 2021 06:12:58 +0900
parents b9113f671dec
children f7343e8d74ca
line wrap: on
line source

---
marp: true
title: Gears OS UEFI対応
paginate: true

theme: default
size: 16:9
style: |
  section {
    background-color: #FFFFFF;
    font-size: 40px;
    color: #4b4b4b;
    font-family: "Arial", "Hiragino Maru Gothic ProN";
  }

  section.title {
    font-size: 40px;
    padding: 40px;
  }
  section.title h1 {
    text-align: center;
  }

  section.slide h1 {
    position: absolute;
    left: 50px; top: 35px;
  }

---
<!-- class: title -->
# <!--fit--> Gears OS のBootに関する研究

- 奥田光希
    - 琉球大学工学部工学科知能情報コース
- 河野 真治
    - 琉球大学工学部

---

# OSとアプリケーションの信頼性を高めたい

- Meta計算を用いて信頼性を高めるGearsOSを提案している
- x.v6を元にRaspberry Pi上で動くGearsOSを実装中
- キーボードやマウスが使えない
- デバイスドライバを作る必要がある
---
# BIOS問題
- x.v6の起動はBIOSを使っている
- IntelがCompatibility Support Module(CSM)をやめた
- BIOSを前提としたOSが動かなくなるかも
- キーボードやマウスはUSB
- USBドライバを作るのは難しい
---
# <!--fit--> Gears OSをUEFIでBootさせよう
---
# UEFIへの移行
- CPUなどの機種依存性を避けることができる
- GearsOSはCbC(Continuation based C)で記述されていて、CPUやデバイスに影響されない
- 様々な組み込みシステムに対してGearsOSを応用できる様になる
- UEFIのApplicationによりUSBドライバ開発が簡単になる

---
# 研究の成果
- UEFIの開発環境をSingularityで作成した
- gnu-efiで作成したUEFI Applicationをqemu-system-armで動かすことができた
- RaspberryPiにUEFIをファームウェアとして設定し、実行することができた
- ミニマムなKernel Loaderを調査しARM xv6用に書き直した
---
# CbC(Continuation based C)
- 並列信頼研究で開発されているプログラミング言語
- C言語の下位言語
- 関数呼び出しではなく継続(goto)
- 関数の代わりにCodeGearという単位でプログラミングを行う。

---

# GearsOS
- 並列信頼研究で開発されているOS
- 信頼性と拡張性がテーマ
- CbCによって記述されている
- x.v6をCbCで書き直して実装している
---

# UEFI
- Unified Extensible Firmware Interfaceの略
- OSとプラットフォームファームウェアの間のソフトウェアインタフェースを定義する仕様
- Intel、AMD、Apple、Microsoftなどの企業からなるUnified EFI Forumの元で開発
- BIOSの後継
---

# UEFIの利点
- CPUやドライバに依存しない
- 2TBを超える大きなディスクからBootできる
- メモリも64bitなら理論上16EB
- BIOSより高速でBoot
- オープン仕様だから開発が簡単

---

# UEFI 開発環境
- EDK2
- gnu-efi
- qemu
- Singularity

---

# gnu-efi
- システムのネイティブGCCでUEFIアプリケーションをコンパイルできる
- UEFI Applicationをリンクするためのライブラリがある
- UEFI Applicationの開発に特化している
- EDK2のファームウェアがベース
---

# qemu
- 異なるアーキテクチャのプログラムを動かすエミュレータ
- 本開発ではX86上でARMを動かした
- gnu-efiで実装したUEFIを動かした


---
# singularity
- ユーザーが自身の計算環境を完全再現し、保持できる様にしたLinuxコンテナ
- 学科の新システムで利用できる
- CbC GCC ARM CrossCompile環境を作った
- UEFIの開発環境を作った
---
# UEFI Application
- UEFI Boot Managreがロード、実行するプログラムのこと
- C言語で記述可能
- OSがなくてもプログラムを書ける
- CPUやドライバに依存しない

---
# UEFI Applicationの例
Hello.c
``` 
#include <efi.h>
#include <efilib.h>
 
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
  InitializeLib(ImageHandle, SystemTable);
  Print(L"Hello, world!\n");
  return EFI_SUCCESS;
}
```
---
# Gears OS UEFI Bootの課題
- UEFIからx.v6はBootできない
- x.v6はUEFIに対応されてない
- x.v6のBootLoaderが必要
- BootLoaderを作成する 
---
# Boot Loader

- OSをLoadしてBootさせる役割をもつプログラム
- UEFI ApplicationとしてC言語で実装できる
---
# Boot Loaderの役割
1. 電源が入る
1. UEFIが立ち上がる
1. Boot ManagerからBootLoaderが起動する
1. BootLoaderがOSのKernelをメモリにLoadさせる
1. Kernelがinitプロセスを起動
1. initプロセスがOSのBootプロセスを起動
1. OSがBootされる

---
# BootLoader.c
- efi_mainの引数設定

```
#include<efi.h>
#include<efilib.h>

EFI_STATUS
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_DEVICE_PATH *Path;
    EFI_LOADED_IMAGE *LoadedImageParent;
    EFI_LOADED_IMAGE *LoadedImage;
    EFI_HANDLE Image;
    CHAR16 *Options = L"root=/dev/sda2 rootfstype=btrfs rw quiet splash";
    EFI_STATUS Status=EFI_SUCCESS;

    InitializeLib(ImageHandle, SystemTable);
    Print(L"Hello, EFI!\n");
```
---
- uefi_call_wrapperでプロトコルを呼び出している

```
    Status = uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &
    LoadedImageProtocol,(void**)&LoadedImageParent, 
    ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
```
- エラー文
```
    if (EFI_ERROR(Status)) {
        Print(L"Could not get LoadedImageProtocol handler %r\n", Status);
        return Status;
    }
```
---
- xv6.imgのデバイスパスをPathに格納している
- このデバイスパスはKernelをLoadするときに使う
```
    Path = FileDevicePath(LoadedImageParent->DeviceHandle, L"\\xv6.img");
```
- エラー文
```
    if (Path == NULL) {
        Print(L"Could not get device path.");
        return EFI_INVALID_PARAMETER;
    }
```
---
- ここでデバイスパスを使いKernelをLoadする。
- これでKernelがメモリに展開される。
```
    Status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, ImageHandle,
     Path, NULL, 0, &Image);
```
- エラー文
```
    if (EFI_ERROR(Status)) {
        Print(L"Could not load %r", Status);
        FreePool(Path);
        return Status;
    }
```
---
- LoadしたKernelイメージについてLoadedImageProtocolを入手
- LoadOptionsに起動オプションを指定し、Kernel コマンドラインを指定
```
    Status = uefi_call_wrapper(BS->OpenProtocol, 6, 
    Image, &LoadedImageProtocol, 
    (void**)&LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
    if (EFI_ERROR(Status)) {
        Print(L"Could not get LoadedImageProtocol handler %r\n", Status);
        uefi_call_wrapper(BS->UnloadImage, 1, Image);
        FreePool(Path);
        return Status;
    }
    LoadedImage->LoadOptions = Options;
    LoadedImage->LoadOptionsSize = (StrLen(LoadedImage->LoadOptions)+1) * sizeof(CHAR16);
    Print(L"Hello,6!\n");
```
---

- Loadされたイメージを起動
- Kernelが起動する
```    
    Status = uefi_call_wrapper(BS->StartImage, 3, Image, NULL, NULL);
    uefi_call_wrapper(BS->UnloadImage, 1, Image);
    FreePool(Path);
    
    return EFI_SUCCESS;
}
```
---
# 大変だったこと
- EDK2は汎用的だがARMのConfigなどの書き換えが困難
- UEFI開発の情報が少なく、偏りがあった
- UEFI独特のプログラムの書き方があった
- 低レベルの開発に慣れていなかった

---
# 今後の課題

- Singularity上のqemu-system-armにgdbを接続する
- そのgdbでKernel Loaderをデバックする
- xv6 KernelにUEFIからBootするコードを入れる
- xv6を書き換えたGearsOSを実装する
- USB Driverを実装し、キーボードやマウスを使える様にする

---
# ご清聴ありがとうございました