news 2026/10/24 1:23:42

手写UEFI引导程序:从EDK2环境搭建到U盘启动盘实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手写UEFI引导程序:从EDK2环境搭建到U盘启动盘实战

简介:这是一份《一个UEFI引导程序的实现》PDF电子书,作者田宇以迭代式实例讲解了如何从零构建UEFI引导程序,适合操作系统理论初学者、软件工程师及业余爱好者。书中先对比UEFI与BIOS的结构组成和启动流程,说明UEFI取代BIOS的原因;再基于TianoCore EDK2搭建开发环境,讲解GPT磁盘布局、ESP文件系统、UEFI镜像与系统表、调用约定和协议;最后逐步实现引导程序,涵盖图形显示模式配置、物理内存获取、存储介质文件读取、64位处理器平台及系统内核引导启动,并融入Linux内核精髓。资源为1个PDF文件,压缩包2.36MB,内容章节完整、目录清晰,便于对照源码与运行示例研习。已有2379人学习下载,适合想深入理解UEFI引导流程并动手实践操作系统的读者。

1. UEFI引导程序:为什么值得亲手写一遍

现代计算机的引导过程早已不是BIOS时代的“读MBR、跳实模式”那么简单。只要你打算做一个自己的操作系统、想搞懂Linux内核是怎么被加载的,或者被2TB磁盘容量限制、16位实模式这些BIOS遗留问题折磨过,就绕不开UEFI引导程序。这本书从TianoCore EDK2环境搭建讲起,手把手带你把一个可运行的UEFI引导程序写出来,再把它放到U盘上真正启动。适合正在学习操作系统原理、准备阅读Linux内核源码,或者想给现有系统增加UEFI引导支持的开发者。

2. 搭建TianoCore EDK2开发环境:先把编译器链条理顺

2.1 环境选型与依赖包安装

本书使用的开发环境是CentOS7 + TianoCore EDK2的UDK2018分支。EDK2是Intel开源的UEFI开发环境,它自带一套独立的编译系统,支持GCC、MinGW、MSVC等工具链。之所以选CentOS7而不是更新的发行版,一方面是因为UDK2018分支发布时CentOS7还是主流服务器系统,GCC 4.8的工具链版本和EDK2的兼容性经过验证;另一方面,EDK2编译时对工具链版本有隐式依赖,新版本GCC编译出的固件有时反而会在运行时出奇怪问题,这点后面避坑章节细说。

先执行依赖包安装:

yum install build-essential git uuid-dev iasl nasm libuuid-devel

这里有个需要注意的问题:build-essential和uuid-dev是Debian系发行版的包名,在CentOS7的yum源里并不存在这个叫法。我一般会按CentOS的包名习惯拆开安装:

yum install -y make gcc gcc-c++ git iasl nasm libuuid-devel

参数说明:

  • make、gcc、gcc-c++:编译BaseTools和EDK2模块组必需的基础编译链
  • iasl:Intel ACPI编译器,编译ACPI相关的表和DSDT时要用
  • nasm:汇编器,UEFI固件里少量汇编代码需要它完成编译
  • libuuid-devel:提供UUID相关头文件和库,GPT分区操作和UEFI变量处理会用到

装完后用gcc --version确认一下版本,只要不报告找不到命令就算通过。EDK2对GCC版本的要求是能识别GCC48这个工具链标签即可,新版本GCC也能用,但需要在target.txt里换对应的TOOL_CHAIN_TAG,新手不建议一上来就换。

如果是在纯命令行的CentOS7上操作,记得先把网络配好。yum安装时卡住最常见的就是源不可达,国内网络环境下我一般会先替换成可用的yum镜像源再执行安装,这一步不做的话,后面git clone和yum install都可能在半路超时,浪费时间又打击信心。

2.2 克隆EDK2源码并切换UDK2018分支

依赖装好之后,从EDK2的git仓库拉取源码:

git clone https://github.com/tianocore/edk2.git cd edk2/ git checkout UDK2018

说明:clone下来默认是在master分支,master的代码变化快,和这本书配套的是UDK2018分支,所以clone完成后立即切换分支。这里建议用git checkout而不是git branch加参数,切换完用git branch确认当前位于UDK2018。

这里有个细节:后续编译OVMF或ShellPkg之前,都需要在当前仓库目录下执行git submodule update --init --recursive。EDK2的部分模块依赖第三方子模块(比如openssl、FatPkg等),不先拉取子模块,build阶段会直接报缺少头文件或目录不存在,而且报错信息和具体原因往往对不上,非常容易让人觉得是自己配置错了。

2.3 编译BaseTools并初始化编译环境

EDK2自带的编译工具链需要先编译一遍,后续build命令才能正常工作:

make -C BaseTools/

说明:BaseTools目录里存放的是EDK2的固件编译工具,包括GenFw(镜像转换工具)、GenFv(固件卷生成工具)、EfiRom等。make -C BaseTools/会编译出这些工具的本地可执行文件。编译时间取决于机器性能,通常几分钟到十几分钟。

BaseTools编译完成后,初始化EDK2的编译环境:

BaseTools/BuildEnv . ./edksetup.sh

这两条命令的作用是设置EDK2的环境变量和路径。注意中间的BaseTools/BuildEnv和edksetup.sh是两个可执行脚本,前者设置工具链路径,后者加载EDK2的编译环境变量。我习惯执行完建议用echo $EDK_TOOLS_PATH确认路径已正确设置,如果输出为空,说明脚本没有正常执行,往往是当前目录不对——必须在edk2源码根目录下执行。

如果你之前装过其他版本的EDK2,Conf目录下会残留旧的环境配置文件。保险的做法是删除Conf目录里除了target.txt之外的历史配置,或者直接执行make clean清掉BaseTools的旧编译产物再重新编译。旧产物版本不一致会引起各种莫名其妙的链接错误,这类问题排查起来最费时间,不如一开始就清干净。

提示:执行edksetup.sh之前,务必确认当前shell在edk2源码根目录。脚本内部会相对路径定位Conf目录,目录不对时环境变量设了个寂寞,build命令会直接报找不到平台配置。

2.4 target.txt三个关键配置项

EDK2的模块组编译配置集中在Conf/target.txt文件里,这个文件是build命令的输入配置文件。这本书的目标是编译64位OVMF固件和Shell应用,对应的最小配置是:

ACTIVE_PLATFORM = OvmfPkg/OvmfPkgX64.dsc TOOL_CHAIN_TAG = GCC48 TARGET_ARCH = X64

参数说明:

  • ACTIVE_PLATFORM:指定要编译的平台模块组,OvmfPkgX64.dsc是OVMF(开放虚拟机固件)在X64架构下的平台描述文件
  • TOOL_CHAIN_TAG:告诉build命令用哪套工具链,GCC48对应CentOS7默认自带的GCC 4.8
  • TARGET_ARCH:目标处理器架构,这里X64就是64位模式

这三个变量是联动的:TARGET_ARCH决定了最终固件运行在什么模式,TOOL_CHAIN_TAG必须和系统里实际安装的GCC版本对应。如果系统装的是GCC 8或更高版本,可以试试改成GCC5/GCC7这类更新的工具链标签,但可能需要在tools_def.txt里确认对应配置存在,新手建议保持GCC48不动。

配置好后执行build,如果没有报错,会在Build/OvmfX64/DEBUG_GCC48/FV目录下生成OVMF.fd固件文件。到这里,EDK2的编译链就完全跑通了,下一步就是编译真正的UEFI应用程序。

3. 编译UEFI Shell并制作U盘启动盘:做出第一个能跑的UEFI程序

3.1 配置ShellPkg模块组

UEFI Shell既是本书实验的验证工具,也是后续排查引导问题的基础环境。EDK2里已经集成了ShellPkg模块组,只需要把target.txt里的ACTIVE_PLATFORM换成ShellPkg/ShellPkg.dsc,其他两个变量保持不变:

ACTIVE_PLATFORM = ShellPkg/ShellPkg.dsc TOOL_CHAIN_TAG = GCC48 TARGET_ARCH = X64

改完配置后执行:

git submodule update --init --recursive build

说明:build命令会读取Conf/target.txt,按照ACTIVE_PLATFORM指定的模块组描述文件去编译。第一次编译ShellPkg会同时把MdePkg、MdeModulePkg等基础包编一遍,所以输出信息会很长,看到网络、文件系统、键盘鼠标等驱动模块一个个被编译属于正常现象。

UEFI Shell默认会加载FAT文件系统驱动和PCI设备驱动,所以编译时这些模块都会被一并编进Shell.efi里,这也解释了为什么一个Shell应用编译产物有几百KB甚至更大。你不需要额外配置任何东西就能在Shell里访问FAT分区,这是后面验证环节能跑通的前提。

3.2 编译产物路径与文件识别

编译完成后,Shell应用位于以下路径:

Build/Shell/DEBUG_GCC48/X64/Shell.efi

补充说明:Build目录下按模块组名、编译类型、工具链标签、架构分层的目录结构是EDK2的统一产物布局。DEBUG_GCC48表示这是调试版本、GCC48工具链编译、X64架构。Shell.efi是PE/COFF格式的UEFI可执行文件,它的头部格式和Windows下的PE文件同源,UEFI固件通过文件系统协议读取它并加载执行。

此时可以顺手验证一下文件格式:

file Build/Shell/DEBUG_GCC48/X64/Shell.efi

正常情况下输出会显示PE32+ executable (EFI application) x86-64,确认无误后这个文件就是我们要放到U盘上的核心内容。如果你在Build目录里看到多个Shell.efi,优先取DEBUG_GCC48路径下的那个,RELEASE版本是Release编译模式的产物,会在后续生成,两者都能用,但DEBUG版本的调试符号和日志信息更全,学习阶段建议用DEBUG版本。

3.3 用DiskGenius转换U盘为GPT布局并创建ESP分区

UEFI固件要求可引导块设备必须包含ESP系统分区。普通U盘出厂默认是MBR分区表,Windows下用DiskGenius把分区表类型转换为GUID格式,具体操作是:清空U盘扇区数据,右键磁盘→转换分区表类型为GUID格式,软件会弹出确认对话框提醒原分区将失效,确认后磁盘变成GPT布局。

接下来点击新建分区,在弹出的对话框里勾选“建立ESP分区”,分配20MB空间,勾选“对齐到此扇区数的整数倍”,按4096扇区(2097152字节)对齐。ESP分区的作用是存放UEFI引导程序,分区格式会被格式化为FAT16/FAT32。再创建一个10MB的FAT32分区,GPT磁盘布局下只有主分区类型,不存在扩展分区和逻辑分区的概念,所以可见分区比MBR时代更干净。

这里有两个点值得展开。第一,ESP分区的大小20MB在当前场景够用,因为只是放一个Shell.efi和后续的引导程序,但如果你打算在ESP里同时放多个操作系统的引导加载器,建议留到100MB以上;第二,4096扇区对齐是现代SSD和U盘的通用对齐方案,对齐后访问性能更好,在虚拟机环境里影响不明显,但换到物理机上差距就出来了。

还有一点需要留意:DiskGenius创建ESP分区后,U盘里会出现两个分区,但Windows资源管理器里能看到的只有FAT32分区,ESP分区完全不可见。这会让很多人误以为ESP分区没创建成功,其实只要用Linux挂载确认一下就能验证。

3.4 挂载U盘拷贝引导文件

Windows系统出于保护机制限制了对ESP分区的访问,资源管理器里看不到它。解决方法是把U盘插到CentOS7机器上,Linux内核原生支持GPT分区表,用root权限可以直接挂载。

先查看U盘设备节点:

[root@promote edk2]# fdisk -l /dev/sdb Disk /dev/sdb: 33 MB, 33554432 bytes, 65536 sectors Disk label type: dos Device Boot Start End Blocks Id System /dev/sdb1 1 4294967295 2147483647+ ee GPT

看起来只显示了一个/dev/sdb1,而且分区类型是GPT伪分区,这不是我们创建的ESP分区。原因是fdisk这个工具对GPT分区表的兼容性不好,它把protective MBR里的记录当成一个分区列出来了。用ls命令能看到真实情况:

[root@promote edk2]# ls /dev/sdb* /dev/sdb /dev/sdb1 /dev/sdb2

其中/dev/sdb1是ESP分区,/dev/sdb2是FAT32分区。确认节点后再执行拷贝:

mount /dev/sdb1 /mnt/ mkdir -p /mnt/EFI/BOOT cp /root/Desktop/edk2/Build/Shell/DEBUG_GCC48/X64/Shell.efi /mnt/EFI/BOOT/BOOTx64.EFI sync umount /mnt/

这几条命令的逻辑是先挂载ESP分区到/mnt,创建EFI/BOOT目录——这是UEFI规范约定的默认引导路径,然后把Shell.efi复制过去并改名为BOOTx64.EFI。UEFI固件在找不到其他引导项时,会按照\EFI\BOOT\BOOTx64.EFI这个默认路径去尝试加载64位应用程序,所以改名这一步不能省略。sync强制刷盘,确保数据落盘后再umount,避免拔掉U盘后文件丢失。

