全局变量

  • gST
    • 系统表构成
    • 系统表的使用
  • gBS
    • 启动服务表的结构
  • gDS

gST

gST全称为global system table (在 uEFIL 里面,全面变量都会有个小写字母 g 在变量的前面,表征 global 的意思。) 是UEFI的基础服务之一的系统表。系统表是最重要的数据结构之一,它是用户空间通往内核空间的通道。有了它,UEFI应用程序和驱动才可以访问UEFI内核、硬件资源和I/O设备。

系统表构成

系统表可分为如下6部分:

  • 表头:包括表的版本号、表的CRC校验码等。
  • 固件信息:包括固件开发商名字的字符串和固件的版本号。
  • 标准输入控制台、标准输出控制台、标准错误控制台。
  • 启动服务表
  • 运行时服务表
  • 系统配置表
    结构体定义如下:
///
/// EFI System Table
///
typedef struct {///EFI系统表的表头。EFI_TABLE_HEADER                  Hdr;/// 指向空终止字符串的指针,固件提供商CHAR16                            *FirmwareVendor;/// 固件版本号UINT32                            FirmwareRevision;/// 活动控制台输入设备的句柄。该句柄必须支持EFI_SIMPLE_TEXT_INPUT_PROTOCOL和EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL。EFI_HANDLE                        ConsoleInHandle;/// 指向与ConsoleInHandle关联的EFI_SIMPLE_TEXT_INPUT_PROTOCOL接口的指针。EFI_SIMPLE_TEXT_INPUT_PROTOCOL    *ConIn;/// 活动控制台输出设备的句柄。EFI_HANDLE                        ConsoleOutHandle;///指向与ConsoleOutHandle关联的EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL接口的指针。EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut;///活动的标准错误控制台设备的句柄。该句柄必须支持EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL。EFI_HANDLE                        StandardErrorHandle;/// 一个指向与standderrorhandle关联的EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL接口的指针。/// 这三个控制台设备以及ConIn、ConOut、stdErr三个Protocol在驱动ConSplitterDxe中被初始化。EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *StdErr;/// 指向EFI运行时服务表的指针。EFI_RUNTIME_SERVICES              *RuntimeServices;/// 指向引导服务表的指针EFI_BOOT_SERVICES                 *BootServices;/// 缓冲区ConfigurationTable中的系统配置表的数量。UINTN                             NumberOfTableEntries;/// 指向系统配置表的指针。ConfigurationTable是系统配置表,它指向EFI_CONFIGURATION_TABLE数组,数组中的每一项是一个表。/// 例如,ConfigurationTable通常会包含APCI(Advance Configuration and Power Interface)表,/// ACPI在系统配置表中可以表示为:{gEfiAcpiTableGuid,EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER*}EFI_CONFIGURATION_TABLE           *ConfigurationTable;
} EFI_SYSTEM_TABLE;

(1) 表头 EFI_TABLE_HEADER , UEFI中的表通常都是以EFI_TABLE_HEADER开头,EFI_TABLE_HEADER的数据结构如下:

typedef struct {/// Signature为64位的无符号整数,EDK2提供了宏SIGNATURE_64(A,B,C,D,E,F,G,H),它用于将ASCII码串转化为64位的无符号整数。//例如,EFI_SYSTEM_TABLE的Signature为SIGNATURE_64(‘I’,’B’,’I’,’ ‘,’S’,’Y’,’S’,’T’)。UINT64 Signature;/// 该表所符合的EFI规范的修订。该字段的上16位为主要修订值,下16位为次要修订值。UINT32 Revision;/// HeaderSize是整个表的长度,对系统表来讲,就是sizeof(EFI_SYSTEM_TABLE)。 UINT32 HeaderSize;/// CRC32是标的校验码。计算CRC32校验码时,首先将数据结构中CRC32域清零,/// 然后计算整张表(表大小为HeaderSize)的CRC32码,计算后将校验码填充到CRC32域。UINT32 CRC32;/// 保留字段,必须设置为0。UINT32 Reserved;
} EFI_TABLE_HEADER;

系统表的使用

在UEFI中只有一个地址空间,所有的程序都运行在RING0优先级,应用程序地址空间占用UEFI地址空间的一部分。既然用户空间和内核空间是一个整体,在应用程序内也就可以直接使用内核空间的任何地址了,那么在应用程序内,只要得到了系统表的地址,就可以使用系统表。系统表的地址可以通过模块的入口函数的参数得到。

