UEFI基础服务——记录
学习戴正华大佬的《UEFI原理与编程》第5章记录如下。UEFI 的核心任务是为 OS 准备好软硬件运行环境。它向上暴露的接口分两种启动服务Boot Services和运行时服务Runtime Services统称为 UEFI 服务。任何 UEFI 应用或驱动都是通过系统表拿到这两个服务表的指针。5.1 系统表5.1.1 概述系统表是整个 UEFI 编程的入口。它本质上是一个全局结构体在 DXE 阶段被初始化也就是说 SEC、PEI 阶段用不了只有到了 DXE 及以后才能访问。每个 .efi 文件Image被加载到内存后UEFI 固件会调用它的入口函数并把系统表指针传进去。入口函数的签名typedef EFI_STATUS(EFIAPI *EFI_IMAGE_ENTRY_POINT) ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable );Image 和 ImageHandle 的区别Image 是加载到内存后的可执行程序实体一个数据结构ImageHandle 是这个 Image 的句柄——可以理解为 Image 的身份证用来唯一标识这个 Image。驱动/应用之间的交互比如 Protocol 的安装和查找都是通过 Handle 来关联的。具体调用链.efi 文件加载后形成 Image 对象_ModuleEntryPoint的地址被填到Image-EntryPoint然后固件执行Image-EntryPoint(ImageHandle, SystemTable)最终进入 .inf 里指定的模块入口函数。5.1.2 系统表的结构typedef struct { EFI_TABLE_HEADER Hdr; CHAR16 *FirmwareVendor; // 固件厂商名 UINT32 FirmwareRevision; // 固件版本 EFI_HANDLE ConsoleInHandle; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; // 键盘输入 EFI_HANDLE ConsoleOutHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut; // 屏幕输出 EFI_HANDLE StandardErrorHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr; // 错误输出也是屏幕 EFI_RUNTIME_SERVICES *RuntimeServices; // 运行时服务表 EFI_BOOT_SERVICES *BootServices; // 启动服务表 UINTN NumberOfTableEntries; EFI_CONFIGURATION_TABLE *ConfigurationTable; // 配置表数组 } EFI_SYSTEM_TABLE;几点理解1表头 EFI_TABLE_HEADERUEFI 里所有表都用EFI_TABLE_HEADER开头启动服务表、运行时服务表都是。这个 Header 里有 64 位 Signature跟 GUID 类似的思路用于标识表的类型、版本号、整表大小、CRC32 校验值。CRC32 是这样算的先把 CRC32 字段清零算整表的 CRC再填回去。如果表被篡改或者损坏校验就对不上。2控制台系统表提供了 3 套控制台ConIn键盘、ConOut屏幕、StdErr屏幕。每套包含一个设备句柄和一个对应的 Protocol。有了这些UEFI 应用不用关心底层硬件细节直接调 Protocol 的函数就行。3配置表ConfigurationTable是一个数组每一项是一对GUID 数据指针。ACPI 表、SMBIOS 表、设备树等等都挂在这上面。OS Loader 通过它获取硬件信息交给内核这个设计很巧妙——用 GUID 做索引随意扩展不用改系统表结构。5.2 启动服务启动服务表在 DXE 阶段初始化通过gST-BootServices或gBS访问。它提供的服务覆盖了 UEFI 应用在启动阶段ExitBootServices 之前几乎所有需求共 8 类。注虽然也叫表但它不像系统表那样存数据——启动服务表里基本都是函数指针。5.2.1 八类服务概览类别说明典型使用场景事件服务事件、定时器、任务优先级TPL创建回调事件、设置定时器内存管理分配/释放内存页或池驱动分配缓冲区Protocol 管理安装/卸载 Protocol、注册通知驱动提供 ProtocolProtocol 使用查找/打开/关闭 Protocol应用调用驱动服务驱动管理Connect/Disconnect 控制器加载驱动到设备Image 服务加载/卸载/启动 .efi 文件OS Loader 加载内核ExitBootServices结束启动服务移交控制权OS Loader 接管系统其他CopyMem、SetMem、CRC32、Stall 等通用工具操作启动服务表的结构体非常大100 行但理清分类后其实很好记。额外提几点TPL任务优先级RaiseTPL/RestoreTPL 用来在关键区域提升优先级防止其他事件打断。跟中断屏蔽的思路类似但用的是软件优先级。事件UEFI 的事件模型支持多种类型通知事件、定时器事件等。CreateEvent 的时候可以指定回调函数和触发条件核心是异步通知机制。Protocol 函数的历史包袱InstallProtocolInterface和ReinstallProtocolInterface是早期版本遗留下来的新代码应该用InstallMultipleProtocolInterfaces它一次可以安装多个 Protocol而且会在失败时自动回滚。5.2.2 内存管理服务详解内存管理服务分三组1AllocatePool / FreePool —— 按字节分配最常用的内存分配方式类似 C 的 malloc/free。必须成对调用。CHAR16 *Buffer NULL; gBS-AllocatePool(EfiBootServicesCode, 1024, (VOID**)Buffer); gBS-FreePool(Buffer);内存类型是关键参数。AllocatePool第一个参数指定内存类型这决定了内存在 ExitBootServices 之后的命运EfiBootServicesCode/EfiBootServicesDataExitBootServices 后固件回收。用于 UEFI 驱动和应用自身。EfiLoaderCode/EfiLoaderData由 OS Loader 和 OS 决定是否回收。用于存放交给内核的数据比如内存映射表。EfiACPIReclaimMemoryACPI 表初始化完成后回收。EfiRuntimeServicesCode/EfiRuntimeServicesData等ExitBootServices 后保留给运行时服务继续用。理解这个很重要——如果你在 Boot Service 里分配了一块EfiBootServicesData内存想在 RT 阶段继续用那就会挂掉因为这块内存已经被回收了。2AllocatePages / FreePages —— 按物理页分配当你需要整页内存或者不想分配跨页时用这个。驱动开发中很常见因为有些硬件 DMA 要求物理连续而且 DMA 缓冲区通常以页为单位。EFI_PHYSICAL_ADDRESS pages 0; // 0 表示让固件自己选地址 gBS-AllocatePages(AllocateAnyPages, EfiBootServicesCode, 3, pages); // 拿到的是物理地址操作内存前要转成指针 CHAR16 *Str (CHAR16*)pages; gBS-FreePages(pages, 3);重要AllocatePages返回的是物理地址EFI_PHYSICAL_ADDRESS不是指针。在 32 位 UEFI 上如果物理内存超过 4GBAllocateAnyPages可能分配到 4G 以上的物理地址32 位指针够不着——这时候要用AllocateMaxAddress限制允许分配的最大物理地址。Type参数的三种分配方式AllocateAnyPages任意地址AllocateMaxAddress分配的页面物理地址不能超过传入值AllocateAddress强制分配到指定物理地址3GetMemoryMap —— 获取系统内存布局这是 ExitBootServices 之前必须调用的服务。它返回整个系统的内存映射表每个条目EFI_MEMORY_DESCRIPTOR描述了一块内存的类型、物理地址、虚拟地址、页数和属性。调用有个经典的两步走模式先传个 0 大小的 Buffer 让固件告诉你需要多大分配好再调一次。MapKey是当前内存映射的版本标识ExitBootServices 时要传这个 Key防止内存映射在你获取之后被修改如果 Key 变了说明驱动对内存做了操作就得重新获取。5.2.3 启动服务的生命周期总结gBS从 DXE 初始化开始可用到gBS-ExitBootServices()成功后结束。ExitBootServices 执行后被回收的启动服务表中除EFI_TABLE_HEADER外的所有函数指针都失效ConIn、ConOut、StdErr相关的控制台设备/Protocol 失效EfiBootServicesCode和EfiBootServicesData类型的内存被回收保留的gRT—— 运行时服务继续可用ConfigurationTable—— 配置表保留ACPI、SMBIOS 等 HW 信息FirmwareVendor和FirmwareRevision字符串调试技巧在 ExitBootServices 前后分别看gST的地址和其成员地址可以确认哪些区域被释放了。书中提到可以用asm int 3打调试断点来观察。MapKey的坑如果第一次 GetMemoryMap 拿到 MapKey 后在调用 ExitBootServices 之前又有代码调了分配/释放内存MapKey 就对不上了ExitBootServices 会失败。正确的做法是检测到失败后重新 GetMemoryMap 再调。5.3 运行时服务运行时服务同样在 DXE 阶段初始化但它的生命周期比启动服务长得多——一直到操作系统运行期间都存活给 OS 提供底层服务。gRT提供了 4 类服务类别说明时间服务读写硬件 RTC、唤醒定时器虚拟内存SetVirtualAddressMap、ConvertPointer变量服务读写 UEFI 变量Get/Set Variable其他ResetSystem重启、Capsule 更新、查询变量信息5.3.1 时间服务GetTime / SetTime直接操作 RTC 硬件。时间结构体包含年月日时分秒纳秒和时区。注意几个细节EFI_TIME有两个 Padding 字节Pad1、Pad2这是为了字节对齐TimeZone-1440 到 1440单位分钟UTC 时区是 0。还有一个特殊值 2047 表示时区未知Daylight夏令时标志Nanosecond字段精度看起来很高但实际受限于 RTC 硬件精度EFI_TIME_CAPABILITIES描述时钟硬件能力Resolution时钟每秒脉冲数Accuracy精度单位 ppm百万分之一SetsToZero是否在设置时间时清零亚秒计数器GetWakeupTime / SetWakeupTime操作系统用这个实现定时开机——比如笔记本在 AC 状态下设置唤醒时间关机后 RTC 到时触发上电。5.3.2 变量服务UEFI 变量是运行在 Flash 上的键值存储用 (GUID Name) 作为唯一标识。OS 装好后的启动项、Secure Boot 密钥、固件设置都存成变量。核心三个接口GetVariable读取变量SetVariable写入变量可以附加属性如 Non-Volatile、BootService、Runtime、Authenticated Write 等GetNextVariableName遍历所有变量5.3.3 虚拟内存服务这两个接口只能在 ExitBootServices 之后调用。由于 OS 启用分页后物理地址就不能直接用了所以 RT 阶段要先把运行时服务使用的物理地址映射到虚拟地址。调用流程SetVirtualAddressMap传入内存映射表物理地址→虚拟地址的映射固件内部遍历并更新。然后ConvertPointer用于将某个指针的指向从物理地址改为虚拟地址——注意它转换的是指针的指针。小结UEFI 的这套服务设计其实很清晰系统表 导航中心从这里拿到一切启动服务 DXE 到 OS Loader 期间的工具箱内存管理 Protocol 操作 Image 加载功能最强运行时服务 OS 运行后还能用的精简接口时间 变量 复位理解生命周期这个概念特别重要什么内存在什么时候分配、什么时候回收什么服务在什么时候可用。

相关新闻

Android渗透测试环境搭建:Kali Linux与MSFvenom实战指南

Android渗透测试环境搭建:Kali Linux与MSFvenom实战指南

1. 项目概述:为什么需要搭建Android渗透测试环境?如果你对移动安全感兴趣,或者想验证自己开发的Android应用是否存在安全隐患,那么亲手搭建一个本地的渗透测试环境是必经之路。这就像木匠需要自己的工具箱,厨师需要自己…

2026/7/14 4:18:40 阅读更多 →
kali2026.2 2026kali换中文输入法

kali2026.2 2026kali换中文输入法

1:sudo apt install fcitx fcitx-googlepinyin 2:sudo apt install fcitx-frontend-gtk3 fcitx-frontend-qt5 注:这里第二到第六可能不需要,但我成功运行了,可能是等待的时间不够3:im-config -n fcitx4&…

2026/7/14 4:14:39 阅读更多 →
LLaMA-2中文适配实战:从词表扩展到指令微调

LLaMA-2中文适配实战:从词表扩展到指令微调

1. 项目背景与核心挑战当我们需要让一个以英文训练为主的大语言模型(如LLaMA、GPT等)理解并流畅处理中文指令时,会遇到几个典型问题:词汇表不匹配:英文预训练模型的tokenizer通常不包含中文字符,导致中文文…

2026/7/14 4:08:36 阅读更多 →

最新新闻

C++ CAD数据交换:libdxfrw库读写DXF/DWG文件实战指南

C++ CAD数据交换:libdxfrw库读写DXF/DWG文件实战指南

1. 项目概述:为什么你需要关注 libdxfrw?如果你正在用 C 开发与 CAD 数据打交道的应用,无论是做机械设计软件、建筑信息模型(BIM)工具、数控(CNC)加工路径生成,还是游戏引擎的地图编…

2026/7/14 6:27:29 阅读更多 →
stable-diffusion.cpp:纯C/C++实现AI绘画推理,打造轻量高效的生成式AI运行时

stable-diffusion.cpp:纯C/C++实现AI绘画推理,打造轻量高效的生成式AI运行时

1. 项目概述:为什么我们需要一个纯C/C的Stable Diffusion推理库?如果你玩过AI绘画,大概率用过Stable Diffusion WebUI或者ComfyUI。它们功能强大,但背后依赖的是Python、PyTorch这一整套庞大的生态。启动慢、内存占用高、环境配置…

2026/7/14 6:25:29 阅读更多 →
可白嫖源码---课程设计--毕业设计--21926品牌车衣供应商直播带货及线下店管理系统(案例分析)-附源码

可白嫖源码---课程设计--毕业设计--21926品牌车衣供应商直播带货及线下店管理系统(案例分析)-附源码

本文仅展示核心实现逻辑与部分代码片段,完整项目源码、配套文档、数据库脚本内容较多,篇幅有限无法全部放出。 有需要完整资源的同学,可以在评论区留言【资料或领源码】,我会一 一回复站内私信,发送完整文件 目录 摘 …

2026/7/14 6:23:29 阅读更多 →
多维聚合与滚动计算:银行级数据聚合的工程实践

多维聚合与滚动计算:银行级数据聚合的工程实践

1. 项目概述:为什么多维聚合不是“加个groupby”就能搞定的事我在银行数据平台组干了八年,从最早用SQL写几十行嵌套子查询做客户分层,到后来带团队搭实时风险计算引擎,踩过的坑比写的代码还多。今天聊的这个主题——“多维聚合中的…

2026/7/14 6:21:28 阅读更多 →
《操作系统》实验手记 | 从逻辑地址到共享内存:一次完整的内存管理实践

《操作系统》实验手记 | 从逻辑地址到共享内存:一次完整的内存管理实践

1. 实验目标与核心概念第一次打开Bochs调试器时,看到黑屏上闪烁的光标和满屏的十六进制数字,我意识到这将是一次深入操作系统内核的探险。这次实验要完成两个关键任务:一是手动追踪变量i0x12345678从逻辑地址到物理地址的完整翻译过程&#x…

2026/7/14 6:19:28 阅读更多 →
稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理)

稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理)

以下是稳定版 Foster → Cauer 转换(使用经典连分式展开 + 数值保护 + 后处理): 完整稳定版 C# 代码(推荐替换) public static (double[] Rcauer, double[] Ccauer) FosterToCauerStable(

2026/7/14 6:17:27 阅读更多 →

日新闻

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

AI Agent数据越界行为如何被精准溯源?——基于GDPR/CCPA双合规的5层审计框架实战指南

更多请点击: https://kaifayun.com 第一章:AI Agent数据越界行为的合规性挑战与溯源必要性 AI Agent在自主执行任务过程中,可能因提示注入、上下文污染或权限配置缺陷,无意或有意访问、缓存、传输受保护数据(如PII、G…

2026/7/14 0:01:13 阅读更多 →
Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

Perplexity vs ChatGPT vs Claude:实测127组复杂查询任务,谁才是真正可靠的“事实型AI助手”?

更多请点击: https://codechina.net 第一章:Perplexity 怎么用 Perplexity 是衡量语言模型预测能力的核心指标,数值越低表示模型对文本序列的不确定性越小、预测越精准。它本质上是交叉熵损失的指数形式,计算公式为:…

2026/7/14 0:01:13 阅读更多 →
全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

全球首发!五一视界定制物理AI卫星ECS-1剑指万亿赛道