整个拷贝操作里最容易出错的是目标路径。很多初学者把Shell.efi直接拷贝到ESP分区根目录改名BOOTx64.EFI,但UEFI引导管理器默认不会去根目录找引导文件,它只会按\EFI\BOOT\BOOTx64.EFI这个固定路径查找。目录结构少一层,引导就失败,而且失败提示往往是很笼统的“找不到可引导设备”,查起来全靠经验。

注意:ESP分区的挂载操作需要root权限,普通用户执行mount会报Operation not permitted。另外,U盘的文件系统如果之前被Windows格式化过,建议在DiskGenius里重新分区而不是只转换分区表,清空残留分区记录能省去后续很多兼容性麻烦。

4. 配置UEFI虚拟机环境:让固件从U盘引导

4.1 创建64位虚拟机

考虑到大部分读者手头没有支持UEFI引导的裸机,或者不想为了一个引导程序反复重启物理机,这本书的实践环境选择在VMware虚拟机里完成。创建虚拟机时需要选择64位操作系统环境,这是因为UEFI引导程序最终运行在64位保护模式下,32位环境无法复现书中的X64架构实验结果。

虚拟机磁盘镜像可以选择现有Linux/Windows的安装镜像做基础,也可以直接创建一个空虚拟机。我一般建议创建一个空虚拟机,后续只用U盘做引导介质,避免硬盘上的既有引导器干扰UEFI固件的启动顺序。内存建议分配到2GB以上,UEFI固件在DXE阶段会加载大量驱动,内存太小会出现固件卡死的现象。

虚拟机创建过程中,选择客户机操作系统版本时尽量选带“64-bit”字样的项。某些版本的VMware如果一开始创建了32位虚拟机,后面再改成64位会比较麻烦,需要重建虚拟机或修改虚拟机配置文件里的guestOS参数,别给自己找麻烦,一开始就选对。系统安装步骤可以直接跳过,因为实验不需要在虚拟机上装系统,U盘本身就是引导介质。

4.2 修改固件类型为UEFI

VMware虚拟机默认使用传统BIOS作为引导固件,这和我们的目标不符,需要手动修改。进入虚拟机设置→选项→高级→固件类型,将固件类型改为UEFI,点击确定保存。

这一步是整个实验的关键转折点:只有固件类型是UEFI,虚拟机才会按照UEFI规范去扫描ESP分区、加载BOOTx64.EFI,而不是去读取传统MBR引导扇区。如果保持BIOS固件不变,前面花大力气做的GPT分区U盘插进去根本不会被识别,现象就是开机黑屏或直接进入无引导设备提示,让人误以为U盘制作失败。

为什么UEFI固件能找到U盘上的Shell?这与UEFI的设计思路有关。UEFI固件自带引导管理器(Boot Manager),它在启动时会扫描每个块设备上的ESP分区,查找\EFI\BOOT\BOOTx64.EFI文件。找到后,通过FAT文件系统驱动把文件读入内存,按照PE/COFF镜像格式解析并执行。整个流程不再依赖引导扇区代码,不再需要实模式下的中断调用,而是完全以文件为单位进行操作,这正是UEFI比BIOS灵活的原因。这也是为什么我们在拷贝文件时必须严格放置在EFI/BOOT目录下并命名为BOOTx64.EFI——引导管理器查的就是这个路径,路径不对,一切白费。

修改固件类型后,建议顺手检查一下虚拟机的引导顺序,确保UEFI固件会把USB设备放在引导列表的前面。VMware的固件配置里可以通过上下键调整引导顺序,U盘排第一、硬盘往后放,这样插着U盘就能优先从U盘引导。

4.3 添加USB控制器

如果虚拟机创建时没有配置USB控制器,进入虚拟机→硬件界面,点击“添加硬件设备”向导,在设备类型里选择USB控制器,按向导提示完成添加。添加完成后,在硬件列表里可以看到新出现的USB控制器设备,对它设置USB兼容性版本和连接状态。

这里有一个容易被忽略的细节:U盘要在虚拟机启动之前连接到USB控制器上。VMware的USB设备连接不是在虚拟机设置里勾选,而是在虚拟机窗口底部的设备图标菜单里选择“连接”,或者在虚拟机设置里配置启动时连接。我一般先把U盘插到物理机USB口,在虚拟机开机前通过设备菜单把U盘分配给虚拟机,再启动虚拟机,这样UEFI固件在枚举USB总线时就能发现U盘,引导自然成功。

如果启动后才把U盘接入虚拟机,UEFI固件的引导设备选择阶段可能已经结束,即使后续能在Shell里看到U盘设备,也无法把它作为启动介质,需要重启虚拟机才能正常引导。这个细节在物理机上同样适用:开机后再插U盘,按F12进启动菜单也常常看不到U盘选项,因为固件在POST阶段就已经完成USB设备枚举了。

4.4 卸下网络适配器

UEFI固件在BDS阶段会主动探测网络适配器,尝试从PXE网络引导服务器获取启动映像。在无DHCP和TFTP服务的实验环境里,这个过程会一直等到网络超时,导致整个引导过程慢得让人以为机器死机了。

解决办法是在虚拟机硬件配置里把网络适配器卸下或设为不连接。操作路径是虚拟机设置→硬件→网络适配器→取消“启动时连接”的勾选,或者直接删除该设备。卸掉网络适配器之后,UEFI固件会快速跳过网络引导检测,几秒钟内就能进入Shell或引导失败提示,实验节奏顺畅很多。

这个网络引导等待的问题不仅发生在VMware里,物理机裸机装UEFI时同样会遇到。很多品牌的台式机默认开启PXE引导,插着网线开机就会卡在“Start PXE over IPv4”的界面,解决思路是一样的——要么在固件设置里禁用网络引导,要么拔掉网线。把虚拟机当成实验平台的好处就在这里,硬件配置可以随意调整,不用在BIOS设置里翻来找去。

5. 避坑与排查:这些坑我都踩过

EDK2这套环境说难不难,但每一步都有对应的“标准答案”。如果只是照着命令敲出现报错就懵了,很容易卡在一两个细节上怀疑人生。下面这几条是我在复现这本书实验过程中真实踩过的坑,每条都按现象→原因→解决写清楚,你在搭建环境时遇见了,直接对照处理即可。

5.1 现象:yum install build-essential报No package

原因:build-essential是Debian/Ubuntu系统的包组名称,CentOS7的yum源里根本没有这个包名,直接照抄会装不上。

解决:改为按CentOS7的包名安装,实际需要的是make、gcc、gcc-c++、iasl、nasm、libuuid-devel。如果是在全新最小化安装的CentOS7上操作,还要额外确保git已经装上。装完之后用rpm -q make gcc确认关键包存在。

还有一个小坑:CentOS7最小化安装时,默认的yum源可能不全,尤其是extras和epel源未启用的情况下,nasm和iasl可能装不上。遇到No package nasm available就先检查yum源配置,启用epel源后再试。我一般会在安装完系统后第一时间执行yum install epel-release,把扩展源加上,避免后续装包时缺这少那。

5.2 现象:编译ShellPkg时openssl头文件缺失

原因:EDK2的部分模块依赖git子模块,比如加密相关的openssl、FAT文件系统驱动可能依赖FatPkg子模块。clone主仓库时子模块默认不会拉下来,不执行git submodule update --init --recursive直接build,编译到依赖模块就报错。这类报错信息往往指向另一个模块,看起来像玄学,其实是子模块缺失导致的链式编译失败。

解决:在edk2源码根目录执行git submodule update --init --recursive,等子模块全部下载完再重新build。网络环境差时这一步可能很慢,中间断了就重新执行一遍,git会断点续传。

还有一类编译问题值得单独说。如果你之前编译过master分支的EDK2,再切回UDK2018分支时,Conf目录里会保留旧的target.txt和tools_def.txt,这些旧配置可能引用了master分支才存在的模块路径,导致build阶段报“文件不存在”或“平台描述文件缺失”。我一般会执行make -C BaseTools clean清理旧编译产物,必要时删掉Conf目录重新执行edksetup.sh生成默认配置,再手动改target.txt。这个习惯帮我避开了很多莫名其妙的编译问题。

5.3 现象:fdisk -l只显示一个GPT伪分区

原因:fdisk工具对GPT分区表的兼容性不好,它读取的是protective MBR里的分区记录,所以把整个GPT磁盘当成一个类型为ee(GPT)的分区显示出来,并不是真的有只有一个分区。

解决:用ls /dev/sdb*或parted /dev/sdb print查看真实分区布局。ls能看到/dev/sdb1(ESP分区)和/dev/sdb2(FAT32分区)两个设备节点,说明GPT分区创建成功,放心继续挂载操作。不要因为fdisk的输出和预期不符就反复重新分区,那是白费功夫。

5.4 现象:Windows资源管理器里看不到ESP分区