既可以通过模块入口函数UefiMain中使用传入参数SystemTable访问系统表,也可以使用gST变量访问,gST变量定义在用户空间,变量在函数UefiBootServicesTableLibConstructor中被初始化,这个函数是库UefiBootServicesTableLib的构造函数,在AutoGen.c中的ProcessLibraryConstructorList被调用。它指向的系统表定义在UEFI内核中,但需要在应用程序或驱动工程文件的[LibraryClasses]里引用UefiBootServicesTableLib。以下面的键盘事件为例:

#include<Uefi.h>
#include<Library/UefiBootServicesTableLib.h>//使用gST需要添加
EFI_Status
UefiMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE *SystemTable)
{EFI_STATUS Status;UINTN Index;EFI_INPUT_KEY Key;CHAR16 StrBuffer[4] = {0};/// 直接使用SystemTable SystemTable->BootServices->WaitForEvent(1,&SystemTable->ConIn->WaitForKey,&Index);Status = SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn,&Key);/// 使用gSTgST -> ConOut -> OutputString(gST -> ConOut,L"Please enter any key\n");gBS->WaitForEvent(1,&gST->ConIn->WaitForKey,&Index);Status = gST->ConIn->ReadKeyStroke(gST->ConIn,&Key);StrBuffer[0] = Key.UnicodeChar;StrBuffer[1] = '\n';SystemTable->ConOut->OutputString(SystemTable->ConOut,StrBuffer);gST->ConOut->OutputString(gST->ConOut,StrBuffer);return EFI_SUCCESS;
}

差异似乎只是使用gST和gBS替换掉SystemTable和SystemTable -> BootServices。

gBS

gBS指的是系统表下的SystemTable->BootService,这个被称为启动服务。系统进人DXE阶段时启动服务表被初始化,最终通过SystemTable指针将启动服务(BS)表传递给UEFI应用程序或驱动程序。UEFI应用程序和驱动程序可以通过gST->BootServices或gBS访问启动服务表。
Boot Service Table是一个结构体, 包含了所有Boot Service阶段可用的函数创建好之后,在UEFI环境下可以一直被使用,直到UEFI将控制权交给OS,并且OS调用了ExitBootService()。Boot Service是对整个系统资源的直接使用,当控制权交给OS后,OS就掌握了系统的完全控制权,这时就不再允许其它服务在未经OS允许的情况下直接对系统进行操作。

  • 事件触发函数
  • Memory Allocation Services
  • Protocol Handle Services
  • Image Services
    启动服务是UEFI的核心数据结构,通过它可以使用计算机系统内的资源。它提供的服务可以分为以下几类:
  • UEFI事件服务:事件是异步操作的基础。有了事件的支持,才可以在UEFI系统内执行并发操作。
  • 内存管理服务:主要提供内存的分配与释放服务,管理系统内存映射。
  • Protocol管理服务:提供了安装Protocol与卸载Protocol的服务,以及注册Protocol通知函数(该函数在Protocol安装时调用)的服务。
  • Protocol使用类服务:包括Protocol的打开与关闭,查找支持Protocol的控制器。
  • 驱动管理服务:包括用于将驱动安装到控制器的connect服务,以及将驱动从控制器上卸载的disconnect服务。
  • Image管理服务:此类服务包括加载、卸载、启动和退出UEFI应用程序或驱动。
  • ExitBootServices:用于结束启动服务,此服务成功返回后系统进人RT期。
  • 其他服务。

启动服务表的结构

启动服务也称启动服务表,它由UEFI表头和表项组成。表中每一项是一个函数指针,这个函数用于提供一项服务。开发UEFI应用和驱动离不开启动服务,深人理解启动服务提供的每一个服务是开发者一项必不可少的任务。上文提到过,启动服务中的服务大致可以分为8类:UEFI事件服务、内存管理服务、Protocol管理服务、Protocol使用类服务、驱动管理服务、Image管理服务、ExitBootServices及其他服务。

