ACPI

本文深入探讨了BIOS如何通过ACPI支持操作系统,包括提供ACPI表、S3唤醒功能及平台寄存器恢复等。介绍了EFI_ACPI_SDT_PROTOCOL协议,详细解析了ACPI表的获取、回调函数注册及AML代码管理。同时,阐述了关键数据结构如EFI_ACPI_TABLE_INSTANCE和EFI_ACPI_TABLE_LIST的作用。

BIOS 对于ACPI 的支持包括以下几个方面:

  1. 提供ACPI 表告诉操作系统信息,包括ASL 代码
  2. 提供S3 唤醒功能,包括平台寄存器恢复

EFI_ACPI_SDT_PROTOCOL 是PI 规范中定义的协议。它给用户提供了接口用来获取ACPI 表,

添加ACPI 表的回调函数,并且提供接口管理AML 代码。

typedef struct _EFI_ACPI_SDT_PROTOCOL {
  ///
  /// A bit map containing all the ACPI versions supported by this protocol.
  ///
  EFI_ACPI_TABLE_VERSION    AcpiVersion;
  EFI_ACPI_GET_ACPI_TABLE2  GetAcpiTable;
  EFI_ACPI_REGISTER_NOTIFY  RegisterNotify;
  EFI_ACPI_OPEN             Open;
  EFI_ACPI_OPEN_SDT         OpenSdt;
  EFI_ACPI_CLOSE            Close;
  EFI_ACPI_GET_CHILD        GetChild;
  EFI_ACPI_GET_OPTION       GetOption;
  EFI_ACPI_SET_OPTION       SetOption;
  EFI_ACPI_FIND_PATH        FindPath;
} EFI_ACPI_SDT_PROTOCOL;

 

GetAcpiTable : 获取ACPI 表。

RegisterNotify: 注册ACPI 表的回调函数。

 

 

EFI_ACPI_TABLE_INSTANCE 数据结构

实现EFI_ACPI_TABLE_PROTOCOL我驱动定义了ACPI_TABLE_INSTANCE 内部数据结构。

其中最关键的是TableList, 它是系统ACPI Table 的链表。

//
// ACPI support protocol instance data structure
//
typedef struct {
  UINTN                                         Signature;
  EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp1;                 // Pointer to RSD_PTR structure
  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp3;                 // Pointer to RSD_PTR structure
  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt1;                 // Pointer to RSDT table header
  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt3;                 // Pointer to RSDT table header
  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;                  // Pointer to XSDT table header
  EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt1;                 // Pointer to FADT table header
  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt3;                 // Pointer to FADT table header
  EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs1;                 // Pointer to FACS table header
  EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs3;                 // Pointer to FACS table header
  EFI_ACPI_DESCRIPTION_HEADER                   *Dsdt1;                 // Pointer to DSDT table header
  EFI_ACPI_DESCRIPTION_HEADER                   *Dsdt3;                 // Pointer to DSDT table header
  LIST_ENTRY                                    TableList;
  UINTN                                         NumberOfTableEntries1;  // Number of ACPI 1.0 tables
  UINTN                                         NumberOfTableEntries3;  // Number of ACPI 3.0 tables
  UINTN                                         CurrentHandle;
  EFI_ACPI_TABLE_PROTOCOL                       AcpiTableProtocol;
  EFI_ACPI_SDT_PROTOCOL                         AcpiSdtProtocol;
  LIST_ENTRY                                    NotifyList;
} EFI_ACPI_TABLE_INSTANCE;

 

EFI_ACPI_TABLE_LIST 数据结构

EFI_ACPI_TABLE_INSTANCE.TableList 记录了所有ACPI table 的一个双向链表,键表结构如下:

EFI_ACPI_TABLE_LIST

typedef struct {
  UINT32                  Signature;
  LIST_ENTRY          Link;
  EFI_ACPI_TABLE_VERSION  Version;
  EFI_ACPI_COMMON_HEADER  *Table;
  EFI_PHYSICAL_ADDRESS    PageAddress;
  UINTN                   NumberOfPages;
  UINTN                   Handle;
} EFI_ACPI_TABLE_LIST;

 

 

EFI_ACPI_NOTIFY_LIST 数据结构

EFI_ACPI_TABLE_INSTANCE.NotifyList 记录了所有ACPI table 回调函数的一个双向链表,链表结构如下:

//
// ACPI Notify List Entry definition.
//
//  Signature must be set to EFI_ACPI_NOTIFY_LIST_SIGNATURE
//  Link is the linked list data.
//  Notification is the callback function.
//
typedef struct {
  UINT32                   Signature;
  LIST_ENTRY               Link;
  EFI_ACPI_NOTIFICATION_FN Notification;
} EFI_ACPI_NOTIFY_LIST;

  //
  // Check for invalid input parameters
  //
  if ((AcpiTableBuffer == NULL) || (TableKey == NULL)
     || (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer)->Length != AcpiTableBufferSize)) {
    return EFI_INVALID_PARAMETER;
  }

 

检查AcpiTableBuffer 与Tablekey 是否为空。检查AcpiTableBufferSize 与AcpiTableBuffer 中的Length

是否一致,不一致的话返回错误。

计算AcpiTable 中的校验和。

  //
  // Install the ACPI table
  //
  AcpiTableBufferConst = AllocateCopyPool (AcpiTableBufferSize,AcpiTableBuffer);
  *TableKey = 0;
  Status = AddTableToList (
             AcpiTableInstance,
             AcpiTableBufferConst,
             TRUE,
             Version,
             TableKey
             );
  if (!EFI_ERROR (Status)) {
    Status = PublishTables (
               AcpiTableInstance,
               Version
               );
  }
  FreePool (AcpiTableBufferConst);

  //
  // Add a new table successfully, notify registed callback
  //
  if (FeaturePcdGet (PcdInstallAcpiSdtProtocol)) {
    if (!EFI_ERROR (Status)) {
      SdtNotifyAcpiList (
        AcpiTableInstance,
        Version,
        *TableKey
        );
    }

 

InstallAcpiTable通过AddTableToList 去安装ACPI 表。

如果成功的话,再调用PublishTable 把Acpi 表更新到UEFI ConfiguraitonTable 中。这样,操作系统就可以

通过UEFI ConfigurationTable 找到AcpiTable.

 

 

笔记本的风扇控制 ---------------------------------------- 09 November 2006. Summary of changes for version 20061109: 1) ACPI CA Core Subsystem: Optimized the Load ASL operator in the case where the source operand is an operation region. Simply map the operation region memory, instead of performing a bytewise read. (Region must be of type SystemMemory, see below.) Fixed the Load ASL operator for the case where the source operand is a region field. A buffer object is also allowed as the source operand. BZ 480 Fixed a problem where the Load ASL operator allowed the source operand to be an operation region of any type. It is now restricted to regions of type SystemMemory, as per the ACPI specification. BZ 481 Additional cleanup and optimizations for the new Table Manager code. AcpiEnable will now fail if all of the required ACPI tables are not loaded (FADT, FACS, DSDT). BZ 477 Added #pragma pack(8/4) to acobject.h to ensure that the structures in this header are always compiled as aligned. The ACPI_OPERAND_OBJECT has been manually optimized to be aligned and will not work if it is byte-packed. Example Code and Data Size: These are the sizes for the OS- independent acpica.lib produced by the Microsoft Visual C++ 6.0 32- bit compiler. The debug version of the code includes the debug output trace mechanism and has a much larger code and data size. Previous Release: Non-Debug Version: 78.1K Code, 17.1K Data, 95.2K Total Debug Version: 155.4K Code, 63.1K Data, 218.5K Total Current Release: Non-Debug Version: 77.9K Code, 17.0K Data, 94.9K Total Debug Version: 155.2K Code, 63.1K Data, 218.3K Total 2) iASL Compiler/Disassembler and Tools: Fixed a problem where the presence of the _OSI predefined control method within complex expressions could cause an internal compiler error. AcpiExec: Implemented full region support for multiple address spaces. SpaceId is now part of the REGION object. BZ 429 ---------------------------------------- 11 Oc
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值