【UEFI基础】System Table和Architecture Protocols

System Table

System Table是UEFI软件架构中最重要的一个部分,基本的代码都离不开它。

下面是一个基本的UEFI模块中会包含的Entry Point,它就有一个参数是System Table:

typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_ENTRY_POINT) (
  IN EFI_HANDLE ImageHandle, 
  IN EFI_SYSTEM_TABLE *SystemTable 
);

以8254Timer这个模块为例,它的inf模块中有以下的代码:

[Defines]
  INF_VERSION                    = 0x00010005
  BASE_NAME                      = Timer
  MODULE_UNI_FILE                = Timer.uni
  FILE_GUID                      = f2765dec-6b41-11d5-8e71-00902707b35e
  MODULE_TYPE                    = DXE_DRIVER
  VERSION_STRING                 = 1.0

  ENTRY_POINT                    = TimerDriverInitialize

其中的ENTRY_POINT就指向了该模块的入口:

/**
  Initialize the Timer Architectural Protocol driver

  @param ImageHandle     ImageHandle of the loaded driver
  @param SystemTable     Pointer to the System Table

  @retval EFI_SUCCESS            Timer Architectural Protocol created
  @retval EFI_OUT_OF_RESOURCES   Not enough resources available to initialize driver.
  @retval EFI_DEVICE_ERROR       A device error occured attempting to initialize the driver.

**/
EFI_STATUS
EFIAPI
TimerDriverInitialize (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{

后续的代码会使用到SystemTable中包含的内容。

System Table包含了一系列的指针,指向Console设备,指向Runtime Service Table,Boot Service Table、DXE Service Table和Configuration Table,前两张表包含了很多的基础函数,最后一张表包含了ACPI、SMBIOS等表。

System Table的建立

System Table的建立是在DXE阶段(所以在这之前的PEI阶段并没有,里面提供的基础函数也不能用),具体的代码在DxeMain.c中,下面列出简单的代码:

EFI_SYSTEM_TABLE mEfiSystemTableTemplate = {
  {
    EFI_SYSTEM_TABLE_SIGNATURE,                                           // Signature
    EFI_SYSTEM_TABLE_REVISION,                                            // Revision
    sizeof (EFI_SYSTEM_TABLE),                                            // HeaderSize
    0,                                                                    // CRC32
    0                                                                     // Reserved
  },
  NULL,                                                                   // FirmwareVendor
  0,                                                                      // FirmwareRevision
  NULL,                                                                   // ConsoleInHandle
  NULL,                                                                   // ConIn
  NULL,                                                                   // ConsoleOutHandle
  NULL,                                                                   // ConOut
  NULL,                                                                   // StandardErrorHandle
  NULL,                                                                   // StdErr
  NULL,                                                                   // RuntimeServices
  &mBootServices,                                                         // BootServices
  0,                                                                      // NumberOfConfigurationTableEntries
  NULL                                                                    // ConfigurationTable
};
  //
  // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData
  // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table
  //
  gDxeCoreST = AllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate);
  ASSERT (gDxeCoreST != NULL);

  gDxeCoreRT = AllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate);
  ASSERT (gDxeCoreRT != NULL);

  gDxeCoreST->RuntimeServices = gDxeCoreRT;

在System Table中需要特别介绍的就是Boot Service Table和Runtime Service Table,在UEFI开发中一定会用到其中提供的函数。

Boot Service Table

它主要分为以下的几类:

与事件相关的:

函数名 类型 函数描述
CreateEvent  Boot  Creates a general-purpose event structure 
CreateEventEx  Boot  Creates an event structure as part of an event group 
CloseEvent  Boot  Closes and frees an event structure 
SignalEvent  Boot  Signals an event 
WaitForEvent  Boot  Stops execution until an event is signaled 
CheckEvent  Boot  Checks whether an event is in the signaled state 
SetTimer  Boot  Sets an event to be signaled at a particular time 
RaiseTPL  Boot  Raises the task priority level 
RestoreTPL  Boot  Restores/lowers the task priority level 

与内存相关的:

函数名 类型 函数描述
AllocatePages  Boot  Allocates pages of a particular type. 
FreePages  Boot  Frees allocated pages. 
GetMemoryMap  Boot  Returns the current boot services memory map and memory map key. 
AllocatePool  Boot  Allocates a pool of a particular type. 
FreePool  Boot  Frees allocated pool. 

与Protocol相关的:

函数名 类型 函数描述
InstallProtocolInterface  Boot  Installs a protocol interface on a device handle. 
UninstallProtocolInterface  Boot  Removes a protocol interface from a device handle. 
ReinstallProtocolInterface  Boot  Reinstalls a protocol interface on a device handle. 
RegisterProtocolNotify  Boot  Registers an event that is to be signaled whenever an interface is installed for a specified protocol. 
LocateHandle  Boot  Returns an array of handles that support a specified protocol. 
HandleProtocol  Boot  Queries a handle to determine if it supports a specified protocol. 
LocateDevicePath  Boot  Locates all devices on a device path that support a specified protocol and returns the handle to the device that is closest to the path. 
OpenProtocol  Boot  Adds elements to the list of agents consuming a protocol interface. 
CloseProtocol  Boot  Removes elements from the list of agents consuming a protocol interface. 
OpenProtocolInformation  Boot  Retrieve the list of agents that are currently consuming a protocol interface. 
ConnectController  Boot  Uses a set of precedence rules to find the best set of drivers to manage a controller. 
DisconnectController  Boot  Informs a set of drivers to stop managing a controller. 
ProtocolsPerHandle  Boot  Retrieves the list of protocols installed on a handle. The return buffer is automatically allocated. 
LocateHandleBuffer  Boot  Retrieves the list of handles from the handle database that meet the search criteria. The return buffer is automatically allocated. 
LocateProtocol  Boot  Finds the first handle in the handle database the supports the requested protocol. 
InstallMultipleProtocolInterfaces  Boot  Installs one or more protocol interfaces onto a handle. 
UninstallMultipleProtocolInterfaces  Boot  Uninstalls one or more protocol interfaces from a handle. 

与Image相关的:

函数名 类型 函数描述
LoadImage  Boot  Loads an EFI image into memory. 
StartImage  Boot  Transfers control to a loaded image’s entry point. 
UnloadImage  Boot  Unloads an image. 
EFI_IMAGE_ENTRY_POINT  Boot  Prototype of an EFI Image’s entry point. 
Exit  Boot  Exits the image’s entry point. 
ExitBootServices  Boot  Terminates boot services. 

及其它:

函数名 类型 函数描述
SetWatchDogTimer  Boot  Resets and sets a watchdog timer used during boot services time. 
Stall  Boot  Stalls the processor. 
CopyMem  Boot  Copies the contents of one buffer to another buffer. 
SetMem  Boot  Fills a buffer with a specified value. 
GetNextMonotonicCount  Boot  Returns a monotonically increasing count for the platform. 
InstallConfigurationTable  Boot  Adds, updates, or removes a configuration table from the EFI System Table. 
CalculateCrc32  Boot  Computes and returns a 32-bit CRC for a data buffer. 

Runtime Service Table

在Boot Service中有一个ExitBootServices,还函数被调用后Boot Serice Table中的函数就不能再使用了,但是Runtime Service Table中的函数仍然可以使用,这些函数在OS中也仍旧可以调用,当然前提是OS支持。

Runtime Serivces有以下几类:

与变量相关的:

函数名 类型 函数描述
GetVariable  Runtime  Returns the value of a variable. 
GetNextVariableName  Runtime  Enumerates the current variable names. 
SetVariable  Runtime  Sets the value of a variable. 
QueryVariableInfo  Runtime  Returns information about the EFI variables 

与时间相关的:

函数名 类型 函数描述
GetTime  Runtime  Returns the current time and date, and the time-keeping capabilities of the platform. 
SetTime  Runtime  Sets the current local time and date information. 
GetWakeupTime  Runtime  Returns the current wakeup alarm clock setting. 
SetWakeupTime  Runtime  Sets the system wakeup alarm clock time. 

与虚拟内存相关的:

函数名 类型 函数描述
SetVirtualAddressMap  Runtime  Used by an OS loader to convert from physical addressing to virtual addressing. 
ConvertPointer  Runtime  Used by EFI components to convert internal pointers when switching to virtual addressing. 

及其它:

函数名 类型 函数描述
GetNextHighMonotonicCount  Runtime  Returns the next high 32 bits of the platform’s monotonic counter. 
ResetSystem  Runtime  Resets the entire platform. 
UpdateCapsule  Runtime  Pass capsules to the firmware. The firmware may process the capsules immediately or return a value to be passed into ResetSystem() that will cause the capsule to be processed by the firmware as part of the reset process. 
QueryCapsuleCapabilities  Runtime  Returns if the capsule can be supported via UpdateCapsule()

Runtime Service与Boot Service不同,它并不是在DxeMain.c中直接建立好的,它刚开始基本上是一个空的表:

EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = {
  {
    EFI_RUNTIME_SERVICES_SIGNATURE,                               // Signature
    EFI_RUNTIME_SERVICES_REVISION,                                // Revision
    sizeof (EFI_RUNTIME_SERVICES),                                // HeaderSize
    0,                                                            // CRC32
    0                                                             // Reserved
  },
  (EFI_GET_TIME)                    CoreEfiNotAvailableYetArg2,   // GetTime
  (EFI_SET_TIME)                    CoreEfiNotAvailableYetArg1,   // SetTime
  (EFI_GET_WAKEUP_TIME)             CoreEfiNotAvailableYetArg3,   // GetWakeupTime
  (EFI_SET_WAKEUP_TIME)             CoreEfiNotAvailableYetArg2,   // SetWakeupTime
  (EFI_SET_VIRTUAL_ADDRESS_MAP)     CoreEfiNotAvailableYetArg4,   // SetVirtualAddressMap
  (EFI_CONVERT_POINTER)             CoreEfiNotAvailableYetArg2,   // ConvertPointer
  (EFI_GET_VARIABLE)                CoreEfiNotAvailableYetArg5,   // GetVariable
  (EFI_GET_NEXT_VARIABLE_NAME)      CoreEfiNotAvailableYetArg3,   // GetNextVariableName
  (EFI_SET_VARIABLE)                CoreEfiNotAvailableYetArg5,   // SetVariable
  (EFI_GET_NEXT_HIGH_MONO_COUNT)    CoreEfiNotAvailableYetArg1,   // GetNextHighMonotonicCount
  (EFI_RESET_SYSTEM)                CoreEfiNotAvailableYetArg4,   // ResetSystem
  (EFI_UPDATE_CAPSULE)              CoreEfiNotAvailableYetArg3,   // UpdateCapsule
  (EFI_QUERY_CAPSULE_CAPABILITIES)  CoreEfiNotAvailableYetArg4,   // QueryCapsuleCapabilities
  (EFI_QUERY_VARIABLE_INFO)         CoreEfiNotAvailableYetArg4    // QueryVariableInfo
};

可以看到很多的CoreEfiNotAvailableYetxx。

Runtime Service需要在DXE阶段运行过程中一个个的填补。

比如关于时间的几个接口的初始化:

/**
  This is the declaration of an EFI image entry point. This can be the entry point to an application
  written to this specification, an EFI boot service driver, or an EFI runtime driver.

  @param  ImageHandle           Handle that identifies the loaded image.
  @param  SystemTable           System Table for this image.

  @retval EFI_SUCCESS           The operation completed successfully.

**/
EFI_STATUS
EFIAPI
InitializeRealTimeClock (
  IN EFI_HANDLE                            ImageHandle,
  IN EFI_SYSTEM_TABLE                      *SystemTable
  )
{
  EFI_STATUS  Status;

  LibRtcInitialize (ImageHandle, SystemTable);

  SystemTable->RuntimeServices->GetTime       = GetTime;
  SystemTable->RuntimeServices->SetTime       = SetTime;
  SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime;
  SystemTable->RuntimeServices->SetWakeupTime = SetWakeupTime;

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mHandle,
                  &gEfiRealTimeClockArchProtocolGuid,
                  NULL,
                  NULL
                  );

  return Status;
}

再比如关于变量的几个接口:

EFI_STATUS
EFIAPI
VariableServiceInitialize (
  IN EFI_HANDLE                         ImageHandle,
  IN EFI_SYSTEM_TABLE                   *SystemTable
  )
{
  EFI_STATUS                            Status;
  EFI_EVENT                             ReadyToBootEvent;
  EFI_EVENT                             EndOfDxeEvent;

  Status = VariableCommonInitialize ();
  ASSERT_EFI_ERROR (Status);

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mHandle,
                  &gEdkiiVariableLockProtocolGuid,
                  &mVariableLock,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mHandle,
                  &gEdkiiVarCheckProtocolGuid,
                  &mVarCheck,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);

  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;
  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;
  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;

Architecture Protocols

与Runtime Service类似,Architecture Protocols也是在DXE阶段运行的过程中逐渐填充的。

以下是所有的Architecture Protocols,这些Protocols是UEFI运行所必须的:

//
// DXE Core Global Variables for all of the Architectural Protocols.
// If a protocol is installed mArchProtocols[].Present will be TRUE.
//
// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event
// and mArchProtocols[].Registration as it creates events for every array
// entry.
//
EFI_CORE_PROTOCOL_NOTIFY_ENTRY  mArchProtocols[] = {
  { &gEfiSecurityArchProtocolGuid,         (VOID **)&gSecurity,      NULL, NULL, FALSE },
  { &gEfiCpuArchProtocolGuid,              (VOID **)&gCpu,           NULL, NULL, FALSE },
  { &gEfiMetronomeArchProtocolGuid,        (VOID **)&gMetronome,     NULL, NULL, FALSE },
  { &gEfiTimerArchProtocolGuid,            (VOID **)&gTimer,         NULL, NULL, FALSE },
  { &gEfiBdsArchProtocolGuid,              (VOID **)&gBds,           NULL, NULL, FALSE },
  { &gEfiWatchdogTimerArchProtocolGuid,    (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
  { &gEfiRuntimeArchProtocolGuid,          (VOID **)&gRuntime,       NULL, NULL, FALSE },
  { &gEfiVariableArchProtocolGuid,         (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiVariableWriteArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiCapsuleArchProtocolGuid,          (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiResetArchProtocolGuid,            (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiRealTimeClockArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
  { NULL,                                  (VOID **)NULL,            NULL, NULL, FALSE }
};

DXE的开始,最后一列都是FALSE的。

DXE阶段各种模块在安装Protocols时会执行一个回调函数,来判断安装的是否是上表中的特定Protocol,如果是的话FALSE就会被设置成TRUE。

从DXE进入BDS之前这些Protocols必须全部被安装,否则就是出错(可以看到进入BDS阶段需要的Protocol也在里面:gEfiBdsArchProtocolGuid)。

你可能感兴趣的:(UEFI开发基础,uefi,bios)