不改 BIOS,不重装系统:用一块 U 盘让老服务器从 NVMe 启动 PVE

服务器固件不能从 PCIe NVMe 启动,但 PVE 已经装在 NVMe 上。本文用一个 Windows 小工具,把 U 盘做成 rEFInd 跳板盘,加载 NVMe 驱动后链式启动 PVE 的 GRUB;不改 BIOS、不重装系统,内核升级也无需维护。

适用场景:服务器主板不能从 PCIe NVMe 启动,但 PVE 已经装在 NVMe 上。你不想刷 BIOS,也不想重装系统,只想让它正常开机。

先说结论:用一块 U 盘承载 rEFInd 和 NVMe DXE 驱动,开机时由 U 盘“看见”NVMe,再把启动权交给 NVMe 上的 PVE GRUB。U 盘可以长期插在服务器内部,内核升级也不需要重做。

整套方案的核心不是“绕过固件”,而是在固件和 PVE 之间补上一个自带 NVMe 驱动的小型引导环境。


一、问题:系统装得上,为什么启动不了?

很多人第一次遇到这个问题,会以为是“主板完全不认 NVMe”。其实不是。

典型现场是这样的:

  • PVE 安装器里,NVMe 清清楚楚地列着,安装一切正常;
  • 安装完成重启,BIOS 启动菜单里却找不到这块盘;
  • 启动顺序里只有 SATA、USB、网络,没有 UEFI: NVMe...。

原因在于两个阶段使用的驱动不是同一套:

阶段 谁在访问 NVMe 结果
安装 / 进入 Linux 后 Linux 内核自带的 nvme 驱动 能识别、能分区、能安装
开机选启动项时 主板 UEFI 固件 固件没有 NVMe DXE 驱动,看不到盘

UEFI 固件要通过 DXE(Driver Execution Environment) 驱动来识别存储控制器。老平台可能只带了 SATA、USB、AHCI 的 DXE,没有 NvmExpressDxe。固件看不到 NVMe,自然也不会把它列进启动菜单。

所以问题的本质是:固件缺少一个能在启动阶段访问 NVMe 的驱动。


二、PVE 默认布局里的一个死结

要理解为什么不能“让 rEFInd 直接启动内核”,先看 PVE 默认把盘分成了什么样。

PVE 系统盘与跳板 U 盘的布局
PVE 默认 UEFI 安装:ESP 在前,LVM 在后;跳板 U 盘只有一个 FAT32 ESP。

典型的 PVE UEFI 安装(ext4 + LVM)会得到三块分区:

分区 大小 作用
p1 1 MB BIOS boot,传统 GRUB 的遗留区域
p2 512 MB EFI System Partition(ESP),FAT32,存放 EFI/proxmox/grubx64.efi 和 grub.cfg
p3 剩余空间 LVM PV,里面是 pve-root、pve-swap 等逻辑卷

关键在于:PVE 默认把 /boot 也放在 pve-root 这个逻辑卷里,而不是单独分一个 /boot 分区。

于是形成两个事实:

  1. rEFInd 能读 p2。 它自带 FAT 驱动,能读取 ESP 上的 GRUB 文件。
  2. rEFInd 读不了 p3。 它的 drivers_x64 里有 ext2/ext4/btrfs 等文件系统驱动,但没有 LVM 驱动。逻辑卷不是普通分区,rEFInd 无法把 pve-root 当成文件系统挂起来。

死结就在这里:

rEFInd 想直接找内核
        ↓
内核在 /boot
        ↓
/boot 在 pve-root 逻辑卷里
        ↓
rEFInd 没有 LVM 驱动,读不到

这也解释了一个常见误区:在 U 盘根目录放一个 refind_linux.conf,并不能让默认 PVE 直接启动。rEFInd 是在“内核所在目录”里找这个文件的;它连 /boot 都进不去,自然不会读到你放在 U 盘根目录的那份配置。


三、跳板盘的启动链路

既然 rEFInd 读不了 LVM,就不要让它读。让它把“接力棒”交给一个能读 LVM 的引导器——PVE 自己的 GRUB。

五段启动链路
从服务器固件到 LVM 里的内核,五个阶段各司其职。

完整链路是:

