UEFI Spec 学习笔记---7 - Services — Boot Services(1)

Boot Services是由可能在 UEFI 环境中运行的接口函数的代码定义的。这些代码包括设备管理和扩展性的 protocol, 以及在预启动环境中运行的应用和 OS loader 。

服务分为两类:

  • BootServices---在EFI_BOOT_SERVICES.ExitBootServices(). 调用前可以使用
  • RuntimeServices---任何时候都可以使用

UEFI application 必须通过 boot service 来访问设备以及内存管理,使用 boot service 时通过一个全局指针(gBS etc) 。BootServices 是由 OS loader 加载EFI_BOOT_SERVICES.ExitBootServices() 来结束使用的,而 OSloader 本质上也是一个 UEFI application,调不调用EFI_BOOT_SERVICES.ExitBootServices()是看该 UEFI application 是否继续使用 Boot services 或者 boot service 的环境。

包括如下的 services:

• Event, Timer, and Task Priority Services (Section 7.1)

• Memory Allocation Services (Section 7.2)

• Protocol Handler Services (Section 7.3)

• Image Services (Section 7.4)

• Miscellaneous Services (Section 7.5)

7.1 Event, Timer, and Task Priority Services

引导服务环境中的执行发生在不同的任务优先级级别(tpl)上。引导服务环境只向UEFI应用程序和驱动程序展示了这些级别中的三个:

• TPL_APPLICATION**,** the lowest priority level

• TPL_CALLBACK, an intermediate priority level

• TPL_NOTIFY, the highest priority level

以高优先级执行的任务可能会中断以低优先级执行的任务。例如,在TPL_NOTIFY级别运行的任务可能会中断在TPL_APPLICATION或TPL_CALLBACK级别运行的任务。虽然TPL_NOTIFY是向引导服务应用程序公开的最高级别,但固件可能有它处理的更高任务优先级项。例如,固件可能必须处理更高优先级的任务,如计时器刻度和内部设备。因此,有第四个TPL, TPL_HIGH_LEVEL,专为固件使用而设计。

执行代码可以通过调用EFI_BOOT_SERVICES.RaiseTPL()函数暂时提高其优先级级别。在调用EFI_BOOT_SERVICES.RestoreTPL()函数将优先级降低到低于挂起事件通知的优先级之前,这样做会屏蔽以相同或更低优先级运行的代码的事件通知。在许多UEFI服务功能和协议接口功能可以执行的TPL级别上有限制。限制说明如表7-3所示。

7.2 Memory Allocation Services

主要提供对应的接口用于内存分配和释放内存,以及获取系统的内存信息。

在预启动的过程中,所有固件组成必须使用 BootService 的接口来对内存进行使用和释放,同时 Boot Service 也会动态更新维护内存,防止出现内存泄漏等问题。同时 EFI image 只能使用自己分配的内存,并且在 image 执行完毕之后需要将分配的内存释放,包括这包括所有 memory page、分配的 Pool、打开的 handle 等。

如下函数实例:在 HandleProtocol 调用获取所有安装该 protocol 的 handle 保存到 buffer 之后,需要使用 FreePool 来释放。

for (Index = 0; Index < HandleCount; Index++) {
    Status = EfiTestChildHandle (HandleBuffer[Index], ChildHandle, ProtocolGuid);
    if (!EFI_ERROR (Status)) {
      Status = gBS->HandleProtocol (HandleBuffer[Index], ProtocolGuid, (VOID **)&Interface);
      if (!EFI_ERROR (Status)) {
        gBS->FreePool (HandleBuffer);
        return Interface;
      }
    }
  }

  gBS->FreePool (HandleBuffer);

内存分配时会传入内存类型,不同类型是对于不同的内容。同事根据ExitBootServices() 的调用也会有不同的类型使用:

ExitBootServices 调用前

ExitBootServices 调用后

一个调用ExitBootServices()的映像(即UEFI OS Loader)首先调用

