eb4ac3c334
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>
442 lines
14 KiB
Bash
Executable file
442 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 $@
|