2019年12月7日土曜日

OVMFのバグ

今ちょっといろいろあってUEFIアプリを書いてます。
検証をQEMU上で行ってるんですが、なぜかプログラムを実行するたびに使用可能メモリが減っていきます。
実機でテストすると全く起きない。
どこまで削ったら起きなくなるのか突き詰めていったら、見つかりました。
TestString()という、画面表示できる文字列か検証するAPI。
これを呼ぶとメモリが減っていきました。

で、QEMU用のUEFIっていうのはオープンソースのOVMFっていう実装を使ってます。
なのでソースみりゃわかるかなと。

ダウンロードしてきてGREPかけて・・・多分これ。

EFI_STATUS
EFIAPI
GraphicsConsoleConOutTestString (
  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
  IN  CHAR16                           *WString
  )
{
  EFI_STATUS            Status;
  UINT16                Count;

  EFI_IMAGE_OUTPUT      *Blt;

  Blt   = NULL;
  Count = 0;

  while (WString[Count] != 0) {
    Status = mHiiFont->GetGlyph (
                         mHiiFont,
                         WString[Count],
                         NULL,
                         &Blt,
                         NULL
                         );
    if (Blt != NULL) {
      FreePool (Blt);
      Blt = NULL;
    }
    Count++;

    if (EFI_ERROR (Status)) {
      return EFI_UNSUPPORTED;
    }
  }

  return EFI_SUCCESS;
}
Bltをfreeしてるってことは内部でメモリ割り当ててるのね。
これは怪しいのでGetGryphの実装を探してみると、たぶんこれ

EFI_STATUS
EFIAPI
HiiGetGlyph (
  IN  CONST EFI_HII_FONT_PROTOCOL    *This,
  IN  CHAR16                         Char,
  IN  CONST EFI_FONT_DISPLAY_INFO    *StringInfo,
  OUT EFI_IMAGE_OUTPUT               **Blt,
  OUT UINTN                          *Baseline OPTIONAL
  )
{
~中略~
  *Blt = Image;
~後略
Imageが実体ね。これを探してみると

  Image = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
  if (Image == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Exit;
  }
  Image->Width   = Cell.Width;
  Image->Height  = Cell.Height;

  if (Image->Width * Image->Height > 0) {
    Image->Image.Bitmap = AllocateZeroPool (Image->Width * Image->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
    if (Image->Image.Bitmap == NULL) {
      FreePool (Image);
      Status = EFI_OUT_OF_RESOURCES;
      goto Exit;
    }

はい。Imageは構造体で、Bitmapという要素にもメモリ割り当ててるね。
ってことでBltだけfreeするのはアウトですね。
とりあえずTestStringを呼ばなきゃいいんだけど、UEFIの実装ってまちまちでフォントも入ってるかテストしてみなきゃわからないんですよねー。
実際に"|”と”}”が実装されていない環境もありました。"{"はあるのにw。

これ直してビルドすればいいんだけど、環境整えるのがめんどくさいw
誰か直してくれないかなぁ?