summaryrefslogtreecommitdiff
path: root/bootctrl
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2019-09-16 17:20:03 -0700
committerDavid Anderson <dvander@google.com>2019-10-16 17:01:25 -0700
commitb93d670bb9a892c31ee6b1751395af6cc363306c (patch)
treebbd740ce967132fca29207626bc560bf963e87cb /bootctrl
parentc4b7b9f13f9168885650e3f8fb22e73f11f5c597 (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.bp9
-rw-r--r--bootctrl/BootControlShared.cpp156
-rw-r--r--bootctrl/BootControlShared.h47
-rw-r--r--bootctrl/LegacyBootControl.cpp8
-rw-r--r--bootctrl/LegacyBootControl.h19
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