服务器 UEFI 固件
    │  只认 FAT32,加载 U 盘的 \EFI\BOOT\BOOTX64.EFI
    ▼
U 盘上的 rEFInd
    │  从 drivers_x64 加载 nvme_x64.efi
    ▼
NVMe DXE 驱动生效
    │  固件此时能看见 NVMe 控制器和分区
    ▼
NVMe ESP 上的 PVE GRUB
    │  \EFI\proxmox\grubx64.efi,读取自己的 grub.cfg
    ▼
LVM 里的 /boot 与内核
    │  /dev/mapper/pve-root → /boot/vmlinuz-*
    ▼
PVE 启动

几个设计上的关键点:

  • U 盘只负责“看见 NVMe”。 它不承载内核,也不参与内核升级。
  • GRUB 从 NVMe ESP 上执行,而不是复制到 U 盘。 GRUB 的 grubx64.efi 有自己的 prefix 和模块路径,复制到 U 盘后很可能找不到配置和模块;在原位执行则保持它熟悉的环境。
  • 内核升级由 PVE 自己维护。 每次升级后,PVE 会更新 ESP 上的引导配置(GRUB 的 grub.cfg,或 systemd-boot 的 loader/entries);rEFInd 只是每次把控制权交过去,不需要改任何东西。
  • U 盘可以长期插在服务器内部 USB 口。 只要 BIOS 启动顺序把 UEFI: <U盘> 放在第一位,重启就不需要每次按 F11。

这就是“零维护”的含义:不是永远不坏,而是内核升级、GRUB 更新都不需要重新制作跳板盘。


四、工具如何自动完成

整个 Windows 工具可以分成四段:探测、决策、写入、校验。

工具的四段式流水线
探测 → 决策 → 写入 → 校验;危险动作集中在第三段。

4.1 探测:先把事实读准

工具不靠分区大小猜,而是用 GPT 类型 GUID 识别分区:

$EspTypeGuid      = 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
$LvmTypeGuid      = 'e6d6d379-f507-44c2-a23c-238f2a3df928'
$LinuxFsTypeGuid  = '0fc63daf-8483-4772-8e79-3d69d8477de4'
$BiosBootTypeGuid = '21686148-6449-6e6f-744e-656564454649'

这四个 GUID 分别对应 ESP、Linux LVM、Linux 文件系统、BIOS boot。磁盘列表里的 ESP+LVM 备注就来自这里。

如果 PVE 盘接在 Windows 上,工具会临时给 ESP 分配一个盘符,只读地找:

EFI\proxmox\grubx64.efi
EFI\proxmox\shimx64.efi
EFI\debian\grubx64.efi
EFI\systemd\systemd-bootx64.efi
EFI\BOOT\grubx64.efi

找不到时,还会检查 EFI\BOOT\BOOTX64.EFI 的内容里是否包含 GRUB 或 systemd-boot,最后递归找任意 grubx64.efi。读取完成后,临时盘符会被移除。

4.2 决策:生成链式启动配置

如果检测到 PVE 引导器,工具会生成类似下面的 refind.conf:

# Generated by PVE Jump Drive Tool
timeout 5
use_nvram false
scanfor internal,external,optical
also_scan_dirs boot
dont_scan_dirs EFI/refind

menuentry "Proxmox VE (NVMe GRUB)" {
    volume 12345678-1234-1234-1234-123456789abc
    loader \EFI\proxmox\grubx64.efi
}

default_selection "Proxmox VE (NVMe GRUB)"

每一项都有明确目的:

指令 作用 为什么这样设
timeout 5 菜单停留 5 秒 有可靠默认项时自动启动,失败也能手动选
use_nvram false 不写 UEFI NVRAM 跳板盘可能换口、换机器;不污染服务器启动项
scanfor internal,external,optical 扫描内置、外置、光驱 兼容 NVMe、SATA、USB
dont_scan_dirs EFI/refind 不扫描第二份 rEFInd 避免菜单出现重复条目
volume <GUID> 指定加载器所在分区 用分区 GUID,不用会变的 fs0:
loader <路径> 要加载的 EFI 文件 指向 NVMe ESP 上的 PVE GRUB

为什么用分区 GUID,而不是盘符?

UEFI 的卷编号在不同启动、不同插槽下会变化。今天 U 盘是 fs1:,明天可能是 fs0:。分区 GUID 跟着分区走,不跟着枚举顺序走。

