osdev-jpでは、OS開発に有用な情報を収集し公開しています

View My GitHub Profile

Block I/O Protocol を使うとブロックデバイスを読めます。

EDK II を仮定したサンプルコードで説明しています。

Block I/O Protocol を開く

プロトコルを開くには OpenProtocol を使います。

EFI_BLOCK_IO_PROTOCOL* block_io;

status = gBS->OpenProtocol(
    handle,
    &gEfiBlockIoProtocolGuid,
    (VOID**)&block_io,
    image_handle, // agent handle
    NULL,
    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);

handle にはブロックデバイスを表す device handle を指定する必要があります。

Device Handle を得る

方法は 2 つあります。1 つは LocateHandle を使って適したハンドルを検索する方法,もう 1 つは Loaded Image Protocol から起動デバイスのハンドルを得る方法です。

LocateHandle で device handle を得る

EFI_HANDLE handles_supports_blockio[16];
UINTN handles_size = sizeof(handles_supports_blockio);
status = gBS->LocateHandle(ByProtocol, &gEfiBlockIoProtocolGuid, NULL,
                           &handles_size, handles_supports_blockio);

Block I/O Protocol をサポートするハンドルが handle_size / sizeof(EFI_HANDLE) 個得られます。筆者の QEMU で実験したところ 4 つのハンドルが得られました。そのうち 1 つだけにメディアが挿入されており,それが起動メディアです。

Loaded Image Protocol から device handle を得る

LocateHandle では UEFI BIOS が発見したすべてのブロックデバイスが検索されるようです。起動メディアを得られれば良い場合は loaded image から得るのが便利。

まず Loaded Image Protocol を開きます。

EFI_LOADED_IMAGE_PROTOCOL* loaded_image;
status = gBS->OpenProtocol(
    image_handle,
    &gEfiLoadedImageProtocolGuid,
    (VOID**)&loaded_image,
    image_handle,
    NULL,
    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);

loaded_image->DeviceHandle が起動メディアの device handle です。これを OpenProtocol の第 1 引数に指定すれば起動メディアに関する Block I/O Protocol を開けます。