- 固件
- 操作系统
- 驱动开发
- 嵌入式
【免费下载链接】edk2
EDK II
本篇文章围绕 MdeModulePkg 中TraceHubDebugSysTLib库展开,系统讲解 EDK II 固件如何借助 Trace Hub 硬件与 MIPI SYS-T 子模块,在 SEC/PEI/DXE/SMM 各阶段输出调试消息与目录(Catalog)消息。读者读完可以掌握该库的顶层 API、三个库实例(Base/Pei/DxeSmm)的选型差异、三个 Trace Hub 相关 PCD 与gTraceHubDebugInfoHobGuidHOB 的配置方法,以及底层实例计数、可见性判断与 MMIO 地址解析的实现机制,从而在自己的平台 DSC/FDF 中正确集成并配置 Trace Hub 调试能力。
TraceHubDebugSysTLib 是什么
TraceHubDebugSysTLib是 EDK II 中用于输出 Trace Hub 消息的顶层(top level)库。它本身不直接操作 Trace Hub 寄存器,而是通过MIPI SYS-T 子模块(即MipiSysTLib,头文件mipi_syst.h)将调试字符串、目录消息(Catalog Message)以 MIPI SYS-T 协议格式写到 Trace Hub 的 MMIO 地址上,供 Trace Hub 硬件采集并经调试探针(如 Intel DCI / ITP)在主机侧还原为可读日志。
该库的公共 API 声明位于 MdePkg/Include/Library/TraceHubDebugSysTLib.h,实现代码位于 MdeModulePkg/Library/TraceHubDebugSysTLib 目录,该目录下共包含三个可实例化的库(各有一个.inf与其对应实现.c),外加两个内部公共实现文件:
BaseTraceHubDebugSysTLib.inf/BaseTraceHubDebugSysTLib.cPeiTraceHubDebugSysTLib.inf/PeiTraceHubDebugSysTLib.cDxeSmmTraceHubDebugSysTLib.inf/DxeSmmTraceHubDebugSysTLib.cInternalTraceHubApi.c/InternalTraceHubApi.h(非公共接口:实例计数与打包)InternalTraceHubApiCommon.c/InternalTraceHubApiCommon.h(公共内部接口:可见性判断、GUID 字节序转换、消息输出判定、MMIO 地址与消息可见性读取)
使用该库前,用户必须正确配置三个 Trace Hub 相关 PCD 以及一个 HOB(详见下文)。PCD 的详细定义见 MdeModulePkg.dec,HOB 的详细定义见 TraceHubDebugInfoHob.h。
顶层 API:三种消息输出接口
库对外只暴露三个函数,全部位于MdePkg/Include/Library/TraceHubDebugSysTLib.h,所有实现均遵循EFIAPI调用约定并返回RETURN_STATUS。
1.TraceHubSysTDebugWrite— 输出调试字符串
RETURN_STATUS EFIAPI TraceHubSysTDebugWrite ( IN TRACE_HUB_SEVERITY_TYPE SeverityType, IN UINT8 *Buffer, IN UINTN NumberOfBytes );将一段原始调试字符串(Buffer,长度NumberOfBytes)按SeverityType指定的严重级别写入 Trace Hub。参数校验逻辑(见 BaseTraceHubDebugSysTLib.c)为:NumberOfBytes == 0时直接返回RETURN_SUCCESS(无数据可写),Buffer == NULL时返回RETURN_INVALID_PARAMETER。
2.TraceHubSysTWriteCataLog64StatusCode— 输出目录状态码消息
RETURN_STATUS EFIAPI TraceHubSysTWriteCataLog64StatusCode ( IN TRACE_HUB_SEVERITY_TYPE SeverityType, IN UINT64 Id, IN GUID *Guid );输出一条带目录 ID(Id)和驱动 GUID(Guid)的状态码消息。实现中会先将 GUID 从小端转为大端写入MipiSystHandle.systh_guid,并置位systh_tag.et_guid = 1(见 PeiTraceHubDebugSysTLib.c);若Guid == NULL,则退化为模块/单元标签模式(et_modunit = 2、et_guid = 0)。Guid == NULL在 Base 实现中会直接返回RETURN_INVALID_PARAMETER。
3.TraceHubSysTWriteCataLog64— 输出带参数的目录消息
RETURN_STATUS EFIAPI TraceHubSysTWriteCataLog64 ( IN TRACE_HUB_SEVERITY_TYPE SeverityType, IN UINT64 Id, IN UINTN NumberOfParams, ... );变参函数,输出目录消息并可携带最多与MipiSystHandle.systh_param数组容量等长的 32 位参数(实现通过VA_START/VA_ARG逐一填充systh_param,见 BaseTraceHubDebugSysTLib.c);NumberOfParams超过systh_param容量时返回RETURN_INVALID_PARAMETER。
严重级别枚举TRACE_HUB_SEVERITY_TYPE
三个 API 的第一个参数统一使用该枚举(定义于TraceHubDebugSysTLib.h):
| 值 | 枚举名 | 含义 |
|---|---|---|
| 0 | SeverityNone | 无级别 |
| 1 | SeverityFatal | 致命错误 |
| 2 | SeverityError | 错误 |
| 3 | SeverityWarning | 警告 |
| 4 | SeverityNormal | 常规信息 |
| 5–7 | SeverityUser1/2/3 | 用户自定义级别 |
三个 Trace Hub PCD 配置详解
按 Readme.md 要求,使用本库前必须配置以下三个 PCD(均属于gEfiMdeModulePkgTokenSpaceGuid,定义于 MdeModulePkg.dec):
PcdTraceHubDebugLevel(UINT8,默认 0x0)
指示 Trace Hub 的调试级别,决定哪些严重级别的消息会被输出。合法取值如下:
| 值 | 宏 | 允许输出的严重级别 |
|---|---|---|
| 0x0 | TraceHubDebugLevelError | 仅SeverityFatal、SeverityError |
| 0x1 | TraceHubDebugLevelErrorWarning | 追加SeverityWarning |
| 0x2 | TraceHubDebugLevelErrorWarningInfo | 追加SeverityNormal |
| 0x3 | TraceHubDebugLevelErrorWarningInfoVerbose | 全部级别 |
该过滤逻辑实现在 InternalTraceHubApiCommon.c 的TraceHubDataEnabled()中:先判断使能标志,再按调试级别与消息严重级别的组合决定放行或丢弃。
PcdEnableTraceHubDebugMsg(BOOLEAN,默认 FALSE)
全局开关:FALSE关闭 Trace Hub 调试消息,TRUE打开。对应 HOB 结构中的Flag字段。
PcdTraceHubDebugMmioAddress(UINT64,默认 0)
Trace Hub 消息输出目标的 MMIO 基地址。实现中(CheckWhetherToOutputMsg,见 InternalTraceHubApiCommon.c)会将该地址填入MipiSystHandle.systh_platform.TraceHubPlatformData.MmioAddr,若地址为 0 则直接判定消息无需输出(返回RETURN_ABORTED)。因此该 PCD 必须被配置为平台实际 Trace Hub MMIO 基地址,否则即使使能开关打开也不会产生任何输出。
在平台中覆盖 PCD
三个库的.inf均声明了上述 PCD(例如 PeiTraceHubDebugSysTLib.inf 的[Pcd]段)。平台可在 DSC 的[PcdsFixedAtBuild]或[PcdsDynamic]中覆盖默认值,例如:
[PcdsFixedAtBuild] gEfiMdeModulePkgTokenSpaceGuid.PcdEnableTraceHubDebugMsg|TRUE gEfiMdeModulePkgTokenSpaceGuid.PcdTraceHubDebugLevel|0x2 gEfiMdeModulePkgTokenSpaceGuid.PcdTraceHubDebugMmioAddress|0xFED0F000Trace Hub HOB:gTraceHubDebugInfoHobGuid
除 PCD 外,Readme 还要求配置gTraceHubDebugInfoHobGuid对应的 HOB。其 GUID 定义为:
{ 0xf88c9c23, 0x646c, 0x4f6c, { 0x8e, 0x3d, 0x36, 0xa9, 0x43, 0xc1, 0x08, 0x35 } }(见 MdeModulePkg.dec 的[Guids]段。)
HOB 数据结构TRACEHUB_DEBUG_INFO_HOB定义于 TraceHubDebugInfoHob.h,当前修订版本号TRACEHUB_DEBUG_INFO_HOB_REVISION = 1:
typedef struct { UINT16 Revision; // 结构修订版本 BOOLEAN Flag; // 使能/禁用 Trace Hub 调试消息 UINT8 DebugLevel; // Trace Hub 调试级别 UINT8 Rvsd[4]; // 保留字段 UINT64 TraceHubMmioAddress; // Trace Hub 调试消息输出 MMIO 地址 } TRACEHUB_DEBUG_INFO_HOB;该 HOB 的作用是让早期阶段(如 SEC/PEI)发现多个 Trace Hub 调试实例时,把每个实例的配置以 HOB 形式传递给后续阶段,从而支持多 Trace Hub 实例场景。这与单一固定 PCD 仅能描述一个实例形成对比。
三个库实例的差异与选型
Readme 将库分为三个实例,它们共享顶层 API 与大部分内部逻辑,差异集中在"配置来源"和"适用模块类型"上。
BaseTraceHubDebugSysTLib.inf — 固定 PCD,单实例
- 适用阶段:
LIBRARY_CLASS = TraceHubDebugSysTLib(无模块类型限定,即 SEC/PEI/DXE/SMM 均可用),见 BaseTraceHubDebugSysTLib.inf。 - 行为:仅基于固定 PCD 输出 Trace Hub 消息,只支持单个 Trace Hub 调试实例。其
CountThDebugInstance()直接返回 1(见 BaseTraceHubDebugSysTLib.c),不会查询 HOB。 - 适用场景:不需要 HOB 机制、硬件只有一个 Trace Hub 实例的简单平台,或 SEC 等尚无 HOB 服务的阶段。
PeiTraceHubDebugSysTLib.inf — PEI 阶段,PCD + HOB
- 适用阶段:
LIBRARY_CLASS = TraceHubDebugSysTLib|PEI_CORE PEIM,见 PeiTraceHubDebugSysTLib.inf。 - 行为:基于固定 PCD 与 HOB 输出消息。一旦检测到
gTraceHubDebugInfoHobGuidHOB 即应用 HOB 中的配置(Flag、DebugLevel、TraceHubMmioAddress);若不存在 HOB 则回退使用 PCD 配置。 - 实例遍历:
CountThDebugInstance()(见 InternalTraceHubApi.c)会统计系统中该 GUID HOB 的个数;无 HOB 时计为 1(即回退到 PCD 的单实例)。消息循环用GetFirstGuidHob/GetNextGuidHob遍历全部实例(见 PeiTraceHubDebugSysTLib.c)。
DxeSmmTraceHubDebugSysTLib.inf — DXE/SMM 阶段,PCD + HOB
- 适用阶段:
LIBRARY_CLASS = TraceHubDebugSysTLib|DXE_CORE DXE_DRIVER SMM_CORE DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION,见 DxeSmmTraceHubDebugSysTLib.inf。 - 行为:与 PEI 实例相同,基于固定 PCD 与 HOB 输出消息,无 HOB 时回退到 PCD。
- 构造器机制:该库声明了
CONSTRUCTOR = DxeSmmTraceHubDebugSysTLibConstructor。构造器(见 DxeSmmTraceHubDebugSysTLib.c)在库被链接进模块时执行一次:先CountThDebugInstance()统计实例数,再用AllocateZeroPool分配实例数组,最后调用PackThDebugInstance()把所有实例配置一次性打包进内存数组。PackThDebugInstance()(见 InternalTraceHubApi.c)在有 HOB 时逐个CopyMem复制 HOB 数据,无 HOB 时用三个固定 PCD 填充数组元素。这种"构造时快照"避免了每次输出消息都重复遍历 HOB 列表,更适合 DXE/SMM 高频调用场景。
三个实例速查对比
| 库实例 | 配置来源 | 实例数 | 适用模块类型 | 特殊机制 |
|---|---|---|---|---|
| BaseTraceHubDebugSysTLib | 仅固定 PCD | 固定 1 个 | 通用(无模块限定) | 无 |
| PeiTraceHubDebugSysTLib | PCD + HOB(HOB 优先) | 按 HOB 计数,无 HOB 则 1 | PEI_CORE、PEIM | 每次调用遍历 HOB |
| DxeSmmTraceHubDebugSysTLib | PCD + HOB(HOB 优先) | 按 HOB 计数,无 HOB 则 1 | DXE/SMM 系列模块 | 库构造器快照实例配置 |
内部实现机制:消息如何被决定输出
无论哪个实例,底层都会复用 InternalTraceHubApiCommon.c 中的公共判定逻辑,一条消息是否真正写入 Trace Hub 取决于三层条件:
- 使能标志:
GetTraceHubMsgVisibility()读取配置(有 HOB 时读ThDbgContext->Flag,否则读FixedPcdGetBool (PcdEnableTraceHubDebugMsg));TraceHubDataEnabled()中Flag == TraceHubRoutingDisable(即 FALSE)直接不输出。 - 调试级别过滤:
TraceHubDataEnabled()按DbgLevel与SeverityType组合判定(见上文 PCD 取值表),例如DbgLevel == TraceHubDebugLevelError时只有SeverityFatal/SeverityError放行。 - MMIO 地址有效性:
GetTraceHubMmioAddress()解析输出地址(HOB 优先,否则FixedPcdGet64 (PcdTraceHubDebugMmioAddress)),地址为 0 时CheckWhetherToOutputMsg返回RETURN_ABORTED,消息被丢弃。
只有全部条件通过,MipiSystWriteDebug或MipiSystWriteCatalog才会真正把消息写入 Trace Hub MMIO。此外,目录消息还会通过SwapBytesGuid()(InternalTraceHubApiCommon.c)将 GUID 的Data1/Data2/Data3字段做小端/大端互换,以满足 MIPI SYS-T 协议对 GUID 字段的字节序要求。
使用限制与注意事项
Readme 明确给出一条重要限制:Trace Hub 调试库目前不支持DXE_RUNTIME_DRIVER类型的模块。这是因为运行时驱动在 ExitBootServices 之后运行于无 MMU 映射保障的环境,直接访问 Trace Hub MMIO 地址可能导致异常;需要运行时输出时应改用其他日志通道(如普通串口DebugLib或非易失性日志),或将消息发送逻辑放在 DXE 驱动而非 Runtime 驱动中。
另外还需注意:TraceHubDebugSysTLib是输出路径的"顶层库",它依赖MipiSysTLib(mipi_syst.h)完成 SYS-T 协议封装;平台若要启用完整 Trace Hub 调试链路,还需保证硬件侧 Trace Hub 控制器(通常位于 SoC 的 Debug 子系统)已被正确初始化和使能,并把对应的 MMIO 基地址填入 PCD/HOB。
在平台中的集成步骤
综合上文,在一个 EDK II 平台中启用 Trace Hub 调试消息的完整步骤如下:
- 声明库依赖:在模块的
.inf中[LibraryClasses]添加TraceHubDebugSysTLib(以及传递依赖的MipiSysTLib),并[Packages]包含MdePkg/MdePkg.dec与MdeModulePkg/MdeModulePkg.dec。若需要 HOB 支持,还需在[Guids]中声明gTraceHubDebugInfoHobGuid(参考 PeiTraceHubDebugSysTLib.inf 的写法)。 - 选择实例:在平台 DSC 的
[LibraryClasses.common.PEIM]、[LibraryClasses.common.DXE_DRIVER]等段中,把TraceHubDebugSysTLib映射到PeiTraceHubDebugSysTLib/DxeSmmTraceHubDebugSysTLib(或纯固定 PCD 场景使用BaseTraceHubDebugSysTLib)。 - 配置三个 PCD:按上文表格在
[PcdsFixedAtBuild]或动态 PCD 段设置PcdEnableTraceHubDebugMsg、PcdTraceHubDebugLevel、PcdTraceHubDebugMmioAddress。 - (可选)发布 HOB:多实例场景下,由早期阶段(SEC/PEI)以
gTraceHubDebugInfoHobGuid为 GUID 构建TRACEHUB_DEBUG_INFO_HOB数据并发布,后续阶段即可自动发现并遍历所有实例;无 HOB 时库会安全回退到 PCD。 - 调用 API:在代码中
#include <Library/TraceHubDebugSysTLib.h>,按需调用TraceHubSysTDebugWrite(调试字符串)、TraceHubSysTWriteCataLog64StatusCode(状态码)或TraceHubSysTWriteCataLog64(带参目录消息)。
通过以上配置,固件即可在 SEC/PEI/DXE/SMM 各阶段把调试消息经 MIPI SYS-T 协议送入 Trace Hub,由调试探针在主机侧还原成可读日志——这也是 Intel 平台固件调试中"无串口"场景下常用的可追踪日志方案。
- 固件
- 操作系统
- 驱动开发
- 嵌入式
【免费下载链接】edk2
EDK II
相关推荐
UEFI固件更新工具:基于EDK II的CapsuleApp开发全指南
UEFI固件更新工具:基于EDK II的CapsuleApp开发全指南 引言:固件更新的痛点与解决方案 你是否曾面临过UEFI固件更新过程中认证失败、依赖冲突或
固件操作系统驱动开发嵌入式V8 Message 测试框架解析:基于预期输出的 JavaScript 错误消息测试指南
V8 Message 测试框架解析:基于预期输出的 JavaScript 错误消息测试指南 导读 本文以 V8 仓库中 test/message/README.
语言运行时编译器JIT编译解释器内存管理UEFI NVMe驱动开发:基于EDK II的PCIe设备驱动实现
UEFI NVMe驱动开发:基于EDK II的PCIe设备驱动实现 引言:NVMe驱动开发的技术挑战与解决方案 你是否在UEFI环境中面临NVMe(Non Vo
固件操作系统驱动开发嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考