为什么关闭 NVRAM 写入?

对一块可能随时拔走的 U 盘来说,把自己注册进服务器启动项没有必要,还可能留下一个指向“当前 USB 口”的失效条目。关闭后,启动完全依赖 BIOS 里的 UEFI: <U盘> 顺序,行为更可控。

4.3 写入:双份安装,双份驱动

工具会把 rEFInd 同时复制到两个目录:

EFI\BOOT\      ← UEFI 默认回退路径,BOOTX64.EFI 放这里
EFI\refind\    ← rEFInd 的常规目录,保留完整副本

原因很简单:

  • 很多主板即使没有 NVRAM 条目,也会自动扫描 \EFI\BOOT\BOOTX64.EFI;
  • EFI\refind 是 rEFInd 的“家目录”,配置、图标、字体、驱动都在这里更符合习惯;
  • 两个目录都放一份 drivers_x64,因为 rEFInd 是从“自己所在目录”加载驱动的。

NVMe 驱动也因此在两处各放一份:

Copy-Item -LiteralPath $NvmeDriver `
    -Destination (Join-Path $bootDrivers 'nvme_x64.efi') -Force
Copy-Item -LiteralPath $NvmeDriver `
    -Destination (Join-Path $refindDrivers 'nvme_x64.efi') -Force

少任何一份,都可能出现“从一个入口启动能看到 NVMe,从另一个入口看不到”的诡异现象。

4.4 校验:不给自己“成功的假象”

制作完成后,工具会逐一检查 8 个关键文件是否存在且非空:

EFI\BOOT\BOOTX64.EFI
EFI\BOOT\refind.conf
EFI\BOOT\drivers_x64\nvme_x64.efi
EFI\BOOT\drivers_x64\ext4_x64.efi
EFI\refind\refind_x64.efi
EFI\refind\refind.conf
EFI\refind\drivers_x64\nvme_x64.efi
refind_linux.conf

少一个就报错,不会打印“制作成功”。日志会写到工具目录,并复制一份到 U 盘根目录的 tool-log.txt。


五、三个安全设计,避免“选错盘”

下面的代码是工具里的关键片段,省略了错误处理和兜底分支;完整实现见 Make-PveRefindUsb.ps1。

分区工具最怕误操作。这个工具在写入前加了几道闸:

  1. 跳板盘必须是 USB,不能是 Windows 系统盘,不能和 PVE 系统盘相同,也不能是工具自己所在的盘。
  2. 必须输入 ERASE 才会清空;其他任何输入都取消。
  3. 写入前再复核一次总线类型、容量和序列号:
$fresh = Get-Disk -Number $jump.Number
if ($fresh.BusType -ne 'USB') { throw '跳板盘不再是 USB 磁盘,已中止。' }
if ([uint64]$fresh.Size -ne [uint64]$jump.Size) { throw '磁盘容量发生变化,已中止。' }
if ($jump.SerialNumber -and $fresh.SerialNumber -and
    ($fresh.SerialNumber -ne $jump.SerialNumber)) {
    throw '磁盘序列号发生变化,已中止。'
}

从选择磁盘到输入 ERASE 之间,用户可能拔插了设备,Windows 也可能重新编号。只靠最初读到的对象是不够的。

另外,工具支持 -DryRun:不写任何磁盘,只在 .\dryrun\ESP 生成文件,用来检查目录结构和配置内容。


六、制作步骤

6.1 准备

项目 要求
Windows Windows 10/11 x64,PowerShell 5.1+
权限 管理员
跳板 U 盘 ≥ 1 GB,建议 4 GB+,会被完全清空
PVE 系统盘 建议通过 USB 转接盒接入,仅用于只读识别
服务器 UEFI 启动,可关闭 Secure Boot

把 PVE 的 NVMe 接到 Windows 时,资源管理器可能提示“需要格式化磁盘”。不要格式化,不要初始化,点取消。工具只读它的 ESP 分区。

工具在启动时只枚举一次磁盘。请先把 PVE 盘和 U 盘都接好,再运行。

6.2 运行

双击项目根目录的:

制作PVE跳板盘.cmd

它会自动请求管理员权限,然后调用同目录下的 Make-PveRefindUsb.ps1。

