LAKITU:chromeos-installer: Add support for new dm-verity format.

Add patch in installer to support new dm verity format.

BUG=b/240174341
TEST=presubmit, validation, k8s, manual auto-update test.
RELEASE_NOTE=None

Change-Id: Icc551ef6610c784424ca01d98a44144989d27e80
Reviewed-on: https://cos-review.googlesource.com/c/third_party/overlays/chromiumos-overlay/+/36690
Tested-by: Cusky Presubmit Bot <presubmit@cos-infra-prod.iam.gserviceaccount.com>
Reviewed-by: Vaibhav Rustagi <vaibhavrustagi@google.com>
diff --git a/chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3565.ebuild b/chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3566.ebuild
similarity index 89%
rename from chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3565.ebuild
rename to chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3566.ebuild
index b017eee..312482c 100644
--- a/chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3565.ebuild
+++ b/chromeos-base/chromeos-installer/chromeos-installer-0.0.3-r3566.ebuild
@@ -1,8 +1,9 @@
 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Distributed under the terms of the GNU General Public License v2
 
-EAPI="5"
+EAPI="7"
 
+inherit cros-constants
 CROS_WORKON_COMMIT="f35f2919309cf11b0ddd9deb24a6b145d40d9254"
 CROS_WORKON_TREE=("a625767bb59509159091f2ab0b71f8b9b4b2e353" "ef9e5cc7e9b9b963d2308f285e853f72a569615d" "6fc4c6b35e5c71304e6fed40a7a24e6401d38df3" "e7dba8c91c1f3257c34d4a7ffff0ea2537aeb6bb")
 CROS_WORKON_PROJECT="chromiumos/platform2"
@@ -60,6 +61,16 @@
 	platform_test "run" "${OUT}/cros_installer_test"
 }
 
+src_prepare() {
+	# The workdir is platform2/nnapi - we need to pop up one level in the stack
+	# to apply our patches.
+	pushd .. || exit
+	eapply -p1 "${FILESDIR}/installer-support-new-dm-format.patch"
+	popd || exit
+
+	eapply_user
+}
+
 src_install() {
 	dobin "${OUT}"/cros_installer
 	if use mtd ; then
diff --git a/chromeos-base/chromeos-installer/files/installer-support-new-dm-format.patch b/chromeos-base/chromeos-installer/files/installer-support-new-dm-format.patch
new file mode 100644
index 0000000..d9155aa
--- /dev/null
+++ b/chromeos-base/chromeos-installer/files/installer-support-new-dm-format.patch
@@ -0,0 +1,127 @@
+From 5a583d1f3ff73c62a92cef6838412a212d8e94e2 Mon Sep 17 00:00:00 2001
+From: Meena Shanmugam <meenashanmugam@google.com>
+Date: Mon, 10 Oct 2022 00:10:18 +0000
+Subject: [PATCH] LAKITU:chromeos-installer: Update postinstall programs to
+ use new dm format.
+
+COS uses upstream dm format for the upcoming releases. Automatic updates
+update the bootloader configurations. Inorder to auto-update work with
+the upstream format, these auto-update postinstall programs need to be
+modified to support both new and old format. Once these changes are
+approved and merged in chromeOS upstream, this patch can be removed.
+
+Change-Id: Icb9af46e0b2bed4aa7c44f658d1b49252fc993bc
+---
+ installer/chromeos_legacy.cc   | 17 ++++++++++++++---
+ installer/chromeos_setimage.cc | 35 +++++++++++++++++++++++++++++-----
+ 2 files changed, 44 insertions(+), 8 deletions(-)
+
+diff --git a/installer/chromeos_legacy.cc b/installer/chromeos_legacy.cc
+index 10f14ab991..276f633961 100644
+--- a/installer/chromeos_legacy.cc
++++ b/installer/chromeos_legacy.cc
+@@ -38,6 +38,9 @@ bool UpdateLegacyKernel(const InstallConfig& install_config) {
+ string ExplandVerityArguments(const string& kernel_config,
+                               const string& root_uuid) {
+   string kernel_config_dm = ExtractKernelArg(kernel_config, "dm");
++  if ( kernel_config_dm.empty()) {
++    kernel_config_dm = ExtractKernelArg(kernel_config, "dm-mod.create");
++  }
+ 
+   // The verity config from the kernel contains short hand symbols for
+   // partition names that we have to expand to specific UUIDs.
+@@ -228,7 +231,8 @@ bool EfiGrubUpdate(const string& input,
+     base::ReplaceFirstSubstringAfterOffset(&(*line), 0, "linuxefi", "linux");
+ 
+     if (line->find(kernel_pattern) != string::npos) {
+-      if (ExtractKernelArg(*line, "dm").empty()) {
++      if (ExtractKernelArg(*line, "dm").empty() &&
++          ExtractKernelArg(*line, "dm-mod.create").empty()) {
+         // If it's an unverified boot line, just set the root partition to boot.
+         if (!SetKernelArg("root", "PARTUUID=" + root_uuid, &(*line))) {
+           LOG(ERROR) << "Unable to update unverified root flag in " << *line;
+@@ -236,8 +240,15 @@ bool EfiGrubUpdate(const string& input,
+         }
+       } else {
+         if (!SetKernelArg("dm", verity_args, &(*line))) {
+-          LOG(INFO) << "Unable to update verified dm flag.";
+-          return false;
++          if (!SetKernelArg("dm-mod.create", verity_args, &(*line))) {
++            LOG(INFO) << "Unable to update verified dm flag.";
++            return false;
++          }
++        }
++        // Update grub.cfg with the new dm format
++        std::size_t found = line->find("dm=");
++        if (found != std::string::npos) {
++          line->replace(found, 3, "dm-mod.create=");
+         }
+       }
+     }
+diff --git a/installer/chromeos_setimage.cc b/installer/chromeos_setimage.cc
+index b2772d3c25..0906a25d1c 100644
+--- a/installer/chromeos_setimage.cc
++++ b/installer/chromeos_setimage.cc
+@@ -77,7 +77,12 @@ bool SetImage(const InstallConfig& install_config) {
+   //
+ 
+   string kernel_config_root = ExtractKernelArg(kernel_config, "root");
++  int version = 0;
+   string dm_config = ExtractKernelArg(kernel_config, "dm");
++  if (dm_config.empty()) {
++    dm_config = ExtractKernelArg(kernel_config, "dm-mod.create");
++    version =1;
++  }
+   std::vector<string> dm_parts = base::SplitString(
+       dm_config, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+ 
+@@ -95,11 +100,24 @@ bool SetImage(const InstallConfig& install_config) {
+     return false;
+   }
+ 
++  string rootfs_sectors;
++  string verity_algorithm;
++  string expected_hash;
++  string salt;
+   // Extract specific verity arguments
+-  string rootfs_sectors = ExtractKernelArg(verity_args, "hashstart");
+-  string verity_algorithm = ExtractKernelArg(verity_args, "alg");
+-  string expected_hash = ExtractKernelArg(verity_args, "root_hexdigest");
+-  string salt = ExtractKernelArg(verity_args, "salt");
++  if (version == 1) {
++    std::vector<string> verity_parts = base::SplitString(
++        verity_args, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
++    rootfs_sectors = verity_parts[9];
++    verity_algorithm = verity_parts[10];
++    expected_hash = verity_parts[11];
++    salt = verity_parts[12];
++  } else {
++    rootfs_sectors = ExtractKernelArg(verity_args, "hashstart");
++    verity_algorithm = ExtractKernelArg(verity_args, "alg");
++    expected_hash = ExtractKernelArg(verity_args, "root_hexdigest");
++    salt = ExtractKernelArg(verity_args, "salt");
++  }
+ 
+   bool enable_rootfs_verification = IsReadonly(kernel_config_root);
+ 
+@@ -109,9 +127,16 @@ bool SetImage(const InstallConfig& install_config) {
+   LOG(INFO) << "Setting up verity.";
+   LoggingTimerStart();
+   verity::DmBht bht;
++  uint64_t sectors;
++  if (version == 1) {
++    sectors = (atoi(rootfs_sectors.c_str()) << 3) / 8;
++  } else {
++    sectors = (atoi(rootfs_sectors.c_str())) / 8;
++  }
++
+   int result = chromeos_verity(&bht, verity_algorithm,
+                                install_config.root.device(), getpagesize(),
+-                               (uint64_t)(atoi(rootfs_sectors.c_str()) / 8),
++                               sectors,
+                                salt, expected_hash, enable_rootfs_verification);
+   LoggingTimerFinish();
+ 
+-- 
+2.38.0.413.g74048e4d9e-goog
+