EFI_BOOT_SERVICES.GetMemoryMap()获取当前内存映射。在调用 ExitBootServices()之后,映像隐式地拥有映射中所有未使用的内存。这 包括内存类型EfiLoaderCode, EfiLoaderData, EfiBootServicesCode, EfiBootServicesData和eficonconventional memory。UEFI操作系统Loader和操作系统需要 保留标记为EfiRuntimeServicesCode和EfiRuntimeServicesData的内存。

AllocatePagesFreePages

用于从系统上获取内存区域,和释放内存,单位 k 是 4K,也就是对应是 4K 的也就是一个 Page.

typedef
EFI_STATUS
(EFIAPI *EFI_ALLOCATE_PAGES) (
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT EFI_PHYSICAL_ADDRESS *Memory
)

typedef
EFI_STATUS
(EFIAPI *EFI_FREE_PAGES) (
IN EFI_PHYSICAL_ADDRESS Memory,
IN UINTN Pages
);

GetMemoryMap

获取当前内存 map 也就是内存使用情况。

typedef
EFI_STATUS
(EFIAPI *EFI_GET_MEMORY_MAP) (
IN OUT UINTN *MemoryMapSize,
OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
OUT UINTN *MapKey,
OUT UINTN *DescriptorSize,
OUT UINT32 *DescriptorVersion
)

AllocatePoolFreePool

分配一个池内存,size 是以 byte 的,可以自己输入大小而不需要对齐。

typedef
EFI_STATUS
(EFIAPI *EFI_ALLOCATE_POOL) (
IN EFI_MEMORY_TYPE PoolType,
IN UINTN Size,
OUT VOID **Buffer
)

typedef
EFI_STATUS
(EFIAPI *EFI_FREE_POOL) (
IN VOID *Buffer
)

7.3 Protocol Handler Services

在 UEFI 抽象出了由一个全局唯一的 GUID 以及 protocol 实体的 protocol 结构体,结构中包含访问 device 的函数以及所需要的数据。

应用程序可以在 device handle 上面安装 protocol,以及通过 Handle service 来对 handle 上的 Protocol 进行操作,以及确认是否支持某个 protocol.

Driver Model Boot Services

解决方案是在句柄数据库本身中跟踪协议接口的使用情况。为此, 每个协议接口都包含一个正在使用该协议接口的代理列表。图7-2 显示了一个带有这些新代理列表的句柄数据库示例。代理由一个图像句柄、一个 控制器句柄和一些属性组成。图像句柄标识正在 使用协议接口的驱动程序或应用程序。控制器句柄标识正在使用 协议接口的控制器。由于驱动程序可以管理多个控制器,驱动程序的 图像句柄和控制器的控制器句柄的组合唯一地标识正在使用 协议接口的代理。这些属性显示了如何使用协议接口。

相关推荐
API_technology1 小时前
api开发及运用小红书笔记详情api如何获取笔记详情信息
大数据·开发语言·数据库·数据仓库·笔记·爬虫
大丈夫立于天地间2 小时前
ospf收敛特性及其他的小特性
网络·网络协议·学习·算法·智能路由器·信息与通信
小卡规划2 小时前
检验统计量与p值笔记
笔记
J不A秃V头A3 小时前
自定义SqlSessionFactory时mybatis-config.xml失效
java·开发语言
星雨流星天的笔记本4 小时前
英语外刊写作积累(2024.09)
学习
静水楼台x4 小时前
Java中json的一点理解
java·后端·json
wangqiaowq4 小时前
Apache PAIMON 学习
学习
晴空๓4 小时前
如何查看特定版本的Spring源码
java·spring boot·spring
羊小猪~~5 小时前
MYSQL学习笔记(二):基本的SELECT语句使用(基本、条件、聚合函数查询)
数据库·笔记·sql·学习·mysql·考研·数据分析
然然阿然然5 小时前
2025.1.15——二、字符型注入
网络·数据库·sql·学习·网络安全