Monday, 6 January 2025

Debugging grub2 menus that won't fully boot (e.g. ArchLinux ISOs)

If you need to construct a grub2 menu, but then find that it does not work, you can add in some extra debug lines. For instance the grub2 read command will wait for you to press the RETURN key before continuing execution and an echo command can be used to track progress and view grub2 variable values.

Here is an example grub2 menu display output screen...



and here is the grub2 menu that was used...
menuentry "Arch Linux with Parameters" {
set iso_path="/_ISO/LINUX/archlinux-2024.12.01-x86_64.iso"
search --no-floppy -f --set=root $iso_path
probe -u $root --set=archiso_img_dev_uuid
loopback loop $iso_path
ls
echo
ls (loop)/
echo
ls /
echo
ls /_ISO/LINUX/
echo
echo archiso_img_dev_uuid=${archiso_img_dev_uuid}  iso_path=${iso_path}  root=${root} 
read
linux (loop)/arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop=${iso_path}
initrd (loop)/arch/boot/x86_64/initramfs-linux.img
read
}

This menu sets iso_path to the path of the ISO file we wish to boot.

Next we search for the ISO file (-f) and set the variable root - this changes the grub2 current root folder to the device containing the ISO. 

Next we probe for the UUID of this ISO and set the variable archiso_img_dev_uuid to the UUID.

Then we mount the ISO file using the path, as we have already changed $root to the same drive.

Now we use ls, read and echo commands to debug the outcome. 

We can see that the ls command has shown us the devices and partitions in the system and also that the (loop) device was successfully created.

The ls (loop)/ command has displayed the contents inside the ISO. We could have used a command like
 
ls (loop)/arch/boot/x86_64/

to check that the files vmlinuz-linux and initramfs-linux.img actually exist, but this can also easily be checked by opening the ISO in 7Zip beforehand.

ls / shows us files on the root device (the device that has a /_ISO folder and contains our ISO file).

We then list the files in the /_ISO/LINUX/ folder which should include our archlinux iso. We can check the case (uppercase/lowercase) is correct and the spelling. Also we must beware of spaces in the filename because space characters are not coped as parameters in linux and initrd command lines and so must be avoided.

Finally we list the variables we are going to use $archiso_img_dev_uuid, $iso_path and $root.

The linux command line is using these variables.

The final read command allows us to check for any error messages from the linux and initrd command lines before the kernel runs and clears the screen.

If the linux boot code appears to load and run, but you do not get the expected result, it may be that your particular computer may require additional boot kernel parameter 'cheat codes'. For instance common ones are for disabling EDD, nomodeset and special magic for nVidia graphics cards, etc.

These cheat codes will vary from Linux distro to Linux distro, so you will have to search online for them. e.g. Kernel Parameters for ArchLinux and Kernel Mode settings.

Here is an example which worked for one user with a PC containing an nVidia GPU that just showed a blank screen when booted using the above standard menu. The extra kernel parameters are show in bold.

linux (loop)/arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop=${iso_path} nvidia nvidia-drm.modeset=1 nouveau.modeset=0 module_blacklist=nouveau

You can also examine other .cfg files that may be inside the ISO file or similar ISO files and look for any special kernel parameters or try asking on reddit, etc.

Here is an example /boot/grub/loopback.cfg file from an ArchCraft 2025 ISO and you can see the extra cheat codes that are used for nVidia in red.

# https://www.supergrubdisk.org/wiki/Loopback.cfg

# Search for the ISO volume
search --no-floppy --set=archiso_img_dev --file "${iso_path}"
probe --set archiso_img_dev_uuid --fs-uuid "${archiso_img_dev}"

# Get a human readable platform identifier
if [ "${grub_platform}" == 'efi' ]; then
archiso_platform='UEFI'
if [ "${grub_cpu}" == 'x86_64' ]; then
archiso_platform="x64 ${archiso_platform}"
elif [ "${grub_cpu}" == 'i386' ]; then
archiso_platform="IA32 ${archiso_platform}"
else
archiso_platform="${grub_cpu} ${archiso_platform}"
fi
elif [ "${grub_platform}" == 'pc' ]; then
archiso_platform='BIOS'
else
archiso_platform="${grub_cpu} ${grub_platform}"
fi

# Set default menu entry
default=archcraft
timeout=10
timeout_style=menu

# Menu entries
menuentry "Boot Archcraft (x86_64, ${archiso_platform}, Default)" --class archcraft --class arch --class gnu-linux --class gnu --class os --id 'archcraft' {
set gfxpayload=keep
linux /arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" quiet splash loglevel=3 udev.log_level=3 vt.global_cursor_default=0 cow_spacesize=5G copytoram=n nvme_load=yes lsm=landlock,lockdown,yama,integrity,apparmor,bpf
initrd /arch/boot/x86_64/initramfs-linux.img
}

menuentry "Boot Archcraft (x86_64, ${archiso_platform}, OpenSource)" --class archcraft --class arch --class gnu-linux --class gnu --class os --id 'archcraftos' {
set gfxpayload=keep
linux /arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" quiet splash loglevel=3 udev.log_level=3 vt.global_cursor_default=0 cow_spacesize=5G copytoram=n module_blacklist=nvidia,nvidia_modeset,nvidia_uvm,nvidia_drm nouveau.modeset=1 radeon.modeset=1 i915.modeset=1 nvme_load=yes lsm=landlock,lockdown,yama,integrity,apparmor,bpf
initrd /arch/boot/x86_64/initramfs-linux.img
}

menuentry "Boot Archcraft (x86_64, ${archiso_platform}, Nvidia)" --class archcraft --class arch --class gnu-linux --class gnu --class os --id 'archcraftpn' {
set gfxpayload=keep
linux /arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" quiet splash loglevel=3 udev.log_level=3 vt.global_cursor_default=0 cow_spacesize=5G copytoram=n nvidia nvidia-drm.modeset=1 nouveau.modeset=0 module_blacklist=nouveau radeon.modeset=1 i915.modeset=1 nvme_load=yes lsm=landlock,lockdown,yama,integrity,apparmor,bpf
initrd /arch/boot/x86_64/initramfs-linux-nvidia.img
}

menuentry "Boot Archcraft (x86_64, ${archiso_platform}, Nomodeset)" --class archcraft --class arch --class gnu-linux --class gnu --class os --id 'archcraftnm' {
set gfxpayload=keep
linux /arch/boot/x86_64/vmlinuz-linux archisobasedir=arch img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" quiet splash loglevel=3 udev.log_level=3 vt.global_cursor_default=0 cow_spacesize=5G copytoram=n nomodeset module_blacklist=nvidia,nvidia_modeset,nvidia_uvm,nvidia_drm nouveau.modeset=0 radeon.modeset=0 i915.modeset=0 nvme_load=yes lsm=landlock,lockdown,yama,integrity,apparmor,bpf
initrd /arch/boot/x86_64/initramfs-linux.img
}

if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
set gfxpayload=800x600,1024x768
linux /boot/memtest86+/memtest.efi
}
fi
if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then
menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool {
set gfxpayload=800x600,1024x768
linux /boot/memtest86+/memtest
}
fi
if [ "${grub_platform}" == 'efi' ]; then
if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then
menuentry 'UEFI Shell' --class efi {
chainloader /shellx64.efi
}
elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then
menuentry 'UEFI Shell' --class efi {
chainloader /shellia32.efi
}
fi

menuentry 'UEFI Firmware Settings' --class efi --id 'uefi-firmware' {
fwsetup
}
fi

menuentry 'System shutdown' --class shutdown --class poweroff {
halt
}

menuentry 'System restart' --class restart --class reboot {
reboot
}


Other stuff

A linux command line may also contain command parameters like quiet which reduces screen text messages and splash which produces a splash screen image. Both of these can usually safely be removed so that you can see all possible error messages during booting and perhaps obtain a clue as to the nature of the problem.

Another thing to watch is a double hyphen in the kernel parameters line. If you are adding extra kernel parameters, make sure to add them before the -- characters or else they will be interpreted as post-boot parameters and so will probably be ignored!
 

No comments:

Post a Comment