在之前的文章中介绍过直接将 BMP文件存放在EFI 文件中 【参考1】,本文继续研究如何将其他格式的文件放在EFI 中的方法。
首先,我搜索了一下,没有发现直接将其他格式按照类似的方法放在EFI文件中的方法(从Win32编程的角度来说,这个是以Resource/资源文件的方式存放)。其次,如果将文件直接修改后缀为BMP,在编译过程中,工具会对资源文件进行检查,如果不是BMP将会报错。对于这种,可以将二进制文件通过加文件头的方式伪装成一个BMP文件。但是这样做估计会比较麻烦。
在阅读代码的过程中,处理BMP文件的代码位于 \BaseTools\Source\Python\AutoGen\GenC.py 文件中,可以看到支持三种图形格式,分别是PNG、JPG和BMP。对于后两者,都有针对这种类型的文件分析动作。
if File.Ext.upper() == '.PNG':
TempBuffer = pack('B', EFI_HII_IIBT_IMAGE_PNG)
TempBuffer += pack('I', len(Buffer))
TempBuffer += Buffer
elif File.Ext.upper() == '.JPG':
ImageType, = struct.unpack('4s', Buffer[6:10])
if ImageType != b'JFIF':
EdkLogger.error("build", FILE_TYPE_MISMATCH, "The file %s is not a standard JPG file." % File.Path)
TempBuffer = pack('B', EFI_HII_IIBT_IMAGE_JPEG)
TempBuffer += pack('I', len(Buffer))
TempBuffer += Buffer
elif File.Ext.upper() == '.BMP':
TempBuffer, TempPalette = BmpImageDecoder(File, Buffer, PaletteIndex, FileObj.TransParent)
if len(TempPalette) > 1:
PaletteIndex += 1
NewPalette = pack('H', len(TempPalette))
NewPalette += TempPalette
PaletteBuffer += NewPalette
PaletteStr = WriteLine(PaletteStr, '// %s: %s: %s' % (DecToHexStr(PaletteIndex - 1, 4), ID, DecToHexStr(PaletteIndex - 1, 4)))
TempPaletteList = AscToHexList(NewPalette)
PaletteStr = WriteLine(PaletteStr, CreateArrayItem(TempPaletteList, 16) + '\n')
ImageBuffer += TempBuffer
BufferStr = WriteLine(BufferStr, '// %s: %s: %s' % (DecToHexStr(Index, 4), ID, DecToHexStr(Index, 4)))
TempBufferList = AscToHexList(TempBuffer)
BufferStr = WriteLine(BufferStr, CreateArrayItem(TempBufferList, 16) + '\n')
StringH.Append(Line)
Index += 1
于是,首先将【参考1】中的BMP文件后缀修改为 PNG ,然后重新编译。我们知道BMP文件开头的数值是 42 4D 76 6B,使用工具直接查看:

结合之前的知识,结合前面 PNG 打包的如下代码:
TempBuffer = pack('B', EFI_HII_IIBT_IMAGE_PNG)
TempBuffer += pack('I', len(Buffer))
TempBuffer += Buffer
猜测格式应该是:
EFI_HII_PACKAGE_LIST_HEADER
EFI_HII_IMAGE_PACKAGE_HDR
Type(EFI_HII_IIBT_IMAGE_PNG==0x19)
Length(len(Buffer)) //这里也就是我们放入的 BMP 的大小
针对上面的内容,编写如下代码进行验证:
/** @file
Logo DXE Driver, install Edkii Platform Logo protocol.
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
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.
**/
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/HiiDatabase.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/HiiImageEx.h>
#include <Protocol/PlatformLogo.h>
#include <Protocol/HiiPackageList.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/ShellLib.h>
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
{ \
0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \
}
static EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
//DO NOT REMOVE IMAGE_TOKEN (IMG_LOGO)
/**
Entrypoint of this module.
This function is the entrypoint of this module. It installs the Edkii
Platform Logo protocol.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
EFI_HII_IMAGE_PACKAGE_HDR *ImageHeader;
UINT8 *ImageData;
UINTN FileSize;
EFI_FILE_HANDLE FileHandle;
//Step1. Get Package List Header Address
//
// Retrieve HII package list from ImageHandle
//
Status = gBS->OpenProtocol (
ImageHandle,
&gEfiHiiPackageListProtocolGuid,
(VOID **) &PackageListHeader,
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
Print(L"HII Image Package with logo not found in PE/COFF resource section\n");
return Status;
}
Print(L"PackageList :\nGUID=[%g] Length=[%X]\n",
PackageListHeader->PackageListGuid,
PackageListHeader->PackageLength);
//Step2. Parser HII Image
ImageHeader=(EFI_HII_IMAGE_PACKAGE_HDR*)(PackageListHeader+1);
ImageData=(UINT8 *)(ImageHeader+1);
FileSize=ImageData[1]+(ImageData[2]<<8)+(ImageData[3]<<16)+(ImageData[4]<<24);
Print(L"Type: 0x%x Size:%d\n",ImageData[0],FileSize);
//Create a new file
Status = ShellOpenFileByName(L"dump.bin",
(SHELL_FILE_HANDLE *)&FileHandle,
EFI_FILE_MODE_READ |
EFI_FILE_MODE_WRITE|
EFI_FILE_MODE_CREATE,
0);
if(Status != RETURN_SUCCESS) {
Print(L"CreatFile failed [%r]!\n",Status);
return EFI_SUCCESS;
}
Status = ShellWriteFile(FileHandle,
&FileSize,
&ImageData[5]);
//Close the source file
ShellCloseFile(&FileHandle);
Print(L"Dump.bin is generated!\n");
return Status;
}
运行结果:

使用 Beyond Compare 可以看到dump.bin 和TestImage.png内容完全相同。
本文提到的完整文件:
参考:
1. https://www.lab-z.com/stu169bmp/ BMP 放在 EFI 文件中(下)