Step to UEFI (271)资源打包再研究

在之前的文章中介绍过直接将 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,使用工具直接查看:

打包后的分拣分析,注意ASCII 的 BM 是 BMP的头

结合之前的知识,结合前面 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;
}

运行结果:

打包之后运行EFI 就释放资源文件

使用 Beyond Compare 可以看到dump.bin 和TestImage.png内容完全相同。

本文提到的完整文件:

HIIImageTest2下载

参考:

1. https://www.lab-z.com/stu169bmp/  BMP 放在 EFI 文件中(下)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注