Loading boot_control/include/libboot_control/libboot_control.h +23 −0 Original line number Diff line number Diff line Loading @@ -62,5 +62,28 @@ class BootControl { unsigned int current_slot_ = 0; }; // Helper functions to write the Virtual A/B merge status message. These are // separate because BootControl uses bootloader_control_ab in vendor space, // whereas the Virtual A/B merge status is in system space. A HAL might not // use bootloader_control_ab, but may want to use the AOSP method of maintaining // the merge status. // If the Virtual A/B message has not yet been initialized, then initialize it. // This should be called when the BootControl HAL first loads. // // If the Virtual A/B message in misc was already initialized, true is returned. // If initialization was attempted, but failed, false is returned, and the HAL // should fail to load. bool InitMiscVirtualAbMessageIfNeeded(); // Save the current merge status as well as the current slot. bool SetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus status); // Return the current merge status. If the saved status is SNAPSHOTTED but the // slot hasn't changed, the status returned will be NONE. bool GetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus* status); } // namespace bootable } // namespace android boot_control/libboot_control.cpp +71 −9 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ bool BootControl::Init() { UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl); } if (!InitMiscVirtualAbMessageIfNeeded()) { return false; } num_slots_ = boot_ctrl.nb_slot; return true; } Loading Loading @@ -335,18 +339,15 @@ bool BootControl::IsValidSlot(unsigned int slot) { } bool BootControl::SetSnapshotMergeStatus(MergeStatus status) { bootloader_control bootctrl; if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false; bootctrl.merge_status = (unsigned int)status; return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl); return SetMiscVirtualAbMergeStatus(current_slot_, status); } MergeStatus BootControl::GetSnapshotMergeStatus() { bootloader_control bootctrl; if (!LoadBootloaderControl(misc_device_, &bootctrl)) return MergeStatus::UNKNOWN; return (MergeStatus)bootctrl.merge_status; MergeStatus status; if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) { return MergeStatus::UNKNOWN; } return status; } const char* BootControl::GetSuffix(unsigned int slot) { Loading @@ -356,5 +357,66 @@ const char* BootControl::GetSuffix(unsigned int slot) { return kSlotSuffixes[slot]; } bool InitMiscVirtualAbMessageIfNeeded() { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION) { // Already initialized. return true; } message = {}; message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION; if (!WriteMiscVirtualAbMessage(message, &err)) { LOG(ERROR) << "Could not write merge status: " << err; return false; } return true; } bool SetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus status) { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } message.merge_status = static_cast<uint8_t>(status); message.source_slot = current_slot; if (!WriteMiscVirtualAbMessage(message, &err)) { LOG(ERROR) << "Could not write merge status: " << err; return false; } return true; } bool GetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus* status) { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } // If the slot reverted after having created a snapshot, then the snapshot will // be thrown away at boot. Thus we don't count this as being in a snapshotted // state. *status = static_cast<MergeStatus>(message.merge_status); if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) { *status = MergeStatus::NONE; } return true; } } // namespace bootable } // namespace android bootloader_message/bootloader_message.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,49 @@ bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, err); } static bool ValidateSystemSpaceRegion(size_t offset, size_t size, std::string* err) { if (size <= SYSTEM_SPACE_SIZE_IN_MISC && offset <= (SYSTEM_SPACE_SIZE_IN_MISC - size)) { return true; } *err = android::base::StringPrintf("Out of bound access (offset %zu size %zu)", offset, size); return false; } static bool ReadMiscPartitionSystemSpace(void* data, size_t size, size_t offset, std::string* err) { if (!ValidateSystemSpaceRegion(offset, size, err)) { return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_misc_partition(data, size, misc_blk_device, SYSTEM_SPACE_OFFSET_IN_MISC + offset, err); } static bool WriteMiscPartitionSystemSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!ValidateSystemSpaceRegion(offset, size, err)) { return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(data, size, misc_blk_device, SYSTEM_SPACE_OFFSET_IN_MISC + offset, err); } bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err) { return ReadMiscPartitionSystemSpace(message, sizeof(*message), offsetof(misc_system_space_layout, virtual_ab_message), err); } bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err) { return WriteMiscPartitionSystemSpace(&message, sizeof(message), offsetof(misc_system_space_layout, virtual_ab_message), err); } extern "C" bool write_reboot_bootloader(void) { std::string err; return write_reboot_bootloader(&err); Loading bootloader_message/include/bootloader_message/bootloader_message.h +26 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,28 @@ static_assert(sizeof(struct bootloader_control) == "struct bootloader_control has wrong size"); #endif // Holds Virtual A/B merge status information. Current version is 1. New fields // must be added to the end. struct misc_virtual_ab_message { uint8_t version; uint8_t merge_status; // IBootControl 1.1, MergeStatus enum. uint8_t source_slot; // Slot number when merge_status was written. uint8_t reserved[61]; } __attribute__((packed)); #define MISC_VIRTUAL_AB_MESSAGE_VERSION 1 #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) static_assert(sizeof(struct misc_virtual_ab_message) == 64, "struct misc_virtual_ab_message has wrong size"); #endif // This struct is not meant to be used directly, rather, it is to make // computation of offsets easier. New fields must be added to the end. struct misc_system_space_layout { misc_virtual_ab_message virtual_ab_message; } __attribute__((packed)); #ifdef __cplusplus #include <string> Loading Loading @@ -247,6 +269,10 @@ bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::s // offset is in relative to the start of the vendor space. bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); // Read or write the Virtual A/B message from system space in /misc. bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); #else #include <stdbool.h> Loading Loading
boot_control/include/libboot_control/libboot_control.h +23 −0 Original line number Diff line number Diff line Loading @@ -62,5 +62,28 @@ class BootControl { unsigned int current_slot_ = 0; }; // Helper functions to write the Virtual A/B merge status message. These are // separate because BootControl uses bootloader_control_ab in vendor space, // whereas the Virtual A/B merge status is in system space. A HAL might not // use bootloader_control_ab, but may want to use the AOSP method of maintaining // the merge status. // If the Virtual A/B message has not yet been initialized, then initialize it. // This should be called when the BootControl HAL first loads. // // If the Virtual A/B message in misc was already initialized, true is returned. // If initialization was attempted, but failed, false is returned, and the HAL // should fail to load. bool InitMiscVirtualAbMessageIfNeeded(); // Save the current merge status as well as the current slot. bool SetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus status); // Return the current merge status. If the saved status is SNAPSHOTTED but the // slot hasn't changed, the status returned will be NONE. bool GetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus* status); } // namespace bootable } // namespace android
boot_control/libboot_control.cpp +71 −9 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ bool BootControl::Init() { UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl); } if (!InitMiscVirtualAbMessageIfNeeded()) { return false; } num_slots_ = boot_ctrl.nb_slot; return true; } Loading Loading @@ -335,18 +339,15 @@ bool BootControl::IsValidSlot(unsigned int slot) { } bool BootControl::SetSnapshotMergeStatus(MergeStatus status) { bootloader_control bootctrl; if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false; bootctrl.merge_status = (unsigned int)status; return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl); return SetMiscVirtualAbMergeStatus(current_slot_, status); } MergeStatus BootControl::GetSnapshotMergeStatus() { bootloader_control bootctrl; if (!LoadBootloaderControl(misc_device_, &bootctrl)) return MergeStatus::UNKNOWN; return (MergeStatus)bootctrl.merge_status; MergeStatus status; if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) { return MergeStatus::UNKNOWN; } return status; } const char* BootControl::GetSuffix(unsigned int slot) { Loading @@ -356,5 +357,66 @@ const char* BootControl::GetSuffix(unsigned int slot) { return kSlotSuffixes[slot]; } bool InitMiscVirtualAbMessageIfNeeded() { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION) { // Already initialized. return true; } message = {}; message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION; if (!WriteMiscVirtualAbMessage(message, &err)) { LOG(ERROR) << "Could not write merge status: " << err; return false; } return true; } bool SetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus status) { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } message.merge_status = static_cast<uint8_t>(status); message.source_slot = current_slot; if (!WriteMiscVirtualAbMessage(message, &err)) { LOG(ERROR) << "Could not write merge status: " << err; return false; } return true; } bool GetMiscVirtualAbMergeStatus(unsigned int current_slot, android::hardware::boot::V1_1::MergeStatus* status) { std::string err; misc_virtual_ab_message message; if (!ReadMiscVirtualAbMessage(&message, &err)) { LOG(ERROR) << "Could not read merge status: " << err; return false; } // If the slot reverted after having created a snapshot, then the snapshot will // be thrown away at boot. Thus we don't count this as being in a snapshotted // state. *status = static_cast<MergeStatus>(message.merge_status); if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) { *status = MergeStatus::NONE; } return true; } } // namespace bootable } // namespace android
bootloader_message/bootloader_message.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,49 @@ bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, err); } static bool ValidateSystemSpaceRegion(size_t offset, size_t size, std::string* err) { if (size <= SYSTEM_SPACE_SIZE_IN_MISC && offset <= (SYSTEM_SPACE_SIZE_IN_MISC - size)) { return true; } *err = android::base::StringPrintf("Out of bound access (offset %zu size %zu)", offset, size); return false; } static bool ReadMiscPartitionSystemSpace(void* data, size_t size, size_t offset, std::string* err) { if (!ValidateSystemSpaceRegion(offset, size, err)) { return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return read_misc_partition(data, size, misc_blk_device, SYSTEM_SPACE_OFFSET_IN_MISC + offset, err); } static bool WriteMiscPartitionSystemSpace(const void* data, size_t size, size_t offset, std::string* err) { if (!ValidateSystemSpaceRegion(offset, size, err)) { return false; } auto misc_blk_device = get_misc_blk_device(err); if (misc_blk_device.empty()) { return false; } return write_misc_partition(data, size, misc_blk_device, SYSTEM_SPACE_OFFSET_IN_MISC + offset, err); } bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err) { return ReadMiscPartitionSystemSpace(message, sizeof(*message), offsetof(misc_system_space_layout, virtual_ab_message), err); } bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err) { return WriteMiscPartitionSystemSpace(&message, sizeof(message), offsetof(misc_system_space_layout, virtual_ab_message), err); } extern "C" bool write_reboot_bootloader(void) { std::string err; return write_reboot_bootloader(&err); Loading
bootloader_message/include/bootloader_message/bootloader_message.h +26 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,28 @@ static_assert(sizeof(struct bootloader_control) == "struct bootloader_control has wrong size"); #endif // Holds Virtual A/B merge status information. Current version is 1. New fields // must be added to the end. struct misc_virtual_ab_message { uint8_t version; uint8_t merge_status; // IBootControl 1.1, MergeStatus enum. uint8_t source_slot; // Slot number when merge_status was written. uint8_t reserved[61]; } __attribute__((packed)); #define MISC_VIRTUAL_AB_MESSAGE_VERSION 1 #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) static_assert(sizeof(struct misc_virtual_ab_message) == 64, "struct misc_virtual_ab_message has wrong size"); #endif // This struct is not meant to be used directly, rather, it is to make // computation of offsets easier. New fields must be added to the end. struct misc_system_space_layout { misc_virtual_ab_message virtual_ab_message; } __attribute__((packed)); #ifdef __cplusplus #include <string> Loading Loading @@ -247,6 +269,10 @@ bool ReadMiscPartitionVendorSpace(void* data, size_t size, size_t offset, std::s // offset is in relative to the start of the vendor space. bool WriteMiscPartitionVendorSpace(const void* data, size_t size, size_t offset, std::string* err); // Read or write the Virtual A/B message from system space in /misc. bool ReadMiscVirtualAbMessage(misc_virtual_ab_message* message, std::string* err); bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::string* err); #else #include <stdbool.h> Loading