EDK2 開発:UEFI アプリケーションからのシェルコマンド実行手法

UEFI ファームウェアの開発プロセスにおいて、コンポーネント内部からシリアルコンソール上で利用可能なシェル機能を実行したい場合があります。これは Linux 環境における C プログラム内の system() 関数呼び出しと機能的には類似していますが、UEFI 標準プロトコルを活用する必要があります。

モジュール定義ファイル(INF)の設定

まず、プロジェクト用の INF ファイルを作成します。ここではモジュールタイプとして UEFI_APPLICATION を指定し、必要となるライブラリとプロトコルを依存関係として記述します。

[Defines]
INF_VERSION                     = 0x0001001A
BASE_NAME                       = Edk2ShellCaller
FILE_GUID                       = 12345678-ABCD-EF01-2345-6789ABCDEF01
MODULE_TYPE                     = UEFI_APPLICATION
VERSION_STRING                  = 1.1
ENTRY_POINT                     = Edk2Entry

[Sources]
Edk2ShellCaller.c

[Packages]
MdePkg/MdePkg.dec

[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
UefiBootServicesTableLib

[Protocols]
gEfiShellProtocolGuid

ソースコードの実装

メインのエントリーポイントでは、ブートサービステーブルを使用してシェンプラットフォームのプロトコルを検索します。検索が成功した場合、取得したプロトコルポインタを通じてコマンドを実行します。

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Shell.h>

#define DEFAULT_STATUS          EFI_SUCCESS

/**
 * UEFI アプリケーションのエントリポイント。
 * @param ImageHandle             画像ハンドル
 * @param SystemTable             システムテーブル
 */
EFI_STATUS EFIAPI Edk2Entry(
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
)
{
  EFI_STATUS           RetCode = DEFAULT_STATUS;
  EFI_SHELL_PROTOCOL   *pShellInterface = NULL;
  
  // 監視タイマーのリセット
  SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
  
  Print(L"Starting Shell Command Execution...\r\n");
  
  // UEFI シェルプロトコルの検索
  RetCode = SystemTable->BootServices->LocateProtocol(
              &gEfiShellProtocolGuid,
              NULL,
              (VOID **)&pShellInterface
            );
              
  if (EFI_ERROR(RetCode)) {
    Print(L"Failed to locate shell protocol.\r\n");
    return RetCode;
  }

  // シェルコマンド「version」の実行
  RetCode = pShellInterface->Execute(
              &ImageHandle,
              L"version",
              NULL,
              &RetCode
            );

  if (!EFI_ERROR(RetCode)) {
    Print(L"Command executed successfully.\r\n");
  } else {
    Print(L"Command execution failed.\r\n");
  }
  
  return RetCode;
}

ビルド構成への組み込み

最後に、ターゲット DSC ファイル(例:MdeModulePkg.dsc)の [Components] セクションへ新しく作成した INF ファイルを登録します。

[Components.Ia32]
# ... 既存のコンポーネント ...
Edk2App/Edk2ShellCaller.inf

上記の手順完了後、EDK2 ビルドツールチェーンを使用してバイナリを生成すれば、アプリケーション起動時に指定された UEFI シェル機能が実行されます。ビルド環境の構築については、各 EDK2 バージョンに対応した環境構築ガイドを参照してください。

タグ: uefi EDK2 EFI_SHELL_PROTOCOL C言語 firmware_development

8月1日 17:10 投稿