PEI阶段的“搬家“——UEFI启动流程中你的代码是怎么从临时内存搬到真内存的

发布时间:2026/7/31 8:31:46

PEI阶段的“搬家“——UEFI启动流程中你的代码是怎么从临时内存搬到真内存的
本文基于EDK2源码MdeModulePkg/Core/Pei逐行拆解不是翻译spec。先说结论UEFI启动流程中PEI阶段的核心矛盾只有一句话早期代码在临时RAM里跑但临时RAM只有几十KB迟早要搬到真正的DRAM里去。这个搬迁过程——从临时内存到永久内存的迁移——是PEI Core最精巧也最容易出bug的地方。❌ 搬错了 → 指针全乱 → 机器直接死✅ 搬对了 → 后续所有模块才能在真正的内存里舒展手脚一、为什么需要临时内存按下电源键之后CPU从SPI Flash里读出第一段代码SEC阶段然后跳进PEI Core。但这时候DRAM还没初始化——内存控制器还没配置DDR还没训练你连一根内存条都不能用。那代码在哪跑CPU内部有一小块SRAM叫Temporary RAM临时RAM。在Intel平台上这通常是CPU Cache-as-RAMCAR机制——把L2/L3 Cache当RAM用。属性数值临时RAM大小一般只有64KB~128KBStack区域给PEI Core和早期PEIM跑代码用Heap区域放HOB列表和早期内存分配SEC把这些信息打包成EFI_SEC_PEI_HAND_OFF结构体交给PEI Coretypedefstruct_EFI_SEC_PEI_HAND_OFF{UINT16 DataSize;// 结构体大小VOID*BootFirmwareVolumeBase;// BFV起始地址SPI Flash映射区UINTN BootFirmwareVolumeSize;// BFV大小VOID*TemporaryRamBase;// 临时RAM起始地址UINTN TemporaryRamSize;// 临时RAM总大小VOID*PeiTemporaryRamBase;// PEI Heap起始地址UINTN PeiTemporaryRamSize;// PEI Heap大小VOID*StackBase;// Stack起始地址UINTN StackSize;// Stack大小}EFI_SEC_PEI_HAND_OFF;类比临时RAM就像酒店临时寄存柜——你刚到酒店行李先塞进寄存柜房间还没准备好。柜子很小64KB但够你先洗个脸换身衣服。二、PEI Core第一次进场——只做最轻的事看PeiMain.c里的PeiCore()函数入口当OldCoreData NULL时第一次进PEI Core代码非常克制if(OldCoreDataNULL){// 第一次进PEI Core临时RAM还没搬家ZeroMem(PrivateData,sizeof(PEI_CORE_INSTANCE));PrivateData.SignaturePEI_CORE_HANDLE_SIGNATURE;CopyMem(PrivateData.ServiceTableShadow,gPs,sizeof(gPs));}它做了什么步骤操作含义①ZeroMem (PrivateData)把PEI Core的私有数据结构清零②CopyMem ServiceTableShadow把PEI Services Table拷贝到临时RAM③建HOB列表InitializeMemoryServices()把HobList指向临时RAM关键代码——HOB账本建在临时RAM上PrivateData.HobList.RawSecCoreData-PeiTemporaryRamBase;PeiCoreBuildHobHandoffInfoTable(BOOT_WITH_FULL_CONFIGURATION,(EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData-PeiTemporaryRamBase,(UINTN)SecCoreData-PeiTemporaryRamSize);HOB的整个账本——记录内存分布、资源分配、固件卷信息——全部写在临时RAM上。然后PEI Core开始dispatch PEIM逐个执行早期模块。这些模块也在临时RAM的Stack上跑HOB也在临时RAM的Heap上增长。⚠️一切都在那64KB的寄存柜里进行。三、谁触发搬家——PeiInstallPeiMemory()某个早期PEIM通常是Memory Init PEIM比如Intel FSP中的MrcInit完成DRAM训练后调用PeiInstallPeiMemory(PeiServices,MemoryBegin,MemoryLength);看MemoryServices.c里这个函数的实现EFI_STATUS EFIAPIPeiInstallPeiMemory(IN CONST EFI_PEI_SERVICES**PeiServices,IN EFI_PHYSICAL_ADDRESS MemoryBegin,IN UINT64 MemoryLength){PrivateDataPEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices);// 只能调用一次调两次直接ASSERTif(PrivateData-PeiMemoryInstalled){ASSERT(FALSE);returnEFI_SUCCESS;}PrivateData-PhysicalMemoryBeginMemoryBegin;PrivateData-PhysicalMemoryLengthMemoryLength;PrivateData-FreePhysicalMemoryTopMemoryBeginMemoryLength;// 关键设这个flag告诉PEI Core该搬家了PrivateData-SwitchStackSignalTRUE;returnEFI_SUCCESS;}这个函数做的事情极其简单——只是记下永久内存的地址和大小然后设一个flag。它不搬任何东西不切换Stack不迁移HOB。类比你告诉前台房间准备好了前台在账本上记下房间号但不会立刻让你冲进去——因为你的行李还在寄存柜里没搬你现在手上还拿着寄存柜的钥匙。为什么不能立刻搬因为调用PeiInstallPeiMemory()的PEIM此刻还在临时RAM的Stack上跑。你不能在自己脚底下拆地板——立刻搬迁Stack当前函数的返回地址、局部变量全部失效直接crash。四、搬家的时机——Dispatcher回来之后PEI Dispatcher在每次dispatch完一个PEIM之后会检查SwitchStackSignal。如果flag被设了调用PeiCheckAndSwitchStack()——这才是真正搬家的地方。8个步骤按顺序执行Step 1 · 在永久内存里预留新StackNewStackSizeRShiftU64(Private-PhysicalMemoryLength,1);NewStackSizeALIGN_VALUE(NewStackSize,EFI_PAGE_SIZE);NewStackSizeMIN(PcdGet32(PcdPeiCoreMaxPeiStackSize),NewStackSize);新Stack大小 内存总大小的一半但不超过PcdPeiCoreMaxPeiStackSize限制从永久内存底部开始分配。Step 2 · 计算偏移量TopOfOldStack(UINTN)SecCoreData-StackBaseSecCoreData-StackSize;TopOfNewStackPrivate-PhysicalMemoryBeginNewStackSize;if(TopOfNewStackTopOfOldStack){StackOffsetPositiveTRUE;StackOffset(UINTN)(TopOfNewStack-TopOfOldStack);}else{StackOffsetPositiveFALSE;StackOffset(UINTN)(TopOfOldStack-TopOfNewStack);}新旧Stack顶的偏移量。偏移方向正/负很重要——临时RAM和永久RAM的地址谁高谁低取决于平台实现。Step 3 · Heap搬迁HeapTemporaryRamSize(UINTN)(Private-HobList.HandoffInformationTable-EfiFreeMemoryBottom-Private-HobList.HandoffInformationTable-EfiMemoryBottom);CopyMem((UINT8*)(UINTN)BaseOfNewHeap,PeiTemporaryRamBase,HeapTemporaryRamSize);直接把整个临时RAM的Heap内容包括HOB列表拷贝到永久内存。一个CopyMem把寄存柜里的账本和行李搬到新房间。Step 4 · Stack搬迁CopyMem((UINT8*)(UINTN)(TopOfNewStack-TemporaryStackSize),TemporaryStackBase,TemporaryStackSize);把旧Stack上的内容完整拷贝到新Stack。这包括了当前PEI Core函数的返回地址、局部变量、函数参数——全部。Step 5 · 迁移已分配的Memory PagesMigrateMemoryPages(Private,FALSE);如果早期PEIM在临时RAM阶段已通过AllocatePages分过内存页这些页也要搬Private-MemoryPages.Size(UINTN)(Private-HobList.HandoffInformationTable-EfiMemoryTop-Private-HobList.HandoffInformationTable-EfiFreeMemoryTop);NewMemPagesBasePrivate-FreePhysicalMemoryTop-Private-MemoryPages.Size;NewMemPagesBase~(UINT64)EFI_PAGE_MASK;CopyMem((VOID*)(UINTN)NewMemPagesBase,(VOID*)(UINTN)Private-MemoryPages.Base,Private-MemoryPages.Size);Step 6 · 修正所有指针——这是最危险的一步搬迁之后所有指向临时RAM的指针都失效了。PEI Core必须逐一修正修正HOB列表指针if(OldCoreData-HeapOffsetPositive){OldCoreData-HobList.RawOldCoreData-HeapOffset;}else{OldCoreData-HobList.Raw-OldCoreData-HeapOffset;}修正PPI数据库指针OldCoreData-PpiData.PpiList.PpiPtrs(PEI_PPI_LIST_POINTERS*)((UINT8*)OldCoreData-PpiData.PpiList.PpiPtrsHeapOffset);修正FV Handle指针、PeimState数组、FileHandles数组……一行一行修每个都不能漏。修正Memory Allocation HOB里的地址if((MemAllocHob-MemoryBaseAddressOldMemPagesBase)(MemAllocHob-MemoryBaseAddress(OldMemPagesBaseOldMemPagesSize))){if(PrivateData-MemoryPages.OffsetPositive){MemAllocHob-MemoryBaseAddressPrivateData-MemoryPages.Offset;}else{MemAllocHob-MemoryBaseAddress-PrivateData-MemoryPages.Offset;}}类比搬家之后纸笔记的所有东西在第3号寄存柜都得改成东西在301房第2个柜子。漏改一条你就找不到那件东西了。在固件里漏改一个指针机器就死了。Step 7 · Shadow PeiCore到永久内存OldCoreData-ShadowedPeiCoreShadowPeiCore(OldCoreData);把PEI Core自身从Flash拷到永久内存执行——XIP变成内存执行速度大幅提升。Step 8 · 切换Stack重入PeiCoreOldCoreData-ShadowedPeiCore(SecCoreData,PpiList,OldCoreData);// Should never reach here.ASSERT(FALSE);旧Stack上的PeiCore函数到此为止不再返回。新的PeiCore在永久内存的新Stack上重新开始执行。五、第二次进场——Permanent Memory上的新生活第二次进PeiCore()OldCoreData ! NULL且ShadowedPeiCore已经有值。走另一个分支CopyMem(NewSecCoreData,SecCoreDataPtr,sizeof(NewSecCoreData));CopyMem(PrivateData,OldCoreData,sizeof(PrivateData));然后安装最重要的PPI// 安装Memory Discovered PPI——告诉所有人真正的内存来了StatusPeiServicesInstallPpi(mMemoryDiscoveredPpi);ProcessDispatchNotifyList(PrivateData);gEfiPeiMemoryDiscoveredPpiGuid是PEI阶段最重要的PPI之一。所有注册了Notify的PEIM会被唤醒——比如需要大块内存的模块现在终于可以干活了。然后继续PeiDispatcherdispatch剩余的PEIM。这次它们在真正的DRAM上跑有充足的Stack和Heap不再受64KB限制。最终PEI Core找到gEfiDxeIplPpiGuid把HOB列表交给DXE IPLPEI阶段结束。六、实战踩坑点坑1临时RAM溢出临时RAM只有64KB左右。如果早期PEIM分配太多HOB或PoolPeiCreateHob会返回EFI_OUT_OF_RESOURCESFreeMemoryHandOffHob-EfiFreeMemoryTop-HandOffHob-EfiFreeMemoryBottom;if(FreeMemoryLength){DEBUG((DEBUG_ERROR,PeiCreateHob fail: Length - 0x%08x\n,(UINTN)Length));returnEFI_OUT_OF_RESOURCES;}经验临时RAM阶段的代码要极致精简。PeiAllocatePool有硬限制——最大不能超过0xFFF8 - sizeof(EFI_HOB_MEMORY_POOL)大约64KB不到。任何大数组、大数据结构都不要在这里分配。坑2Stack偏移方向搞错HeapOffsetPositive和StackOffsetPositive决定指针修正的方向。不同平台上临时RAM地址可能高于也可能低于永久RAM地址。如果平台代码把这两个值搞反了 → 所有指针修正都是反的 → 机器直接死 → 死得很深 → JTAG调试器都不一定能抓到。坑3PeiInstallPeiMemory只能调一次if(PrivateData-PeiMemoryInstalled){DEBUG((DEBUG_ERROR,ERROR: PeiInstallPeiMemory is called more than once!\n));ASSERT(FALSE);returnEFI_SUCCESS;}Debug版直接断死Release版忽略。如果有两个PEIM都试图注册永久内存——要么是平台配置错了要么是FSP和自定义Memory Init PEIM冲突了。坑4TemporaryRamSupportPPI vs 直接CopyMem搬迁Stack有两种路径条件搬迁方式注意事项平台提供gEfiTemporaryRamSupportPpiGuid调用TemporaryRamMigration()Intel平台一般提供因为CAR需要特殊Cache刷新平台不提供该PPIPEI Core自己CopyMem搬⚠️ 必须确保Cache一致性CAR模式下非常危险七、从源码学什么这段搬迁代码的价值不只是知道怎么搬。它展示了一个固件设计原则在资源受限的早期阶段所有操作都要可逆、可迁移。HOB列表就是一个可搬迁的账本——它不直接引用临时RAM的绝对地址而是通过偏移量修正来实现搬迁。PEI Core的私有数据结构也设计成了可以被整体拷贝和偏移修正的形态。这个原则在BIOS开发的很多地方都有体现场景类似机制PCI资源分配先临时分配再根据冲突调整ACPI表构建在临时缓冲区建好再拷到最终位置SMM通信缓冲区先在SMRAM外构建再迁入理解了PEI的搬迁机制后面遇到类似设计就能一眼看出本质。源码路径索引文件内容MdeModulePkg/Core/Pei/PeiMain/PeiMain.cPeiCore主入口搬迁总控MdeModulePkg/Core/Pei/Memory/MemoryServices.cInstallPeiMemory、AllocatePages、内存迁移MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.cDispatcher和Stack切换逻辑MdeModulePkg/Core/Pei/Hob/Hob.cHOB操作创建、安装SEC HOBMdeModulePkg/Core/Pei/PeiMain.hPEI_CORE_INSTANCE结构体定义MdePkg/Include/Pi/PiPeiCis.hEFI_SEC_PEI_HAND_OFF定义

相关新闻

2:大模型深度对比 | 五大场景实测

2:大模型深度对比 | 五大场景实测

2026/7/31 8:21:45

2026年7月,榜单数字早已不再等于生产选择——真正决定胜负的,是在真实任务中的单任务成本与工作流适配度。 引言:当“跑分”不再等于“好用” 上一篇文章,我们梳理了2026年大模型的全景格局。但站在选型决策前,还有一…

空调集群等效储能建模与微电网经济调度MATLAB实现

空调集群等效储能建模与微电网经济调度MATLAB实现

2026/7/31 8:21:45

1. 项目背景与核心价值空调集群作为建筑能耗的主要组成部分,在微电网系统中具有显著的负荷调节潜力。传统调度方法往往将空调视为刚性负荷,忽略了其热储能特性。这项研究创新性地提出等效储能聚合模型,将分散的空调设备虚拟为集中式储能单元&…

NUMA-04 显存迁回内存:AMD/Intel 的 SVM 与Eviction的实现是否考虑了NUMA

NUMA-04 显存迁回内存:AMD/Intel 的 SVM 与Eviction的实现是否考虑了NUMA

2026/7/31 8:21:45

前三篇的迁移都在“普通内存 ↔ 普通内存”。但 GPU 显存 CPU 根本访问不到,它是怎么被纳入进程地址空间、又怎么在缺页时自动迁回内存,以及回迁时怎么选择numa node。这将是本文的主题。 0. 本章要回答的问题 GPU 显存这种 CPU 不能直接读的内存&#…

C++内存管理进阶:从原理到实战,掌握智能指针与性能优化

C++内存管理进阶:从原理到实战,掌握智能指针与性能优化

2026/7/31 9:32:09

1. 项目概述:从“能用”到“精通”的必经之路如果你已经写过一些C程序,用过new和delete,也大概知道指针是什么,那么恭喜你,你已经跨过了C编程的第一道门槛。但接下来,你可能会遇到一些更“诡异”的问题&…

从GPT-2到Qwen2:预训练目标函数演进史,及微调阶段必须重写的3个Loss层(附梯度流可视化对比图)

从GPT-2到Qwen2:预训练目标函数演进史,及微调阶段必须重写的3个Loss层(附梯度流可视化对比图)

2026/7/31 9:32:09

更多请点击: https://codechina.net 第一章:从GPT-2到Qwen2:预训练目标函数演进史,及微调阶段必须重写的3个Loss层(附梯度流可视化对比图) 预训练目标函数的演进并非线性叠加,而是由建模假设、…

3分钟掌握视频转PPT神器:一键提取视频中的幻灯片内容

3分钟掌握视频转PPT神器:一键提取视频中的幻灯片内容

2026/7/31 9:32:09

3分钟掌握视频转PPT神器:一键提取视频中的幻灯片内容 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 你是否曾经为从教学视频、会议录像中手动截取PPT而烦恼?…

AI写测试=替代工程师?资深QA总监的12项不可替代能力清单(2024最新认证标准)

AI写测试=替代工程师?资深QA总监的12项不可替代能力清单(2024最新认证标准)

2026/7/31 9:32:09

更多请点击: https://codechina.net 第一章:AI写测试替代工程师?资深QA总监的12项不可替代能力清单(2024最新认证标准) 当AI生成测试用例的准确率突破92%(据IEEE 2024 QA Survey),真…

网络掩码实战指南:从IP规划到ACL配置的深度解析

网络掩码实战指南:从IP规划到ACL配置的深度解析

2026/7/31 9:32:09

1. 从“16位的掩码”说起:网络工程师的日常与基本功 看到“16位的掩码”这个标题,很多刚入行的网络工程师或者正在备考认证的朋友可能会心一笑,或者眉头一皱。这看起来是一个再基础不过的概念&a…

突发,TRD陷入论文工厂事件!

突发,TRD陷入论文工厂事件!

2026/7/31 9:22:01

近日,有网友发现,一篇2024年发表于《Transportation Research Part D: Transport and Environment》的文章,其图片、表格和公式与2022年《Atmosphere》上的一篇论文高度相似。(左:TRD涉事论文 右:Atmosp…

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

[具身智能-649]:个人电脑搭建 RTSP 服务完整方案(Windows / Ubuntu 双平台,适配 RDK X5 rtsp2display 调试)

2026/7/30 9:53:22

目标:电脑作为RTSP 服务端,循环推送 H264/H265 视频流; RDK X5 通过 rtsp2display 拉流预览,完全不需要在开发板编译 live555。 提供两套成熟方案: ✅ 方案 A:FFmpeg(最简单,优先推…

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

2026/7/30 1:17:46

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

PDF拆分压完图糊了?2026国内免费实测,档案员都在用的组合方案

2026/7/30 2:52:37

说实话,提到PDF拆分再压缩,我真是被折腾得够呛。 上个月公司年度合同归档,一份300多页的PDF总合同,需要按年份拆分成三个独立文件,再分别压缩到10MB以内方便邮件发送各部门确认。我心想这还不简单?先找个海…

2026优质EMBA择校榜单:校友圈质量高的EMBA适配民企创始人

2026优质EMBA择校榜单:校友圈质量高的EMBA适配民企创始人

2026/7/31 0:01:23

【客观独立测评】深耕商科教育测评多年,聚焦民企创始人、科创企业实控人择校痛点,避开镀金空壳、课程脱节、圈层杂乱的踩坑问题,结合真实办学数据与学员口碑,整理出适配实业高管的高性价比EMBA榜单,理性分析各项目适配…

绝区零一条龙:5分钟快速上手的终极自动化助手

绝区零一条龙:5分钟快速上手的终极自动化助手

2026/7/31 0:01:23

绝区零一条龙:5分钟快速上手的终极自动化助手 【免费下载链接】ZenlessZoneZero-OneDragon 绝区零 一条龙 | 全自动 | 自动闪避 | 自动每日 | 自动空洞 | 支持手柄 项目地址: https://gitcode.com/gh_mirrors/ze/ZenlessZoneZero-OneDragon 绝区零一条龙是一…

2026民企老板EMBA择校榜单:人脉圈广的EMBA高性价比测评

2026民企老板EMBA择校榜单:人脉圈广的EMBA高性价比测评

2026/7/31 0:01:23

【客观中立测评声明】本文基于学费成本、课程落地、圈层纯度、长期赋能四大维度实测打分,无商业洗脑吹捧,仅为民企创始人、科创高管提供真实择校参考,规避镀金踩坑陷阱。不少民营企业家读EMBA容易踩两大坑:盲目追名校排名&#xf…