From 121bec542e2f6b3c23c9ad5209545f21cf8b1897 Mon Sep 17 00:00:00 2001 From: Kelvin Zhang Date: Tue, 31 May 2022 14:43:59 -0700 Subject: [PATCH] Implement bootctrl aidl There's already a libboot_control, which provides implementation for bootcontrol HAL. Implement AIDL bootctrl server by wrapping libboot_control Test: th Bug: 227536004 Change-Id: Ia54f91f7fd17b6e86956e458cdf0c36c31624dbc --- .../include/private/boot_control_definition.h | 3 + boot/aidl/default/Android.bp | 34 ++++ boot/aidl/default/BootControl.cpp | 152 ++++++++++++++++++ boot/aidl/default/BootControl.h | 45 ++++++ boot/aidl/default/boot-default.rc | 5 + boot/aidl/default/boot-default.xml | 6 + boot/aidl/default/main.cpp | 38 +++++ 7 files changed, 283 insertions(+) create mode 100644 boot/aidl/default/Android.bp create mode 100644 boot/aidl/default/BootControl.cpp create mode 100644 boot/aidl/default/BootControl.h create mode 100644 boot/aidl/default/boot-default.rc create mode 100644 boot/aidl/default/boot-default.xml create mode 100644 boot/aidl/default/main.cpp diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h index 8f021117ee..57c2f73d36 100644 --- a/boot/1.1/default/boot_control/include/private/boot_control_definition.h +++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h @@ -14,6 +14,9 @@ * limitations under the License. */ +#include + +#include /** * The A/B-specific bootloader message structure (4-KiB). diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp new file mode 100644 index 0000000000..7294faaf89 --- /dev/null +++ b/boot/aidl/default/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2022 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. +// + +cc_binary { + name: "android.hardware.boot-service.default", + defaults: ["libboot_control_defaults"], + relative_install_path: "hw", + init_rc: ["boot-default.rc"], + vintf_fragments: ["boot-default.xml"], + vendor: true, + shared_libs: [ + "libbase", + "libbinder_ndk", + "android.hardware.boot@1.1", + "android.hardware.boot-V1-ndk", + ], + static_libs: [ + "libboot_control", + ], + srcs: ["main.cpp", "BootControl.cpp"], +} diff --git a/boot/aidl/default/BootControl.cpp b/boot/aidl/default/BootControl.cpp new file mode 100644 index 0000000000..4e3c21b8a4 --- /dev/null +++ b/boot/aidl/default/BootControl.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022 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. + */ + +#include "BootControl.h" +#include + +#include + +using HIDLMergeStatus = ::android::bootable::BootControl::MergeStatus; +using ndk::ScopedAStatus; + +namespace aidl::android::hardware::boot { + +BootControl::BootControl() { + CHECK(impl_.Init()); +} + +ScopedAStatus BootControl::getActiveBootSlot(int32_t* _aidl_return) { + *_aidl_return = impl_.GetActiveBootSlot(); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::getCurrentSlot(int32_t* _aidl_return) { + *_aidl_return = impl_.GetCurrentSlot(); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::getNumberSlots(int32_t* _aidl_return) { + *_aidl_return = impl_.GetNumberSlots(); + return ScopedAStatus::ok(); +} + +namespace { + +static constexpr MergeStatus ToAIDLMergeStatus(HIDLMergeStatus status) { + switch (status) { + case HIDLMergeStatus::NONE: + return MergeStatus::NONE; + case HIDLMergeStatus::UNKNOWN: + return MergeStatus::UNKNOWN; + case HIDLMergeStatus::SNAPSHOTTED: + return MergeStatus::SNAPSHOTTED; + case HIDLMergeStatus::MERGING: + return MergeStatus::MERGING; + case HIDLMergeStatus::CANCELLED: + return MergeStatus::CANCELLED; + } +} + +static constexpr HIDLMergeStatus ToHIDLMergeStatus(MergeStatus status) { + switch (status) { + case MergeStatus::NONE: + return HIDLMergeStatus::NONE; + case MergeStatus::UNKNOWN: + return HIDLMergeStatus::UNKNOWN; + case MergeStatus::SNAPSHOTTED: + return HIDLMergeStatus::SNAPSHOTTED; + case MergeStatus::MERGING: + return HIDLMergeStatus::MERGING; + case MergeStatus::CANCELLED: + return HIDLMergeStatus::CANCELLED; + } +} + +} + +ScopedAStatus BootControl::getSnapshotMergeStatus(MergeStatus* _aidl_return) { + *_aidl_return = ToAIDLMergeStatus(impl_.GetSnapshotMergeStatus()); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::getSuffix(int32_t in_slot, std::string* _aidl_return) { + if (!impl_.IsValidSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str()); + } + *_aidl_return = impl_.GetSuffix(in_slot); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::isSlotBootable(int32_t in_slot, bool* _aidl_return) { + if (!impl_.IsValidSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str()); + } + *_aidl_return = impl_.IsSlotBootable(in_slot); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::isSlotMarkedSuccessful(int32_t in_slot, bool* _aidl_return) { + if (!impl_.IsValidSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str()); + } + *_aidl_return = impl_.IsSlotMarkedSuccessful(in_slot); + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::markBootSuccessful() { + if (!impl_.MarkBootSuccessful()) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED, + "Operation failed"); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::setActiveBootSlot(int32_t in_slot) { + if (!impl_.IsValidSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str()); + } + if (!impl_.SetActiveBootSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED, + "Operation failed"); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::setSlotAsUnbootable(int32_t in_slot) { + if (!impl_.IsValidSlot(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + INVALID_SLOT, (std::string("Invalid slot ") + std::to_string(in_slot)).c_str()); + } + if (!impl_.SetSlotAsUnbootable(in_slot)) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED, + "Operation failed"); + } + return ScopedAStatus::ok(); +} + +ScopedAStatus BootControl::setSnapshotMergeStatus(MergeStatus in_status) { + if (!impl_.SetSnapshotMergeStatus(ToHIDLMergeStatus(in_status))) { + return ScopedAStatus::fromServiceSpecificErrorWithMessage(COMMAND_FAILED, + "Operation failed"); + } + return ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::boot diff --git a/boot/aidl/default/BootControl.h b/boot/aidl/default/BootControl.h new file mode 100644 index 0000000000..54cd32d410 --- /dev/null +++ b/boot/aidl/default/BootControl.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 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 +#include + +namespace aidl::android::hardware::boot { + +class BootControl final : public BnBootControl { + public: + BootControl(); + ::ndk::ScopedAStatus getActiveBootSlot(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus getCurrentSlot(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus getNumberSlots(int32_t* _aidl_return) override; + ::ndk::ScopedAStatus getSnapshotMergeStatus( + ::aidl::android::hardware::boot::MergeStatus* _aidl_return) override; + ::ndk::ScopedAStatus getSuffix(int32_t in_slot, std::string* _aidl_return) override; + ::ndk::ScopedAStatus isSlotBootable(int32_t in_slot, bool* _aidl_return) override; + ::ndk::ScopedAStatus isSlotMarkedSuccessful(int32_t in_slot, bool* _aidl_return) override; + ::ndk::ScopedAStatus markBootSuccessful() override; + ::ndk::ScopedAStatus setActiveBootSlot(int32_t in_slot) override; + ::ndk::ScopedAStatus setSlotAsUnbootable(int32_t in_slot) override; + ::ndk::ScopedAStatus setSnapshotMergeStatus( + ::aidl::android::hardware::boot::MergeStatus in_status) override; + + private: + ::android::bootable::BootControl impl_; +}; + +} // namespace aidl::android::hardware::boot diff --git a/boot/aidl/default/boot-default.rc b/boot/aidl/default/boot-default.rc new file mode 100644 index 0000000000..589f803e37 --- /dev/null +++ b/boot/aidl/default/boot-default.rc @@ -0,0 +1,5 @@ +service vendor.boot-default /vendor/bin/hw/android.hardware.boot-service.default + class early_hal + user root + group root + diff --git a/boot/aidl/default/boot-default.xml b/boot/aidl/default/boot-default.xml new file mode 100644 index 0000000000..23ccc4e36c --- /dev/null +++ b/boot/aidl/default/boot-default.xml @@ -0,0 +1,6 @@ + + + android.hardware.boot + IBootControl/default + + diff --git a/boot/aidl/default/main.cpp b/boot/aidl/default/main.cpp new file mode 100644 index 0000000000..70b284e385 --- /dev/null +++ b/boot/aidl/default/main.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 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. + */ + +#include "BootControl.h" + +#include +#include +#include + +using aidl::android::hardware::boot::BootControl; +using aidl::android::hardware::boot::IBootControl; + +int main(int, char* argv[]) { + android::base::InitLogging(argv, android::base::KernelLogger); + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr service = ndk::SharedRefBase::make(); + + const std::string instance = std::string(BootControl::descriptor) + "/default"; + auto status = AServiceManager_addService(service->asBinder().get(), instance.c_str()); + CHECK_EQ(status, STATUS_OK) << "Failed to add service " << instance << " " << status; + LOG(INFO) << "IBootControl AIDL service running..."; + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +}