exynos9601: add hidl bootctrl hal
authorPaul Keith <javelinanddart@gmail.com>
Mon, 23 Mar 2020 20:33:06 +0000 (15:33 -0500)
committerJan Altensen <info@stricted.net>
Sat, 17 Oct 2020 14:30:56 +0000 (16:30 +0200)
Signed-off-by: Jan Altensen <info@stricted.net>
Co-authored-by: Jan Altensen <info@stricted.net>
Change-Id: Iaa34a28b1d518249ab2d7f21bee28c676af8ac97

common.mk
hidl/boot/Android.bp [new file with mode: 0644]
hidl/boot/BootControl.cpp [new file with mode: 0644]
hidl/boot/BootControl.h [new file with mode: 0644]
hidl/boot/android.hardware.boot@1.0-service.xml [new file with mode: 0644]
hidl/boot/bctl_metadata.h [new file with mode: 0644]
proprietary-files-vendor.txt

index 913fe298c7bb7545e3bff4b58ab2acab205b7f10..787e58ccf74301af8b54fd2f8126ed450b1ddc21 100644 (file)
--- 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 (file)
index 0000000..5c20f47
--- /dev/null
@@ -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 (file)
index 0000000..382b857
--- /dev/null
@@ -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 <fstream>
+
+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<char*>(&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<const char*>(&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<uint32_t> BootControl::getNumberSlots() {
+    return 2;
+}
+
+Return<uint32_t> 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<void> 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<void> 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<void> 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<BoolResult> BootControl::isSlotBootable(uint32_t slot) {
+    bctl_metadata_t data;
+    BoolResult ret = BoolResult::FALSE;
+
+    if (slot < 2) {
+        if (readMetadata(data)) {
+            ret = static_cast<BoolResult>(data.slot_info[slot].bootable);
+        } else {
+            ret = BoolResult::FALSE;
+        }
+    } else {
+        ret = BoolResult::INVALID_SLOT;
+    }
+
+    return ret;
+}
+
+Return<BoolResult> BootControl::isSlotMarkedSuccessful(uint32_t slot) {
+    bctl_metadata_t data;
+    BoolResult ret = BoolResult::FALSE;
+
+    if (slot < 2) {
+        if (readMetadata(data)) {
+            ret = static_cast<BoolResult>(data.slot_info[slot].boot_successful);
+        } else {
+            ret = BoolResult::FALSE;
+        }
+    } else {
+        ret = BoolResult::INVALID_SLOT;
+    }
+
+    return ret;
+}
+
+Return<void> 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 (file)
index 0000000..23bdd2e
--- /dev/null
@@ -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 <android-base/properties.h>
+#include <android/hardware/boot/1.0/IBootControl.h>
+
+#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<uint32_t> getNumberSlots() override;
+    Return<uint32_t> getCurrentSlot() override;
+    Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
+    Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
+    Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
+    Return<BoolResult> isSlotBootable(uint32_t slot) override;
+    Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
+    Return<void> 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 (file)
index 0000000..899656d
--- /dev/null
@@ -0,0 +1,12 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.boot</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
+
diff --git a/hidl/boot/bctl_metadata.h b/hidl/boot/bctl_metadata.h
new file mode 100644 (file)
index 0000000..c78015b
--- /dev/null
@@ -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
index eb10d0032ff98df54284a81dfbe89b5384640a40..0640092871eba6066b9b016241d43790ce4b6430 100644 (file)
@@ -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