Skip to content

Commit 2604ee6

Browse files
committed
OCPBUGS-54594: update bootloader on aarch64 systems
The aarch64 kernel changed the file format [1] [2] and older RHEL8 based systems (4.12 and 4.11) need to update the bootloader otherwise the system won't boot when they get upgraded to 4.19 based on RHEL 9.6. Let's add a systemd unit here that will update the bootloader. Also need to add code that will handle the RAID case because bootupd doesn't currently handle that case. It's worth mentioning that we did hit this upstream in Fedora CoreOS as well [3] and we took this fix from that [4] and another similar issue [5] as inspiration here. [1] https://bugzilla.redhat.com/show_bug.cgi?id=2162369 [2] https://issues.redhat.com/browse/RHEL-25537 [3] coreos/fedora-coreos-tracker#1441 [4] coreos/fedora-coreos-config#2308 [5] coreos/fedora-coreos-config#3042 Fixes: https://issues.redhat.com/browse/OCPBUGS-54594
1 parent 9d8f56f commit 2604ee6

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

overlay.d/05rhcos/usr/lib/systemd/system-preset/43-manifest-rhcos.preset

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,8 @@ enable nmstate.service
2222
# This unit is not activated on OSTree systems, but it still pulls in
2323
# `network-online.target`. Explicitly disable it.
2424
disable dnf-makecache.timer
25+
26+
# Enable the unit to update the bootloader on aarch64
27+
# machines so they can boot 9.6+ kernels.
28+
# https://issues.redhat.com/browse/OCPBUGS-54594
29+
enable coreos-bootupctl-update-aarch64.service
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[Unit]
2+
Description=Update Bootloader for aarch64 systems
3+
Documentation=https://issues.redhat.com/browse/OCPBUGS-54594
4+
ConditionArchitecture=arm64
5+
ConditionFirmware=uefi
6+
ConditionKernelCommandLine=!ignition.firstboot
7+
ConditionPathExists=!/run/ostree-live
8+
ConditionPathExists=!/var/lib/coreos-update-bootloader-aarch64-OCPBUGS-54594.stamp
9+
RequiresMountsFor=/boot
10+
11+
[Service]
12+
Type=oneshot
13+
# Only run once regardless of success or failure so we touch
14+
# our stamp file here.
15+
ExecStartPre=touch /var/lib/coreos-update-bootloader-aarch64-OCPBUGS-54594.stamp
16+
ExecStart=/usr/libexec/coreos-update-bootloader
17+
RemainAfterExit=yes
18+
MountFlags=slave
19+
20+
[Install]
21+
WantedBy=multi-user.target
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# https://issues.redhat.com/browse/OCPBUGS-54594
5+
6+
# This script updates the bootloader using bootupd when it's safe
7+
# and manually otherwise. Right now bootupd doesn't support RAID-1
8+
# setups and also not sure of the behavior if there are multiple
9+
# EFI-SYSTEM labeled filesystems attached.
10+
11+
# Function that actually does the manual copy
12+
copy_to_esp_device() {
13+
local device=$1
14+
mount $device /boot/efi
15+
echo "[Before Update: ${device}]"
16+
find /boot/efi/ -type f | xargs sha256sum
17+
cp -rp /usr/lib/bootupd/updates/EFI /boot/efi
18+
echo "[After Update: ${device}]"
19+
find /boot/efi/ -type f | xargs sha256sum
20+
umount /boot/efi
21+
}
22+
23+
# Handle RAID case manually since bootupd doesn't support it.
24+
# https://github.com/coreos/bootupd/issues/132
25+
update_raid_esp() {
26+
local boot_raid_device=$1
27+
local devices_json="${2}"
28+
echo "Detected boot raid device is: $boot_raid_device"
29+
# Next we'll find all the devices that are a part of that
30+
# RAID array that have an ESP (i.e. a vfat formatted partition
31+
# with a label that starts with "esp-", like "esp-1", "esp-2").
32+
# and we'll capture the device name for the partition.
33+
esp_partitions=$(
34+
jq --arg raid_device "${boot_raid_device}" -r '
35+
.blockdevices[]
36+
| select(.children[]?.children[]?.name == $raid_device)
37+
| .children[]
38+
| select(
39+
(.fstype == "vfat") and
40+
(.parttype == "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")
41+
)
42+
| .name' <<< "${devices_json}")
43+
for part in $esp_partitions; do
44+
echo "Found ESP replica in ${part}; updating"
45+
copy_to_esp_device $part
46+
done
47+
}
48+
49+
main() {
50+
# Grab the info about the systems disks from `lsblk`.
51+
block_devices_json=$(lsblk --paths --output-all --json)
52+
53+
# Find the device the boot filesystem is mounted from
54+
# (i.e. /dev/md126 or /dev/sda3).
55+
boot_fs_device=$(findmnt -n -o SOURCE --target /boot)
56+
57+
# Grab the JSON for the boot partition (i.e. /dev/sda3). This partition
58+
# could hold the filesystem directly or it could be a linux_raid_member
59+
# in which case the $boot_fs_device will be in the "children" of this
60+
# device. Choose .[0] here since we only need to look at the first device
61+
# (only RAID will have more than 1 anyway).
62+
boot_fs_partition_json=$(
63+
jq --arg boot_fs_device "${boot_fs_device}" -r '
64+
[
65+
.blockdevices[].children[]?
66+
| select(
67+
.name == $boot_fs_device or
68+
.children[]?.name == $boot_fs_device
69+
)
70+
] | .[0]' <<< "${block_devices_json}")
71+
if [ "${boot_fs_partition_json}" == "null" ]; then
72+
echo "Couldn't gather information about ${boot_fs_device}" >&2
73+
exit 1
74+
fi
75+
76+
# Grab the partition fstype (useful to determine if it's RAID)
77+
boot_fs_partition_fstype=$(jq -r '.fstype' <<< "${boot_fs_partition_json}")
78+
79+
# Determine how many devices are attached with filesystems
80+
# with the "EFI-SYSTEM" label.
81+
num_efi_system_devices=$(
82+
jq -r '
83+
[
84+
.blockdevices[]
85+
| select(.children[]?.label == "EFI-SYSTEM")
86+
] | length' <<< "${block_devices_json}")
87+
88+
# Now do the updates based on what situation we are in.
89+
if [ "${boot_fs_partition_fstype}" == 'linux_raid_member' ]; then
90+
# If it's RAID we'll update manually.
91+
update_raid_esp $boot_fs_device "${block_devices_json}"
92+
elif [ "${num_efi_system_devices}" -gt 1 ]; then
93+
echo "Detected more than one ESP device in a non-RAID setup"
94+
echo "Falling back to manual copy"
95+
# If there is more than one device with the EFI-SYSTEM label
96+
# then we'll need to manually do this to make sure we copy
97+
# to the right one.
98+
esp_device=$(
99+
jq --arg boot_fs_device "$boot_fs_device" -r '
100+
.blockdevices[]
101+
| select(.children[]?.name == $boot_fs_device)
102+
| .children[]
103+
| select(.label == "EFI-SYSTEM")
104+
| .name' <<< "${block_devices_json}")
105+
copy_to_esp_device $esp_device
106+
else
107+
echo "Found ESP; calling 'bootupctl update'"
108+
bootupctl update
109+
fi
110+
sync # write data out to backing devices
111+
}
112+
113+
main

0 commit comments

Comments
 (0)