mirror of
https://github.com/flatcar/scripts.git
synced 2026-05-04 19:56:32 +02:00
grub: the one bootloader to rule them all
This uses our new GRUB2 features to handle GPT priority partition selection, terminal selection, OEM tweaks, etc. The old SYSLINUX and PV-GRUB configs are now unused except for maintaining compatibility with older installs. Of the old configs only the ones that coreos-postinst copies are needed. The new setup supports using GRUB2 under Xen, giving us automatic fallback support on all of our platforms for the very first time! Since grub.cfg is copied into place instead of generated, build_image's --boot_args option is no longer supported. It could be re-added later with some sed goo but for now it is easy enough to just edit grub.cfg.
This commit is contained in:
parent
52872481f5
commit
d443daa168
@ -22,8 +22,6 @@ DEFAULT_GROUP=developer
|
||||
# Developer-visible flags.
|
||||
DEFINE_string board "${DEFAULT_BOARD}" \
|
||||
"The board to build an image for."
|
||||
DEFINE_string boot_args "" \
|
||||
"Additional boot arguments to pass to the commandline"
|
||||
DEFINE_boolean enable_rootfs_verification ${FLAGS_TRUE} \
|
||||
"Default all bootloaders to use kernel-based root fs integrity checking."
|
||||
DEFINE_string output_root "${DEFAULT_BUILD_ROOT}/images" \
|
||||
|
||||
@ -242,11 +242,7 @@ finish_image() {
|
||||
if mountpoint -q "${root_fs_dir}"/boot; then
|
||||
install_grub=1
|
||||
${BUILD_LIBRARY_DIR}/configure_bootloaders.sh \
|
||||
--arch=${ARCH} \
|
||||
--disk_layout="${disk_layout}" \
|
||||
--boot_dir="${root_fs_dir}"/usr/boot \
|
||||
--esp_dir="${root_fs_dir}"/boot \
|
||||
--boot_args="${FLAGS_boot_args}"
|
||||
--boot_dir="${root_fs_dir}"/usr/boot
|
||||
fi
|
||||
|
||||
if [[ -n "${FLAGS_developer_data}" ]]; then
|
||||
@ -273,7 +269,7 @@ finish_image() {
|
||||
# This script must mount the ESP partition differently, so run it after unmount
|
||||
if [[ "${install_grub}" -eq 1 ]]; then
|
||||
local target
|
||||
for target in i386-pc x86_64-efi; do
|
||||
for target in i386-pc x86_64-efi x86_64-xen; do
|
||||
${BUILD_LIBRARY_DIR}/grub_install.sh \
|
||||
--target="${target}" --disk_image="${disk_img}"
|
||||
done
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Helper script to generate GRUB bootloader configuration files for
|
||||
# x86 platforms.
|
||||
# Helper script to generate bootloader configuration files for systems
|
||||
# that predate our new GRUB2 based gptprio bootloader.
|
||||
|
||||
SCRIPT_ROOT=$(readlink -f $(dirname "$0")/..)
|
||||
. "${SCRIPT_ROOT}/common.sh" || exit 1
|
||||
@ -14,16 +14,8 @@ SCRIPT_ROOT=$(readlink -f $(dirname "$0")/..)
|
||||
assert_inside_chroot
|
||||
|
||||
# Flags.
|
||||
DEFINE_string arch "x86" \
|
||||
"The boot architecture: arm or x86. (Default: x86)"
|
||||
DEFINE_string boot_dir "/tmp/boot" \
|
||||
"Path to boot directory in root filesystem (Default: /tmp/boot)"
|
||||
DEFINE_string esp_dir "" \
|
||||
"Path to ESP partition mount point (Default: none)"
|
||||
DEFINE_string boot_args "" \
|
||||
"Additional boot arguments to pass to the commandline (Default: '')"
|
||||
DEFINE_string disk_layout "base" \
|
||||
"The disk layout type to use for this image."
|
||||
|
||||
# Parse flags
|
||||
FLAGS "$@" || exit 1
|
||||
@ -34,17 +26,10 @@ switch_to_strict_mode
|
||||
common_args="console=tty0 ro noswap cros_legacy"
|
||||
common_args="${common_args} ${FLAGS_boot_args}"
|
||||
|
||||
# Get partition UUIDs from the json config
|
||||
get_uuid() {
|
||||
"${BUILD_LIBRARY_DIR}/disk_util" --disk_layout="${FLAGS_disk_layout}" \
|
||||
readuuid "$1"
|
||||
}
|
||||
|
||||
# Filesystem command line args.
|
||||
root_args="root=LABEL=ROOT rootflags=subvol=root"
|
||||
gptprio_args="${root_args} usr=gptprio:"
|
||||
slot_a_args="${root_args} usr=PARTUUID=$(get_uuid USR-A)"
|
||||
slot_b_args="${root_args} usr=PARTUUID=$(get_uuid USR-B)"
|
||||
slot_a_args="${root_args} usr=PARTLABEL=USR-A"
|
||||
slot_b_args="${root_args} usr=PARTLABEL=USR-B"
|
||||
|
||||
GRUB_DIR="${FLAGS_boot_dir}/grub"
|
||||
SYSLINUX_DIR="${FLAGS_boot_dir}/syslinux"
|
||||
@ -73,11 +58,6 @@ EOF
|
||||
default 1
|
||||
$(< "${GRUB_DIR}/menu.lst.A")
|
||||
EOF
|
||||
sudo cp "${GRUB_DIR}/menu.lst.A" "${GRUB_DIR}/menu.lst"
|
||||
|
||||
# menu.lst needs to go under boot/grub so pvgrub can find it reliably
|
||||
sudo mkdir -p "${FLAGS_esp_dir}/boot/grub"
|
||||
sudo cp "${GRUB_DIR}/menu.lst" "${FLAGS_esp_dir}/boot/grub"
|
||||
}
|
||||
|
||||
# Build configuration files for syslinux
|
||||
@ -87,45 +67,11 @@ configure_syslinux() {
|
||||
|
||||
# Add ttyS0 as a secondary console, useful for qemu -nographic
|
||||
# This leaves /dev/console mapped to tty0 (vga) which is reasonable default.
|
||||
if [[ ${common_args} == *console=ttyS* ]] ; then
|
||||
syslinux_args="${common_args}"
|
||||
else
|
||||
syslinux_args="console=ttyS0,115200n8 ${common_args}"
|
||||
fi
|
||||
syslinux_args="console=ttyS0,115200n8 ${common_args}"
|
||||
|
||||
sudo_clobber "${SYSLINUX_DIR}/syslinux.cfg" <<EOF
|
||||
PROMPT 1
|
||||
# display boot: prompt for a half second
|
||||
TIMEOUT 5
|
||||
# never sit at the prompt longer than a minute
|
||||
TOTALTIMEOUT 600
|
||||
|
||||
# controls which kernel is the default
|
||||
include /syslinux/default.cfg
|
||||
|
||||
include /syslinux/boot_kernel.cfg
|
||||
|
||||
# coreos.A
|
||||
include /syslinux/root.A.cfg
|
||||
|
||||
# coreos.B
|
||||
include /syslinux/root.B.cfg
|
||||
EOF
|
||||
|
||||
sudo_clobber "${SYSLINUX_DIR}/default.cfg" <<<"DEFAULT boot_kernel"
|
||||
sudo_clobber "${SYSLINUX_DIR}/default.cfg.A" <<<"DEFAULT coreos.A"
|
||||
sudo_clobber "${SYSLINUX_DIR}/default.cfg.B" <<<"DEFAULT coreos.B"
|
||||
|
||||
# Different files are used so that the updater can only touch the file it
|
||||
# needs to for a given change. This will minimize any potential accidental
|
||||
# updates issues, hopefully.
|
||||
sudo_clobber "${SYSLINUX_DIR}/boot_kernel.cfg" <<EOF
|
||||
label boot_kernel
|
||||
menu label boot_kernel
|
||||
kernel vmlinuz-boot_kernel
|
||||
append ${syslinux_args} ${gptprio_args}
|
||||
EOF
|
||||
|
||||
sudo_clobber "${SYSLINUX_DIR}/root.A.cfg" <<EOF
|
||||
label coreos.A
|
||||
menu label coreos.A
|
||||
@ -139,21 +85,7 @@ label coreos.B
|
||||
kernel vmlinuz.B
|
||||
append ${syslinux_args} ${slot_b_args}
|
||||
EOF
|
||||
|
||||
sudo cp -r "${SYSLINUX_DIR}/." "${FLAGS_esp_dir}/syslinux"
|
||||
|
||||
# Stage all kernels with the only one we built.
|
||||
for kernel in syslinux/{vmlinuz-boot_kernel,vmlinuz.A,vmlinuz.B}
|
||||
do
|
||||
sudo cp "${FLAGS_boot_dir}/vmlinuz" "${FLAGS_esp_dir}/${kernel}"
|
||||
done
|
||||
}
|
||||
|
||||
[[ -d "${FLAGS_esp_dir}" ]] || die_notrace "--esp_dir is required"
|
||||
|
||||
if [[ "${FLAGS_arch}" = "x86" || "${FLAGS_arch}" = "amd64" ]]; then
|
||||
configure_pvgrub
|
||||
configure_syslinux
|
||||
else
|
||||
error "No bootloader configuration for ${FLAGS_arch}"
|
||||
fi
|
||||
configure_pvgrub
|
||||
configure_syslinux
|
||||
|
||||
@ -1,13 +1,75 @@
|
||||
# Main GRUB config
|
||||
|
||||
# Load any and all video drivers.
|
||||
# Required under UEFI to boot Linux with a working console.
|
||||
insmod all_video
|
||||
|
||||
# Use both default text console and ttyS0
|
||||
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
|
||||
terminal_input console serial
|
||||
terminal_output console serial
|
||||
# Default menuentry id and boot timeout
|
||||
set default="coreos"
|
||||
set timeout=1
|
||||
|
||||
# Re-use the existing syslinux configuration
|
||||
echo "Loading SYSLINUX configuration..."
|
||||
insmod syslinuxcfg
|
||||
syslinux_source -s /syslinux/syslinux.cfg
|
||||
# Default kernel args for root filesystem and console.
|
||||
set linux_root="root=LABEL=ROOT"
|
||||
set linux_console=""
|
||||
|
||||
# Anything else the OEM adds should use this variable.
|
||||
set linux_append=""
|
||||
|
||||
|
||||
# Search for the OEM partition, load additional configuration if found.
|
||||
search --no-floppy --set oem --label OEM --hint "$root"
|
||||
if [ -n "$oem" -a -f "($oem)/grub.cfg" ]; then
|
||||
source "($oem)/grub.cfg"
|
||||
fi
|
||||
|
||||
# If no specific console has been set by the OEM then select based on
|
||||
# platform, most systems use vga text as primary and ttyS0 as secondary.
|
||||
if [ -z "$linux_console" ]; then
|
||||
if [ "$grub_platform" = pc ]; then
|
||||
set linux_console="console=ttyS0,115200n8 console=tty0"
|
||||
serial com0 --speed=115200 --word=8 --parity=no
|
||||
terminal_input console serial_com0
|
||||
terminal_output console serial_com0
|
||||
elif [ "$grub_platform" = efi ]; then
|
||||
set linux_console="console=ttyS0,115200n8 console=tty0"
|
||||
elif [ "$grub_platform" = xen ]; then
|
||||
set linux_console="console=hvc0"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Load a kernel and boot! $root must point at USR-A or USR-B
|
||||
function load_coreos {
|
||||
# UEFI uses linuxefi/initrdefi instead of linux/initrd
|
||||
if [ "$grub_platform" = efi ]; then
|
||||
set suf="efi"
|
||||
else
|
||||
set suf=""
|
||||
fi
|
||||
|
||||
echo "Loading ($root)/boot/vmlinuz"
|
||||
linux$suf /boot/vmlinuz $linux_console $linux_root "$@" $linux_append
|
||||
|
||||
if [ -f /boot/initrd ]; then
|
||||
echo "Loading ($root)/boot/initrd"
|
||||
initrd$suf /boot/initrd
|
||||
fi
|
||||
|
||||
echo "Booting CoreOS!"
|
||||
}
|
||||
|
||||
# TODO: systemd 217 added mount.usr=, once we update we should switch
|
||||
menuentry "CoreOS default" --id=coreos {
|
||||
gptprio.next -d root -u usr_uuid
|
||||
load_coreos usr=PARTUUID=$usr_uuid
|
||||
}
|
||||
|
||||
menuentry "CoreOS USR-A" --id=coreos-a {
|
||||
search --no-floppy --set root --part-label USR-A --hint "$root"
|
||||
load_coreos usr=PARTLABEL=USR-A
|
||||
}
|
||||
|
||||
menuentry "CoreOS USR-B" --id=coreos-b {
|
||||
search --no-floppy --set root --part-label USR-B --hint "$root"
|
||||
load_coreos usr=PARTLABEL=USR-B
|
||||
}
|
||||
|
||||
@ -29,11 +29,8 @@ switch_to_strict_mode
|
||||
# Our GRUB lives under coreos/grub so new pygrub versions cannot find grub.cfg
|
||||
GRUB_DIR="coreos/grub/${FLAGS_target}"
|
||||
|
||||
# Assumes the ESP is the first partition, GRUB cannot search for it by type.
|
||||
GRUB_PREFIX="(,gpt1)/coreos/grub"
|
||||
|
||||
# Modules required to find and read everything else from ESP
|
||||
CORE_MODULES=( fat part_gpt gzio )
|
||||
CORE_MODULES=( fat part_gpt search_fs_uuid gzio )
|
||||
|
||||
# Name of the core image, depends on target
|
||||
CORE_NAME=
|
||||
@ -46,6 +43,9 @@ case "${FLAGS_target}" in
|
||||
x86_64-efi)
|
||||
CORE_NAME="core.efi"
|
||||
;;
|
||||
x86_64-xen)
|
||||
CORE_NAME="core.elf"
|
||||
;;
|
||||
*)
|
||||
die_notrace "Unknown GRUB target ${FLAGS_target}"
|
||||
;;
|
||||
@ -57,14 +57,10 @@ esac
|
||||
# the kernel can automatically detach the loop devices on unmount. When
|
||||
# using a single loop device with partitions there is no such cleanup.
|
||||
# That's the story of why this script has all this goo for loop and mount.
|
||||
STAGE_DIR=
|
||||
ESP_DIR=
|
||||
LOOP_DEV=
|
||||
|
||||
cleanup() {
|
||||
if [[ -d "${STAGE_DIR}" ]]; then
|
||||
rm -rf "${STAGE_DIR}"
|
||||
fi
|
||||
if [[ -d "${ESP_DIR}" ]]; then
|
||||
if mountpoint -q "${ESP_DIR}"; then
|
||||
sudo umount "${ESP_DIR}"
|
||||
@ -77,24 +73,7 @@ cleanup() {
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
STAGE_DIR=$(mktemp --directory)
|
||||
mkdir -p "${STAGE_DIR}/${GRUB_DIR}"
|
||||
|
||||
info "Compressing modules in ${GRUB_DIR}"
|
||||
for file in "/usr/lib/grub/${FLAGS_target}"/*{.lst,.mod}; do
|
||||
out="${STAGE_DIR}/${GRUB_DIR}/${file##*/}"
|
||||
gzip --best --stdout "${file}" > "${out}"
|
||||
done
|
||||
|
||||
info "Generating ${GRUB_DIR}/${CORE_NAME}"
|
||||
grub-mkimage \
|
||||
--compression=auto \
|
||||
--format "${FLAGS_target}" \
|
||||
--prefix "${GRUB_PREFIX}" \
|
||||
--output "${STAGE_DIR}/${GRUB_DIR}/${CORE_NAME}" \
|
||||
"${CORE_MODULES[@]}"
|
||||
|
||||
info "Installing GRUB ${FLAGS_target} to ${FLAGS_disk_image##*/}"
|
||||
info "Installing GRUB ${FLAGS_target} in ${FLAGS_disk_image##*/}"
|
||||
LOOP_DEV=$(sudo losetup --find --show --partscan "${FLAGS_disk_image}")
|
||||
ESP_DIR=$(mktemp --directory)
|
||||
|
||||
@ -117,7 +96,33 @@ if [[ ! -b "${LOOP_DEV}p1" ]]; then
|
||||
fi
|
||||
|
||||
sudo mount -t vfat "${LOOP_DEV}p1" "${ESP_DIR}"
|
||||
sudo cp -r "${STAGE_DIR}/." "${ESP_DIR}/."
|
||||
sudo mkdir -p "${ESP_DIR}/${GRUB_DIR}"
|
||||
|
||||
info "Compressing modules in ${GRUB_DIR}"
|
||||
for file in "/usr/lib/grub/${FLAGS_target}"/*{.lst,.mod}; do
|
||||
out="${ESP_DIR}/${GRUB_DIR}/${file##*/}"
|
||||
gzip --best --stdout "${file}" | sudo_clobber "${out}"
|
||||
done
|
||||
|
||||
info "Generating ${GRUB_DIR}/load.cfg"
|
||||
# Include a small initial config in the core image to search for the ESP
|
||||
# by filesystem ID in case the platform doesn't provide the boot disk.
|
||||
# The existing $root value is given as a hint so it is searched first.
|
||||
ESP_FSID=$(sudo grub-probe -t fs_uuid -d "${LOOP_DEV}p1")
|
||||
sudo_clobber "${ESP_DIR}/${GRUB_DIR}/load.cfg" <<EOF
|
||||
search.fs_uuid ${ESP_FSID} root \$root
|
||||
set prefix=(\$root)/coreos/grub
|
||||
set
|
||||
EOF
|
||||
|
||||
info "Generating ${GRUB_DIR}/${CORE_NAME}"
|
||||
sudo grub-mkimage \
|
||||
--compression=auto \
|
||||
--format "${FLAGS_target}" \
|
||||
--prefix "(,gpt1)/coreos/grub" \
|
||||
--config "${ESP_DIR}/${GRUB_DIR}/load.cfg" \
|
||||
--output "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
|
||||
"${CORE_MODULES[@]}"
|
||||
|
||||
# This script will get called a few times, no need to re-copy grub.cfg
|
||||
if [[ ! -f "${ESP_DIR}/coreos/grub/grub.cfg" ]]; then
|
||||
@ -136,9 +141,17 @@ case "${FLAGS_target}" in
|
||||
x86_64-efi)
|
||||
info "Installing default x86_64 UEFI bootloader."
|
||||
sudo mkdir -p "${ESP_DIR}/EFI/boot"
|
||||
sudo cp "${STAGE_DIR}/${GRUB_DIR}/${CORE_NAME}" \
|
||||
sudo cp "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
|
||||
"${ESP_DIR}/EFI/boot/bootx64.efi"
|
||||
;;
|
||||
x86_64-xen)
|
||||
info "Installing default x86_64 Xen bootloader."
|
||||
sudo mkdir -p "${ESP_DIR}/xen" "${ESP_DIR}/boot/grub"
|
||||
sudo cp "${ESP_DIR}/${GRUB_DIR}/${CORE_NAME}" \
|
||||
"${ESP_DIR}/xen/pvboot-x86_64.elf"
|
||||
sudo cp "${BUILD_LIBRARY_DIR}/menu.lst" \
|
||||
"${ESP_DIR}/boot/grub/menu.lst"
|
||||
;;
|
||||
esac
|
||||
|
||||
cleanup
|
||||
|
||||
4
build_library/menu.lst
Normal file
4
build_library/menu.lst
Normal file
@ -0,0 +1,4 @@
|
||||
timeout 0
|
||||
title CoreOS GRUB2
|
||||
root (hd0,0)
|
||||
kernel /xen/pvboot-x86_64.elf
|
||||
Loading…
x
Reference in New Issue
Block a user