init: allow first stage mount to read an fstab

Now that we have a first stage ramdisk (or use recovery in its place),
it's possible to place a vendor specific fstab along with first stage
init, removing the need for device tree modifications to have an
fstab.

Bug: 117933812
Test: hikey boots with only an fstab in first stage ramdisk
Test: blueline mainline boots with a disabled DT fstab and an fstab in recovery
Change-Id: I4460b88851557a75ba06ff795cd842e7dfb6da46
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 750ed71..4e8ab0b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1032,8 +1032,9 @@
     for (i = 0; i < fstab->num_entries; i++) {
         /* Don't mount entries that are managed by vold or not for the mount mode*/
         if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
-             ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
-             ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) {
+            ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
+            ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i])) ||
+            fs_mgr_is_first_stage_mount(&fstab->recs[i])) {
             continue;
         }
 
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 31b0944..0fde22e 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -57,7 +57,7 @@
 
 struct flag_list {
     const char *name;
-    int flag;
+    unsigned int flag;
 };
 
 static struct flag_list mount_flags[] = {
@@ -102,6 +102,7 @@
         {"formattable", MF_FORMATTABLE},
         {"slotselect", MF_SLOTSELECT},
         {"nofail", MF_NOFAIL},
+        {"first_stage_mount", MF_FIRST_STAGE_MOUNT},
         {"latemount", MF_LATEMOUNT},
         {"reservedsize=", MF_RESERVEDSIZE},
         {"quota", MF_QUOTA},
@@ -998,6 +999,10 @@
     return fstab->fs_mgr_flags & MF_NOFAIL;
 }
 
+int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab) {
+    return fstab->fs_mgr_flags & MF_FIRST_STAGE_MOUNT;
+}
+
 int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
     return fstab->fs_mgr_flags & MF_LATEMOUNT;
 }
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 57e984d..5945236 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -74,7 +74,7 @@
     return false;
 }
 
-bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>&) {
+bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>&) {
     return false;
 }
 
@@ -82,7 +82,7 @@
     return {};
 }
 
-std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<const fstab_rec*>&) {
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>&) {
     return {};
 }
 
@@ -805,7 +805,7 @@
     return ret;
 }
 
-bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>& fsrecs) {
+bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>& fsrecs) {
     std::vector<fstab_rec> recs;
     for (const auto& rec : fsrecs) recs.push_back(*rec);
     fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
@@ -828,8 +828,7 @@
     return {};
 }
 
-std::vector<std::string> fs_mgr_overlayfs_required_devices(
-        const std::vector<const fstab_rec*>& fsrecs) {
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>& fsrecs) {
     std::vector<fstab_rec> recs;
     for (const auto& rec : fsrecs) recs.push_back(*rec);
     fstab fstab = {static_cast<int>(fsrecs.size()), &recs[0]};
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 711446c..11df255 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -118,6 +118,8 @@
 #define MF_LOGICAL        0x10000000
 #define MF_CHECKPOINT_BLK 0x20000000
 #define MF_CHECKPOINT_FS  0x40000000
+#define MF_FIRST_STAGE_MOUNT \
+                          0x80000000
 // clang-format on
 
 #define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index deaf4cb..b60f042 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -22,10 +22,9 @@
 #include <vector>
 
 bool fs_mgr_overlayfs_mount_all(fstab* fstab);
-bool fs_mgr_overlayfs_mount_all(const std::vector<const fstab_rec*>& fstab);
+bool fs_mgr_overlayfs_mount_all(const std::vector<fstab_rec*>& fstab);
 std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab);
-std::vector<std::string> fs_mgr_overlayfs_required_devices(
-        const std::vector<const fstab_rec*>& fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(const std::vector<fstab_rec*>& fstab);
 bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                             bool* change = nullptr);
 bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 80bdb87..4706028 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -84,6 +84,7 @@
 int fs_mgr_is_formattable(const struct fstab_rec* fstab);
 int fs_mgr_is_slotselect(const struct fstab_rec* fstab);
 int fs_mgr_is_nofail(const struct fstab_rec* fstab);
+int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab);
 int fs_mgr_is_latemount(const struct fstab_rec* fstab);
 int fs_mgr_is_quota(const struct fstab_rec* fstab);
 int fs_mgr_is_logical(const struct fstab_rec* fstab);
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index d35329e..432aa62 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -84,7 +84,7 @@
 
     bool need_dm_verity_;
 
-    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
+    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab_;
     std::string lp_metadata_partition_;
     std::vector<fstab_rec*> mount_fstab_recs_;
     std::set<std::string> required_devices_partition_names_;
@@ -132,15 +132,27 @@
 // Class Definitions
 // -----------------
 FirstStageMount::FirstStageMount()
-    : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
-    if (device_tree_fstab_) {
-        // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
-        // for easier manipulation later, e.g., range-base for loop.
-        for (int i = 0; i < device_tree_fstab_->num_entries; i++) {
-            mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]);
+    : need_dm_verity_(false), fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
+    // Stores fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
+    // for easier manipulation later, e.g., range-base for loop.
+    if (fstab_) {
+        // DT Fstab predated having a first_stage_mount fs_mgr flag, so if it exists, we use it.
+        for (int i = 0; i < fstab_->num_entries; i++) {
+            mount_fstab_recs_.push_back(&fstab_->recs[i]);
         }
     } else {
-        LOG(INFO) << "Failed to read fstab from device tree";
+        // Fstab found in first stage ramdisk, which should be a copy of the normal fstab.
+        // Mounts intended for first stage are explicitly flagged as such.
+        fstab_.reset(fs_mgr_read_fstab_default());
+        if (fstab_) {
+            for (int i = 0; i < fstab_->num_entries; i++) {
+                if (fs_mgr_is_first_stage_mount(&fstab_->recs[i])) {
+                    mount_fstab_recs_.push_back(&fstab_->recs[i]);
+                }
+            }
+        } else {
+            LOG(INFO) << "Failed to read fstab from device tree";
+        }
     }
 
     auto boot_devices = fs_mgr_get_boot_devices();
@@ -411,7 +423,7 @@
     }
 
     // heads up for instantiating required device(s) for overlayfs logic
-    const auto devices = fs_mgr_overlayfs_required_devices(device_tree_fstab_.get());
+    const auto devices = fs_mgr_overlayfs_required_devices(mount_fstab_recs_);
     for (auto const& device : devices) {
         if (android::base::StartsWith(device, "/dev/block/by-name/")) {
             required_devices_partition_names_.emplace(basename(device.c_str()));
@@ -423,7 +435,7 @@
         }
     }
 
-    fs_mgr_overlayfs_mount_all(device_tree_fstab_.get());
+    fs_mgr_overlayfs_mount_all(mount_fstab_recs_);
 
     return true;
 }