悲しいことにVMWarePlayerではGraphics Output Protocolに実装不足があったのでNt32Pkgを使って試してます。
使った画像は/MdeModulePkg/Logo/Logo.bmp。
何か表示出来ればいいという程度で作ったのでBMPの処理関係はいろいろ決め打ちです。
infファイル
## @file # This is the shell application # # Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved. # # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at # http://opensource.org/licenses/bsd-license.php # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. # # ## [Defines] INF_VERSION = 0x00010006 BASE_NAME = TestApp FILE_GUID = 305671d4-c671-4792-8ada-e424a87f4632 MODULE_TYPE = UEFI_APPLICATION VERSION_STRING = 1.0 ENTRY_POINT = UefiMain # # The following information is for reference only and not required by the build tools. # # VALID_ARCHITECTURES = IA32 X64 IPF EBC # [Sources] Main.c [Packages] MdePkg/MdePkg.dec ShellPkg/ShellPkg.dec [LibraryClasses] UefiApplicationEntryPoint UefiLib [Guids] gEfiFileInfoGuid [Protocols] gEfiGraphicsOutputProtocolGuid gEfiSimpleFileSystemProtocolGuid
と、cソースファイル
#include <Uefi.h> #include <Library/BaseLib.h> #include <Library/UefiApplicationEntryPoint.h> #include <Library/UefiLib.h> #include <Library/DebugLib.h> #include <Library/MemoryAllocationLib.h> #include <Guid/FileInfo.h> #include <Protocol/DevicePath.h> #include <Protocol/GraphicsOutput.h> #include <Protocol/SimpleFileSystem.h> #define MAX_BUFFER_SIZE SIZE_1MB EFI_SYSTEM_TABLE *gST; EFI_BOOT_SERVICES *gBS; #pragma pack(1) typedef struct { CHAR8 Type[2]; UINT32 Size; UINT32 Reserved; UINT32 Offset; UINT32 CoreHeaderSize; UINT32 Width; UINT32 Height; UINT16 Planes; UINT16 BitCount; } BITMAP_FILE_HEADER; #pragma pack() STATIC EFI_STATUS LoadBitmapFile ( IN CHAR16 *Path, OUT VOID **BmpBuffer, OUT UINTN *BmpSize ); STATIC EFI_STATUS DrawBmp ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, IN VOID *BmpBuffer, IN UINTN BmpSize ); EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status = EFI_SUCCESS; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; VOID *BmpBuffer = NULL; UINTN BmpSize; gST = SystemTable; gBS = gST->BootServices; gBS->LocateProtocol ( &gEfiGraphicsOutputProtocolGuid, NULL, &GraphicsOutput ); Status = LoadBitmapFile (L"Logo.bmp", &BmpBuffer, &BmpSize); if (EFI_ERROR (Status)) { if (BmpBuffer != NULL) { FreePool (BmpBuffer); return Status; } } Status = DrawBmp (GraphicsOutput, BmpBuffer, BmpSize); if (BmpBuffer != NULL) { FreePool (BmpBuffer); } return EFI_SUCCESS; } STATIC EFI_STATUS LoadBitmapFile ( IN CHAR16 *Path, OUT VOID **BmpBuffer, OUT UINTN *BmpSize ) { EFI_STATUS Status = EFI_SUCCESS; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFile; EFI_FILE_PROTOCOL *Root; EFI_FILE_PROTOCOL *File; UINTN BufferSize; VOID *Buffer = NULL; Status = gBS->LocateProtocol ( &gEfiSimpleFileSystemProtocolGuid, NULL, &SimpleFile ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%r on Locate EFI Simple File System Protocol.\n", Status)); return Status; } Status = SimpleFile->OpenVolume (SimpleFile, &Root); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%r on Open volume.\n", Status)); return Status; } Status = Root->Open (Root, &File, Path, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%r on Open file.\n", Status)); return Status; } BufferSize = MAX_BUFFER_SIZE; Buffer = AllocatePool (BufferSize); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } Status = File->Read ( File, &BufferSize, Buffer ); if (BufferSize == MAX_BUFFER_SIZE) { DEBUG ((EFI_D_ERROR, "Buffer Size Too Small.\n")); if (Buffer != NULL) { FreePool (Buffer); } return EFI_OUT_OF_RESOURCES; } Buffer = ReallocatePool (BufferSize, MAX_BUFFER_SIZE, Buffer); *BmpBuffer = Buffer; *BmpSize = BufferSize; return EFI_SUCCESS; } STATIC EFI_STATUS DrawBmp ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, IN VOID *BmpBuffer, IN UINTN BmpSize ) { EFI_STATUS Status = EFI_SUCCESS; BITMAP_FILE_HEADER *BitmapHeader; UINT8 *BitmapData; UINT32 *Palette; UINTN Pixels; UINTN XIndex; UINTN YIndex; UINTN Pos; UINTN BltPos; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; BitmapHeader = (BITMAP_FILE_HEADER *) BmpBuffer; DEBUG ((EFI_D_ERROR, "%d x %d\n", BitmapHeader->Width, BitmapHeader->Height)); if (BitmapHeader->CoreHeaderSize != 40) { return EFI_UNSUPPORTED; } if (BitmapHeader->BitCount != 8) { return EFI_UNSUPPORTED; } BitmapData = (UINT8*)BmpBuffer + BitmapHeader->Offset; Palette = (UINT32*) ((UINT8*)BmpBuffer + 0x36);/*決め打ち*/ Pixels = BitmapHeader->Width * BitmapHeader->Height; BltBuffer = AllocateZeroPool ( sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Pixels ); if (BltBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } for (YIndex = BitmapHeader->Height; YIndex > 0; YIndex--) { for (XIndex = 0; XIndex < BitmapHeader->Width; XIndex++) { Pos = (YIndex - 1) * ((BitmapHeader->Width + 3) / 4) * 4 + XIndex; BltPos = (BitmapHeader->Height - YIndex) * BitmapHeader->Width + XIndex; BltBuffer[BltPos].Blue = (UINT8) BitFieldRead32 (Palette[BitmapData[Pos]], 0 , 7 ); BltBuffer[BltPos].Green = (UINT8) BitFieldRead32 (Palette[BitmapData[Pos]], 8 , 15); BltBuffer[BltPos].Red = (UINT8) BitFieldRead32 (Palette[BitmapData[Pos]], 16, 23); BltBuffer[BltPos].Reserved = (UINT8) BitFieldRead32 (Palette[BitmapData[Pos]], 24, 31); } } Status = GraphicsOutput->Blt ( GraphicsOutput, BltBuffer, EfiBltBufferToVideo, 0 , 0 , /*Source X, Y*/ 200 , 200 , /*Dest X, Y*/ BitmapHeader->Width, BitmapHeader->Height, /*Width, Height*/ 0 ); FreePool (BltBuffer); return EFI_SUCCESS; }
実行結果はこんな感じです。
地味ではありますが、画像ファイルが表示されました。
今回はBitmapファイルのフォーマットに触れることが出来、色々と悩まされつつも楽しかったです。
標準でBMPファイルを扱えるプロトコルがあればよかったのですが、軽く調べた中では見つからず、結果として普段触らない領域に触れることが出来ました。
参考:
UEFI仕様
Bitmapフォーマット情報
0 件のコメント:
コメントを投稿