原因:Windows系统对GPT磁盘的ESP分区默认不分配盘符,也不允许通过资源管理器访问,这是系统的保护机制,不是分区没创建成功。

解决:不需要在Windows下访问ESP分区。把U盘插到CentOS7或其他Linux系统上,用mount /dev/sdb1 /mnt挂载后操作即可。如果手头只有Windows,也可以用DiskGenius的浏览文件功能向ESP分区拷贝文件,但那样不如Linux下方便,我一般都是在Linux虚拟机里做这一步。

类似的坑在制作Linux启动U盘时也会遇到。很多人U盘插上去发现引导不了,第一反应是U盘没做对,实际上往往是固件引导模式不对——传统BIOS模式的机器要写MBR引导,UEFI模式的机器要写GPT+ESP分区,两者不能混用。本书里的实验全程走UEFI路径,所以U盘的分区表必须转为GPT,这也是前面特意用DiskGenius转换分区表类型的原因。

5.5 现象:虚拟机UEFI引导卡在PXE网络启动

原因:VMware默认固件是BIOS,没改成UEFI时GPT磁盘无法引导;改成UEFI后如果网络适配器还连着,固件会尝试PXE网络引导,等待DHCP超时,看起来像死机。

解决:第一件事去虚拟机设置确认固件类型已经是UEFI;第二件事把网络适配器卸下或取消“启动时连接”。还有第三件事,U盘要提前连接到虚拟机的USB控制器上再开机,启动后再插U盘可能错过引导设备枚举阶段。这三件事按顺序检查一遍,绝大多数引导失败问题都能解决。

如果确认以上都没问题,但虚拟机还是不进Shell,可以在开机时按F2进入UEFI固件设置界面,查看Boot Manager里是否列出了USB设备,以及引导顺序里U盘是不是排在第一。UEFI固件设置界面本身就是排错工具,不要忽略它。

6. 装完怎么验证跑通:用U盘把虚拟机拉进UEFI Shell

验证的关键动作是:把前面做好的U盘插入已配置UEFI固件的虚拟机,开机,看到UEFI Shell命令行界面。

6.1 验证步骤

具体操作流程:虚拟机处于关机状态→设备菜单里把U盘连接到USB控制器→开机→UEFI固件启动后自动扫描引导设备→从U盘的\EFI\BOOT\BOOTx64.EFI加载Shell.efi→进入Shell命令行。

进入Shell后,先执行map -r,这条命令刷新并显示当前UEFI可访问的设备映射表。正常情况下能看到fs0:这类FAT文件系统句柄,以及blk0:这样的块设备句柄。如果能看到fs0:,说明FAT文件系统驱动加载成功,ESP分区被正确识别。

再用内存映射命令验证UEFI环境状态:

Shell> memmap

输出会列出当前UEFI环境下的物理内存映射表,包括可用内存(Available)、保留内存(Reserved)、MMIO区域等。能在Shell里看到真实内存布局,说明UEFI固件已经完成了PEI和DXE阶段的内存初始化,CPU运行在64位保护模式下,这比任何教科书描述都直观。

如果U盘没有被识别,先用exit命令退到固件设置菜单,检查引导顺序里USB是否排在第一位。实在不行就重启虚拟机,在固件设置界面用Boot Manager手动选择U盘设备。

6.2 一个值得保留的验证习惯

验证完Shell能进,还不算完整走通。你可以顺手在Shell里访问ESP分区确认引导文件位置:

Shell> fs0: FS0:\> dir \EFI\BOOT\

能看到BOOTx64.EFI列出来,说明从分区创建、文件拷贝到固件加载这条UEFI引导链路全部畅通。这套验证习惯我后来在排查物理机的引导故障时也一直沿用:凡是UEFI引导不走,先确认ESP分区存在且引导文件路径正确,再排查固件设置,基本能定位90%的问题。

从那以后我每次做完U盘引导盘,都会先在虚拟机里跑一遍这套验证流程再拿给物理机用,省掉了不少来回插拔U盘的时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 1:23:38

PCA9422与PIC32MZ1024EFE144的低功耗电源管理方案实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 1:23:14

Files文件管理器:三阶归档逻辑实现结构化文件整理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 1:20:34

PCA9422与PIC18LF46K80的低功耗电源管理实战:从电源树到状态机

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 1:20:34

基于PCA9422与STM32F417ZG的嵌入式智能电源管理设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 1:20:07

基于PCA9422与PIC18的低功耗电池电源管理方案设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 1:19:18

交通大脑落地实践:数据融合、轻量模型与人机协同

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华