typedef struct {EFI_TABLE_HEADER                Hdr;// 任务优先级服务:用于提升、降低当前程序的优先级EFI_RAISE_TPL                   RaiseTPL;EFI_RESTORE_TPL                 RestoreTPL;//内存管理服务主要提供内存的分配与释放服务、管理系统内存映射。EFI_ALLOCATE_PAGES              AllocatePages;//分配内存EFI_FREE_PAGES                  FreePages;//释放内存EFI_GET_MEMORY_MAP              GetMemoryMap;//获得当前内存映射(物理地址<->虚地址)EFI_ALLOCATE_POOL               AllocatePool;//分配内存页EFI_FREE_POOL                   FreePool;//释放内存页// 事件服务专指BS中函数名以Event结尾的6个服务。UEFI事件服务是事件服务、定时器服务和任务优先级服务的统称。// 事件服务用于产生、关闭、触发、等待事件和检査事件状态。// 定时器服务用于设置定时器属性。EFI_CREATE_EVENT                  CreateEvent;//生成一个事件对象EFI_SET_TIMER                     SetTimer;//设置定时器属性EFI_WAIT_FOR_EVENT                WaitForEvent;//等待事件组中的任一事件被触发EFI_SIGNAL_EVENT                  SignalEvent;//触发事件对象EFI_CLOSE_EVENT                   CloseEvent;//关闭事件对象EFI_CHECK_EVENT                   CheckEvent;//检查事件状态// Protocol管理服务 UEFI提供了安装和卸载Protocol的服务,以及注册Protocol通知函数(该函数在Protocol安装时调用)的服务。EFI_INSTALL_PROTOCOL_INTERFACE    InstallProtocolInterface;//安装Protocol到设备上EFI_REINSTALL_PROTOCOL_INTERFACE  ReinstallProtocolInterface;//重新安装ProtocolEFI_UNINSTALL_PROTOCOL_INTERFACE  UninstallProtocolInterface;//从设备上卸载ProtocolEFI_REGISTER_PROTOCOL_NOTIFY      RegisterProtocolNotify;//为指定的Protocol注册通知事件,当这个Protocol安装时,该事件触发// 以下相关为Protocol使用类服务EFI_HANDLE_PROTOCOL               HandleProtocol;//打开 Protocol, OpenProtocol 的简化版VOID                              *Reserved;EFI_LOCATE_HANDLE                 LocateHandle;//找出支持指定Protocol的所有Handle,调用者负责分配和释放内存EFI_LOCATE_DEVICE_PATH            LocateDevicePath;  // 在指定的设备路径下找出支持给定Protocol的设备,并返回离指定的设备路径最近的设备EFI_INSTALL_CONFIGURATION_TABLE   InstallConfigurationTable;//从EFI系统表中添加、更新或删除配置表项。// Image管理服务,此类服务包括加载、卸载、启动和退出UEFI应用程序或驱动。EFI_IMAGE_LOAD                    LoadImage;//加载.efi文件至内存并生成ImageEFI_IMAGE_START                   StartImage;//启动Image,也就是调用Image的人口函数EFI_EXIT                          Exit;//退出ImageEFI_IMAGE_UNLOAD                  UnloadImage;//卸载Image//ExitBootServices用于结束启动服务,此服务成功返回后,系统进人RT期。操作系统加载器从启动服务接过对计算机系统的控制权后必须调用此服务。EFI_EXIT_BOOT_SERVICES            ExitBootServices;//结束启动服务// 其他服务EFI_GET_NEXT_MONOTONIC_COUNT      GetNextMonotonicCount;//获得系统单调计数器的下一个值EFI_STALL                         Stall;//暂停CPU指定的微秒数EFI_SET_WATCHDOG_TIMER            SetWatchdogTimer;//设置“看门狗”定时器,即在指定的时间内若系统无反应,则重启系统// 驱动管理服务 此类服务包括用于将驱动安装到控制器的connect服务,以及将驱动从控制器上卸载的disconnect服务。EFI_CONNECT_CONTROLLER            ConnectController;// 将驱动安装到指定的设备控制器EFI_DISCONNECT_CONTROLLER         DisconnectController;// 将驱动从指定的设备控制器卸载//Protocol使用类服务 该服务包括Protocol的打开与关闭、査找支持Protocol的控制器。EFI_OPEN_PROTOCOL                 OpenProtocol; // 打开 ProtocolEFI_CLOSE_PROTOCOL                CloseProtocol; // 关闭 ProtocolEFI_OPEN_PROTOCOL_INFORMATION     OpenProtocolInformation;// 返回指定Protocol的打开信息// Library ServicesEFI_PROTOCOLS_PER_HANDLE          ProtocolsPerHandle;//(Protocol使用)找出指定Handle上安装的所有ProtocolEFI_LOCATE_HANDLE_BUFFER          LocateHandleBuffer;//(Protocol使用)找出支持指定Protocol的所有Handleo系统负责分配内存,调用者负责释放内存EFI_LOCATE_PROTOCOL               LocateProtocol;//(Protocol使用)找出系统中指定Protocol的第一个实例EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES    InstallMultipleProtocolInterfaces;///(Protocol管理)安装多个Protocol到设备上EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES  UninstallMultipleProtocolInterfaces;///(Protocol管理)从设备上卸载多个Protocol// 32-bit CRC ServicesEFI_CALCULATE_CRC32               CalculateCrc32;//计算CRC32校验码// Miscellaneous ServicesEFI_COPY_MEM                      CopyMem;//复制内存EFI_SET_MEM                       SetMem;//设置指定内存区域的值EFI_CREATE_EVENT_EX               CreateEventEx;//(事件服务)生成一个事件对象并将该事件加人到一个组内
} EFI_BOOT_SERVICES;

