0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

mikanOS 3章を整理 [後編]

Last updated at Posted at 2022-03-28

はじめに

前回の記事では何もしない kernel を
ブートしていました。
今回はカーネルから画面の色を
変更する所まで整理したいと思います。

⇦前|mikanOS 3章を整理[前編] || mikanOS 4章を整理[前編]|後⇨

ブートローダーから画像を変えるフロー

まずは画素を変える事をゴールに
フローを整理してみます。

flow_chart.png

Graphics Output Protocol を検索

LocateHandleBuffer() を使います。
検索したプロトコルを workmemory に用意した領域に一度貯めます。
ただココで注意なのは貯めたプロトコルは EFI_HANDLE であることです。

無題.png

Graphics Output Protocol を Open

OpenProtocol を使っていますが、
実際は HandleProtocol に変形させて使っています。

openprotocol.png
[注意]
以下にあるように HandleProtocol ではなく、
OpenProtocol の使用を推奨しています。
chuui.png

メモリ領域の割り当て

Description の最後の方に記載があるが、Buffer を使うのであれば
AllocatePool() を call する必要があると書いてある。
おそらく章を追うと何処かで追加されると思う。

free_pool.png

Frame Buffer Base で色指定

まずは画素の定義を確認。Blt() で行けそうな気がした。
buffer_pixel.png
しかし、3章では Blt() を使わない
Frame Buffer Base を使う
sample コードを参考に UEFI の規格を追ってみた。

buffer_pixel_test.png
なるほど。
FrameBufferSize も取り出して for 分を回せば、
全ピクセルの色を指定したプログラムができる。

プログラムで総括

Graphic_Open.c

EFI_STATUS OpenGOP(EFI_HANDLE image_handle,
                   EFI_GRAPHICS_OUTPUT_PROTOCOL** gop) {
  UINTN num_gop_handles = 0;
  EFI_HANDLE* gop_handles = NULL;
  /*search the Graphic open protocol*/
  gBS->LocateHandleBuffer(
      ByProtocol,
      &gEfiGraphicsOutputProtocolGuid,
      NULL,
      &num_gop_handles,
      &gop_handles);
  /*open the Graphic open protocol*/
  gBS->OpenProtocol(
      gop_handles[0],
      &gEfiGraphicsOutputProtocolGuid,
      (VOID**)gop,
      image_handle,
      NULL,
      EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
  /*alocate memory area for system*/
  FreePool(gop_handles);

  return EFI_SUCCESS;
}

EFI_STATUS EFIAPI UefiMain(
    EFI_HANDLE image_handle,
    EFI_SYSTEM_TABLE* system_table) 
  {
    //open graphic protocol
    EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
    status = OpenGOP(image_handle, &gop);
    if (EFI_ERROR(status)) {Print(L"Fail to open graphic\n");}

    //write graphic
    UINT8* frame_buffer = (UINT8*)gop->Mode->FrameBufferBase;
    for (UINTN i = 0; i < gop->Mode->FrameBufferSize; ++i) {
        frame_buffer[i] = 255;
    }

    Print(L"All done\n");
    while (1);
    return EFI_SUCCESS;
}

その他メモ

グラフィックの操作は Console I/O protocol に分類されます。
UEFI specification によると、Boot service 中に有効となる protocol になります。

カーネルから Frame Buffer base を制御するために

kernel ファイルの引数として
FrameBufferBase, FrameBufferSize
の 2 つが必要です。

追加してみましょう。

compare.c
  /*[before]*/
    typedef void EntryPointType(void);
    EntryPointType* entry_point = (EntryPointType*)entry_addr;
    entry_point();

  /*[after]*/
    typedef void EntryPointType(UINT64, UINT64);
    EntryPointType* entry_point = (EntryPointType*)entry_addr;
    entry_point(gop->Mode->FrameBufferBase, gop->Mode->FrameBufferSize);

念のため kernel 側のコードも載せておきます。

main.cpp
#include <cstdint>

extern "C" void KernelMain(uint64_t frame_buffer_base,
                           uint64_t frame_buffer_size) {
  uint8_t* frame_buffer = reinterpret_cast<uint8_t*>(frame_buffer_base);
  for (uint64_t i = 0; i < frame_buffer_size; ++i) {
    frame_buffer[i] = i % 256;
  }
  while (1) __asm__("hlt");
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?