From 063a41e266bfe224a5ccf88cb0bb3cb6defabf65 Mon Sep 17 00:00:00 2001 From: Paul Keith Date: Mon, 23 Mar 2020 15:33:06 -0500 Subject: [PATCH] exynos9601: add hidl bootctrl hal Signed-off-by: Jan Altensen Co-authored-by: Jan Altensen Change-Id: Iaa34a28b1d518249ab2d7f21bee28c676af8ac97 --- common.mk | 9 +- hidl/boot/Android.bp | 31 ++ hidl/boot/BootControl.cpp | 266 ++++++++++++++++++ hidl/boot/BootControl.h | 66 +++++ .../android.hardware.boot@1.0-service.xml | 12 + hidl/boot/bctl_metadata.h | 41 +++ proprietary-files-vendor.txt | 4 - 7 files changed, 420 insertions(+), 9 deletions(-) create mode 100644 hidl/boot/Android.bp create mode 100644 hidl/boot/BootControl.cpp create mode 100644 hidl/boot/BootControl.h create mode 100644 hidl/boot/android.hardware.boot@1.0-service.xml create mode 100644 hidl/boot/bctl_metadata.h diff --git a/common.mk b/common.mk index 913fe29..787e58c 100644 --- a/common.mk +++ b/common.mk @@ -76,7 +76,10 @@ TARGET_SCREEN_WIDTH := 1080 # bootctrl PRODUCT_PACKAGES += \ - android.hardware.boot@1.0 + android.hardware.boot@1.0 \ + android.hardware.boot@1.0-service \ + android.hardware.boot@1.0-impl.exynos9610 \ + android.hardware.boot@1.0-impl.exynos9610.recovery # camera PRODUCT_PACKAGES += \ @@ -200,10 +203,6 @@ PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \ $(COMMON_PATH)/configs/public.libraries.txt:$(TARGET_COPY_OUT_VENDOR)/etc/public.libraries.txt -# Recovery -PRODUCT_PACKAGES += \ - android.hardware.boot@1.0-impl.exynos.recovery - # ril PRODUCT_PACKAGES += \ android.hardware.radio.config@1.0 \ diff --git a/hidl/boot/Android.bp b/hidl/boot/Android.bp new file mode 100644 index 0000000..5c20f47 --- /dev/null +++ b/hidl/boot/Android.bp @@ -0,0 +1,31 @@ +// Copyright (C) 2020 The LineageOS 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. + +cc_library_shared { + name: "android.hardware.boot@1.0-impl.exynos9610", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + recovery_available: true, + srcs: ["BootControl.cpp"], + + shared_libs: [ + "libbase", + "libhidlbase", + "libhidltransport", + "libhardware", + "libutils", + "android.hardware.boot@1.0", + ], +} diff --git a/hidl/boot/BootControl.cpp b/hidl/boot/BootControl.cpp new file mode 100644 index 0000000..382b857 --- /dev/null +++ b/hidl/boot/BootControl.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2020 The LineageOS 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. + */ + +#include "BootControl.h" + +#include + +namespace android { +namespace hardware { +namespace boot { +namespace V1_0 { +namespace implementation { + +bool BootControl::readMetadata(bctl_metadata_t& data) { + std::fstream in(mBlkDevice, std::ios::binary | std::ios::in); + + if (in.fail()) { + return false; + } + + in.seekg(BCTL_METADATA_OFFSET); + + if (in.fail()) { + return false; + } + + in.read(reinterpret_cast(&data), sizeof(bctl_metadata_t)); + + if (!validateMetadata(data)) { +#if 0 + /* this is what samsung does, probably not what we desire */ + data = resetMetadata(); + if (validateMetadata(data)) { + return true; + } +#endif + return false; + } + + return !in.eof() && !in.fail(); +} + +bool BootControl::writeMetadata(bctl_metadata_t& data) { + if (!validateMetadata(data)) return false; + + // We use std::ios::in | std::ios::out even though we only write so that + // we don't truncate or append to the file, but rather overwrite the file + // in the exact place that we want to write the struct to. + std::fstream out(mBlkDevice, std::ios::binary | std::ios::in | std::ios::out); + + if (out.fail()) { + return false; + } + + out.seekp(BCTL_METADATA_OFFSET); + + if (out.fail()) { + return false; + } + + out.write(reinterpret_cast(&data), sizeof(bctl_metadata_t)); + + return !out.eof() && !out.fail(); +} + +bool BootControl::validateMetadata(bctl_metadata_t& data) { + if (data.slot_info[0].magic != BCTL_METADATA_MAGIC || + data.slot_info[1].magic != BCTL_METADATA_MAGIC) { + return false; + } + + return true; +} + +bctl_metadata_t BootControl::resetMetadata() { + bctl_metadata_t data{}; + + // reset to defaults + data.slot_info[0].magic = BCTL_METADATA_MAGIC; + data.slot_info[0].bootable = 1; + data.slot_info[0].is_active = 1; + data.slot_info[0].boot_successful = 0; + data.slot_info[0].tries_remaining = 7; + + data.slot_info[1].magic = BCTL_METADATA_MAGIC; + data.slot_info[1].bootable = 1; + data.slot_info[1].is_active = 0; + data.slot_info[1].boot_successful = 0; + data.slot_info[1].tries_remaining = 7; + + return data; +} + +// Methods from ::android::hardware::boot::V1_0::IBootControl follow. +Return BootControl::getNumberSlots() { + return 2; +} + +Return BootControl::getCurrentSlot() { + bctl_metadata_t data; + std::string slot_suffix = GetProperty("ro.boot.slot_suffix", ""); + + if (!slot_suffix.empty()) { + if (slot_suffix.compare(SLOT_SUFFIX_A) == 0) { + return 0; + } else if (slot_suffix.compare(SLOT_SUFFIX_B) == 0) { + return 1; + } + } else { + // read current slot from metadata incase "ro.boot.slot_suffix" is empty + if (readMetadata(data)) { + // This is a clever hack because if slot b is active, + // is_active will be 0 and if slot a is active, is_active + // will be 1. In other words, the "not" value of slot A's + // is_active var lines up to the current active slot index. + return !data.slot_info[0].is_active; + } + } + + // fallback to slot A + return 0; +} + +Return BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) { + bctl_metadata_t data; + int active_slot = getCurrentSlot(); + + if (readMetadata(data)) { + data.slot_info[active_slot].boot_successful = 1; + data.slot_info[active_slot].tries_remaining = 0; + + if (writeMetadata(data)) { + _hidl_cb(CommandResult{true, ""}); + } else { + _hidl_cb(CommandResult{false, "Failed to write metadata"}); + } + } else { + _hidl_cb(CommandResult{false, "Failed to read metadata"}); + } + + return Void(); +} + +Return BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) { + bctl_metadata_t data; + + if (slot < 2) { + if (readMetadata(data)) { + data.slot_info[slot].bootable = 1; + data.slot_info[slot].is_active = 1; + data.slot_info[slot].boot_successful = 0; + data.slot_info[slot].tries_remaining = 7; + + data.slot_info[!slot].bootable = 1; + data.slot_info[!slot].is_active = 0; + data.slot_info[!slot].boot_successful = 0; + data.slot_info[!slot].tries_remaining = 7; + + if (writeMetadata(data)) { + _hidl_cb(CommandResult{true, ""}); + } else { + _hidl_cb(CommandResult{false, "Failed to write metadata"}); + } + } else { + _hidl_cb(CommandResult{false, "Failed to read metadata"}); + } + } else { + _hidl_cb(CommandResult{false, "Invalid slot"}); + } + + return Void(); +} + +Return BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) { + bctl_metadata_t data; + + if (slot < 2) { + if (readMetadata(data)) { + data.slot_info[slot].bootable = 0; + + if (writeMetadata(data)) { + _hidl_cb(CommandResult{true, ""}); + } else { + _hidl_cb(CommandResult{false, "Failed to write metadata"}); + } + } else { + _hidl_cb(CommandResult{false, "Failed to read metadata"}); + } + } else { + _hidl_cb(CommandResult{false, "Invalid slot"}); + } + + return Void(); +} + +Return BootControl::isSlotBootable(uint32_t slot) { + bctl_metadata_t data; + BoolResult ret = BoolResult::FALSE; + + if (slot < 2) { + if (readMetadata(data)) { + ret = static_cast(data.slot_info[slot].bootable); + } else { + ret = BoolResult::FALSE; + } + } else { + ret = BoolResult::INVALID_SLOT; + } + + return ret; +} + +Return BootControl::isSlotMarkedSuccessful(uint32_t slot) { + bctl_metadata_t data; + BoolResult ret = BoolResult::FALSE; + + if (slot < 2) { + if (readMetadata(data)) { + ret = static_cast(data.slot_info[slot].boot_successful); + } else { + ret = BoolResult::FALSE; + } + } else { + ret = BoolResult::INVALID_SLOT; + } + + return ret; +} + +Return BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) { + if (slot < 2) { + if (slot == 0) { + _hidl_cb(SLOT_SUFFIX_A); + } else { + _hidl_cb(SLOT_SUFFIX_B); + } + } else { + // default to slot A + _hidl_cb(SLOT_SUFFIX_A); + } + + return Void(); +} + +IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) { + return new BootControl(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace boot +} // namespace hardware +} // namespace android diff --git a/hidl/boot/BootControl.h b/hidl/boot/BootControl.h new file mode 100644 index 0000000..23bdd2e --- /dev/null +++ b/hidl/boot/BootControl.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 The LineageOS 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. + */ + +#ifndef ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H +#define ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H + +#include +#include + +#include "bctl_metadata.h" + +namespace android { +namespace hardware { +namespace boot { +namespace V1_0 { +namespace implementation { + +using ::android::base::GetProperty; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::boot::V1_0::BoolResult; +using ::android::hardware::boot::V1_0::CommandResult; + +class BootControl : public IBootControl { + public: + // Methods from ::android::hardware::boot::V1_0::IBootControl follow. + Return getNumberSlots() override; + Return getCurrentSlot() override; + Return markBootSuccessful(markBootSuccessful_cb _hidl_cb) override; + Return setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override; + Return setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override; + Return isSlotBootable(uint32_t slot) override; + Return isSlotMarkedSuccessful(uint32_t slot) override; + Return getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override; + + private: + std::string mBlkDevice = BCTL_METADATA_PARTITION; + + bool readMetadata(bctl_metadata_t& data); + bool writeMetadata(bctl_metadata_t& data); + bool validateMetadata(bctl_metadata_t& data); + bctl_metadata_t resetMetadata(); +}; + +extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name); + +} // namespace implementation +} // namespace V1_0 +} // namespace boot +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H diff --git a/hidl/boot/android.hardware.boot@1.0-service.xml b/hidl/boot/android.hardware.boot@1.0-service.xml new file mode 100644 index 0000000..899656d --- /dev/null +++ b/hidl/boot/android.hardware.boot@1.0-service.xml @@ -0,0 +1,12 @@ + + + android.hardware.boot + hwbinder + 1.0 + + IBootControl + default + + + + diff --git a/hidl/boot/bctl_metadata.h b/hidl/boot/bctl_metadata.h new file mode 100644 index 0000000..c78015b --- /dev/null +++ b/hidl/boot/bctl_metadata.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The LineageOS 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. + */ + +#ifndef SAMSUNG_BCTL_METADATA_H +#define SAMSUNG_BCTL_METADATA_H + +#define BCTL_METADATA_PARTITION "/dev/block/bootdevice/by-name/slotinfo" +#define BCTL_METADATA_OFFSET 0x800 +#define BCTL_METADATA_MAGIC 0x43425845 + +#define SLOT_SUFFIX_A "_a" +#define SLOT_SUFFIX_B "_b" + +// Our internal data structures +struct slot_metadata_t { + uint32_t magic; + uint8_t bootable; + uint8_t is_active; + uint8_t boot_successful; + uint8_t tries_remaining; + uint8_t reserved[8]; +}; + +struct bctl_metadata_t { + slot_metadata_t slot_info[2]; +}; + +#endif // SAMSUNG_BCTL_METADATA_H diff --git a/proprietary-files-vendor.txt b/proprietary-files-vendor.txt index eb10d00..0640092 100644 --- a/proprietary-files-vendor.txt +++ b/proprietary-files-vendor.txt @@ -105,10 +105,6 @@ vendor/lib64/vendor.dolby.hardware.dms@1.0.so vendor/etc/bluetooth/bt_did.conf vendor/etc/bt_stack_level6.conf -# bootctrl -vendor/lib/hw/bootctrl.exynos9610.so -vendor/lib64/hw/bootctrl.exynos9610.so - # camera vendor/lib/libENF.so vendor/lib/libexynoscamera_hifi_plugin.so -- 2.20.1