从启动服务可以看出其功能之强大,通过它可以完全掌控整个计算机系统,其功能与操作系统提供的功能有很多重叠之处。同时它也占用了大量的计算机系统资源。设计启动服务的主要目的是帮助操作系统加载器初始化计算机系统,当操作系统加载器彻底取得对计算机系统的控制权之后,启动服务也就完成了它的使命,启动服务占用的系统资源也需要转交给操作系统加载器。此时需要调用gBS->ExitBootServices,其作用正是结束启动服务、释放启动服务占用的资源以及使用启动服务分配到的启动期资源,将控制权交给操作系统加载器。也就是说,启动服务的生存期在DxeMain与gBS->ExitBootServices之间。

gDS

gDS指的是EFI_DXE_SERVICES,是一个结构体, 包含了只在DXE阶段可用的函数, 一般是DXE Core内部使用

  • Firmware Volume driver用于从BIOS芯片中读取DXE Driver并复制到内存中。
  • Decompress driver用于将压缩打包形式的DXE Driver解压缩
typedef struct {EFI_TABLE_HEADER                Hdr;//// Global Coherency Domain ServicesEFI_ADD_MEMORY_SPACE            AddMemorySpace;//添加预留内存、系统内存或内存映射I/O资源到处理器的全局相干域。EFI_ALLOCATE_MEMORY_SPACE       AllocateMemorySpace;//分配不存在的内存,预留内存,系统内存,或内存映射I/O资源从处理器的全局一致性域。EFI_FREE_MEMORY_SPACE           FreeMemorySpace; //释放不存在的内存、预留内存、系统内存或内存映射来自处理器全局一致性域的I/O资源。EFI_REMOVE_MEMORY_SPACE         RemoveMemorySpace;  //释放不存在的内存,保留内存,系统内存,或内存映射I/O资源从处理器的全局相干域。EFI_GET_MEMORY_SPACE_DESCRIPTOR GetMemorySpaceDescriptor;  //检索包含指定地址的内存区域的描述符。EFI_SET_MEMORY_SPACE_ATTRIBUTES SetMemorySpaceAttributes;  //修改处理器全局一致性域内内存区域的属性。EFI_GET_MEMORY_SPACE_MAP        GetMemorySpaceMap; //返回处理器全局一致性域中的内存资源的映射。EFI_ADD_IO_SPACE                AddIoSpace;  //添加预留I/O或I/O资源到处理器的全局一致性域。EFI_ALLOCATE_IO_SPACE           AllocateIoSpace;  //分配不存在的I/O,保留的I/O,或I/O资源从处理器的全局一致性域。EFI_FREE_IO_SPACE               FreeIoSpace;  //释放不存在的I/O,保留的I/O,或I/O资源从处理器的全局一致性域。EFI_REMOVE_IO_SPACE             RemoveIoSpace;  //从处理器的全局一致性域移除保留的I/O或I/O资源。EFI_GET_IO_SPACE_DESCRIPTOR     GetIoSpaceDescriptor;  //检索包含指定地址的I/O区域的描述符。EFI_GET_IO_SPACE_MAP            GetIoSpaceMap;  //返回处理器全局一致性域中的I/O资源的映射。//// Dispatcher Services//EFI_DISPATCH                    Dispatch;//从固件卷加载和执行DXE驱动程序。EFI_SCHEDULE                    Schedule;//清除存储在固件卷中的组件的SOR (Schedule on Request)标志。EFI_TRUST                       Trust;//将存储在固件卷中的文件从不受信任状态提升到受信任状态。//// Service to process a single firmware volume found in a capsule//EFI_PROCESS_FIRMWARE_VOLUME     ProcessFirmwareVolume;//为系统内存中的固件卷创建一个固件卷句柄。
} EFI_DXE_SERVICES;

