Files
lbmk/config/grub/xhci/config/payload
T
Leah Rowe 429e91f908 make GRUB multi-tree and re-add xhci patches
Re-add xHCI only on haswell and broadwell machines, where
they are needed. Otherwise, keep the same GRUB code.

The xHCI patches were removed because they caused issues
on Sandybridge-based Dell Latitude laptops. See:
https://codeberg.org/libreboot/lbmk/issues/216

The issue was not reported elsewhere, including on the
Haswell/Broadwell hardware where they are needed, but the
build system could only build one version of GRUB.

The older machines do not need xHCI patches, because they
either do not have xHCI patches, or work (in GRUB) because
they're in EHCI mode when running the payload.

So, the problem is that we need the xHCI patches for GRUB
on Haswell/Broadwell hardware, but the patches break
Sandybridge hardware, and we only had the one build of GRUB.
To mitigate this problem, the build system now supports
building multiple revisions of GRUB, with different patches,
and each given coreboot target can say which GRUB tree to use
by setting this in target.cfg:

grubtree="xhci"

In the above example, the "xhci" tree would be used. Some
generic GRUB config has been moved to config/data/grub/
and config/grub/ now looks like config/coreboot/ - also,
the grub.cfg file (named "payload" in each tree) is copied
to the GRUB source tree as ".config", then added to GRUB's
memdisk in the same way, as grub.cfg.

Several other design changes had to be made because of this:

* grub.cfg in memdisk no longer automatically jumps to one
  in CBFS, but now shows a menuentry for it if available

* Certain commands in script/trees are disabled for GRUB,
  such as *config make commands.

* gnulib is now defined in config/submodule/grub/, instead
  of config/git/grub - and this mitigates an existing bug
  where downloading gnulib first would make grub no longer
  possible to download in lbmk.

The coreboot option CONFIG_FINALIZE_USB_ROUTE_XHCI has been
re-enabled on: Dell OptiPlex 9020 MT, Dell OptiPlex 9020 SFF,
Lenovo ThinkPad T440p and Lenovo ThinkPad W541 - now USB should
work again in GRUB.

The GRUB payload has been re-enabled on HP EliteBook 820 G2.

This change will enable per-board GRUB optimisation in the
future. For example, we hardcode what partitions and LVMs
GRUB scans because * is slow on ICH7-based machines, due
to GRUB's design. On other machines, * is reasonably fast,
for automatically enumerating the list of devices for boot.

Use of * (and other wildcards) could enable our GRUB payload
to automatically boot more distros, with minimal fuss. This
can be done at a later date, in subsequent revisions.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2024-06-02 19:58:50 +01:00

291 lines
7.3 KiB
Plaintext

# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (C) 2014-2016,2020-2021,2023-2024 Leah Rowe <leah@libreboot.org>
# Copyright (C) 2015 Klemens Nanni <contact@autoboot.org>
set prefix=(memdisk)/boot/grub
insmod at_keyboard
insmod usb_keyboard
insmod nativedisk
insmod xhci
insmod ehci
insmod ohci
insmod uhci
insmod usb
insmod usbms
insmod regexp
terminal_input --append at_keyboard
terminal_input --append usb_keyboard
terminal_output --append cbmemc
# User interface overrides wherever "keystatus" is supported
# Keep SHIFT key pressed before powering on to disable graphics
if keystatus --shift; then
terminal_output --append vga_text
else
gfxpayload=keep
terminal_output --append gfxterm
if [ -f (cbfsdisk)/background.png ]; then
insmod png
background_image (cbfsdisk)/background.png
elif [ -f (cbfsdisk)/background.jpg ]; then
insmod jpeg
background_image (cbfsdisk)/background.jpg
fi
fi
# Keep CTRL pressed to enable default serial terminal (COM1 or the like)
if keystatus --ctrl; then
serial
terminal_input --append serial
terminal_output --append serial
fi
# Keep ALT pressed to enable spkmodem
if keystatus --alt; then
terminal_output --append spkmodem
fi
set default="0"
if [ -f (cbfsdisk)/timeout.cfg ]; then
source (cbfsdisk)/timeout.cfg
else
set timeout=5
fi
set grub_scan_disk="nvme ahci ata"
if [ -f (cbfsdisk)/scan.cfg ]; then
source (cbfsdisk)/scan.cfg
fi
if [ -f (cbfsdisk)/keymap.gkb ]; then
keymap (cbfsdisk)/keymap.gkb
fi
function really_try_user_config {
set root="${1}"
if [ -f /"${2}"/grub.cfg ]; then
unset superusers
configfile /"${2}"/grub.cfg
fi
}
function try_user_config {
# The @/... entries are for cases where the BTRFS filesystem is being used
for dir in grub boot/grub @/grub @/boot/grub grub2 boot/grub2 @/grub2 @/boot/grub2 boot @/boot; do
really_try_user_config "${1}" "${dir}"
done
for dir in ubuntu debian redhat; do
really_try_user_config "${1}" "EFI/${dir}"
done
}
function search_grub {
echo -n "Attempting to load grub.cfg from '${1}' devices"
for i in 0 1 2 3 4 5 6 7 8; do
for part in 1 2 3 4 5 6 7 8 9 10 11 12; do
if [ "${1}" != "nvme" ]; then
try_user_config "(${1}${i},${part})"
else
# TODO: do we care about other namesapces
try_user_config "(nvme${i}n1,${part})"
fi
done
if [ "${1}" != "nvme" ]; then
# raw devices e.g. (ahci0) instead of (ahci0,1)
try_user_config "(${1}${i})"
else
# TODO: do we care about other namesapces
try_user_config "(nvme${i}n1)"
fi
done
echo # Insert newline
}
function try_isolinux_config {
set root="${1}"
for dir in '' /boot /EFI /@ /@/boot; do
if [ -f "${dir}"/isolinux/isolinux.cfg ]; then
syslinux_configfile -i "${dir}"/isolinux/isolinux.cfg
elif [ -f "${dir}"/syslinux/syslinux.cfg ]; then
syslinux_configfile -s "${dir}"/syslinux/syslinux.cfg
elif [ -f "${dir}"/syslinux/extlinux.conf ]; then
syslinux_configfile -s "${dir}"/syslinux/extlinux.conf
elif [ -f "${dir}"/extlinux/extlinux.conf ]; then
syslinux_configfile -s "${dir}"/extlinux/extlinux.conf
fi
done
}
function search_isolinux {
echo "\nAttempting to parse iso/sys/extlinux config from '${1}' devices"
for i in 0 1 2 3 4 5 6 7 8; do
for part in 1 2 3 4 5 6 7 8 9 10 11 12; do
if [ "${1}" != "nvme" ]; then
try_isolinux_config "(${1}${i},${part})"
else
# TODO: see above
try_isolinux_config "(nvme${i}n1,${part})"
fi
done
if [ "${1}" != "nvme" ]; then
# raw devices e.g. (usb0) instead of (usb0,1)
try_isolinux_config "(${1}${i})"
else
# TODO: do we care about other namesapces
try_isolinux_config "(nvme${i}n1)"
fi
done
echo # Insert newline
}
function try_bootcfg {
try_user_config "${1}"
try_isolinux_config "${1}"
}
function search_bootcfg {
search_grub "${1}"
search_isolinux "${1}"
}
menuentry 'Load Operating System (incl. fully encrypted disks) [o]' --hotkey='o' {
for grub_disk in ${grub_scan_disk}; do
search_bootcfg ${grub_disk}
done
# grub device enumeration is very slow, so checks are hardcoded
# TODO: add more strings, based on what distros set up when
# the user select auto-partitioning on those installers
lvmvol="lvm/grubcrypt-bootvol lvm/grubcrypt-rootvol"
raidvol="md/0 md/1 md/2 md/3 md/4 md/5 md/6 md/7 md/8 md/9"
# in practise, doing multiple redundant checks is perfectly fast and
# TODO: optimize grub itself, and use */? here for everything
for vol in ${lvmvol} ${raidvol} ; do
try_bootcfg "${vol}"
done
unset bootdev
for grub_disk in ${grub_scan_disk}; do
for i in 0 1 2 3 4 5 6 7 8; do
for part in 1 2 3 4 5 6 7 8 9 10 11 12; do
if [ "${grub_disk}" = "ahci" ]; then
bootdev="${bootdev} (ahci${i},${part})"
elif [ "${grub_disk}" = "ata" ]; then
bootdev="${bootdev} (ata${i},${part})"
elif [ "${grub_disk}" = "nvme" ]; then
# TODO: do we care about other namesapces
bootdev="${bootdev} (nvme${i}n1,${part})"
fi
done
done
done
set pager=0
echo -n "Attempting to unlock encrypted volumes"
for dev in ${bootdev} ${lvmvol} ${raidvol}; do
if cryptomount "${dev}" ; then break ; fi
done
set pager=1
echo
# after cryptomount, lvm volumes might be available
for vol in ${lvmvol}; do
try_bootcfg "${vol}"
done
search_bootcfg crypto
for vol in lvm/* ; do
try_bootcfg "${vol}"
done
true # Prevent pager requiring to accept each line instead of whole screen
}
menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on USB [s]' --hotkey='s' {
search_bootcfg usb
}
menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on AHCI [a]' --hotkey='a' {
search_bootcfg ahci
}
menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on ATA/IDE [d]' --hotkey='d' {
search_bootcfg ata
}
menuentry 'Search for GRUB/SYSLINUX/EXTLINUX/ISOLINUX on NVMe [e]' --hotkey='e' {
search_bootcfg nvme
}
if [ -f (cbfsdisk)/grub.cfg ]; then
menuentry 'Load configuration (grub.cfg) in CBFS [t]' --hotkey='t' {
set root='(cbfsdisk)'
if [ -f /grub.cfg ]; then
configfile /grub.cfg
fi
}
fi
if [ -f (cbfsdisk)/grubtest.cfg ]; then
menuentry 'Load test configuration (grubtest.cfg) in CBFS [t]' --hotkey='t' {
set root='(cbfsdisk)'
if [ -f /grubtest.cfg ]; then
configfile /grubtest.cfg
fi
}
fi
if [ -f (cbfsdisk)/seabios.elf ]; then
menuentry 'Load SeaBIOS (payload) [b]' --hotkey='b' {
set root='cbfsdisk'
chainloader /seabios.elf
}
fi
if [ -f (cbfsdisk)/img/grub2 ]; then
menuentry 'Return to SeaBIOS [b]' --hotkey='b' {
set root='cbfsdisk'
chainloader /fallback/payload
}
fi
menuentry 'Poweroff [p]' --hotkey='p' {
halt
}
menuentry 'Reboot [r]' --hotkey='r' {
reboot
}
if [ -f (cbfsdisk)/img/memtest ]; then
menuentry 'Load MemTest86+ [m]' --hotkey='m' {
set root='cbfsdisk'
chainloader /img/memtest
}
fi
submenu 'Other [z]' --hotkey='z' {
menuentry 'Enable default serial terminal [s]' --hotkey='s' {
serial
terminal_input --append serial
terminal_output --append serial
}
menuentry 'Disable default serial terminal' {
terminal_input --remove serial
terminal_output --remove serial
}
menuentry 'Enable gfxterm' {
terminal_output --append gfxterm
terminal_output --remove vga_text
}
menuentry 'Disable gfxterm [g]' --hotkey='g' {
terminal_output --remove gfxterm
terminal_output --append vga_text
}
menuentry 'Enable spkmodem [a]' --hotkey='a' {
terminal_output --append spkmodem
}
menuentry 'Disable spkmodem [z]' --hotkey='z' {
terminal_output --remove spkmodem
}
}