#topicpath
* 河豚板のUEFI/GPT対応 [#td0364db]
RIGHT:EBUG 第68回会合 ~
2019年2月23日、(有)銀座堂 ~
川俣吉広、kaw@on.rim.or.jp
#contents
**発端 [#q0089df3]
Twitterでの[[このtweet>https://twitter.com/ao_kenji/status/1073836123934183424]]がきっかけ。

このやりとりが発端となり、[[河豚板のUEFI対応>https://twitter.com/yoshi_kaw/status/1074110733577637888]]を開始する。

**UEFIとGPT [#a6e0bc70]
:UEFI (Unified Extensible Firmware Interface)|OSとファームウェアとの間のソフトウェアインタフェースを定義する仕様([[Wikipedia>https://ja.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface]])~
従来のBIOS (Legacy BIOS)による起動方法からの置換えを意図している。~
・UEFI用のパーティション(ファイルシステムとしてはFAT)を持つ。~
・そのパーティション内に起動用の実行バイナリが格納されている。このバイナリファイルは*.EFIの拡張子を持ち、UEFIアプリケーションと呼ばれる。

:GPT (GUID (Globally Unique Identifier) Partition Table)|ストレージデバイス上のパーティションテーブルの配置に関する標準規格([[Wikipedia>https://ja.wikipedia.org/wiki/GUID%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB]])~
Legacy BIOSで用いられてきたMBR (Master Boot Record)に替わるものとしてUEFIの一部として定義されている。~
・MBRが扱えるのは最大2TBのディスクを4区画まで~
・GPTでは最大8ZBを128区画まで分割可能

OpenBSDの場合に現状で考えられる起動方法とパーティショニングのパターンを以下に示す。

***Legacy BIOS / MBR [[(参考)>http://caspar.hazymoon.jp/OpenBSD/]] [#r1743fb3]
#ref(MBR.png,wrap,around,right,,50%)
UEFI登場以前から用いられてきた方法

-ハードウェア上のファームウェアがHDDのセクタ0にあるMBRブートコードを実行する。

-MBRブートコードは、ブートフラグがONになっているパーティションの先頭セクタにあるPBR (Partition Boot Record)に実行を移す。
--OpenBSDでは、PBRは/usr/mdec/biosbootが用いられる。

-PBRはOpenBSDのルートファイルシステム上にある/bootを実行する。
--この/bootが「boot>」プロンプトを表示し、カーネル起動に関するユーザからの指定を受け付ける。

-bootは指定にしたがって、該当するカーネルを起動する。

-なお、OpenBSD用と設定された区画(右図の例ではentry 3)は、同時にdisklabelユティリティによる管理範囲(OpenBSD Area)として設定される。
-なお、OpenBSD用と設定された区画(右図の例ではentry 3)は、同時に[[disklabel(8)>https://man.openbsd.org/disklabel]]ユティリティによる管理範囲(OpenBSD Area)として設定される。
OpenBSD Areaの中にdisklabelによるBSDパーティションが作成され、ファイルシステムやスワップ領域として使われる(参考:[[他のBSDユーザのためのOpenBSD管理入門>http://fuguita.org/index.php?EBUG%CA%D9%B6%AF%B2%F1%2F20171118_OpenBSD%B4%C9%CD%FD%C6%FE%CC%E7#lde54a06]])。
#img(,clear)

***UEFI / GPT [#bd88fd91]
#ref(GPT.png,wrap,around,right,,50%)
起動にUEFI、ディスクパーテショニングにGPTを用いるパターン

-ハードウェア上のファームウェアがGPT内でEFI Sysパーティションを探し、この中に \efi\BOOT\BOOT*.EFIという実行ファイル(EFIアプリケーション)があれば実行する。~
このファイル名は、
--i386ではBOOTIA32.EFI
--amd64はBOOTX64.EFI
--arm64はBOOTAA64.EFI

>となっている。

-OpenBSDのEFIアプリケーションは、「boot>」プロンプトを表示し、カーネル起動に関するユーザからの指定を受け付ける。~
これは、MBR起動の場合の/bootに相当する。

-EFIアプリケーションは指定にしたがって、該当するカーネルを起動する。

-なお、GPTの場合にも先頭セクタの部分に、従来のMBRとの互換性を考慮してprotective MBR (保護MBR)というものが書き込まれている。これはfdiskなどのMBRを扱うユティリティが誤ってMBRを書き換えないようにするためのものである。

-OpenBSD Area内の管理については、MBRの場合と同じ。
#img(,clear)

***UEFI / MBR [#ffe7005b]
#ref(ARM64.png,wrap,around,right,,50%)
UEFIとしてEFIアプリケーションがロードされるが、パーテショニングとしてMBRが使われるパターン。GPTは存在しない。~
amd64のインストールメディアやarm64で使われている。

amd64のインストールメディアとarm64とでは細かい箇所で異なっている部分がある(右図はarm64)。

-arm64ではUEFI用のパーティションIDは0C (FAT32L)、amd64インストーラではEF (EFI Sys)。

-arm64ではUEFI用のパーティション内にはU-BOOTも書き込まれている。

-amd64インストーラではMBR boot code、PBR、/bootもセットアップされ、Legacy BIOS・UEFIのどちらでも起動する。
#img(,clear)

***Hybrid MBR [#d8c49092]
#ref(Hyb.png,wrap,around,right,,50%)
MBRとGPTの両方に同じパーテショニング情報を書込み、ブートローダもLegacy BIOS, UEFI共にセットアップしたもの。

-Legacy BIOS・UEFIのどちらでも起動することが期待できる。

-非標準。規格上は定義されていない方法。

-現状ではMBRとGPTとを同時に変更するツールがないため、作成後にパーテショニングを変更することが困難。
#img(,clear)

**OpenBSDでのUEFI実装[#k481c6c6]
2015年に安岡昌彦氏によりカーネルにUEFI対応の機能が[[実装された>https://marc.info/?l=openbsd-cvs&m=144115942223734&w=2]]。

現在では、インストーラ含め、関連ユティリティがUEFI/GPTに対応している。

***インストーラ [#te951c4f]
前述のように、Legacy BIOS、UEFIのいずれからでも起動可。

Legacy BIOS、UEFIのどちらで起動したかによって、パーティショニングのデフォルトも変わる。

UEFIで起動した場合
 Available disks are: wd0 wd1.
 Which disk is the root disk? ('?' for details) [wd0] wd1
 No valid MBR or GPT.
 Use (W)hole disk MBR, whole disk (G)PT or (E)dit? [gpt]       ←インストーラをUEFIで起動した
 Setting OpenBSD GPT partition to whole wd1...done.              ので、GPTがデフォルト
 The auto-allocated layout for wd1 is:
 #                size           offset  fstype [fsize bsize   cpg]
   a:        819776.0K             1024  4.2BSD   2048 16384     1 # /
   b:         83090.0K          1640576    swap                    
   c:       2097152.0K                0  unused                    
   d:        930704.0K          1806784  4.2BSD   2048 16384     1 # /usr
   e:        263024.0K          3668192  4.2BSD   2048 16384     1 # /home
   i:           480.0K               64   MSDOS                             ←EFI Sys領域
 Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout? [a]

Legacy BIOSで起動した場合
 Available disks are: wd0 wd1.
 Which disk is the root disk? ('?' for details) [wd0] wd1
 No valid MBR or GPT.
 Use (W)hole disk MBR, whole disk (G)PT or (E)dit? [whole]     ←MBRがデフォルト
 Setting OpenBSD MBR partition to whole wd1...done.
 The auto-allocated layout for wd1 is:
 #                size           offset  fstype [fsize bsize   cpg]
   a:           800.6M               64  4.2BSD   2048 16384     1 # /
   b:            81.1M          1639616    swap                    
   c:          2048.0M                0  unused                    
   d:           908.9M          1805824  4.2BSD   2048 16384     1 # /usr
   e:           256.9M          3667232  4.2BSD   2048 16384     1 # /home
 Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout? [a] 
***fdisk [#qb5830d2]
パーティションのメンテナンスツールfdisk(8)は、パーティションの初期化時にオプションによってMBRかGPTかを指定する。
パーティションのメンテナンスツール[[fdisk(8)>https://man.openbsd.org/fdisk]]は、パーティションの初期化時にオプションによってMBRかGPTかを指定する。

MBRで初期化
 # fdisk -i wd1
 Do you wish to write new MBR and partition table? [n] y
 Writing MBR at offset 0.
 # fdisk wd1
 Disk: wd1       geometry: 520/128/63 [4194304 Sectors]
 Offset: 0       Signature: 0xAA55
             Starting         Ending         LBA Info:
  #: id      C   H   S -      C   H   S [       start:        size ]
 -------------------------------------------------------------------------------
  0: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
  1: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
  2: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 *3: A6      0   1   2 -    519 127  63 [          64:     4193216 ] OpenBSD     

GPTで初期化
 # fdisk -i -g wd1
 Do you wish to write new GPT? [n] y
 Writing MBR at offset 0.
 Writing GPT.
 # fdisk wd1
 Disk: wd1       Usable LBA: 64 to 4194240 [4194304 Sectors]
    #: type                                 [       start:         size ]
 ------------------------------------------------------------------------
    3: OpenBSD                              [          64:      4194177 ]
 パーティションの詳細を見る
 ↓
 # fdisk -v wd1
 Primary GPT:
 Disk: wd1       Usable LBA: 64 to 4194240 [4194304 Sectors]
 GUID: 09d92128-d884-40f8-9e17-a606721cd8c7
    #: type                                 [       start:         size ]
       guid                                 name
 ------------------------------------------------------------------------
    3: OpenBSD                              [          64:      4194177 ]
       376b4152-9c45-4d7a-8392-5f0f3e015d51 OpenBSD Area                    
 
 Secondary GPT:
 Disk: wd1       Usable LBA: 64 to 4194240 [4194304 Sectors]
 GUID: 09d92128-d884-40f8-9e17-a606721cd8c7
    #: type                                 [       start:         size ]
       guid                                 name
 ------------------------------------------------------------------------
    3: OpenBSD                              [          64:      4194177 ]
       376b4152-9c45-4d7a-8392-5f0f3e015d51 OpenBSD Area                    
 
 MBR:
 Disk: wd1       geometry: 520/128/63 [4194304 Sectors]
 Offset: 0       Signature: 0xAA55
             Starting         Ending         LBA Info:
  #: id      C   H   S -      C   H   S [       start:        size ]
 ---------------------------------------------------------------------------
  0: EE      0   0   2 - 532610   4   4 [           1:  4294967295 ] EFI GPT
  1: 00      0   0   0 -      0   0   0 [           0:           0 ] unused 
  2: 00      0   0   0 -      0   0   0 [           0:           0 ] unused 
  3: 00      0   0   0 -      0   0   0 [           0:           0 ] unused 
 # 
***installboot [#i0c2305e]
OpenBSDでは、ブートローダの書込みにinstallboot(8)を使用する。
OpenBSDでは、ブートローダの書込みに[[installboot(8)>https://man.openbsd.org/installboot]]を使用する。

-対象ディスクがMBRで区画分けされている場合、PBRと/bootを書込む
 # mount /dev/wd1a /mnt
 # installboot -r /mnt wd1 /usr/mdec/biosboot /usr/mdec/boot
                           ↑                 ↑
                           PBR                secondary loader
 # umount /mnt

-対象ディスクがGPTで区画分けされている場合、EFIアプリケーションをEFI Sysパーティションに\efi\boot\*.EFIとして書込む
 # installboot wd1

**河豚板での実装[#p656b6cc]
***配布物 [#h0d27fc6]
-ISO版は変更しない。

-img版は、以下のように対応する。
--i386版は、Legacy BIOS/MBRにする(UEFIアプリケーションが供給されていないため)。

--amd64版は、Hybrid MBRとし、Legacy BIOS/UEFIのいずれでも使用できるようにする。

--arm64版は、UEFI/MBRにする(オリジナルのOpenBSD/arm64と同じ)。

***usbfadm [#y8bbf7e2]
usbfadm (USB Flashdrive ADMinistration tool) - 河豚板付属のUSBメモリ管理ツール~
実際はUSBメモリ限らず、ストレージデバイス般で使用可
[[usbfadm (USB Flashdrive ADMinistration tool)>https://github.com/ykaw/FuguIta/blob/master/rdroot/boottmp/usbfadm]] - 河豚板付属のUSBメモリ管理ツール~
実際はUSBメモリに限らず、ストレージデバイス般で使用可

用途
-TMPFSのデータをUSBメモリに保存する~
:syncコマンド|TMPFSのデータをUSBメモリに保存する~
読み出しは次回起動時に「起動モード3」を指定する。

-LiveUSB版の河豚板を新規作成する~
:newdriveコマンド|LiveUSB版の河豚板を新規作成する~
LiveUSB版河豚板のディスクイメージを作成する

UEFI/GPT対応として
-LiveUSB版の河豚板を新規作成する機能に
--起動方法としてLegacy/BIOS and/or UEFIを指定出来るようにする
UEFI/GPT対応として、newdriveコマンドに
-起動方法としてLegacy/BIOS and/or UEFIを指定出来るようにする

--パーティショニングとしてMBR and/or GPTを指定出来るようにする
-パーティショニングとしてMBR and/or GPTを指定出来るようにする

#ref(FuguIta.png,wrap,around,right,,50%)
河豚板のパーティション構成
-EFI sys ... UEFIブートの際に必要 (Legacy BIOS、データ保存専用デバイスでは不要)
-OpenBSD Area
--a
---河豚板のファイルツリー(実際にはlndirを使ってtmpfsにマッピング)
---デバイスをファイル保存用のみに使う場合は不要
--d
---usbfadmを使ってTMPFS内のデータをUSBメモリに保存する場合に必要
-FAT ... ユーザの指示がある場合、ディスクに空きがあれば作成

Hybrid MBRを用い、かつパーティションを全て作成する場合、右図のようになる。
#img(,clear)

***アーキテクチャ依存部 - 組み合わせとデフォルト [#c8399f2d]
「アーキテクチャ毎の対応表」を見るとわかるように、ブート方法、及びパーティションテーブルの選択肢はアーキテクチャ毎に変わってくる。例えばi386ではUEFIが、arm64ではLegacy BIOSを選択できてもOSが対応していないため、意味がない。~
さらに、ユーザが「データ保存のみ」を選択した場合はブートローダが不要となる。以上より選択の組合せは以下のようになる。
|CENTER:|CENTER:|CENTER:|CENTER:|CENTER:|c
|                       |Legacy BIOS|UEFI        |Hybrid|non-boot&br;(data only)|h
|BGCOLOR(#e0e0e0):MBR   |i386, amd64|amd64, arm64|N/A   |all|
|BGCOLOR(#e0e0e0):GPT   |N/A        |amd64, arm64|N/A   |all|
|BGCOLOR(#e0e0e0):Hybrid|N/A        |N/A         |amd64 |all|
|>|>|>|>|CENTER:BGCOLOR(#d0d0e0):アーキテクチャ毎の対応表|
-i386はEFIアプリケーションが供給されていないため、UEFI起動不可
-arm64はU-BOOT起動のため、Legacy BIOS起動不可


この複雑さを緩和するため、今回の改修では/usr/fugutia/etc/usbfadm.confというファイルを新設した。~
例えば、ie386の場合、このファイルに~
例えば、i386の場合、このファイルに~
 disable_uefiboot=Yes
などと記述することで、UEFIブートを選択肢からはずせるようにした。
などと記述することで、UEFI起動を選択肢からはずせるようにした。
一方arm64の場合、Legacy BIOSでは起動できないので、
 disable_legacyboot=Yes
となる。

またarm64の場合は以下の理由から、さらなる処理が必要となる。

-基本はUEFI/MBRの構成だが、MBRブートフラグとUEFI Sysのパーティションタイプを変更する必要がある。

-OpenBSD/arm64では、
-OpenBSD/arm64はHDMI出力が実されておらずシリアルコンソールとなるため、OpenBSD/arm64をインストールする際はピンヘッダにUSBシリアルなどを用意し、シリアル端末を接続する必要がある。
--FuguIta/arm64では、インストール作業の敷を下げるため、配布物をメディアに書き込んで起動した段階でSSHによるリモートアクセスが可能となっており、シリアルI/Fを用意せずとも使用できるようになっている。

usbfadm_postproc.sh
--そのため、FuguIta/arm64は他のプラットフォーム用と異なり、SSHアクセスを可能にするための各種設定や、その設定を用いて自動的に起動する設定がdパーティションに書き込まれている。~
arm64のusbfadmでnewdriveを実行してリマスタリングを行う場合、これらdパーティションに書き込まれている容もセットアップする必要がある。

--よって、新しいusbfadmでは、newdriveコマンドの実行の最後の部分に/usr/fuguita/etc/usbfadm_postproc.shというシェルスクリプトを実行するようにした。FuguIta/arm64では、[[usbfadm_postproc.sh>https://github.com/ykaw/FuguIta/blob/master/lib/usbfadm_postproc.sh.arm64]]に上で説明したようなプラットフォーム固有の処理が書き込まれている。

***Hybrid MBRのの作成 [#ic36ec74]
[[OpenBSDでのUEFI実>#k481c6c6]]で説明したように、OpenBSDのfdiskコマンドにはディスクをMBR、GPTそれぞれのパーティションで初期化する機能を持っているが、MBRとGPTを同時に作成しHybrid MBRとする機能は持っていない。

今回のUEFI対応では、以下のような方法でHybrid MBRを実した。
#ref(mkHybrid.png,wrap,around,left,,50%)
-1. ディスクをMBRで初期化する ... fdisk -i

-2a. パーティションを作成し、newfs, newfs_msdosを行う
-2b. installbootを実行する ... PBRと/bootが書き込まれる
-2c. MBRをddで吸出しファイルとして保存しておく

-3. ディスクをGPTで初期化する ... fdisk -i -g

-4a. MBRと同じ構成でGPTパーティションを作成する
-4b. installbootを実行する ... EFIアプリケーションが書き込まれる
-4c. 保存しておいたMBRをddでprotective MBRに上書きする
#img(,clar)

**開発環境 [#l6de7a38]

----
#topicpath


Front page   New Page list Search Recent changes   Help   RSS of recent changes