blob: 10f0ffe2e9006509d91ba210d1131d549c12a4f6 [file] [log] [blame]
Kelvin Zhangb66d2a02022-06-15 13:10:58 -07001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <BootControlClient.h>
18
19#include <aidl/android/hardware/boot/IBootControl.h>
20#include <android-base/logging.h>
Daniel Zheng28b6b2b2024-10-08 12:39:17 -070021#include <android/binder_ibinder.h>
Kelvin Zhangb66d2a02022-06-15 13:10:58 -070022#include <android/binder_manager.h>
23#include <android/hardware/boot/1.0/IBootControl.h>
24#include <android/hardware/boot/1.1/IBootControl.h>
25#include <android/hardware/boot/1.2/IBootControl.h>
26#include "utils/StrongPointer.h"
27
28#define CONCAT(x, y) x##y
29
30#define LOG_NDK_STATUS(x) \
31 do { \
32 const auto CONCAT(status, __COUNTER__) = x; \
33 if (!CONCAT(status, __COUNTER__).isOk()) { \
34 LOG(ERROR) << #x << " failed " << CONCAT(status, __COUNTER__).getDescription(); \
35 } \
36 } while (0)
37
38using aidl::android::hardware::boot::MergeStatus;
39
40std::ostream& operator<<(std::ostream& os, MergeStatus status) {
41 switch (status) {
42 case MergeStatus::NONE:
43 os << "MergeStatus::NONE";
44 break;
45 case MergeStatus::UNKNOWN:
46 os << "MergeStatus::UNKNOWN";
47 break;
48 case MergeStatus::SNAPSHOTTED:
49 os << "MergeStatus::SNAPSHOTTED";
50 break;
51 case MergeStatus::MERGING:
52 os << "MergeStatus::MERGING";
53 break;
54 case MergeStatus::CANCELLED:
55 os << "MergeStatus::CANCELLED";
56 break;
57 default:
58 os << static_cast<int>(status);
59 break;
60 }
61 return os;
62}
63
64namespace android::hal {
65class BootControlClientAidl final : public BootControlClient {
66 using IBootControl = ::aidl::android::hardware::boot::IBootControl;
67
68 public:
Daniel Zheng28b6b2b2024-10-08 12:39:17 -070069 explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
70 : module_(module),
71 boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
Daniel Zhengd5d0c552024-10-16 14:01:23 -070072 binder_status_t status =
73 AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
Daniel Zheng28b6b2b2024-10-08 12:39:17 -070074 if (status != STATUS_OK) {
75 LOG(ERROR) << "Could not link to binder death";
76 return;
77 }
78 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -070079
80 BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
81
Daniel Zheng28b6b2b2024-10-08 12:39:17 -070082 ~BootControlClientAidl() {
83 if (boot_control_death_recipient) {
84 AIBinder_unlinkToDeath(module_->asBinder().get(), boot_control_death_recipient, this);
85 }
86 }
87
88 void onBootControlServiceDied() { LOG(ERROR) << "boot control service AIDL died"; }
89
Daniel Zhengcba98612024-10-10 09:54:33 -070090 int32_t GetNumSlots() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -070091 int32_t ret = -1;
92 LOG_NDK_STATUS(module_->getNumberSlots(&ret));
93 return ret;
94 }
95
Daniel Zhengcba98612024-10-10 09:54:33 -070096 int32_t GetCurrentSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -070097 int32_t ret = -1;
98 LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
99 return ret;
100 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700101 MergeStatus getSnapshotMergeStatus() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700102 MergeStatus status = MergeStatus::UNKNOWN;
103 LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
104 return status;
105 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700106 std::string GetSuffix(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700107 std::string ret;
108 const auto status = module_->getSuffix(slot, &ret);
109 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700110 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
111 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700112 return {};
113 }
114 return ret;
115 }
116
Daniel Zhengcba98612024-10-10 09:54:33 -0700117 std::optional<bool> IsSlotBootable(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700118 bool ret = false;
119 const auto status = module_->isSlotBootable(slot, &ret);
120 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700121 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
122 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700123 return {};
124 }
125 return ret;
126 }
127
Daniel Zhengcba98612024-10-10 09:54:33 -0700128 CommandResult MarkSlotUnbootable(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700129 const auto status = module_->setSlotAsUnbootable(slot);
130 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700131 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
132 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700133 }
134 return {.success = status.isOk(), .errMsg = status.getDescription()};
135 }
136
Daniel Zhengcba98612024-10-10 09:54:33 -0700137 CommandResult SetActiveBootSlot(int slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700138 const auto status = module_->setActiveBootSlot(slot);
139 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700140 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
141 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700142 }
143 return {.success = status.isOk(), .errMsg = status.getDescription()};
144 }
145 int GetActiveBootSlot() const {
146 int ret = -1;
147 LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
148 return ret;
149 }
150
151 // Check if |slot| is marked boot successfully.
Daniel Zhengcba98612024-10-10 09:54:33 -0700152 std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700153 bool ret = false;
154 const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
155 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700156 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
157 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700158 return {};
159 }
160 return ret;
161 }
162
Daniel Zhengcba98612024-10-10 09:54:33 -0700163 CommandResult MarkBootSuccessful() override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700164 const auto status = module_->markBootSuccessful();
165 if (!status.isOk()) {
166 LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
167 }
168 return {.success = status.isOk(), .errMsg = status.getDescription()};
169 }
170
Daniel Zhengcba98612024-10-10 09:54:33 -0700171 CommandResult SetSnapshotMergeStatus(
172 aidl::android::hardware::boot::MergeStatus merge_status) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700173 const auto status = module_->setSnapshotMergeStatus(merge_status);
174 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700175 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
176 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700177 }
178 return {.success = status.isOk(), .errMsg = status.getDescription()};
179 }
180
181 private:
182 const std::shared_ptr<IBootControl> module_;
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700183 AIBinder_DeathRecipient* boot_control_death_recipient;
184 static void onBootControlServiceDied(void* client) {
185 BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
186 self->onBootControlServiceDied();
187 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700188};
189
190using namespace android::hardware::boot;
191
192class BootControlClientHIDL final : public BootControlClient {
193 public:
194 BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
195 android::sp<V1_1::IBootControl> module_v1_1,
196 android::sp<V1_2::IBootControl> module_v1_2)
197 : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
198 CHECK(module_v1_ != nullptr);
199 }
200 BootControlVersion GetVersion() const override {
201 if (module_v1_2_ != nullptr) {
202 return BootControlVersion::BOOTCTL_V1_2;
203 } else if (module_v1_1_ != nullptr) {
204 return BootControlVersion::BOOTCTL_V1_1;
205 } else {
206 return BootControlVersion::BOOTCTL_V1_0;
207 }
208 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700209 int32_t GetNumSlots() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700210 const auto ret = module_v1_->getNumberSlots();
211 if (!ret.isOk()) {
212 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
213 }
214 return ret.withDefault(-1);
215 }
216
Daniel Zhengcba98612024-10-10 09:54:33 -0700217 int32_t GetCurrentSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700218 const auto ret = module_v1_->getCurrentSlot();
219 if (!ret.isOk()) {
220 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
221 }
222 return ret.withDefault(-1);
223 }
224
Daniel Zhengcba98612024-10-10 09:54:33 -0700225 std::string GetSuffix(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700226 std::string suffix;
227 const auto ret = module_v1_->getSuffix(
228 slot,
229 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
230 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700231 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700232 }
233 return suffix;
234 }
235
Daniel Zhengcba98612024-10-10 09:54:33 -0700236 std::optional<bool> IsSlotBootable(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700237 const auto ret = module_v1_->isSlotBootable(slot);
238 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700239 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700240 return {};
241 }
242 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
243 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
244 return {};
245 }
246 return bool_result == V1_0::BoolResult::TRUE;
247 }
248
Daniel Zhengcba98612024-10-10 09:54:33 -0700249 CommandResult MarkSlotUnbootable(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700250 CommandResult result;
251 const auto ret =
252 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
253 result.success = error.success;
254 result.errMsg = error.errMsg;
255 });
256 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700257 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700258 }
259 return result;
260 }
261
Daniel Zhengcba98612024-10-10 09:54:33 -0700262 CommandResult SetActiveBootSlot(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700263 CommandResult result;
264 const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
265 result.success = error.success;
266 result.errMsg = error.errMsg;
267 });
268 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700269 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700270 }
271 return result;
272 }
273
Daniel Zhengcba98612024-10-10 09:54:33 -0700274 CommandResult MarkBootSuccessful() override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700275 CommandResult result;
276 const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
277 result.success = error.success;
278 result.errMsg = error.errMsg;
279 });
280 if (!ret.isOk()) {
281 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
282 }
283 return result;
284 }
285
Daniel Zhengcba98612024-10-10 09:54:33 -0700286 std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700287 const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
288 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700289 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700290 return {};
291 }
292 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
293 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
294 return {};
295 }
296 return bool_result == V1_0::BoolResult::TRUE;
297 }
298
Daniel Zhengcba98612024-10-10 09:54:33 -0700299 MergeStatus getSnapshotMergeStatus() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700300 if (module_v1_1_ == nullptr) {
301 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
302 return MergeStatus::UNKNOWN;
303 }
304 const auto ret = module_v1_1_->getSnapshotMergeStatus();
305 if (!ret.isOk()) {
306 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
307 }
308 return static_cast<MergeStatus>(
309 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
310 }
311
Daniel Zhengcba98612024-10-10 09:54:33 -0700312 CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700313 if (module_v1_1_ == nullptr) {
314 return {.success = false,
315 .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
316 }
317 const auto ret =
318 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
319 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700320 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
321 << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700322 }
323 return {.success = ret.isOk(), .errMsg = ret.description()};
324 }
325
Daniel Zhengcba98612024-10-10 09:54:33 -0700326 int32_t GetActiveBootSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700327 if (module_v1_2_ == nullptr) {
328 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
329 return -1;
330 }
331 const auto ret = module_v1_2_->getActiveBootSlot();
332 if (!ret.isOk()) {
333 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
334 }
335 return ret.withDefault(-1);
336 }
337
338 private:
339 android::sp<V1_0::IBootControl> module_v1_;
340 android::sp<V1_1::IBootControl> module_v1_1_;
341 android::sp<V1_2::IBootControl> module_v1_2_;
342};
343
344std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
345 const auto instance_name =
346 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700347 if (AServiceManager_isDeclared(instance_name.c_str())) {
348 auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700349 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700350 if (module == nullptr) {
351 LOG(ERROR) << "AIDL " << instance_name
352 << " is declared but waitForService returned nullptr.";
353 return nullptr;
354 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700355 LOG(INFO) << "Using AIDL version of IBootControl";
356 return std::make_unique<BootControlClientAidl>(module);
357 }
358 LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
359
360 android::sp<V1_0::IBootControl> v1_0_module;
361 android::sp<V1_1::IBootControl> v1_1_module;
362 android::sp<V1_2::IBootControl> v1_2_module;
363 v1_0_module = V1_0::IBootControl::getService();
364 if (v1_0_module == nullptr) {
365 LOG(ERROR) << "Error getting bootctrl v1.0 module.";
366 return nullptr;
367 }
368 v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
369 v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
370 if (v1_2_module != nullptr) {
371 LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
372 } else if (v1_1_module != nullptr) {
373 LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
374 } else {
375 LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
376 }
377
378 return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
379}
380
381} // namespace android::hal