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"