BIOS的全局变量gST gBS gDS相关推荐

  1. BIOS知识枝桠—— Library

    Library overview Lib Overview Lib的文件结构 库的实体: 库的头文件: 库的Dec文件: 库函数的调用: MdePkg 常用Lib PUBLIC DEFINITIONS ...

  2. UEFI Build file

    Mouble 一个模块,有.inf的文件编译 Package 有0个或许多个Mouble组成,有.dsc和.dec文件 Platform 一个特殊的Package文件一定包含一个.dec文件EDK I ...

  3. EDK环境搭建UEFI工程模块文件介绍

    一.UEFI开发环境配置 UEFI开发环境目前支持Windows,Linux,支持的平台也有很多如Intel, AMD,ARM等. 下面主要是介绍如何在windows环境下进行EDK开发. 1.获取E ...

  4. BIOS的BDS阶段解析

    1.概述 BDS全称:Boot Dev Select(启动设备选择) 主要功能是加载并连接驱动程序,管理并启动引导项.在引导操作系统之前会初始化设备(USB键盘鼠标,VGA设备等),然后通过Varia ...

  5. 【整理】BIOS、BootLoader、uboot对比

    bios BIOS是英文"Basic Input Output System"的缩略语,直译过来后中文名称就是"基本输入输出系统".其实,它是一组固化到计算机内 ...

  6. 纯新手DSP编程--5.29--DSP/BIOS任务管理和后台线程

    DSP/BIOS任务管理 1 任务管理 TSK任务管理模块 TSK模块中提供了一系列可以利用的函数,这些函数通过TSK_Handle句柄访问和管理任务对象.通过优先级安排运行,并通过切换函数完成任务切 ...

  7. 从Windows到Bios的桥梁:Windbg跟踪Win7开启ACPI

    点击上方蓝色"终端研发部",选择"设为星标" 学最好的别人,做最好的我们 本文为看雪论坛优秀文章 看雪论坛作者ID:hyjxiaobia 由于windows设备 ...

  8. BIOS 工作流程解析

    学习Linux很长时间了,一直没有时间把经验和挖掘的一些技巧整理出来,这个暑假在家没事,整理了一些与大家分享.由于都是自己的理解和实验产物,所以肯定有些不当之处,期待交流指正!  这个系列文章将以Ub ...

  9. r420服务器安装系统,r420服务器bios设置

    r420服务器bios设置 内容精选 换一换 规划数据服务器与集群处于同一内网,数据服务器IP为192.168.0.90和192.168.0.91.数据源文件格式为CSV.创建导入的目标表tpcds. ...

  10. BIOS知识枝桠——FV

    FV 基本概念 架构组成 File Type&Section Type FV的访问 FV拓展 EFI IMAGE (PE/COFF) FV拓展 EFI OPTIONROM 基本概念 FD:固件 ...

最新文章

  1. 【通用CSS模板】移动端H5页面统一样式.css
  2. 教育部:禁止开学前网授新学期课程
  3. 设计原则:公理系统在编程中的运用
  4. 做好面试前的准备工作
  5. 【转】centos安装vim7.4
  6. oracle时间戳效率问题,时间戳问题 - Oracle开发 - ITPUB论坛-中国专业的IT技术社区...
  7. 北京移动联合中兴通讯率先完成SON 4/5G全制式规模部署
  8. 电力猫服务器的网页,电力猫是如何工作的?
  9. [Unity] 利用Culling Group实现LOD和剔除逻辑
  10. 求95859回文数c语言程序,csdn 回文数
  11. 天融信EDR或企业安全终端卸载需要密码解决办法
  12. 【Springboot】——@Deprecated
  13. 最长递增子序列(Longest Increasing Subsequence)
  14. 纯干货:手把手地教你搭建Oracle Sharding数据库分片技术
  15. 做跨境电商的Anker的也回来“内卷”了?
  16. 个人减肥经验90kg-65kg
  17. Spark RDD使用详解--RDD原理
  18. Keil中取消结构体对齐的方法
  19. c4d流体插件_c4d流体插件下载|C4D流体模拟插件(Jawset TurbulenceFD)下载v1.0 Rev1372 官方最新版_ IT猫扑网...
  20. 盛夏来一杯温热红茶,淡淡茶香解暑去乏

热门文章

  1. azkaban 项目依赖
  2. azkaban 与 java任务_任务调度工具oozie和azkaban的对比
  3. 网页携带参数,将参数通过网址传入到对应的页面输入框内
  4. Scala学习笔记01
  5. 如何让我们的软件跳过360和金山毒霸的“随意拦截”?
  6. 解决Visual Studio 2017 无法启动程序,系统找不到指定文件
  7. 7大Python IDE工具推荐
  8. python123新版个人所得税计算请输入正数_Python训练的数字组合,个人所得税计算,完全平方数,python,之...
  9. Fcitx使用搜狗词库与皮肤
  10. 中移动分布式存储超级大单出炉,浪潮等唱主角