linuxboot / heads

A minimal Linux that runs as a coreboot or LinuxBoot ROM payload to provide a secure, flexible boot environment for laptops, workstations and servers.
https://osresearch.net/
GNU General Public License v2.0
1.43k stars 187 forks source link

NixOS does not boot #1001

Open macpijan opened 3 years ago

macpijan commented 3 years ago

NixOS does not boot after installation (the installer boots fine). The kexec command line is not created correctly.

The original grub.cfg file:

# Automatically generated.  DO NOT EDIT THIS FILE!

    search --set=drive1 --fs-uuid 56D5-4720
    if [ -s $prefix/grubenv ]; then
    load_env
    fi

    # ‘grub-reboot’ sets a one-time saved entry, which we process here and
    # then delete.
    if [ "${next_entry}" ]; then
    set default="${next_entry}"
    set next_entry=
    save_env next_entry
    set timeout=1
    else
    set default=0
    set timeout=5
    fi

    # Setup the graphics stack for bios and efi systems
    if [ "${grub_platform}" = "efi" ]; then
    insmod efi_gop
    insmod efi_uga
    else
    insmod vbe
    fi

        insmod font
        if loadfont ($drive1)//converted-font.pf2; then
        insmod gfxterm
        if [ "${grub_platform}" = "efi" ]; then
        set gfxmode=auto
        set gfxpayload=keep
        else
        set gfxmode=1024x768
        set gfxpayload=text
        fi
        terminal_output gfxterm
        fi

            background_color '#2F302F'

        insmod png
        if background_image --mode 'normal' ($drive1)//background.png; then
        set color_normal=white/black
        set color_highlight=black/white
        else
        set menu_color_normal=cyan/blue
        set menu_color_highlight=white/blue
        fi

menuentry "NixOS - Default" --unrestricted {
search --set=drive1 --fs-uuid 56D5-4720
  linux ($drive1)//kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4
  initrd ($drive1)//kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd
}

submenu "NixOS - All configurations" {
menuentry "NixOS - Configuration 1 (2021-06-26 - 21.05.1187.8112fbe212f)"  {
search --set=drive1 --fs-uuid 56D5-4720
  linux ($drive1)//kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4
  initrd ($drive1)//kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd
}

}

The kexec_default.1.txt created by heads:

NixOS - Default|elf|kernel /grub/()//kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage|initrd /grub/()//kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd|append init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4

I can boot with kexec-boot using following entry:

NixOs - Default|elf|kernel /kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage|initrd /kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd|append init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4
tlaurion commented 3 years ago

@macpijan Where is the grub.cfg in this case? I wondering if https://github.com/osresearch/heads/commit/a0753473510ec598f9db86cfb610cf61156ca5cb is the cause or what should be improved here.

Of course, the grub.cfg file you show here contains ($drive1)/ that should be dodged by the parser, but since there is now two parsers (nitrd/bin/kexec-parse-bls nitrd/bin/kexec-parse-boot) I wonder which path you NixOS is taking (I guess its bls). Both are taking /boot (mountpoint where kernel is found) as argument prior of doing the parsing.

https://github.com/osresearch/heads/blob/a0753473510ec598f9db86cfb610cf61156ca5cb/initrd/bin/kexec-parse-bls https://github.com/osresearch/heads/blob/a0753473510ec598f9db86cfb610cf61156ca5cb/initrd/bin/kexec-parse-boot

Guix and Nix don't have a /boot partition from what I read by default?

macpijan commented 3 years ago

@tlaurion

Where is the grub.cfg in this case?

/boot/grub/grub.cfg

Guix and Nix don't have a /boot partition from what I read by default?

Yes, the official installation manual instructs to install everything (boot and rootfs) in one partition. At least when using MBR. When using GPT, they instruct to create a separate EFI partition. This is bad for several reasons. One of them is heads is trying to check hashes of all of the files in rootfs in such scenario (and they change at each boot obviously).

Nevertheless, I have a separate /boot partition at /dev/sda1 and rootfs on /dev/sda2 (LVM on /dev/sda2 actually, but it does not matter) - which is also required to setup rootfs encryption.

tlaurion commented 2 years ago

@macpijan

Quick but sufficient hack:

test='kernel ($drive1)//kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4'
echo $test | sed "s/([^)]*)\///g"
kernel /kernels/65f9va1ql6x2vy23x4nqw0x18jz3a3x8-linux-5.10.45-bzImage init=/nix/store/0jpc6ilx8xikwrmcgbqsvakl1inbpbxj-nixos-system-nixos-21.05.1187.8112fbe212f/init loglevel=4
test='initrd ($drive1)//kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd'
echo $test | sed "s/([^)]*)\///g"
initrd /kernels/2jaca9jz9qcr08vlbvgnjn2kz3cbp1yf-initrd-linux-5.10.45-initrd
diff --git a/initrd/bin/kexec-parse-boot b/initrd/bin/kexec-parse-boot
index d54d6285..6976b41a 100755
--- a/initrd/bin/kexec-parse-boot
+++ b/initrd/bin/kexec-parse-boot
@@ -94,11 +94,11 @@ grub_entry() {
                        modules="$modules|module $path"
                        ;;
                linux*)
-                       kernel=`echo $trimcmd | cut -d\  -f2`
+                       kernel=`echo $trimcmd | sed "s/([^)]*)\///g" | cut -d\  -f2`
                        append=`echo $trimcmd | cut -d\  -f3-`
                        ;;
                initrd*)
-                       initrd="$val"
+                       initrd=$(echo "$val" | sed "s/([^)]*)\///g" )
                        ;;
        esac
 }

Have something better?