Arch Win11 Dualboot 手动重建 EFI 分区
2024-02-09 23:10:53

前情提要: 硬盘上已经有 Windows 11 和 ArchLinux 两个系统, 因为 Windows 自带的 EFI 只有 100MB 塞不下,所以我直接把他给格式化了, 现在需要重新建立引导.
但是我的 os-prober 无法识别 Windows 11 然后他每次跑卡住了, 所以我准备手写 grub
我的磁盘分区表都是 GPT
下面命令我都不会写 sudo, 需要自己加上就好了

TODO:

  • Arch 用 chainlaoder 引导

0. 准备

  • Arch 安装盘
  • 一个 Windows PE 盘, 我是刷的 Hiren’s BootCD PE, 可以想办法进 Arch 里面(通过 arch-chroot) 然后用下面的方法刷
  • 硬盘还有 300MB 左右的空间分一个独立的 EFI 分区, 位置无所谓, 我上放在 ArchLinux 的分区前

0.0 刷 Hiren’s BootCD PE

  1. 在 ArchLinux 中
  2. 下载 Hiren’s BootCD PE 的 ISO
  3. 格式化一个 U 盘:
    1. 先用 lsblk 看 USB 的标识, 假设是 /dev/sdb
    2. cfdisk /dev/sdb 把里面的都删除了, 然后写入新分区
    3. mkfs.fat -F 32 /dev/sdb 格式化成 FAT32
    4. sudo dd bs=4M if=HBCD_PE_x64.iso of=/dev/sdb conv=fsync oflag=direct status=progress 烧录 ISO

0.1 格式化 EFI 分区

  1. 在 ArchLinux 中
  2. lsblk 看 EFI 分区的标识, 假设是 /dev/nvme0n1
  3. cfdisk /dev/nvme0n1 在里面分一个 300MB 左右的 EFI 分区
  4. mkfs.fat -F 32 /dev/nvme0n1p7 格式化 EFI 分区成 FAT32 (或者不用 -F 32 格式化成 FAT16 也行)