工具会列出磁盘,例如:

编号  总线    大小       型号                          分区表  备注
--------------------------------------------------------------------------------
0     NVMe    1.86 TB    Predator SSD GM7 2TB          GPT     Windows系统盘-禁止
1     USB     1.82 TB    WD Blue SN5000 (USB转接)      GPT     USB,ESP+LVM
2     USB     28.9 GB    SanDisk Ultra USB 3.0         GPT     USB
  • Windows系统盘-禁止:绝对不能选;
  • USB,ESP+LVM:很像 PVE 系统盘(可能是 USB 转接的 NVMe);
  • 只有 USB 的:通常是跳板 U 盘。

6.3 选择与确认

  1. 选择 PVE 系统盘(输入编号;输入 S 可跳过;直接回车使用默认建议);
  2. 选择 跳板 U 盘(必须是 USB,会被清空);
  3. 输入 ERASE 确认;
  4. 等待完成。

完成后会看到:

[+] ESP 就绪:G:  FAT32  1,020.0 MB
[+] 关键文件校验通过:8 项
[+] 跳板盘:G:  FAT32 / REFIND
[+] 链式启动项:Proxmox VE (NVMe GRUB) -> \EFI\proxmox\grubx64.efi

拔盘前使用 Windows 的“安全删除硬件”。


七、服务器端启动

  1. 关机,把跳板 U 盘插到服务器 USB 口(优先主板内部 USB 口,长期插着)。
  2. 开机按 F11 / F12 / F8 进入启动菜单。
  3. 选择 UEFI: <U盘名称>,不要选 Legacy/BIOS。
  4. 在 rEFInd 菜单里选择 Proxmox VE (NVMe GRUB)。
  5. 如果菜单里没有这一项,选择自动扫描到的 grubx64.efi、systemd-bootx64.efi 或 Proxmox 条目。

BIOS 里建议确认:

设置 建议值 原因
Boot Mode UEFI Legacy/CSM 读不到 U 盘的 UEFI 引导文件
Secure Boot Disabled rEFInd 和 NVMe DXE 驱动未签名
USB Boot Enabled 允许从 U 盘启动
Boot Order UEFI: <U盘> 第一 重启不用每次按 F11
PCIe Slot Mode EFI/UEFI(如果有) 让固件愿意枚举 NVMe

长期使用建议把 UEFI: <U盘> 放在启动顺序第一位。U 盘可以一直插在内部 USB 口,不影响 PVE 读写 NVMe。


八、如果 /boot 是独立分区

默认方案是链式启动,适合 /boot 在 LVM 里的 PVE。但如果你的 /boot 是独立 ext4 分区,还可以让 rEFInd 直接引导内核。

三种 /boot 情况的判断
先确认 /boot 的位置,再决定用哪种启动方式。

在 PVE 里执行:

findmnt /boot
输出 结论 下一步
/dev/mapper/pve-root[/boot] /boot 在 LVM 里 什么都不用做,链式启动已经工作
/dev/nvme0n1p2 独立 /boot 分区 可以复制 refind_linux.conf,启用直接引导
只有 BIOS boot + LVM,没有 ESP Legacy 安装 链式启动不可用,需要独立 /boot 或重装 UEFI

如果 /boot 是独立 ext4 分区,把 U 盘根目录的 refind_linux.conf 复制到 /boot:

mkdir -p /mnt/usb
mount /dev/sdX1 /mnt/usb          # 把 sdX1 换成 U 盘分区
cp /mnt/usb/refind_linux.conf /boot/refind_linux.conf
umount /mnt/usb

也可以直接运行 U 盘上的脚本:

sh /mnt/usb/install-refind_linux_conf.sh

之后 rEFInd 菜单会直接列出内核,内核升级后自动出现新版本。

如果 /boot 在 LVM 里,不要做这一步,做了也不会生效。


九、常见问题

9.1 启动菜单里没有 U 盘

  • 服务器是否处于 UEFI 模式,而不是 Legacy/CSM;
  • BIOS 是否启用了 USB Boot;
  • Secure Boot 是否关闭;
  • U 盘是否是 GPT + FAT32(工具会做);
  • 换一个 USB 口,优先主板后置/内部 USB;
  • 有些服务器需要在 BIOS 里把 USB 设备设为 UEFI。

