Skip to content
Snippets Groups Projects
Commit 35ad3506 authored by Zygmunt Krynicki's avatar Zygmunt Krynicki
Browse files

grub: replace stub boot script with sysota-compatible logic


This script implements proper A/B update with automatic rollback.
Refer to sysota.grub(7) manual page for details.

The script should become built-into grub EFI executable but that will be
pursued separately.

Signed-off-by: default avatarZygmunt Krynicki <zygmunt.krynicki@huawei.com>
parent 8e855dd4
No related branches found
No related tags found
No related merge requests found
This commit is part of merge request !50. Comments created here will be created in the context of that merge request.
......@@ -31,6 +31,7 @@ IMAGE_FEATURES:append = " read-only-rootfs"
IMAGE_FSTYPES:append = " squashfs"
WKS_FILE:raspberrypi4-64 ?= "x-raspberrypi.wks.in"
WKS_FILE:raspberrypi2 ?= "x-raspberrypi.wks.in"
WKS_FILE:seco-intel-b68 ?= "x-gpt-efi-disk.wks.in"
IMAGE_FSTYPES:append:seco-intel-b68 = " wic.bz2 wic.bmap"
......
......@@ -105,5 +105,6 @@ PREFERRED_VERSION_optee-os:qemu-generic-arm64 = "3.14.0"
ENABLE_UART ?= "1"
GPU_MEM:raspberrypi4-64 = "128"
GPU_MEM:raspberrypi2 = "32"
SPLASH = "psplash-oniro"
......@@ -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
# SPDX-FileCopyrightText: Huawei Inc.
#
# SPDX-License-Identifier: Apache-2.0
[system]
compatible=Raspberry Pi 2
# Use the custom boot loader backend. The handler program is set in the
# [handlers] section below. This loops in SystemOTA into the update process and
# delegates slot status and slot active flag responsibilities to it.
bootloader=custom
# Keep the RAUC status file in the system data partition, in a directory that
# is common across revisions of the operating system. In other words, this file
# is explicitly exempt from the A/B update process.
statusfile=/run/mount/sysdata/common/status.raucs
# Description of A/B slots used on the Raspberry Pi 2.
# Refer to meta-oniro-core/wic/x-raspberrypi.wks.in for details.
[slot.system.0]
device=/dev/mmcblk0p2
bootname=A
[slot.system.1]
device=/dev/mmcblk0p3
bootname=B
[keyring]
path=/etc/rauc/oniro-insecure-cert.pem
[handlers]
# Use SystemOTA for RAUC pre-install and post-install handlers. This is
# required for correct operation of the custom boot backend as well as for the
# operation of the state management handlers as provided by SystemOTA.
pre-install=/usr/libexec/sysota/rauc-pre-install-handler
post-install=/usr/libexec/sysota/rauc-post-install-handler
# Use SystemOTA to implement the custom RAUC boot backend. On platforms where
# RAUC manages the boot loader directly remove this line and set the correct
# bootloader= in the [system] section.
bootloader-custom-backend=/usr/libexec/sysota/rauc-custom-boot-handler
......@@ -9,6 +9,7 @@
# FIXME(zyga): The file defines RAUC compatible string which is technically
# something that SystemOTA should be responsible for (make/model and remodel
# operations). This should be addressed before re-model is supported.
FILESEXTRAPATHS:prepend:raspberrypi2 := "${THISDIR}/files/raspberrypi2:"
FILESEXTRAPATHS:prepend:raspberrypi4-64 := "${THISDIR}/files/raspberrypi4:"
# Make the RAUC package machine-specific. This lets us put the specific configuration
......
# SPDX-FileCopyrightText: Huawei Inc.
#
# SPDX-License-Identifier: Apache-2.0
[OTA]
BootLoaderType=pi-boot
BootPartitionMountDir=/run/mount/boot
[Device]
Maker=Oniro Project
Model=Raspberry Pi 2B
[Compatible]
Machine=raspberrypi2
[Quirks]
RebootDelay=180
......@@ -117,6 +117,7 @@ SYSTEMD_SERVICE:${PN} = "sysotad.service"
# Specific MACHINE configurations have sysotad.conf which provides the right
# settings, like the boot loader type.
FILESEXTRAPATHS:prepend:raspberrypi2 := "${THISDIR}/files/raspberrypi2:"
FILESEXTRAPATHS:prepend:raspberrypi4-64 := "${THISDIR}/files/raspberrypi4:"
# Make the SystemOTA package machine-specific. This lets us put the specific
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment