Support for conditionally mounting /vendor partition in Microdroid

first_stage_init will only mount the /vendor partition in Microdroid if
the androidboot.microdroid.mount_vendor=1 is provided in the kernel
cmdline.

Bug: 285855433
Test: atest MicrodroidTestApp
Change-Id: I5b840b5474bc52ec2696a0ba6ead0476acddfb1a
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index e1d383a..e871da2 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -257,8 +257,8 @@
     return BootMode::NORMAL_MODE;
 }
 
-static std::unique_ptr<FirstStageMount> CreateFirstStageMount() {
-    auto ret = FirstStageMount::Create();
+static std::unique_ptr<FirstStageMount> CreateFirstStageMount(const std::string& cmdline) {
+    auto ret = FirstStageMount::Create(cmdline);
     if (ret.ok()) {
         return std::move(*ret);
     } else {
@@ -396,7 +396,7 @@
     bool created_devices = false;
     if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
         if (!IsRecoveryMode()) {
-            fsm = CreateFirstStageMount();
+            fsm = CreateFirstStageMount(cmdline);
             if (fsm) {
                 created_devices = fsm->DoCreateDevices();
                 if (!created_devices) {
@@ -456,7 +456,7 @@
         LOG(INFO) << "First stage mount skipped (recovery mode)";
     } else {
         if (!fsm) {
-            fsm = CreateFirstStageMount();
+            fsm = CreateFirstStageMount(cmdline);
         }
         if (!fsm) {
             LOG(FATAL) << "FirstStageMount not available";
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 4961f6a..d0f68a8 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -138,7 +138,7 @@
     return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
 }
 
-static Result<Fstab> ReadFirstStageFstab() {
+static Result<Fstab> ReadFirstStageFstabAndroid() {
     Fstab fstab;
     if (!ReadFstabFromDt(&fstab)) {
         if (ReadDefaultFstab(&fstab)) {
@@ -154,6 +154,24 @@
     return fstab;
 }
 
+// Note: this is a temporary solution to avoid blocking devs that depend on /vendor partition in
+// Microdroid. For the proper solution the /vendor fstab should probably be defined in the DT.
+// TODO(b/285855430): refactor this
+// TODO(b/285855436): verify key microdroid-vendor was signed with.
+// TODO(b/285855436): should be mounted on top of dm-verity device.
+static Result<Fstab> ReadFirstStageFstabMicrodroid(const std::string& cmdline) {
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        return Error() << "failed to read fstab";
+    }
+    if (cmdline.find("androidboot.microdroid.mount_vendor=1") == std::string::npos) {
+        // We weren't asked to mount /vendor partition, filter it out from the fstab.
+        auto predicate = [](const auto& entry) { return entry.mount_point == "/vendor"; };
+        fstab.erase(std::remove_if(fstab.begin(), fstab.end(), predicate), fstab.end());
+    }
+    return fstab;
+}
+
 static bool GetRootEntry(FstabEntry* root_entry) {
     Fstab proc_mounts;
     if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
@@ -206,10 +224,13 @@
     return rollbacked;
 }
 
-// Class Definitions
-// -----------------
-Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create() {
-    auto fstab = ReadFirstStageFstab();
+Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create(const std::string& cmdline) {
+    Result<Fstab> fstab;
+    if (IsMicrodroid()) {
+        fstab = ReadFirstStageFstabMicrodroid(cmdline);
+    } else {
+        fstab = ReadFirstStageFstabAndroid();
+    }
     if (!fstab.ok()) {
         return fstab.error();
     }
@@ -784,7 +805,7 @@
         return;
     }
 
-    auto fstab = ReadFirstStageFstab();
+    auto fstab = ReadFirstStageFstabAndroid();
     if (!fstab.ok()) {
         LOG(ERROR) << fstab.error();
         return;
diff --git a/init/first_stage_mount.h b/init/first_stage_mount.h
index ab14966..54501d8 100644
--- a/init/first_stage_mount.h
+++ b/init/first_stage_mount.h
@@ -28,7 +28,7 @@
     virtual ~FirstStageMount() = default;
 
     // The factory method to create a FirstStageMount instance.
-    static Result<std::unique_ptr<FirstStageMount>> Create();
+    static Result<std::unique_ptr<FirstStageMount>> Create(const std::string& cmdline);
     // Creates devices and logical partitions from storage devices
     virtual bool DoCreateDevices() = 0;
     // Mounts fstab entries read from device tree.