Step to UEFI (248)安装一个自定义的 ACPI Table

UEFI Spec 介绍了一个 EFI_ACPI_TABLE_PROTOCOL,定义如下:

EFI_ACPI_TABLE_PROTOCOL

从介绍可以看出,我们能够使用这个 PROTOCOL 添加(Install)或者删除(Uninstall)一个 ACPI Table。

首先准备一个 ACPI Table, 这里顶一个一个叫做 LBZT 的 Table。

DefinitionBlock ("LABZT.AML", "LBZT", 2, "", "", 0x0)
{
 Name(BUF1, Buffer(){0x00,0x01,0x02,0x03,0x04,0x05})
 Name(BUF2, "www.lab-z.com")
}

DefinitionBlock语法定义如下【参考1】:

DefinitionBlock 语法定义

AMLFileName 是给编译器看的,用于指定输出的 AML 文件名;

TableSignature 是 ACPI Table 的名字(4字节)

ComplianceRevision, 2以及大于2是指定64位;1或者0指定32位(这里我不清楚具体差别,做了一个实验,比如定义:Name(BUF3, 0x1122334455),当ComplianceRevision为0时,编译之后结果发生截断,实际定义是Name(BUF3, 0x22334455);但是当ComplianceRevision为2时,编译结果和代码相同)。如果在处理较大的数值时,需要特别注意这里。

OEMID OEM自定义 ID

TableID  OEM自定义Table 名称(8Bytes)

OEMRevision OEM自定义数值

接下来我们首先自定义一个 ACPI Table 如下:

DefinitionBlock ("LABZ64.AML", "LABZ", 2, "", "", 0x0)
{
 Name(BUF1, Buffer(){0x00,0x01,0x02,0x03,0x04,0x05})
 Name(BUF2, "www.lab-z.com")
 Name(BUF3, 0x1122334455)
}

编译之:

iasl.exe 编译 ASL

得到的是一个二进制文件LABZ64.aml

查看生成的 AML 文件

使用工具转化为C的定义,我们就可以在代码中直接使用了。测试代码如下:

#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/UefiBootServicesTableLib.h>
#include  <Protocol/AcpiTable.h>

extern EFI_BOOT_SERVICES         *gBS;

EFI_GUID gEfiAcpiTableProtocolGuid ={ 
                0xFFE06BDD, 0x6107, 0x46A6, 
                { 0x7B, 0xB2, 0x5A, 0x9C, 0x7E, 0xC5, 0x27, 0x5C }};
                
/* Contents of file LABZ64.aml */
const long int LABZ64_aml_size = 85;
const unsigned char LABZ64_aml[85] = {
    0x4C, 0x41, 0x42, 0x5A, 0x55, 0x00, 0x00, 0x00, 0x02, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x54, 0x4C,
    0x18, 0x10, 0x19, 0x20, 0x08, 0x42, 0x55, 0x46, 0x31, 0x11, 0x09, 0x0A, 0x06, 0x00, 0x01, 0x02,
    0x03, 0x04, 0x05, 0x08, 0x42, 0x55, 0x46, 0x32, 0x0D, 0x77, 0x77, 0x77, 0x2E, 0x6C, 0x61, 0x62,
    0x2D, 0x7A, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x08, 0x42, 0x55, 0x46, 0x33, 0x0E, 0x55, 0x44, 0x33,
    0x22, 0x11, 0x00, 0x00, 0x00
};
                
int
EFIAPI
main (
  IN int Argc,
  IN char **Argv
  )
{
        EFI_STATUS              Status;
        EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
        UINTN                   TableKey;
        
        Status = gBS->LocateProtocol(
                           &gEfiAcpiTableProtocolGuid, 
                           NULL,
                           (VOID **)&AcpiTableProtocol);
        if (EFI_ERROR(Status)) {
            Print(L"Cannot find ACPI_TABLE_PROTOCOL \r\n");
            return Status;
        }
        
        AcpiTableProtocol->InstallAcpiTable(
                                AcpiTableProtocol,
                                (VOID *)LABZ64_aml,
                                LABZ64_aml_size,
                                &TableKey);
        gBS->CloseProtocol ( 
                        AcpiTableProtocol,
                        &gEfiAcpiTableProtocolGuid,
                        gImageHandle,
                        NULL );
        return EFI_SUCCESS;
}

实体机上进行测试,运行 att.efi 之后可以使用 Acpiview 命令查看到如下:

--------------- LABZ Table --------------- 

Address  : 0x44B1D000
Length   : 85
  
00000000 : 4C 41 42 5A 55 00 00 00 - 02 7A 00 00 00 00 00 00   LABZU....z......
00000010 : 00 00 00 00 00 00 00 00 - 00 00 00 00 49 4E 54 4C   ............INTL
00000020 : 18 10 19 20 08 42 55 46 - 31 11 09 0A 06 00 01 02   ... .BUF1.......
00000030 : 03 04 05 08 42 55 46 32 - 0D 77 77 77 2E 6C 61 62   ....BUF2.www.lab
00000040 : 2D 7A 2E 63 6F 6D 00 08 - 42 55 46 33 0E 55 44 33   -z.com..BUF3.UD3
00000050 : 22 11 00 00 00                                      "....

Table Checksum : OK

ACPI Table Header                    :
  Signature                          : LABZ
  Length                             : 85
  Revision                           : 2
  Checksum                           : 0x7A
  Oem ID                             :       
  Oem Table ID                       :         
  Oem Revision                       : 0x0
  Creator ID                         : INTL
  Creator Revision                   : 0x20191018

Table Statistics:
	0 Error(s)
	0 Warning(s)

再进一步,启动到 Windows后用 RW 进行查看也可以看到 LABZ Table

这里是新加入的 ACPI Table

完整代码下载:

参考:

1. https://acpica.org/sites/acpica/files/asl_tutorial_v20190625.pdf

发表回复

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