systemd-boot添加Windows引导项

目录
警告
本文最后更新于 2023-10-05,文中内容可能已过时。

前言

最近把系统换成了CachyOS,用上了ZFS,这个发行版做的一些Tricky还是可以的,例如一些fish的脚本,还有软件与DE的自定义项都比较简洁,比ArcoLinux强上不少。
我的情况是有两块NVMe的硬盘,一块是Windows系统,一块则是CachyOS。我的期望是用Linux Boot Manager去引导两个操作系统,比用Windows Boot Manager去引导Linux要好操作不少。

确定fs alias

看了一下systemd-boot的文档,需要先安装 edk2-shell 来给systemd-boot 加个EFI shell:

sudo pacman -S edk2-shell && cp /usr/share/edk2-shell/x64/Shell.efi /boot/shellx64.efi

然后在boot的时候选择EFI Shell,在shell中,输入map命令,可以得到所有盘的fs alias, 这里我们需要得到是另一块盘的EFI分区。
可以用blkid可以看到所有盘or分区的PARTUUID,在EFI shell的map命令的输出结果中,可以对应上具体的fs alias是哪个盘。

加上Boot脚本

确定了fs alias后就好办了,在/boot/下面新建一个windows.nsh,内容如下:

HD0b:EFI\Microsoft\Boot\Bootmgfw.efi

在这里,我的windows EFI分区的fs alias是HD0b。

然后在/boot/loader/entries/下面新建一个引导项windows.conf

title  Windows
efi     /shellx64.efi
options -nointerrupt -noconsolein -noconsoleout windows.nsh

最后检查一下windows.nsh是否在/boot/目录下面,用bootctl list 看一下boot项的输出,我的输出如下:

         type: Boot Loader Specification Type #1 (.conf)
        title: Windows
           id: windows.conf
       source: /boot//loader/entries/windows.conf
          efi: /boot//shellx64.efi
      options: -nointerrupt -noconsolein -noconsoleout windows.nsh

         type: Boot Loader Specification Type #1 (.conf)
        title: Linux Cachyos Lts Lto (default) (selected)
           id: linux-cachyos-lts-lto.conf
       source: /boot//loader/entries/linux-cachyos-lts-lto.conf
        linux: /boot//vmlinuz-linux-cachyos-lts-lto
       initrd: /boot//amd-ucode.img
               /boot//initramfs-linux-cachyos-lts-lto.img
      options: zfs=zpcachyos/ROOT/cos/root rw zswap.enabled=0 nowatchdog

         type: Boot Loader Specification Type #1 (.conf)
        title: Linux Cachyos Lts Lto (Fallback)
           id: linux-cachyos-lts-lto-fallback.conf
       source: /boot//loader/entries/linux-cachyos-lts-lto-fallback.conf
        linux: /boot//vmlinuz-linux-cachyos-lts-lto
       initrd: /boot//amd-ucode.img
               /boot//initramfs-linux-cachyos-lts-lto-fallback.img
      options: zfs=zpcachyos/ROOT/cos/root rw

可以确定的是,如果输出正确,那么就可以在引导的时候选择windows了。 PS,如果要改默认选择项,在/boot/loader/loader.conf 中可以改掉默认引导项,或者使用bootctl set-default 来指定。

添加Hook自动生成

2023-11-16更新:

上述方案有个问题,如果每更新内核的话,entryies目录下的配置文件会被清空,所以需要有一个机制让内核更新的时候也能把windows.conf复制进去。
这里我选择的是,新建一个service,新建一个pacman的hook,每次在内核更新的时候,会触发hook,然后启动service,将处于其它路径中的配置文件复制到boot分区中去。
方法如下:

  1. 在非boot目录放置上述两个文件:windows.nshwindows.conf。这里我选择的目录是~/conf;
  2. /etc/systemd/system/下面新建一个update-windows-boot.service
    [Unit]
    Description=Update Windows boot entry
    
    [Service]
    ExecStart=/usr/bin/update-windows-entry.sh
    
  3. /usr/bin/下面新建update-windows-entry.sh,别忘记chmod +x 加上权限:
    #!/bin/bash
    cp /home/linxy/conf/windows.nsh /boot/
    cp /home/linxy/conf/windows.conf /boot/loader/entries/
    
  4. /etc/pacman.d/hooks下面新建update-windows-entry.hook:
     [Trigger]
     Operation = Upgrade
     Type = Package
     Target = linux-cachyos
     Target = linux-cachyos-lts
     Target = linux-lts
     Target = linux
    
     [Action]
     Description = Updating Windows boot entry...
     When = PostTransaction
     Exec = /usr/bin/systemctl start update-windows-boot.service
    

其中,target指的就是升级什么包的时候会触发这个hook。配置完成后,即可以在每次升级内核的时候保持windows的boot项。

TODO:也许可以把service去掉,直接执行脚本。有时间再研究吧