diff options
author | David Anderson <dvander@google.com> | 2019-09-16 17:20:03 -0700 |
---|---|---|
committer | David Anderson <dvander@google.com> | 2019-10-16 17:01:25 -0700 |
commit | b93d670bb9a892c31ee6b1751395af6cc363306c (patch) | |
tree | bbd740ce967132fca29207626bc560bf963e87cb /bootctrl | |
parent | c4b7b9f13f9168885650e3f8fb22e73f11f5c597 (diff) |
Implement IBootControl 1.1.
Store the new state for IBootControl 1.1 in the misc partition, using
the reserved section of bootloader_message_ab. The code to read/write
this partition is from the bootloader_message library.
We don't embed libboot_control directly because the 1.0 HAL methods are
implemented using GPT, not misc. Note that the new 1.1 methods are
implemented in a shared file. This is for future implementations of the
HAL that may not rely on the legacy GPT library, but will use the same
misc storage.
Bug: 141131816
Test: vts
Change-Id: I455c202cdd6a21261a2ed1f17dec6efd2ae8116e
Diffstat (limited to 'bootctrl')
-rw-r--r-- | bootctrl/Android.bp | 9 | ||||
-rw-r--r-- | bootctrl/BootControlShared.cpp | 156 | ||||
-rw-r--r-- | bootctrl/BootControlShared.h | 47 | ||||
-rw-r--r-- | bootctrl/LegacyBootControl.cpp | 8 | ||||
-rw-r--r-- | bootctrl/LegacyBootControl.h | 19 |
5 files changed, 224 insertions, 15 deletions
diff --git a/bootctrl/Android.bp b/bootctrl/Android.bp index dba4818..c410f03 100644 --- a/bootctrl/Android.bp +++ b/bootctrl/Android.bp @@ -1,8 +1,10 @@ cc_library { - name: "android.hardware.boot@1.0-impl-pixel-legacy", + name: "android.hardware.boot@1.1-impl-pixel-legacy", + stem: "android.hardware.boot@1.0-impl-1.1-pixel-legacy", vendor: true, recovery_available: true, srcs: [ + "BootControlShared.cpp", "LegacyBootControl.cpp", ], cflags: [ @@ -17,5 +19,10 @@ cc_library { "libhidlbase", "libutils", "android.hardware.boot@1.0", + "android.hardware.boot@1.1", + ], + static_libs: [ + "libbootloader_message_vendor", + "libfstab", ], } diff --git a/bootctrl/BootControlShared.cpp b/bootctrl/BootControlShared.cpp new file mode 100644 index 0000000..193ddea --- /dev/null +++ b/bootctrl/BootControlShared.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "bootcontrolhal" + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/unique_fd.h> +#include <bootloader_message/bootloader_message.h> + +#include "BootControlShared.h" + +namespace android { +namespace hardware { +namespace boot { +namespace V1_1 { +namespace implementation { + +using android::base::unique_fd; +using android::hardware::boot::V1_1::MergeStatus; + +constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix); + +static uint32_t CRC32(const uint8_t *buf, size_t size) { + static uint32_t crc_table[256]; + + // Compute the CRC-32 table only once. + if (!crc_table[1]) { + for (uint32_t i = 0; i < 256; ++i) { + uint32_t crc = i; + for (uint32_t j = 0; j < 8; ++j) { + uint32_t mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + crc_table[i] = crc; + } + } + + uint32_t ret = -1; + for (size_t i = 0; i < size; ++i) { + ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF]; + } + + return ~ret; +} + +uint32_t ComputeChecksum(const bootloader_control *boot_ctrl) { + return CRC32(reinterpret_cast<const uint8_t *>(boot_ctrl), + offsetof(bootloader_control, crc32_le)); +} + +static bool LoadUpdateState(const std::string &misc_device, bootloader_control *buffer) { + unique_fd fd(open(misc_device.c_str(), O_RDONLY)); + if (fd < 0) { + PLOG(ERROR) << "failed to open " << misc_device; + return false; + } + if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) { + PLOG(ERROR) << "failed to lseek " << misc_device; + return false; + } + if (!android::base::ReadFully(fd, buffer, sizeof(bootloader_control))) { + PLOG(ERROR) << "failed to read " << misc_device; + return false; + } + return true; +} + +static bool SaveUpdateState(const std::string &misc_device, bootloader_control *buffer) { + unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC)); + if (fd < 0) { + PLOG(ERROR) << "failed to open " << misc_device; + return false; + } + if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) { + PLOG(ERROR) << "failed to lseek " << misc_device; + return false; + } + + buffer->crc32_le = ComputeChecksum(buffer); + if (!android::base::WriteFully(fd, buffer, sizeof(bootloader_control))) { + PLOG(ERROR) << "failed to write " << misc_device; + return false; + } + return true; +} + +BootControlShared::BootControlShared() { + std::string err; + misc_device_ = get_bootloader_message_blk_device(&err); + if (misc_device_.empty()) { + LOG(FATAL) << "Unable to locate misc device: " << err; + } + + bootloader_control control; + if (!LoadUpdateState(misc_device_, &control)) { + LOG(FATAL) << "Unable to read update state from misc partition"; + } + uint32_t computed_crc32 = ComputeChecksum(&control); + + bool initialize = false; + if (computed_crc32 != control.crc32_le) { + LOG(WARNING) << "Invalid boot control found, expected CRC32 0x" << std::hex + << computed_crc32 << " but found 0x" << std::hex << control.crc32_le; + initialize = true; + } else if (control.magic != BOOT_CTRL_MAGIC) { + LOG(WARNING) << "Invalid boot control magic, " << std::hex << control.magic; + initialize = true; + } + if (initialize) { + LOG(WARNING) << "Re-initializing misc."; + + // We only use the |merge_status| field of this structure. + memset(&control, 0, sizeof(control)); + control.magic = BOOT_CTRL_MAGIC; + control.version = BOOT_CTRL_VERSION; + control.merge_status = static_cast<uint8_t>(MergeStatus::NONE); + SaveUpdateState(misc_device_, &control); + } +} + +Return<bool> BootControlShared::setSnapshotMergeStatus(MergeStatus status) { + bootloader_control control; + if (!LoadUpdateState(misc_device_, &control)) { + return false; + } + control.merge_status = static_cast<uint8_t>(status); + return SaveUpdateState(misc_device_, &control); +} + +Return<MergeStatus> BootControlShared::getSnapshotMergeStatus() { + bootloader_control control; + if (!LoadUpdateState(misc_device_, &control)) { + return MergeStatus::UNKNOWN; + } + return static_cast<MergeStatus>(control.merge_status); +} + +} // namespace implementation +} // namespace V1_1 +} // namespace boot +} // namespace hardware +} // namespace android diff --git a/bootctrl/BootControlShared.h b/bootctrl/BootControlShared.h new file mode 100644 index 0000000..2f7a6a0 --- /dev/null +++ b/bootctrl/BootControlShared.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <android/hardware/boot/1.1/IBootControl.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace boot { +namespace V1_1 { +namespace implementation { + +using ::android::hardware::Return; + +struct BootControlShared : public IBootControl { + BootControlShared(); + + Return<bool> setSnapshotMergeStatus(MergeStatus status) override; + Return<MergeStatus> getSnapshotMergeStatus() override; + + protected: + std::string misc_device_; +}; + +extern "C" IBootControl *HIDL_FETCH_IBootControl(const char *name); + +} // namespace implementation +} // namespace V1_1 +} // namespace boot +} // namespace hardware +} // namespace android diff --git a/bootctrl/LegacyBootControl.cpp b/bootctrl/LegacyBootControl.cpp index e96bb88..a5f29f8 100644 --- a/bootctrl/LegacyBootControl.cpp +++ b/bootctrl/LegacyBootControl.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "android.hardware.boot@1.0-impl" +#define LOG_TAG "android.hardware.boot@1.1-impl" #include <log/log.h> @@ -28,9 +28,11 @@ extern const hw_module_t HAL_MODULE_INFO_SYM; namespace android { namespace hardware { namespace boot { -namespace V1_0 { +namespace V1_1 { namespace implementation { +using ::android::hardware::boot::V1_0::CommandResult; + BootControl::BootControl(boot_control_module_t *module) : mModule(module) {} // Methods from ::android::hardware::boot::V1_0::IBootControl follow. @@ -125,7 +127,7 @@ IBootControl *HIDL_FETCH_IBootControl(const char * /* hal */) { } #endif } // namespace implementation -} // namespace V1_0 +} // namespace V1_1 } // namespace boot } // namespace hardware } // namespace android diff --git a/bootctrl/LegacyBootControl.h b/bootctrl/LegacyBootControl.h index d50e789..64bc797 100644 --- a/bootctrl/LegacyBootControl.h +++ b/bootctrl/LegacyBootControl.h @@ -13,25 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H -#define ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H -#include <android/hardware/boot/1.0/IBootControl.h> -#include <hidl/Status.h> +#pragma once #include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include "BootControlShared.h" + namespace android { namespace hardware { namespace boot { -namespace V1_0 { +namespace V1_1 { namespace implementation { -using ::android::sp; using ::android::hardware::Return; using ::android::hardware::boot::V1_0::BoolResult; -using ::android::hardware::boot::V1_0::IBootControl; -struct BootControl : public IBootControl { +struct BootControl : public BootControlShared { BootControl(boot_control_module_t *module); // Methods from ::android::hardware::boot::V1_0::IBootControl follow. Return<uint32_t> getNumberSlots() override; @@ -50,9 +49,7 @@ struct BootControl : public IBootControl { extern "C" IBootControl *HIDL_FETCH_IBootControl(const char *name); } // namespace implementation -} // namespace V1_0 +} // namespace V1_1 } // namespace boot } // namespace hardware } // namespace android - -#endif // ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H |