1. 重建 Arch 引导

  1. 在 ArchLinux 中
  2. mount /dev/nvme0n1p7 /boot 挂载 EFI 分区, 如果还没挂载
  3. grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB 来装 grub 文件, 参考 ArchWiki
    • 会在 /boot/grub 下创建 grub 文件夹
  4. pacman -S linux intel-ucode 把内核和 ucode 的 img 都写入到 EFI 分区 (如果不是 intel 的就装对应 ucode, 然后你要是用 linux-lts 也可以装 linux-lts)
    • 会在 /boot 下创建 intel-ucode.img, vmlinuz-linux, initramfs-linux.imginitramfs-linux-fallback.img
  5. 记得把 /etc/default/grub 里的 GRUB_DISABLE_OS_PROBER="false" 给注释掉, 因为我们不打算用 os-prober
  6. 进入 /etc/grub.d/ 下, 用 cp 40_custom 10_linux 复制一份 (前面的数字 10 是优先级, 10 会在 grub menu 中显示在 40 的前面, 后面的 linux 是名字可以随便取)
  7. cat /etc/fstab 看一下 EFI 分区和 ArchLinux 分区的 UUID, 假设是 1111-A1B211111111-1111-1111-1111-111111111111
  8. 编辑 /etc/grub.d/10_linux, 改成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/bin/sh
    exec tail -n +3 $0
    # This file provides an easy way to add custom menu entries. Simply type the
    # menu entries you want to add after this comment. Be careful not to change
    # the 'exec tail' line above.
    menuentry "Arch" {
    insmod part_gpt
    insmod fat
    insmod ext2
    insmod gzio
    set root='<EFI DISK PARTISION ID>'
    search --no-floppy --fs-uuid --set=root <EFI UUID>
    linux /vmlinuz-linux root=UUID=<ARCH UUID> rw loglevel=3
    initrd /intel-ucode.img /initramfs-linux.img
    }
    其中 <EFI DISK PARTISION ID> 是 EFI 分区的硬盘表达 (一般来说不准没什么用, 因为如果你插入了其他 USB, 他硬盘顺序就乱了) 比如在 lsblk/dev/nvme0n1 是第一个磁盘, /dev/nvme0n1p7 就代表第7块扇区, 所以他的表达就是 'hd1,7' 或者 'hd1,gpt7' 或者 (hd1,gpt7); <EFI UUID> 是 EFI 分区的 UUID; <ARCH UUID> 是 ArchLinux 分区的 UUID
    /vmilinuz-linux 是内核文件, /intel-ucode.img 是 ucode 文件, /initramfs-linux.img 是内核镜像文件, 他们都在 /boot 下 (在 #1.3 中安装)
    填入后就像:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #!/bin/sh
    exec tail -n +3 $0
    # This file provides an easy way to add custom menu entries. Simply type the
    # menu entries you want to add after this comment. Be careful not to change
    # the 'exec tail' line above.
    menuentry "Arch" {
    insmod part_gpt
    insmod fat
    insmod ext2
    insmod gzio
    set root='hd1,gpt7'
    search --no-floppy --fs-uuid --set=root 1111-A1B2
    linux /vmlinuz-linux root=UUID=11111111-1111-1111-1111-111111111111 rw loglevel=3
    initrd /intel-ucode.img /initramfs-linux.img
    }
  9. grub-mkconfig -o /boot/grub/grub.cfg 生成 grub.cfg
  10. 到目前为止, ArchLinux 的引导就重建好了

2. 重建 Windows 引导

  1. 在 Windows PE 中
  2. diskpart 进入磁盘管理
  3. 参考之前看的 EFI 分区的位置, 选中 EFI 分区, 假设是 hd1,gpt7, 就 select disk 1 然后 select partition 7
  4. assign 把 EFI 分区挂载
  5. 进资源管理器看 EFI 的盘符, 假设是 E:
  6. 进控制台, bcdboot C:\Windows /s E: /f UEFI 重建引导
  7. 进挂载的 EFI 分区, 里面应该有 /EFI/Microsoft/Boot, 然后下面都是 Windows 的引导文件
  8. 目前为止, Windows 的引导就重建好了

3. 重建 grub 引导 Windows

  1. 在 ArchLinux 中
  2. mount /dev/nvme0n1p7 /boot 挂载 EFI 分区, 如果还没挂载
  3. cp /etc/grub.d/10_linux /etc/grub.d/10_windows 复制一份
  4. 修改 /etc/grub.d/10_windows
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/bin/sh
    exec tail -n +3 $0
    # This file provides an easy way to add custom menu entries. Simply type the
    # menu entries you want to add after this comment. Be careful not to change
    # the 'exec tail' line above.
    menuentry "Windows 11" {
    insmod part_gpt
    insmod fat
    insmod ntfs
    set root=<EFI DISK PARTITION ID>
    search --no-floppy --fs-uuid --set=root <EFI UUID>
    insmod chain
    chainloader /EFI/Microsoft/Boot/bootmgfw.efi
    }
    其中 <EFI DISK PARTITION ID> 是 EFI 分区的硬盘表达; <EFI UUID> 是 EFI 分区的 UUID
    /EFI/Microsoft/Boot/bootmgfw.efi 是第2节中 Windows PE 安装的引导文件
    填入后就像:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #!/bin/sh
    exec tail -n +3 $0
    # This file provides an easy way to add custom menu entries. Simply type the
    # menu entries you want to add after this comment. Be careful not to change
    # the 'exec tail' line above.
    menuentry "Windows 11" {
    insmod part_gpt
    insmod fat
    insmod ntfs
    set root='hd1,gpt7'
    search --no-floppy --fs-uuid --set=root 1111-A1B2
    insmod chain
    chainloader /EFI/Microsoft/Boot/bootmgfw.efi
    }
  5. grub-mkconfig -o /boot/grub/grub.cfg 生成 grub.cfg
  6. 到目前为止, grub 的引导就重建好了
-EOF-