Top

おわりに

ここまで読んでいただき、本当にありがとうございます!

ここまで、UEFIでのベアメタルプログラミングの方法について説明しました。「やればできそうだ」と思ってもらえたら嬉しいです。

UEFIはかしこいです。色々な機能を持っていて、色々な事をやってくれます。仕様書の目次を眺めていると、「こんなこともファームウェア側でやってくれるのか」と驚きます*1。また、ソフトウェアの中で最も下のレイヤー*2を扱っているにも関わらず、メモリマップを説明せずに済んでいる事はすごいことです。

[*1] メモリアロケータを持っているのは個人的に驚きでした。

[*2] もちろん、厳密にはより下にファームウェアがありますが。

"はじめに"でも書きましたが、本書のコンセプトには、「UEFIファームウェアの機能をラップしていくだけでOSっぽいものが作れるんじゃ?」という思いがあります。中でも、ファイルシステムの機能をファームウェアが持っているのは強力です。フルスクラッチでOS自作を始めようと考えている人が居れば、UEFIで始めるのも良いんじゃないかなと思います。

最後に、バイナリ短歌で終わりたいと思います(コードリストformat_number_without_header、バイナリリストformat_number_without_header)。サンプルコードのディレクトリは"sample_tanka"です。

リスト1: "msg"ラベルのアドレスにある文字列を出力する

 1: #define CONOUT_ADDR 0xa3819590
 2: #define OUTPUTSTRING_ADDR   0xa387e1b8
 3: 
 4:     .text
 5:     .globl          efi_main
 6: efi_main:
 7:     /* OutputString第1引数(ConOut)をRCXへ格納 */
 8:     movq            $CONOUT_ADDR, %rcx
 9:     /* OutputStringのアドレスをRAXへ格納 */
10:     movq            $OUTPUTSTRING_ADDR, %rax
11:     /* ".ascii"のアドレスをRDXへ格納 */
12:     leaq            msg, %rdx
13:     /* OutputStringを呼び出す */
14:     callq           *%rax
15: 
16:     /* 無限ループ */
17:     jmp             .
18: 
19:     .data
20: msg:
21:     /* "ABCD" */
22:     .ascii          "A\0B\0C\0D\0\0\0"
23:     /* "すごーい" */
24:     /*.ascii                "Y0T0\3740D0\0\0"*/
25:     /* ボス */
26:     /*.ascii                "\326\0\0\0"*/

リスト2: 実行バイナリ逆アセンブル結果(textセクション32バイト、1バイト字余り)

 1: 0000000000401000 <efi_main>:
 2:   401000:       48 b9 90 95 81 a3 00    movabs $0xa3819590,%rcx
 3:   401007:       00 00 00
 4:   40100a:       48 b8 b8 e1 87 a3 00    movabs $0xa387e1b8,%rax
 5:   401011:       00 00 00
 6:   401014:       48 8d 14 25 00 20 40    lea    0x402000,%rdx
 7:   40101b:       00
 8:   40101c:       ff d0                   callq  *%rax
 9:   40101e:       eb fe                   jmp    40101e <efi_main+0x1e>

ここまで読んでいただき、本当にありがとうございました。


Top