9.2 有 rEFInd,但菜单里没有 PVE

  • 确认 PVE 盘 ESP 里有 EFI/proxmox/grubx64.efi、EFI/debian/grubx64.efi 或 EFI/systemd/systemd-bootx64.efi;
  • 确认 U 盘 EFI/BOOT/drivers_x64/nvme_x64.efi 和 EFI/refind/drivers_x64/nvme_x64.efi 都存在;
  • 确认 BIOS 能枚举 PCIe NVMe(有些平台需要把 PCIe 插槽设为 EFI/UEFI 模式);
  • 如果 PVE 是 Legacy 安装,根本没有 ESP,rEFInd 无法链式启动。

9.3 选择 PVE 后黑屏 / GRUB 报错

先在能启动的 PVE 环境里重新生成 GRUB,确保 core 镜像包含 nvme、lvm、ext2:

grub-install --target=x86_64-efi \
  --efi-directory=/boot/efi \
  --bootloader-id=proxmox \
  --modules="nvme lvm ext2 part_gpt"

update-grub

如果是 systemd-boot 方案(常见于 ZFS 根),改用:

proxmox-boot-tool status
proxmox-boot-tool refresh

9.4 内核启动到 initramfs 后找不到根

检查 initramfs 是否包含 NVMe / LVM:

lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'nvme|dm-mod|lvm'

缺少时:

echo nvme >> /etc/initramfs-tools/modules
echo dm-mod >> /etc/initramfs-tools/modules
update-initramfs -u -k all

9.5 根设备不是 /dev/mapper/pve-root

工具会优先从 grub.cfg 读取 root=;读不到时默认 /dev/mapper/pve-root。如果你的 VG/LV 名不同,重新制作时指定:

.\Make-PveRefindUsb.ps1 -RootDevice /dev/mapper/你的VG-你的LV

ZFS 根则用:

.\Make-PveRefindUsb.ps1 -RootDevice ZFS=rpool/ROOT/pve-1

链式启动时,root= 由 PVE 自己的 grub.cfg 决定;这个参数只影响直接内核引导。


十、边界与安全

这套方案不是万能的,先确认边界:

限制 影响 规避
仅 x64 UEFI 32 位 UEFI/ARM 不可用 换平台或找对应架构引导器
Secure Boot 必须关闭 强制签名环境不能直接用 关闭 Secure Boot,或自行签名
固件必须能枚举 NVMe 极老平台可能无解 升级 BIOS、调整 PCIe 模式、换平台
Windows 不能写 ext4/LVM 独立 /boot 的配置要进 PVE 复制 按第八节操作一次
不修改 PVE 的 GRUB 链式启动依赖 PVE 自己的引导器 如果 PVE GRUB 损坏,先修 PVE
U 盘会被清空 数据不可恢复 选盘时确认容量/型号,提前备份

安全提醒:跳板 U 盘会被完全清空;工具对 PVE 系统盘只做只读检查,但任何磁盘操作都有风险。第一次使用建议在可停机的测试环境验证,生产环境先备份 PVE 配置和虚拟机数据。


十一、小结

  • 问题不是 NVMe 坏了,而是固件缺少启动阶段的 NVMe 驱动。
  • PVE 默认把 /boot 放在 LVM 里,而 rEFInd 不能读 LVM,所以用链式启动,让 PVE 自己的 GRUB 接管。
  • U 盘只负责“看见 NVMe”,内核升级由 PVE 维护,跳板盘不需要跟着重做。
  • 只有 /boot 是独立 ext4 分区时,才需要复制 refind_linux.conf 做直接引导。
  • 制作时务必确认磁盘型号和容量,输入 ERASE 前再检查一遍。

如果这篇文章帮你救回了一台“不能从 NVMe 启动”的服务器,欢迎把踩过的坑补充在评论里。

主题测试文章,只做测试使用。发布者:zy,转转请注明出处:https://zynetc.top/?p=2026102709

赞 (0)
zy的头像zy
R730xd 服务器管理器:用 Redfish + IPMI 打造一台戴尔服务器的桌面控制台
上一篇 6天前
VRCLOC:在 VRChat 里点亮同城玩家的中国地图
下一篇 6天前

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注