diff --git a/meta-oniro-core/recipes-bsp/grub/files/grub.cfg b/meta-oniro-core/recipes-bsp/grub/files/grub.cfg index 3d290145cd8f149bffaf3acdd7777980ae85f7d2..6697aacdfbb164ab92fdfa27fa65fe187ec9d070 100644 --- a/meta-oniro-core/recipes-bsp/grub/files/grub.cfg +++ b/meta-oniro-core/recipes-bsp/grub/files/grub.cfg @@ -7,6 +7,86 @@ serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1 -# Boot the "A" slot all the time. This file is a stub. -linux "(hd0,gpt2)/boot/bzImage" root=/dev/sda2 rauc.slot=A $CMDLINE +set CMDLINE="console=ttyS0,115200 panic=60 quiet" + +# Find the boot partition. We need to know where to load from and save the +# environment to. The boot partition is saved into the ONIRO_GRUB_BOOT +# variable. +# +# TODO: switch to out-of-tree search by partition type uuid. +# +# XXX: the boot string is hard-coded but the .wks file allows customization via +# BOOT_PARTITION_LABEL, which is unsupported here. +if search --label --set ONIRO_BOOT_PART --no-floppy --hint-efi=hd0,gpt1 boot; then + echo "note: found ONIRO_BOOT_PART=$ONIRO_BOOT_PART" +else + echo "error: cannot find boot partition, halting" + halt +fi + +# Load a specific list of GRUB variables from the grubenv file. Ideally we +# would never have this and we would use EFI variables instead but this is not +# supported by RAUC without opting out of using GRUB itself. +load_env --skip-sig --file "(${ONIRO_BOOT_PART})/EFI/BOOT/grubenv" SYSOTA_BOOT_ACTIVE SYSOTA_BOOT_TRY SYSOTA_BOOT_TRIED +echo "note: loaded SYSOTA_BOOT_ACTIVE=$SYSOTA_BOOT_ACTIVE SYSOTA_BOOT_TRY=$SYSOTA_BOOT_TRY SYSOTA_BOOT_TRIED=$SYSOTA_BOOT_TRIED" + +# Recover active slot if the file is corrupted. +if [ -z "$SYSOTA_BOOT_ACTIVE" ]; then + echo "warning: SYSOTA_BOOT_ACTIVE is unset, attempting recovery" + if [ -e "(hd0,gpt2)/boot/bzImage" -a -e "(hd0,gpt3)/boot/bzImage" ]; then + # Both slots are available, pick the more recent slot. + # TODO: handle rollback prevention flags (how?) + if [ "(hd0,gpt2)/boot/bzImage" -nt "(hd0,gpt3)/boot/bzImage" ]; then + echo "note: recovered SYSOTA_BOOT_ACTIVE=A (slot A kernel is newer than slot B)" + set SYSOTA_BOOT_ACTIVE="A" + else + echo "note: recovered SYSOTA_BOOT_ACTIVE=B (slot B kernel is newer than slot A)" + set SYSOTA_BOOT_ACTIVE="B" + fi + elif [ -e "(hd0,gpt2)/boot/bzImage" ]; then + echo "note: recovered SYSOTA_BOOT_ACTIVE=A" + set SYSOTA_BOOT_ACTIVE="A" + elif [ -e "(hd0,gpt3)/boot/bzImage" ]; then + echo "note: recovered SYSOTA_BOOT_ACTIVE=B" + set SYSOTA_BOOT_ACTIVE="B" + else + echo "error: cannot recover GRUB environment block: both slots are corrupted, halting" + halt + fi + + echo "note: saving recovered GRUB environment block" + save_env --file "($ONIRO_BOOT_PART)/EFI/BOOT/grubenv" SYSOTA_BOOT_ACTIVE SYSOTA_BOOT_TRY SYSOTA_BOOT_TRIED +fi + +# Find the slot to boot from. +if [ -n "$SYSOTA_BOOT_TRY" ]; then + echo "note: performing one-time boot from slot $SYSOTA_BOOT_TRY" + set SLOT="$SYSOTA_BOOT_TRY" + set SYSOTA_BOOT_TRIED="$SYSOTA_BOOT_TRY" + unset SYSOTA_BOOT_TRY + + echo "note: saving modified GRUB environment block" + save_env --file "($ONIRO_BOOT_PART)/EFI/BOOT/grubenv" SYSOTA_BOOT_ACTIVE SYSOTA_BOOT_TRY SYSOTA_BOOT_TRIED +else + echo "note: performing normal boot from slot $SYSOTA_BOOT_ACTIVE" + set SLOT="$SYSOTA_BOOT_ACTIVE" +fi + +# Load the kernel from a fixed location of the slot selected for booting. +# The partition identifiers below refer to the fixed sys-a and sys-b +# partitions. +# +# For a description of how to package the kernel into the rootfs image, refer +# to the wiki page: +# https://gitlab.eclipse.org/eclipse/oniro-core/sysota/-/wikis/Boot%20Assets%20Specification#efigrub +if [ "$SLOT" == "A" ]; then + # TODO pass root partition by partuuid. + linux "(hd0,gpt2)/boot/bzImage" root=/dev/sda2 rauc.slot=A $CMDLINE +elif [ "$SLOT" == "B" ]; then + linux "(hd0,gpt3)/boot/bzImage" root=/dev/sda3 rauc.slot=B $CMDLINE +else + echo "error: cannot select slot to boot from, halting" + halt +fi + boot