Merge "first stage mount: removing the requirement of by-name prefix for AVB" am: cdad92fdad am: c82235ebbd
am: fec0b13902
Change-Id: I7dec7f517b5b1c601b4372a431789aba1375fbee
This commit is contained in:
commit
acef4a9a09
6 changed files with 188 additions and 133 deletions
|
|
@ -744,23 +744,6 @@ static int handle_encryptable(const struct fstab_rec* rec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string extract_by_name_prefix(struct fstab* fstab) {
|
|
||||||
// We assume that there's an entry for the /misc mount point in the
|
|
||||||
// fstab file and use that to get the device file by-name prefix.
|
|
||||||
// The device needs not to have an actual /misc partition.
|
|
||||||
// e.g.,
|
|
||||||
// - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
|
|
||||||
// - /dev/block/platform/soc.0/7824900.sdhci/by-name/
|
|
||||||
struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
|
|
||||||
if (fstab_entry == nullptr) {
|
|
||||||
LERROR << "/misc mount point not found in fstab";
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
std::string full_path(fstab_entry->blk_device);
|
|
||||||
size_t end_slash = full_path.find_last_of("/");
|
|
||||||
return full_path.substr(0, end_slash + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add ueventd notifiers if they don't exist.
|
// TODO: add ueventd notifiers if they don't exist.
|
||||||
// This is just doing a wait_for_device for maximum of 1s
|
// This is just doing a wait_for_device for maximum of 1s
|
||||||
int fs_mgr_test_access(const char *device) {
|
int fs_mgr_test_access(const char *device) {
|
||||||
|
|
@ -850,7 +833,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
|
||||||
|
|
||||||
if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
|
if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
|
||||||
if (!avb_handle) {
|
if (!avb_handle) {
|
||||||
avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
|
avb_handle = FsManagerAvbHandle::Open(*fstab);
|
||||||
if (!avb_handle) {
|
if (!avb_handle) {
|
||||||
LERROR << "Failed to open FsManagerAvbHandle";
|
LERROR << "Failed to open FsManagerAvbHandle";
|
||||||
return FS_MGR_MNTALL_FAIL;
|
return FS_MGR_MNTALL_FAIL;
|
||||||
|
|
@ -1060,7 +1043,7 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
|
||||||
|
|
||||||
if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
|
if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
|
||||||
if (!avb_handle) {
|
if (!avb_handle) {
|
||||||
avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
|
avb_handle = FsManagerAvbHandle::Open(*fstab);
|
||||||
if (!avb_handle) {
|
if (!avb_handle) {
|
||||||
LERROR << "Failed to open FsManagerAvbHandle";
|
LERROR << "Failed to open FsManagerAvbHandle";
|
||||||
return FS_MGR_DOMNT_FAILED;
|
return FS_MGR_DOMNT_FAILED;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fs_mgr_avb.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
@ -38,9 +40,8 @@
|
||||||
#include <utils/Compat.h>
|
#include <utils/Compat.h>
|
||||||
|
|
||||||
#include "fs_mgr.h"
|
#include "fs_mgr.h"
|
||||||
#include "fs_mgr_avb.h"
|
|
||||||
#include "fs_mgr_avb_ops.h"
|
|
||||||
#include "fs_mgr_priv.h"
|
#include "fs_mgr_priv.h"
|
||||||
|
#include "fs_mgr_priv_avb_ops.h"
|
||||||
#include "fs_mgr_priv_dm_ioctl.h"
|
#include "fs_mgr_priv_dm_ioctl.h"
|
||||||
#include "fs_mgr_priv_sha.h"
|
#include "fs_mgr_priv_sha.h"
|
||||||
|
|
||||||
|
|
@ -457,12 +458,21 @@ static bool get_hashtree_descriptor(const std::string& partition_name,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) {
|
FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) {
|
||||||
if (device_file_by_name_prefix.empty()) {
|
FsManagerAvbOps avb_ops(fstab);
|
||||||
LERROR << "Missing device file by-name prefix";
|
return DoOpen(&avb_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) {
|
||||||
|
if (by_name_symlink_map.empty()) {
|
||||||
|
LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
FsManagerAvbOps avb_ops(std::move(by_name_symlink_map));
|
||||||
|
return DoOpen(&avb_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
|
||||||
// Gets the expected hash value of vbmeta images from kernel cmdline.
|
// Gets the expected hash value of vbmeta images from kernel cmdline.
|
||||||
std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
|
std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
|
||||||
if (!avb_verifier) {
|
if (!avb_verifier) {
|
||||||
|
|
@ -476,8 +486,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsManagerAvbOps avb_ops(device_file_by_name_prefix);
|
AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(
|
||||||
AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify(
|
|
||||||
fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
|
fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
|
||||||
|
|
||||||
// Only allow two verify results:
|
// Only allow two verify results:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fs_mgr_priv_avb_ops.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -36,7 +38,6 @@
|
||||||
#include <utils/Compat.h>
|
#include <utils/Compat.h>
|
||||||
|
|
||||||
#include "fs_mgr.h"
|
#include "fs_mgr.h"
|
||||||
#include "fs_mgr_avb_ops.h"
|
|
||||||
#include "fs_mgr_priv.h"
|
#include "fs_mgr_priv.h"
|
||||||
|
|
||||||
static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
|
static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
|
||||||
|
|
@ -88,11 +89,7 @@ static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNU
|
||||||
return AVB_IO_RESULT_OK;
|
return AVB_IO_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix)
|
void FsManagerAvbOps::InitializeAvbOps() {
|
||||||
: device_file_by_name_prefix_(device_file_by_name_prefix) {
|
|
||||||
if (device_file_by_name_prefix_.back() != '/') {
|
|
||||||
device_file_by_name_prefix_ += '/';
|
|
||||||
}
|
|
||||||
// We only need to provide the implementation of read_from_partition()
|
// We only need to provide the implementation of read_from_partition()
|
||||||
// operation since that's all what is being used by the avb_slot_verify().
|
// operation since that's all what is being used by the avb_slot_verify().
|
||||||
// Other I/O operations are only required in bootloader but not in
|
// Other I/O operations are only required in bootloader but not in
|
||||||
|
|
@ -109,13 +106,31 @@ FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix)
|
||||||
avb_ops_.user_data = this;
|
avb_ops_.user_data = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map)
|
||||||
|
: by_name_symlink_map_(std::move(by_name_symlink_map)) {
|
||||||
|
InitializeAvbOps();
|
||||||
|
}
|
||||||
|
|
||||||
|
FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) {
|
||||||
|
// Constructs the by-name symlink map for each fstab record.
|
||||||
|
// /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a =>
|
||||||
|
// by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
|
||||||
|
for (int i = 0; i < fstab.num_entries; i++) {
|
||||||
|
std::string partition_name = basename(fstab.recs[i].blk_device);
|
||||||
|
by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device;
|
||||||
|
}
|
||||||
|
InitializeAvbOps();
|
||||||
|
}
|
||||||
|
|
||||||
AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
|
AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
|
||||||
size_t num_bytes, void* buffer,
|
size_t num_bytes, void* buffer,
|
||||||
size_t* out_num_read) {
|
size_t* out_num_read) {
|
||||||
// Appends |partition| to the device_file_by_name_prefix_, e.g.,
|
const auto iter = by_name_symlink_map_.find(partition);
|
||||||
// - /dev/block/platform/soc.0/7824900.sdhci/by-name/ ->
|
if (iter == by_name_symlink_map_.end()) {
|
||||||
// - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
|
LERROR << "by-name symlink not found for partition: '" << partition << "'";
|
||||||
std::string path = device_file_by_name_prefix_ + partition;
|
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
|
||||||
|
}
|
||||||
|
std::string path = iter->second;
|
||||||
|
|
||||||
// Ensures the device path (a symlink created by init) is ready to
|
// Ensures the device path (a symlink created by init) is ready to
|
||||||
// access. fs_mgr_test_access() will test a few iterations if the
|
// access. fs_mgr_test_access() will test a few iterations if the
|
||||||
|
|
@ -126,7 +141,7 @@ AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t of
|
||||||
|
|
||||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
|
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
PERROR << "Failed to open " << path.c_str();
|
PERROR << "Failed to open " << path;
|
||||||
return AVB_IO_RESULT_ERROR_IO;
|
return AVB_IO_RESULT_ERROR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,8 +165,7 @@ AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t of
|
||||||
// for EOF).
|
// for EOF).
|
||||||
ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
|
ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
|
||||||
if (num_read < 0 || (size_t)num_read != num_bytes) {
|
if (num_read < 0 || (size_t)num_read != num_bytes) {
|
||||||
PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset "
|
PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset;
|
||||||
<< offset;
|
|
||||||
return AVB_IO_RESULT_ERROR_IO;
|
return AVB_IO_RESULT_ERROR_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,11 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CORE_FS_MGR_AVB_OPS_H
|
#ifndef __CORE_FS_MGR_PRIV_AVB_OPS_H
|
||||||
#define __CORE_FS_MGR_AVB_OPS_H
|
#define __CORE_FS_MGR_PRIV_AVB_OPS_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <libavb/libavb.h>
|
#include <libavb/libavb.h>
|
||||||
|
|
||||||
|
|
@ -43,7 +46,8 @@
|
||||||
//
|
//
|
||||||
class FsManagerAvbOps {
|
class FsManagerAvbOps {
|
||||||
public:
|
public:
|
||||||
FsManagerAvbOps(const std::string& device_file_by_name_prefix);
|
FsManagerAvbOps(const fstab& fstab);
|
||||||
|
FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map);
|
||||||
|
|
||||||
static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
|
static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
|
||||||
return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
|
return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
|
||||||
|
|
@ -56,7 +60,9 @@ class FsManagerAvbOps {
|
||||||
AvbSlotVerifyData** out_data);
|
AvbSlotVerifyData** out_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void InitializeAvbOps();
|
||||||
|
|
||||||
AvbOps avb_ops_;
|
AvbOps avb_ops_;
|
||||||
std::string device_file_by_name_prefix_;
|
std::map<std::string, std::string> by_name_symlink_map_;
|
||||||
};
|
};
|
||||||
#endif /* __CORE_FS_MGR_AVB_OPS_H */
|
#endif /* __CORE_FS_MGR_PRIV_AVB_OPS_H */
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef __CORE_FS_MGR_AVB_H
|
#ifndef __CORE_FS_MGR_AVB_H
|
||||||
#define __CORE_FS_MGR_AVB_H
|
#define __CORE_FS_MGR_AVB_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -31,9 +32,13 @@ enum FsManagerAvbHandleStatus {
|
||||||
kFsManagerAvbHandleErrorVerification = 2,
|
kFsManagerAvbHandleErrorVerification = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FsManagerAvbOps;
|
||||||
|
|
||||||
class FsManagerAvbHandle;
|
class FsManagerAvbHandle;
|
||||||
using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
|
using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
|
||||||
|
|
||||||
|
using ByNameSymlinkMap = std::map<std::string, std::string>;
|
||||||
|
|
||||||
// Provides a factory method to return a unique_ptr pointing to itself and the
|
// Provides a factory method to return a unique_ptr pointing to itself and the
|
||||||
// SetUpAvb() function to extract dm-verity parameters from AVB metadata to
|
// SetUpAvb() function to extract dm-verity parameters from AVB metadata to
|
||||||
// load verity table into kernel through ioctl.
|
// load verity table into kernel through ioctl.
|
||||||
|
|
@ -49,6 +54,13 @@ class FsManagerAvbHandle {
|
||||||
// A typical usage will be:
|
// A typical usage will be:
|
||||||
// - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
|
// - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
|
||||||
//
|
//
|
||||||
|
// There are two overloaded Open() functions with a single parameter.
|
||||||
|
// The argument can be a ByNameSymlinkMap describing the mapping from partition
|
||||||
|
// name to by-name symlink, or a fstab file to which the ByNameSymlinkMap is
|
||||||
|
// constructed from. e.g.,
|
||||||
|
// - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a ->
|
||||||
|
// - ByNameSymlinkMap["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
|
||||||
|
//
|
||||||
// Possible return values:
|
// Possible return values:
|
||||||
// - nullptr: any error when reading and verifying the metadata,
|
// - nullptr: any error when reading and verifying the metadata,
|
||||||
// e.g., I/O error, digest value mismatch, size mismatch, etc.
|
// e.g., I/O error, digest value mismatch, size mismatch, etc.
|
||||||
|
|
@ -61,7 +73,8 @@ class FsManagerAvbHandle {
|
||||||
// - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
|
// - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
|
||||||
// is verified and can be trusted.
|
// is verified and can be trusted.
|
||||||
//
|
//
|
||||||
static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix);
|
static FsManagerAvbUniquePtr Open(const fstab& fstab);
|
||||||
|
static FsManagerAvbUniquePtr Open(ByNameSymlinkMap&& by_name_symlink_map);
|
||||||
|
|
||||||
// Sets up dm-verity on the given fstab entry.
|
// Sets up dm-verity on the given fstab entry.
|
||||||
// The 'wait_for_verity_dev' parameter makes this function wait for the
|
// The 'wait_for_verity_dev' parameter makes this function wait for the
|
||||||
|
|
@ -88,10 +101,10 @@ class FsManagerAvbHandle {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
|
||||||
FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
|
||||||
|
static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops);
|
||||||
|
|
||||||
AvbSlotVerifyData* avb_slot_data_;
|
AvbSlotVerifyData* avb_slot_data_;
|
||||||
FsManagerAvbHandleStatus status_;
|
FsManagerAvbHandleStatus status_;
|
||||||
std::string avb_version_;
|
std::string avb_version_;
|
||||||
|
|
|
||||||
|
|
@ -47,18 +47,22 @@ class FirstStageMount {
|
||||||
bool InitDevices();
|
bool InitDevices();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitRequiredDevices(std::set<std::string>* devices_partition_names);
|
void InitRequiredDevices();
|
||||||
void InitVerityDevice(const std::string& verity_device);
|
void InitVerityDevice(const std::string& verity_device);
|
||||||
bool MountPartitions();
|
bool MountPartitions();
|
||||||
|
|
||||||
virtual bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
|
virtual coldboot_action_t ColdbootCallback(uevent* uevent);
|
||||||
bool* out_need_dm_verity) = 0;
|
|
||||||
|
// Pure virtual functions.
|
||||||
|
virtual bool GetRequiredDevices() = 0;
|
||||||
virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
|
virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
|
||||||
|
|
||||||
|
bool need_dm_verity_;
|
||||||
// Device tree fstab entries.
|
// Device tree fstab entries.
|
||||||
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
|
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
|
||||||
// Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
|
// Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
|
||||||
std::vector<fstab_rec*> mount_fstab_recs_;
|
std::vector<fstab_rec*> mount_fstab_recs_;
|
||||||
|
std::set<std::string> required_devices_partition_names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FirstStageMountVBootV1 : public FirstStageMount {
|
class FirstStageMountVBootV1 : public FirstStageMount {
|
||||||
|
|
@ -67,27 +71,26 @@ class FirstStageMountVBootV1 : public FirstStageMount {
|
||||||
~FirstStageMountVBootV1() override = default;
|
~FirstStageMountVBootV1() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
|
bool GetRequiredDevices() override;
|
||||||
bool* out_need_dm_verity) override;
|
|
||||||
bool SetUpDmVerity(fstab_rec* fstab_rec) override;
|
bool SetUpDmVerity(fstab_rec* fstab_rec) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FirstStageMountVBootV2 : public FirstStageMount {
|
class FirstStageMountVBootV2 : public FirstStageMount {
|
||||||
public:
|
public:
|
||||||
|
friend void SetInitAvbVersionInRecovery();
|
||||||
|
|
||||||
FirstStageMountVBootV2();
|
FirstStageMountVBootV2();
|
||||||
~FirstStageMountVBootV2() override = default;
|
~FirstStageMountVBootV2() override = default;
|
||||||
|
|
||||||
const std::string& by_name_prefix() const { return device_tree_by_name_prefix_; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
|
coldboot_action_t ColdbootCallback(uevent* uevent) override;
|
||||||
bool* out_need_dm_verity) override;
|
bool GetRequiredDevices() override;
|
||||||
bool SetUpDmVerity(fstab_rec* fstab_rec) override;
|
bool SetUpDmVerity(fstab_rec* fstab_rec) override;
|
||||||
bool InitAvbHandle();
|
bool InitAvbHandle();
|
||||||
|
|
||||||
std::string device_tree_vbmeta_parts_;
|
std::string device_tree_vbmeta_parts_;
|
||||||
std::string device_tree_by_name_prefix_;
|
|
||||||
FsManagerAvbUniquePtr avb_handle_;
|
FsManagerAvbUniquePtr avb_handle_;
|
||||||
|
ByNameSymlinkMap by_name_symlink_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static Functions
|
// Static Functions
|
||||||
|
|
@ -102,7 +105,8 @@ static bool inline IsRecoveryMode() {
|
||||||
|
|
||||||
// Class Definitions
|
// Class Definitions
|
||||||
// -----------------
|
// -----------------
|
||||||
FirstStageMount::FirstStageMount() : device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
|
FirstStageMount::FirstStageMount()
|
||||||
|
: need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
|
||||||
if (!device_tree_fstab_) {
|
if (!device_tree_fstab_) {
|
||||||
LOG(ERROR) << "Failed to read fstab from device tree";
|
LOG(ERROR) << "Failed to read fstab from device tree";
|
||||||
return;
|
return;
|
||||||
|
|
@ -136,13 +140,30 @@ bool FirstStageMount::DoFirstStageMount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirstStageMount::InitDevices() {
|
bool FirstStageMount::InitDevices() {
|
||||||
bool need_dm_verity;
|
if (!GetRequiredDevices()) return false;
|
||||||
std::set<std::string> devices_partition_names;
|
|
||||||
|
|
||||||
// The partition name in devices_partition_names MUST have A/B suffix when A/B is used.
|
InitRequiredDevices();
|
||||||
if (!GetRequiredDevices(&devices_partition_names, &need_dm_verity)) return false;
|
|
||||||
|
|
||||||
if (need_dm_verity) {
|
// InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
|
||||||
|
// So if it isn't empty here, it means some partitions are not found.
|
||||||
|
if (!required_devices_partition_names_.empty()) {
|
||||||
|
LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
|
||||||
|
<< android::base::Join(required_devices_partition_names_, ", ");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates devices with uevent->partition_name matching one in the member variable
|
||||||
|
// required_devices_partition_names_. Found partitions will then be removed from it
|
||||||
|
// for the subsequent member function to check which devices are NOT created.
|
||||||
|
void FirstStageMount::InitRequiredDevices() {
|
||||||
|
if (required_devices_partition_names_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (need_dm_verity_) {
|
||||||
const std::string dm_path = "/devices/virtual/misc/device-mapper";
|
const std::string dm_path = "/devices/virtual/misc/device-mapper";
|
||||||
device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
|
device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
|
||||||
if (uevent->path == dm_path) return COLDBOOT_STOP;
|
if (uevent->path == dm_path) return COLDBOOT_STOP;
|
||||||
|
|
@ -150,58 +171,40 @@ bool FirstStageMount::InitDevices() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = false;
|
device_init(nullptr,
|
||||||
InitRequiredDevices(&devices_partition_names);
|
[this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
|
||||||
|
|
||||||
// InitRequiredDevices() will remove found partitions from devices_partition_names.
|
|
||||||
// So if it isn't empty here, it means some partitions are not found.
|
|
||||||
if (!devices_partition_names.empty()) {
|
|
||||||
LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
|
|
||||||
<< android::base::Join(devices_partition_names, ", ");
|
|
||||||
} else {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
device_close();
|
device_close();
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates devices with uevent->partition_name matching one in the in/out
|
coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
|
||||||
// devices_partition_names. Found partitions will then be removed from the
|
// We need platform devices to create symlinks.
|
||||||
// devices_partition_names for the caller to check which devices are NOT created.
|
if (uevent->subsystem == "platform") {
|
||||||
void FirstStageMount::InitRequiredDevices(std::set<std::string>* devices_partition_names) {
|
return COLDBOOT_CREATE;
|
||||||
if (devices_partition_names->empty()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t {
|
|
||||||
// We need platform devices to create symlinks.
|
|
||||||
if (uevent->subsystem == "platform") {
|
|
||||||
return COLDBOOT_CREATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignores everything that is not a block device.
|
// Ignores everything that is not a block device.
|
||||||
if (uevent->subsystem != "block") {
|
if (uevent->subsystem != "block") {
|
||||||
return COLDBOOT_CONTINUE;
|
return COLDBOOT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uevent->partition_name.empty()) {
|
if (!uevent->partition_name.empty()) {
|
||||||
// Matches partition name to create device nodes.
|
// Matches partition name to create device nodes.
|
||||||
// Both devices_partition_names and uevent->partition_name have A/B
|
// Both required_devices_partition_names_ and uevent->partition_name have A/B
|
||||||
// suffix when A/B is used.
|
// suffix when A/B is used.
|
||||||
auto iter = devices_partition_names->find(uevent->partition_name);
|
auto iter = required_devices_partition_names_.find(uevent->partition_name);
|
||||||
if (iter != devices_partition_names->end()) {
|
if (iter != required_devices_partition_names_.end()) {
|
||||||
LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
|
LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
|
||||||
devices_partition_names->erase(iter);
|
required_devices_partition_names_.erase(iter);
|
||||||
if (devices_partition_names->empty()) {
|
if (required_devices_partition_names_.empty()) {
|
||||||
return COLDBOOT_STOP; // Found all partitions, stop coldboot.
|
return COLDBOOT_STOP; // Found all partitions, stop coldboot.
|
||||||
} else {
|
} else {
|
||||||
return COLDBOOT_CREATE; // Creates this device and continue to find others.
|
return COLDBOOT_CREATE; // Creates this device and continue to find others.
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not found a partition or find an unneeded partition, continue to find others.
|
}
|
||||||
return COLDBOOT_CONTINUE;
|
// Not found a partition or find an unneeded partition, continue to find others.
|
||||||
});
|
return COLDBOOT_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
|
// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
|
||||||
|
|
@ -233,10 +236,9 @@ bool FirstStageMount::MountPartitions() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
|
bool FirstStageMountVBootV1::GetRequiredDevices() {
|
||||||
bool* out_need_dm_verity) {
|
|
||||||
std::string verity_loc_device;
|
std::string verity_loc_device;
|
||||||
*out_need_dm_verity = false;
|
need_dm_verity_ = false;
|
||||||
|
|
||||||
for (auto fstab_rec : mount_fstab_recs_) {
|
for (auto fstab_rec : mount_fstab_recs_) {
|
||||||
// Don't allow verifyatboot in the first stage.
|
// Don't allow verifyatboot in the first stage.
|
||||||
|
|
@ -246,7 +248,7 @@ bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devic
|
||||||
}
|
}
|
||||||
// Checks for verified partitions.
|
// Checks for verified partitions.
|
||||||
if (fs_mgr_is_verified(fstab_rec)) {
|
if (fs_mgr_is_verified(fstab_rec)) {
|
||||||
*out_need_dm_verity = true;
|
need_dm_verity_ = true;
|
||||||
}
|
}
|
||||||
// Checks if verity metadata is on a separate partition. Note that it is
|
// Checks if verity metadata is on a separate partition. Note that it is
|
||||||
// not partition specific, so there must be only one additional partition
|
// not partition specific, so there must be only one additional partition
|
||||||
|
|
@ -265,11 +267,11 @@ bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devic
|
||||||
// Includes the partition names of fstab records and verity_loc_device (if any).
|
// Includes the partition names of fstab records and verity_loc_device (if any).
|
||||||
// Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
|
// Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
|
||||||
for (auto fstab_rec : mount_fstab_recs_) {
|
for (auto fstab_rec : mount_fstab_recs_) {
|
||||||
out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
|
required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!verity_loc_device.empty()) {
|
if (!verity_loc_device.empty()) {
|
||||||
out_devices_partition_names->emplace(basename(verity_loc_device.c_str()));
|
required_devices_partition_names_.emplace(basename(verity_loc_device.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -292,15 +294,13 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstStageMountVBootV2 constructor.
|
// FirstStageMountVBootV2 constructor.
|
||||||
// Gets the vbmeta configurations from device tree.
|
// Gets the vbmeta partitions from device tree.
|
||||||
// Specifically, the 'parts' and 'by_name_prefix' below.
|
|
||||||
// /{
|
// /{
|
||||||
// firmware {
|
// firmware {
|
||||||
// android {
|
// android {
|
||||||
// vbmeta {
|
// vbmeta {
|
||||||
// compatible = "android,vbmeta";
|
// compatible = "android,vbmeta";
|
||||||
// parts = "vbmeta,boot,system,vendor"
|
// parts = "vbmeta,boot,system,vendor"
|
||||||
// by_name_prefix = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
|
|
||||||
// };
|
// };
|
||||||
// };
|
// };
|
||||||
// };
|
// };
|
||||||
|
|
@ -310,31 +310,24 @@ FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) {
|
||||||
PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
|
PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: removes by_name_prefix to allow partitions on different block devices.
|
|
||||||
if (!read_android_dt_file("vbmeta/by_name_prefix", &device_tree_by_name_prefix_)) {
|
|
||||||
PLOG(ERROR) << "Failed to read vbmeta/by_name_prefix from dt";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirstStageMountVBootV2::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
|
bool FirstStageMountVBootV2::GetRequiredDevices() {
|
||||||
bool* out_need_dm_verity) {
|
need_dm_verity_ = false;
|
||||||
*out_need_dm_verity = false;
|
|
||||||
|
|
||||||
// fstab_rec->blk_device has A/B suffix.
|
// fstab_rec->blk_device has A/B suffix.
|
||||||
for (auto fstab_rec : mount_fstab_recs_) {
|
for (auto fstab_rec : mount_fstab_recs_) {
|
||||||
if (fs_mgr_is_avb(fstab_rec)) {
|
if (fs_mgr_is_avb(fstab_rec)) {
|
||||||
*out_need_dm_verity = true;
|
need_dm_verity_ = true;
|
||||||
}
|
}
|
||||||
out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
|
required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
|
||||||
}
|
}
|
||||||
|
|
||||||
// libavb verifies AVB metadata on all verified partitions at once.
|
// libavb verifies AVB metadata on all verified partitions at once.
|
||||||
// e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
|
// e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
|
||||||
// for libavb to verify metadata, even if there is only /vendor in the
|
// for libavb to verify metadata, even if there is only /vendor in the
|
||||||
// above mount_fstab_recs_.
|
// above mount_fstab_recs_.
|
||||||
if (*out_need_dm_verity) {
|
if (need_dm_verity_) {
|
||||||
if (device_tree_vbmeta_parts_.empty()) {
|
if (device_tree_vbmeta_parts_.empty()) {
|
||||||
LOG(ERROR) << "Missing vbmeta parts in device tree";
|
LOG(ERROR) << "Missing vbmeta parts in device tree";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -342,16 +335,45 @@ bool FirstStageMountVBootV2::GetRequiredDevices(std::set<std::string>* out_devic
|
||||||
std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
|
std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
|
||||||
std::string ab_suffix = fs_mgr_get_slot_suffix();
|
std::string ab_suffix = fs_mgr_get_slot_suffix();
|
||||||
for (const auto& partition : partitions) {
|
for (const auto& partition : partitions) {
|
||||||
// out_devices_partition_names is of type std::set so it's not an issue to emplace
|
// required_devices_partition_names_ is of type std::set so it's not an issue
|
||||||
// a partition twice. e.g., /vendor might be in both places:
|
// to emplace a partition twice. e.g., /vendor might be in both places:
|
||||||
// - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
|
// - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
|
||||||
// - mount_fstab_recs_: /vendor_a
|
// - mount_fstab_recs_: /vendor_a
|
||||||
out_devices_partition_names->emplace(partition + ab_suffix);
|
required_devices_partition_names_.emplace(partition + ab_suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coldboot_action_t FirstStageMountVBootV2::ColdbootCallback(uevent* uevent) {
|
||||||
|
// Invokes the parent function to see if any desired partition has been found.
|
||||||
|
// If yes, record the by-name symlink for creating FsManagerAvbHandle later.
|
||||||
|
coldboot_action_t parent_callback_ret = FirstStageMount::ColdbootCallback(uevent);
|
||||||
|
|
||||||
|
// Skips the uevent if the parent function returns COLDBOOT_CONTINUE (meaning
|
||||||
|
// that the uevent was skipped) or there is no uevent->partition_name to
|
||||||
|
// create the by-name symlink.
|
||||||
|
if (parent_callback_ret != COLDBOOT_CONTINUE && !uevent->partition_name.empty()) {
|
||||||
|
// get_block_device_symlinks() will return three symlinks at most, depending on
|
||||||
|
// the content of uevent. by-name symlink will be at [0] if uevent->partition_name
|
||||||
|
// is not empty. e.g.,
|
||||||
|
// - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
|
||||||
|
// - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1
|
||||||
|
// - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
|
||||||
|
std::vector<std::string> links = get_block_device_symlinks(uevent);
|
||||||
|
if (!links.empty()) {
|
||||||
|
auto[it, inserted] = by_name_symlink_map_.emplace(uevent->partition_name, links[0]);
|
||||||
|
if (!inserted) {
|
||||||
|
LOG(ERROR) << "Partition '" << uevent->partition_name
|
||||||
|
<< "' already existed in the by-name symlink map with a value of '"
|
||||||
|
<< it->second << "', new value '" << links[0] << "' will be ignored.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent_callback_ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
|
bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
|
||||||
if (fs_mgr_is_avb(fstab_rec)) {
|
if (fs_mgr_is_avb(fstab_rec)) {
|
||||||
if (!InitAvbHandle()) return false;
|
if (!InitAvbHandle()) return false;
|
||||||
|
|
@ -371,7 +393,14 @@ bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
|
||||||
bool FirstStageMountVBootV2::InitAvbHandle() {
|
bool FirstStageMountVBootV2::InitAvbHandle() {
|
||||||
if (avb_handle_) return true; // Returns true if the handle is already initialized.
|
if (avb_handle_) return true; // Returns true if the handle is already initialized.
|
||||||
|
|
||||||
avb_handle_ = FsManagerAvbHandle::Open(device_tree_by_name_prefix_);
|
if (by_name_symlink_map_.empty()) {
|
||||||
|
LOG(ERROR) << "by_name_symlink_map_ is empty";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_));
|
||||||
|
by_name_symlink_map_.clear(); // Removes all elements after the above std::move().
|
||||||
|
|
||||||
if (!avb_handle_) {
|
if (!avb_handle_) {
|
||||||
PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
|
PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -427,7 +456,8 @@ void SetInitAvbVersionInRecovery() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(avb_first_mount.by_name_prefix());
|
FsManagerAvbUniquePtr avb_handle =
|
||||||
|
FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_));
|
||||||
if (!avb_handle) {
|
if (!avb_handle) {
|
||||||
PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
|
PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue