EFI_BOOT_SERVICESや、まだ機能の紹介はしていなかったEFI_RUNTIME_SERVICESには、他にも色々な機能があります。この章ではそれらの一部を紹介します。
UEFIのファームウェアはメモリアロケータを持っていて、EFI_BOOT_SERVICESのAllocatePool()とFreePool()で利用できます(リスト5.1)。
サンプルのディレクトリは"050_bs_malloc"です。
AllocatePool()第1引数の"PoolType"について、"enum EFI_MEMORY_TYPE"には他にもメモリタイプがありますが、仕様書を読む限り、UEFIアプリケーションのデータを配置する領域は"EfiLoaderData"であるようで、この節では"EfiLoaderData"を使用しています。その他のメモリタイプについては仕様書の"6.2 Memory Allocation Services"を見てみてください。
使用例はリスト5.2の通りです。
1: #include "efi.h" 2: #include "common.h" 3: #include "graphics.h" 4: 5: #define IMG_WIDTH 256 6: #define IMG_HEIGHT 256 7: 8: void efi_main(void *ImageHandle __attribute__ ((unused)), 9: struct EFI_SYSTEM_TABLE *SystemTable) 10: { 11: unsigned long long status; 12: struct EFI_GRAPHICS_OUTPUT_BLT_PIXEL *img_buf, *t; 13: unsigned int i, j; 14: 15: efi_init(SystemTable); 16: ST->ConOut->ClearScreen(ST->ConOut); 17: 18: /* 画像バッファ用のメモリを確保 */ 19: status = ST->BootServices->AllocatePool( 20: EfiLoaderData, 21: IMG_WIDTH * IMG_HEIGHT * 22: sizeof(struct EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 23: (void **)&img_buf); 24: assert(status, L"AllocatePool"); 25: 26: /* 画像を生成 */ 27: t = img_buf; 28: for (i = 0; i < IMG_HEIGHT; i++) { 29: for (j = 0; j < IMG_WIDTH; j++) { 30: t->Blue = i; 31: t->Green = j; 32: t->Red = 0; 33: t->Reserved = 255; 34: t++; 35: } 36: } 37: 38: /* 画像描画(フレームバッファへ書き込み) */ 39: blt((unsigned char *)img_buf, IMG_WIDTH, IMG_HEIGHT); 40: 41: /* 確保したメモリを解放 */ 42: status = ST->BootServices->FreePool((void *)img_buf); 43: assert(status, L"FreePool"); 44: 45: while (TRUE); 46: }
リスト5.2では、255x255の画像用バッファ(img_buf)を確保してピクセルデータを配置し、blt()でフレームバッファへの書き込みを行っています。
生成している画像はX軸に青色を、Y軸に緑色を、それぞれ255階調で表示するものです。
試してみると図5.1のような感じです。印刷は白黒なので、ぜひご自身で試してみてください。
メモリ上で動作するだけのUEFIアプリケーションならば電源ボタンで終了しても良いのですが、EFI_RUNTIME_SERVICESのResetSystem()を使用するとPCをシャットダウンしたり、再起動したりできます。
サンプルのディレクトリは"051_rs_resetsystem"です。
EFI_RUNTIME_SERVICESもEFI_BOOT_SERVICES同様にEFI_SYSTEM_TABLEのメンバです。EFI_BOOT_SERVICESはブートローダーに対して機能を提供しているのに対し、EFI_RUNTIME_SERVICESはOS起動後も使用できるという違いがあります。
具体的な契機はEFI_BOOT_SERVICESのExitBootServices()で、この関数を呼ぶと、それ以降EFI_BOOT_SERVICESの機能は無効になりますが、EFI_RUNTIME_SERVICESの機能は引き続き使用可能です。
そして、ResetSystem()はEFI_RUNTIME_SERVICES内でリスト5.3の様に定義されています。
使用例はリスト5.4の通りです。
1: #include "efi.h" 2: #include "common.h" 3: 4: void efi_main(void *ImageHandle __attribute__ ((unused)), 5: struct EFI_SYSTEM_TABLE *SystemTable) 6: { 7: efi_init(SystemTable); 8: ST->ConOut->ClearScreen(ST->ConOut); 9: 10: /* キー入力待ち */ 11: puts(L"何かキーを押すとシャットダウンします。。。\r\n"); 12: getc(); 13: 14: /* シャットダウン */ 15: ST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, 16: NULL); 17: 18: while (TRUE); 19: }
リスト5.4は何かキーを入力するとシャットダウンします。
実行例は図5.2の通りです。