project-lakitu: add verified boot support to grub.cfg on ARM64
Align boot process with x86 systems:
- Use the same menu/choices structure in grub.cfg
- Extract dm verity information from a kernel partition
and pass it to kernel through cmdline
It's still not 100% match funcitonally: kernel B is not populated
because size does not allow doing it yet.
BUG=b/179918454
TEST=presubmit
RELEASE_NOTE=None
Change-Id: I334ab1a3d4bda43c22a7df7ffe4c9a1a75e02327
Reviewed-on: https://cos-review.googlesource.com/c/cos/overlays/board-overlays/+/13230
Tested-by: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
Reviewed-by: Robert Kolchmeyer <rkolchmeyer@google.com>
diff --git a/project-lakitu/scripts/bootloader_install.sh b/project-lakitu/scripts/bootloader_install.sh
index f460eea..fbc4b2d 100755
--- a/project-lakitu/scripts/bootloader_install.sh
+++ b/project-lakitu/scripts/bootloader_install.sh
@@ -31,6 +31,23 @@
ESP_DIR=""
LOOP_DEV=
+# Only let dm-verity block if rootfs verification is configured.
+# Also, set which device mapper correspondes to verity
+dev_wait=0
+ROOTDEV=/dev/dm-0
+if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
+ dev_wait=1
+ if [[ ${FLAGS_enable_bootcache} -eq ${FLAGS_TRUE} ]]; then
+ ROOTDEV=/dev/dm-1
+ fi
+fi
+
+part_index_to_uuid() {
+ local image="$1"
+ local index="$2"
+ sudo cgpt show -i "$index" -u "$image"
+}
+
cleanup() {
if [[ -d "${ESP_DIR}" ]]; then
if mountpoint -q "${ESP_DIR}"; then
@@ -242,20 +259,77 @@
install_efi_bootloaders_arm64_cleanup
trap - EXIT
- # TODO: Add kernel command line items for dm_verity (root file system
- # verification) and gptpriority (for A/B partition switching).
+ # Common verified boot command-line args
+ verity_common="dm_verity.error_behavior=${FLAGS_verity_error_behavior}"
+ verity_common="${verity_common} dm_verity.max_bios=${FLAGS_verity_max_ios}"
+ verity_common="${verity_common} dm_verity.dev_wait=${dev_wait}"
- cat <<EOF | sudo dd of="${ESP_DIR}/efi/boot/grub.cfg" 2>/dev/null
-set default=0
+ # Discover last known partition numbers.
+ part_num_kern_a="$(get_layout_part_number \
+ "${FLAGS_image_type}" KERN-A)"
+ part_num_kern_b="$(get_layout_part_number \
+ "${FLAGS_image_type}" KERN-B)"
+ part_num_root_a="$(get_layout_part_number \
+ "${FLAGS_image_type}" ROOT-A)"
+ part_num_root_b="$(get_layout_part_number \
+ "${FLAGS_image_type}" ROOT-B)"
+ root_a_uuid="PARTUUID=$(part_index_to_uuid "${LOOP_DEV}" ${part_num_root_a})"
+ root_b_uuid="PARTUUID=$(part_index_to_uuid "${LOOP_DEV}" ${part_num_root_b})"
+
+ dm_table=
+ # get cmdline from any kernel partition
+ kernel_cmdline=$(sudo dump_kernel_config "${LOOP_DEV}p${part_num_kern_a}")
+ if echo "$kernel_cmdline" | grep -q 'dm="'; then
+ dm_table=$(echo "$kernel_cmdline" | sed -s 's/.*dm="\([^"]*\)".*/\1/')
+ fi
+ old_root='PARTUUID=%U/PARTNROFF=1'
+ grub_dm_table_a=${dm_table//${old_root}/${root_a_uuid}}
+ grub_dm_table_b=${dm_table//${old_root}/${root_b_uuid}}
+
+ cat <<EOF | sudo dd of="${ESP_DIR}/efi/boot/grub.cfg"
+defaultA=0
+defaultB=1
+gptpriority \$grubdisk ${part_num_kern_a} prioA
+gptpriority \$grubdisk ${part_num_kern_b} prioB
+
+if [ \$prioA -lt \$prioB ]; then
+ set default=\$defaultB
+else
+ set default=\$defaultA
+fi
set timeout=2
-menuentry "image A" {
- linux /syslinux/vmlinuz.A ${common_args} i915.modeset=1 cros_efi \
- root=/dev/sda3
+# NOTE: These magic grub variables are a Chrome OS hack. They are not portable.
+
+menuentry "local image A" {
+ linux /syslinux/vmlinuz.A ${common_args} cros_efi \
+ root=${root_a_uuid}
+}
+
+menuentry "local image B" {
+ linux /syslinux/vmlinuz.B ${common_args} cros_efi \
+ root=${root_b_uuid}
+}
+
+menuentry "verified image A" {
+ linux /syslinux/vmlinuz.A ${common_args} ${verity_common} \
+ cros_efi root=${ROOTDEV} dm="${grub_dm_table_a}"
+}
+
+menuentry "verified image B" {
+ linux /syslinux/vmlinuz.B ${common_args} ${verity_common} \
+ cros_efi root=${ROOTDEV} dm="${grub_dm_table_b}"
}
EOF
+ if [[ ${FLAGS_enable_rootfs_verification} -eq ${FLAGS_TRUE} ]]; then
+ sudo sed -i \
+ -e '/^defaultA=/s:=.*:=2:' \
+ -e '/^defaultB=/s:=.*:=3:' \
+ "${ESP_DIR}/efi/boot/grub.cfg"
+ fi
+
info "Successfully installed arm64 EFI Shim and GRUB2"
info "Installing arm64 kernels"