cbmk/script/roms
Leah Rowe eb4ac3c334 make GRUB multi-tree and re-add xhci patches
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, but we still don't
need xHCI support in Canoeboot's GRUB because none of the
available coreboot targets have xHCI support. However, we
may want it in the future and it helps to keep Canoeboot
in sync with Libreboot (this patch is adapted from lbmk).

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.

There is another reason for merging this design change from
lbmk, and that reasoning also applies to lbmk. Specifically:

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 22:41:46 +01:00

443 lines
14 KiB
Bash
Executable file

#!/usr/bin/env sh
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2014-2016,2020-2021,2023-2024 Leah Rowe <leah@libreboot.org>
# Copyright (c) 2021-2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
# Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>
# Copyright (c) 2022-2023 Alper Nebi Yasak <alpernebiyasak@gmail.com>
# Copyright (c) 2023 Riku Viitanen <riku.viitanen@protonmail.com>
set -u -e
. "include/lib.sh"
seavgabiosrom="elf/seabios/default/libgfxinit/vgabios.bin"
grub_background="background1280x800.png"
cfgsdir="config/coreboot"
picosrc="src/pico-serprog"
picosdk="src/pico-sdk"
stm32src="src/stm32-vserprog"
# Disable all payloads by default.
# target.cfg files have to specifically enable [a] payload(s)
pv="payload_uboot payload_grub_withseabios payload_seabios payload_memtest t"
pv="$pv payload_seabios_withgrub payload_seabios_grubonly payload_grub mt86bin"
v="romdir cbrom initmode displaymode cbcfg targetdir tree keymaps release"
v="$v grub_timeout ubdir board grub_scan_disk uboot_config grubtree grubelf"
eval "$(setvars "n" $pv serprog)"
eval "$(setvars "" $v boards _displaymode _payload _keyboard all targets \
serprog_boards_dir _scandisk)"
main()
{
while [ $# -gt 0 ]; do
case "$1" in
list) x_ items config/coreboot; return 0 ;;
serprog) serprog="y"; shift 1; break ;;
-d) _displaymode="$2" ;;
-p) _payload="$2" ;;
-k) _keyboard="$2" ;;
-s) _scandisk="$2" ;;
*)
[ "$1" = "all" ] && all="y"
boards="$1 $boards"
shift && continue ;;
esac
shift 2
done
if [ "$serprog" = "y" ]; then
handle_serprog $@; return 0
else
[ "$all" != "y" ] || boards="$(items config/coreboot)" || \
$err "Cannot generate list of boards for building"
for x in $boards; do
[ -d "config/coreboot/$x/config" ] && \
handle_coreboot_target "$x"; continue
done
fi
x="directories"
[ "$xbmk_release" = "y" ] && x="archives"
[ -z "$targets" ] && $err "No ROM images were compiled"
printf "\nROM images available in these %s:\n" "$x"
eval "printf \"$targets\""
printf "^^ ROM images available in these %s.\n\n" "$x"
printf "DO NOT flash images from elf/ - please use bin/ instead.\n"
}
handle_serprog()
{
[ -z "${1+x}" ] && $err "bad command. Check $projectname docs."
[ "$1" != "rp2040" ] && [ "$1" != "stm32" ] && $err "bad command"
if [ "$1" = "rp2040" ]; then
serprog_boards_dir="$picosdk/src/boards/include/boards"
[ -d "$picosrc" ] || x_ ./update trees -f "pico-serprog"
elif [ "$1" = "stm32" ]; then
serprog_boards_dir="$stm32src/boards"
[ -d "$stm32src" ] || x_ ./update trees -f "stm32-vserprog"
fi
x_ mkdir -p "bin/serprog_$1"
if [ $# -gt 1 ] && [ "$2" = "list" ]; then
list_serprog_boards "$serprog_boards_dir"
return 0
elif [ $# -gt 1 ]; then
build_${1}_rom "$2"
else
list_serprog_boards "$serprog_boards_dir" | \
while read -r board; do
build_${1}_rom "$board"
done
fi
[ "$xbmk_release" = "y" ] && mkrom_tarball "bin/serprog_$1"; return 0
}
build_rp2040_rom()
{
board="$1"
printf "Building pico-serprog for %s\n" "$board"
x_ cmake -DPICO_BOARD="$board" -DPICO_SDK_PATH="$picosdk" \
-B "$picosrc/build" "$picosrc"
x_ cmake --build "$picosrc/build"
x_ mv "$picosrc/build/pico_serprog.uf2" \
"bin/serprog_rp2040/serprog_$board.uf2"
printf "output to bin/serprog_rp2040/serprog_%s.uf2\n" "$board"
}
build_stm32_rom()
{
board="$1"
printf "Building stm32-vserprog for %s\n" "$board"
x_ make -C "$stm32src" libopencm3-just-make BOARD=$board
x_ make -C "$stm32src" BOARD=$board
x_ mv "$stm32src/stm32-vserprog.hex" \
"bin/serprog_stm32/serprog_$board.hex"
printf "output to bin/serprog_stm32/serprog_%s.hex\n" "$board"
}
list_serprog_boards()
{
basename -a -s .h "$1/"*.h || $err "$1: can't list boards"
}
handle_coreboot_target()
{
eval "$(setvars "n" $pv) $(setvars "" $v)"
grub_background="background1280x800.png"
board="$1"
configure_target
[ "$board" = "$tree" ] && return 0
[ "$xbmk_release" = "y" ] && [ "$release" = "n" ] && return 0
build_payloads
build_target_mainboard
[ -d "bin/$board" ] || return 0
[ "$xbmk_release" = "y" ] || targets="* bin/$board\n$targets"
[ "$xbmk_release" = "y" ] && mkrom_tarball "bin/$board" && \
targets="* bin/${relname}_$board.tar.xz\n$targets"; return 0
}
configure_target()
{
targetdir="$cfgsdir/$board"
[ -f "$targetdir/target.cfg" ] || $err "$board: target.cfg missing"
# Override the above defaults using target.cfg
. "$targetdir/target.cfg"
[ -n "$_scandisk" ] && grub_scan_disk="$_scandisk"
[ -z "$grub_scan_disk" ] && grub_scan_disk="nvme ahci ata"
_ata=""
_ahci=""
_nvme=""
_grub_scan_disk=""
for _disk in $grub_scan_disk; do
[ "$_disk" != "nvme" ] && [ "$_disk" != "ahci" ] && \
[ "$_disk" != "ata" ] && _grub_scan_disk="nvme ahci ata" \
&& break
[ -n "$_ata" ] && [ "$_disk" = "ata" ] && continue
[ -n "$_ahci" ] && [ "$_disk" = "ahci" ] && continue
[ -n "$_nvme" ] && [ "$_disk" = "nvme" ] && continue
eval "_$_disk=\"$_disk\""
_grub_scan_disk="$_grub_scan_disk $_disk"
done
[ -z "$_grub_scan_disk" ] && _grub_scan_disk="nvme ahci ata"
grub_scan_disk="${_grub_scan_disk# }"
[ -n "$grubtree" ] || grubtree="default"
grubelf="elf/grub/$grubtree/payload/grub.elf"
[ -z "$tree" ] && $err "$board: tree not defined"
[ "$payload_memtest" != "y" ] && payload_memtest="n"
[ "$(uname -m)" = "x86_64" ] || payload_memtest="n"
[ "$payload_grub_withseabios" = "y" ] && payload_grub="y"
[ "$payload_grub_withseabios" = "y" ] && \
eval "$(setvars "y" payload_seabios payload_seabios_withgrub)"
[ "$payload_seabios_withgrub" = "y" ] && payload_seabios="y"
[ "$payload_seabios_grubonly" = "y" ] && payload_seabios="y"
[ "$payload_seabios_grubonly" = "y" ] && payload_seabios_withgrub="y"
# The reverse logic must not be applied. If SeaBIOS-with-GRUB works,
# that doesn't mean GRUB-with-SeaBIOS will, e.g. VGA ROM execution
[ "$payload_grub" != "y" ] && [ "$payload_seabios" != "y" ] && \
[ "$payload_uboot" != "y" ] && $err "'$board' defines no payload"
[ "$payload_uboot" != "n" ] && [ "$payload_uboot" != "y" ] && \
payload_uboot="n"
[ "$payload_uboot" = "y" ] && [ -z "$uboot_config" ] && \
uboot_config="default"
# Override all payload directives with cmdline args
[ -z "$_payload" ] && return 0
eval "$(setvars "n" payload_grub payload_memtest payload_seabios \
payload_seabios_withgrub payload_uboot payload_grub_withseabios \
payload_seabios_grubonly)"
eval "payload_$_payload=y"
}
build_payloads()
{
romdir="bin/$board"
cbdir="src/coreboot/$board"
[ "$board" = "$tree" ] || cbdir="src/coreboot/$tree"
cbfstool="cbutils/$tree/cbfstool"
cbrom="$cbdir/build/coreboot.rom"
[ -f "$cbfstool" ] || x_ ./update trees -b coreboot utils $tree
mt86bin="memtest86plus/build64/memtest.bin"
[ "$payload_memtest" != "y" ] || [ -f "src/$mt86bin" ] || \
x_ ./update trees -b memtest86plus
[ "$payload_seabios" = "y" ] && x_ ./update trees -b seabios
if [ "$payload_grub" = "y" ] || [ "$payload_seabios_withgrub" = "y" ] \
|| [ "$payload_seabios_grubonly" = "y" ]; then build_grub_payload
fi
[ "$payload_uboot" = "y" ] && build_uboot_payload; return 0
}
build_grub_payload()
{
for keymapfile in "$grubdata/keymap/"*.gkb; do
[ -f "$keymapfile" ] && keymaps="$keymaps $keymapfile"
done
[ -z "$_keyboard" ] || [ -f "$grubdata/keymap/$_keyboard.gkb" ] || \
$err "build_grub_payload: $_keyboard layout not defined"
[ -n "$_keyboard" ] && keymaps="$grubdata/keymap/$_keyboard.gkb"
[ -f "$grubelf" ] || x_ ./update trees -b grub $grubtree; return 0
}
build_uboot_payload()
{
x_ ./update trees -b u-boot $board
ubdir="elf/u-boot/$board/$uboot_config"
ubootelf="$ubdir/u-boot.elf"
[ ! -f "$ubootelf" ] && [ -f "$ubdir/u-boot" ] && \
ubootelf="$ubdir/u-boot"
[ -f "$ubootelf" ] || $err "$board: Can't find u-boot"; return 0
}
build_target_mainboard()
{
x_ rm -Rf "$romdir"
for x in "normal" "vgarom" "libgfxinit"; do
initmode="$x"
hmode="vesafb"
[ "$initmode" = "vgarom" ] || hmode="corebootfb"
modes="$hmode txtmode"
[ -z "$_displaymode" ] || modes="$_displaymode"
for y in $modes; do
displaymode="$y"
[ "$initmode" = "normal" ] && \
[ "$displaymode" != "txtmode" ] && continue
cbcfg="$targetdir/config/${initmode}_$displaymode"
[ "$initmode" = "normal" ] && cbcfg="${cbcfg%_*}"
build_roms "$cbcfg"; x_ rm -f "$cbrom"
done
done
}
build_roms()
{
cbcfg="$1"
e "$cbcfg" f not && return 0
x_ ./update trees -b coreboot $board
_cbrom="elf/coreboot_nopayload_DO_NOT_FLASH"
_cbrom="$_cbrom/$board/${initmode}_$displaymode"
[ "$initmode" = "normal" ] && _cbrom="${_cbrom%"_$displaymode"}"
_cbrom="$_cbrom/coreboot.rom"
cbrom="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
x_ cp "$_cbrom" "$cbrom"
[ "$payload_memtest" != "y" ] || x_ "$cbfstool" "$cbrom" add-payload \
-f "src/$mt86bin" -n img/memtest -c lzma
[ "$payload_seabios" = "y" ] && build_seabios_roms
[ "$payload_grub" != "y" ] || x_ build_grub_roms "$cbrom" "grub"
[ "$payload_uboot" = "y" ] || return 0
x_ cp "$_cbrom" "$cbrom"
build_uboot_roms
}
build_seabios_roms()
{
if [ "$payload_seabios_withgrub" = "y" ]; then
t="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
x_ cp "$cbrom" "$t"
x_ build_grub_roms "$t" "seabios_withgrub"
else
t="$(mkSeabiosRom "$cbrom" "fallback/payload")" || \
$err "build_seabios_roms: cannot build tmprom"
newrom="$romdir/seabios_${board}_${initmode}_$displaymode"
[ "$initmode" = "normal" ] && newrom="$romdir/seabios" \
&& newrom="${newrom}_${board}_$initmode"
x_ cprom "$t" "$newrom.rom"
fi
x_ rm -f "$t"
}
# Make separate ROM images with GRUB payload, for each supported keymap
build_grub_roms()
{
tmprom="$1"
payload1="$2" # allow values: grub, seabios, seabios_withgrub
grub_cbfs="fallback/payload"
if [ "$payload1" = "grub" ] && [ "$payload_grub_withseabios" = "y" ]
then
_tmpmvrom="$(mkSeabiosRom "$tmprom" "seabios.elf")" || \
$err "build_grub_roms 1 $board: can't build tmprom"
x_ mv "$_tmpmvrom" "$tmprom"
elif [ "$payload1" != "grub" ] && [ "$payload_seabios_withgrub" = "y" ]
then
grub_cbfs="img/grub2"
_tmpmvrom="$(mkSeabiosRom "$tmprom" fallback/payload)" || \
$err "build_grub_roms 2 $board: can't build tmprom"
x_ mv "$_tmpmvrom" "$tmprom"
fi
# we only need insert grub.elf once, for each coreboot config:
x_ "$cbfstool" "$tmprom" add-payload -f "$grubelf" \
-n "$grub_cbfs" -c lzma
# we only need insert background.png once, for each coreboot config:
if [ "$displaymode" = "vesafb" ] || \
[ "$displaymode" = "corebootfb" ]; then
backgroundfile="$grubdata/background/$grub_background"
"$cbfstool" "$tmprom" add -f "$backgroundfile" -n \
background.png -t raw || $err "!bg, $backgroundfile"
fi
tmpcfg="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
printf "set grub_scan_disk=\"%s\"\n" "$grub_scan_disk" > "$tmpcfg" || \
$err "set grub_scandisk, $grub_scan_disk, $tmpcfg"
x_ "$cbfstool" "$tmprom" add -f "$tmpcfg" -n scan.cfg -t raw
printf "set timeout=%s\n" "$grub_timeout" > "$tmpcfg" || \
$err "set timeout, $grub_timeout, $tmpcfg"
[ -z "$grub_timeout" ] || x_ "$cbfstool" "$tmprom" add \
-f "$tmpcfg" -n timeout.cfg -t raw
x_ rm -f "$tmpcfg"
for keymapfile in $keymaps; do
[ -f "$keymapfile" ] || continue
keymap="${keymapfile##*/}"
keymap="${keymap%.gkb}"
tmpgrubrom="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
x_ cp "$tmprom" "$tmpgrubrom"
x_ "$cbfstool" "$tmpgrubrom" add -f "$keymapfile" \
-n keymap.gkb -t raw
newrom="$romdir/${payload1}_${board}_${initmode}_"
newrom="$newrom${displaymode}_$keymap.rom"
[ "$initmode" = "normal" ] && newrom="$romdir/${payload1}_" \
&& newrom="$newrom${board}_${initmode}_$keymap.rom"
x_ cprom "$tmpgrubrom" "$newrom"
if [ "$payload_seabios_withgrub" = "y" ] && \
[ "$payload1" != "grub" ]; then
x_ "$cbfstool" "$tmpgrubrom" add \
-f "$grubdata/bootorder" -n bootorder -t raw
x_ cprom "$tmpgrubrom" "${newrom%.rom}_grubfirst.rom"
if [ "$payload_seabios_grubonly" = "y" ]; then
x_ "$cbfstool" "$tmpgrubrom" add-int -i 0 \
-n etc/show-boot-menu
x_ cprom "$tmpgrubrom" \
"${newrom%.rom}_grubonly.rom"
fi
fi
x_ rm -f "$tmpgrubrom"
done
}
# make a rom in /tmp/ and then print the path of that ROM
mkSeabiosRom() {
_cbrom="$1" # rom to insert seabios in. will not be touched
# (a tmpfile will be made instead)
_seabios_cbfs_path="$2" # e.g. fallback/payload
_seabioself="elf/seabios/default/$initmode/bios.bin.elf"
tmprom="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
x_ cp "$_cbrom" "$tmprom"
x_ "$cbfstool" "$tmprom" add-payload -f "$_seabioself" \
-n "$_seabios_cbfs_path" -c lzma
x_ "$cbfstool" "$tmprom" add-int -i 3000 -n etc/ps2-keyboard-spinup
z="2"; [ "$initmode" = "vgarom" ] && z="0"
x_ "$cbfstool" "$tmprom" add-int -i $z -n etc/pci-optionrom-exec
x_ "$cbfstool" "$tmprom" add-int -i 0 -n etc/optionroms-checksum
[ "$initmode" != "libgfxinit" ] || x_ "$cbfstool" "$tmprom" add -f \
"$seavgabiosrom" -n vgaroms/seavgabios.bin -t raw
printf "%s\n" "$tmprom"
}
build_uboot_roms()
{
tmprom="$(mkUbootRom "$cbrom" "fallback/payload")" || \
$err "build_uboot_roms $board: could not create tmprom"
newrom="$romdir/uboot_payload_${board}_${initmode}_$displaymode.rom"
x_ cprom "$tmprom" "$newrom"
x_ rm -f "$tmprom"
}
# make a rom in /tmp/ and then print the path of that ROM
mkUbootRom() {
_cbrom="$1"
_uboot_cbfs_path="$2"
_ubdir="elf/u-boot/$board/$uboot_config"
_ubootelf="$_ubdir/u-boot.elf"
[ -f "$_ubootelf" ] || _ubootelf="$_ubdir/u-boot"
[ -f "$_ubootelf" ] || $err "mkUbootRom: $board: cant find u-boot"
tmprom="$(mktemp -t coreboot_rom.XXXXXXXXXX)"
x_ cp "$_cbrom" "$tmprom"
x_ "$cbfstool" "$tmprom" add-payload -f "$_ubootelf" \
-n "$_uboot_cbfs_path" -c lzma
printf "%s\n" "$tmprom"
}
cprom()
{
printf "Creating target image: %s\n" "$2"
x_ mkdir -p "${2%/*}"
x_ cp "$1" "$2"
}
main $@