五一视界发布公告,近日,公司与环天智慧科技股份有限公司(“环天智慧”)正式达成空天领域战略合作。环天智慧是国内领先、聚焦天基对地观测遥感卫星总体研制与在轨运营的商业航天企业,同时也是西南地区规模最大、具备全自主可控遥感卫星星座建…

2026/7/14 0:03:13 阅读更多 →

周新闻

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨

互联网大厂 Java 求职面试:燕双非的搞笑回答与技术探讨 在一个阳光明媚的上午,互联网大厂的面试官坐在桌前,准备迎接他的面试候选人——燕双非,一个以搞笑和幽默著称的程序员。第一轮提问 面试官:燕双非,作…

2026/7/13 4:38:36 阅读更多 →
车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估

车载以太网PMA测试设备选型:示波器、VNA、信号源3类仪器关键参数与预算评估在智能驾驶和车联网技术快速发展的今天,车载以太网作为新一代车载网络的核心传输技术,其物理层性能直接决定了数据传输的可靠性和稳定性。1000BASE-T1作为当前主流的…

2026/7/13 4:38:38 阅读更多 →
VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战,5步完成Keil工程转换

VSCode EIDE 插件 2.0:APM32/STM32 项目迁移实战指南嵌入式开发领域正经历一场工具链的静默革命。当传统Keil用户首次打开VSCode的扩展市场搜索EIDE时,往往会惊讶于这个看似简单的插件竟能重构十余年的开发习惯。本文将揭示如何用五个精准步骤&#xff0…

2026/7/13 4:38:40 阅读更多 →

月新闻