1 /*
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>
21 #include <android/binder_ibinder.h>
22 #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
38 using aidl::android::hardware::boot::MergeStatus;
39
40 #define TEST_OP(_x, _y, op) \
41 do { \
42 const auto& x = _x; \
43 const auto& y = _y; \
44 if (!(x op y)) { \
45 LOG(ERROR) << #_x " " #op " " #_y << " failed: " << x << " " #op " " << y; \
46 return {}; \
47 } \
48 } while (0)
49 #define TEST_NE(_x, _y) TEST_OP(_x, _y, !=)
50
operator <<(std::ostream & os,MergeStatus status)51 std::ostream& operator<<(std::ostream& os, MergeStatus status) {
52 switch (status) {
53 case MergeStatus::NONE:
54 os << "MergeStatus::NONE";
55 break;
56 case MergeStatus::UNKNOWN:
57 os << "MergeStatus::UNKNOWN";
58 break;
59 case MergeStatus::SNAPSHOTTED:
60 os << "MergeStatus::SNAPSHOTTED";
61 break;
62 case MergeStatus::MERGING:
63 os << "MergeStatus::MERGING";
64 break;
65 case MergeStatus::CANCELLED:
66 os << "MergeStatus::CANCELLED";
67 break;
68 default:
69 os << static_cast<int>(status);
70 break;
71 }
72 return os;
73 }
74
75 namespace android::hal {
76 class BootControlClientAidl final : public BootControlClient {
77 using IBootControl = ::aidl::android::hardware::boot::IBootControl;
78
79 public:
BootControlClientAidl(std::shared_ptr<IBootControl> module)80 explicit BootControlClientAidl(std::shared_ptr<IBootControl> module)
81 : module_(module),
82 boot_control_death_recipient(AIBinder_DeathRecipient_new(onBootControlServiceDied)) {
83 binder_status_t status =
84 AIBinder_linkToDeath(module->asBinder().get(), boot_control_death_recipient, this);
85 if (status != STATUS_OK) {
86 LOG(ERROR) << "Could not link to binder death";
87 return;
88 }
89 }
90
GetVersion() const91 BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
92
onBootControlServiceDied()93 void onBootControlServiceDied() {
94 LOG(ERROR) << "boot control service AIDL died. Attempting to reconnect...";
95 const auto instance_name =
96 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
97 if (AServiceManager_isDeclared(instance_name.c_str())) {
98 module_ = ::aidl::android::hardware::boot::IBootControl::fromBinder(
99 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
100 if (module_ == nullptr) {
101 LOG(ERROR) << "AIDL " << instance_name
102 << " is declared but waitForService returned nullptr when trying to "
103 "reconnect boot control service";
104 return;
105 }
106 LOG(INFO) << "Reconnected to AIDL version of IBootControl";
107 binder_status_t status = AIBinder_linkToDeath(module_->asBinder().get(),
108 boot_control_death_recipient, this);
109 if (status != STATUS_OK) {
110 LOG(ERROR) << "Could not link to binder death";
111 return;
112 }
113
114 } else {
115 LOG(ERROR) << "Failed to get service manager for: " << instance_name;
116 }
117 }
118
GetNumSlots() const119 int32_t GetNumSlots() const override {
120 int32_t ret = -1;
121 if (!module_) {
122 LOG(ERROR) << "bootctl module not set";
123 return ret;
124 }
125 LOG_NDK_STATUS(module_->getNumberSlots(&ret));
126 return ret;
127 }
128
GetCurrentSlot() const129 int32_t GetCurrentSlot() const override {
130 int32_t ret = -1;
131 if (!module_) {
132 LOG(ERROR) << "bootctl module not set";
133 return ret;
134 }
135 LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
136 return ret;
137 }
138
getSnapshotMergeStatus() const139 MergeStatus getSnapshotMergeStatus() const override {
140 MergeStatus status = MergeStatus::UNKNOWN;
141 if (!module_) {
142 LOG(ERROR) << "bootctl module not set";
143 return status;
144 }
145 LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
146 return status;
147 }
148
GetSuffix(int32_t slot) const149 std::string GetSuffix(int32_t slot) const override {
150 TEST_NE(module_, nullptr);
151 std::string ret;
152 const auto status = module_->getSuffix(slot, &ret);
153 if (!status.isOk()) {
154 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
155 << status.getDescription();
156 return {};
157 }
158 return ret;
159 }
160
IsSlotBootable(int32_t slot) const161 std::optional<bool> IsSlotBootable(int32_t slot) const override {
162 TEST_NE(module_, nullptr);
163 bool ret = false;
164 const auto status = module_->isSlotBootable(slot, &ret);
165 if (!status.isOk()) {
166 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
167 << status.getDescription();
168 return {};
169 }
170 return ret;
171 }
172
MarkSlotUnbootable(int32_t slot)173 CommandResult MarkSlotUnbootable(int32_t slot) override {
174 TEST_NE(module_, nullptr);
175 const auto status = module_->setSlotAsUnbootable(slot);
176 if (!status.isOk()) {
177 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
178 << status.getDescription();
179 }
180 return {.success = status.isOk(), .errMsg = status.getDescription()};
181 }
182
SetActiveBootSlot(int slot)183 CommandResult SetActiveBootSlot(int slot) override {
184 TEST_NE(module_, nullptr);
185 const auto status = module_->setActiveBootSlot(slot);
186 if (!status.isOk()) {
187 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
188 << status.getDescription();
189 }
190 return {.success = status.isOk(), .errMsg = status.getDescription()};
191 }
192
GetActiveBootSlot() const193 int GetActiveBootSlot() const {
194 int ret = -1;
195 if (!module_) {
196 LOG(ERROR) << "bootctl module not set";
197 return ret;
198 }
199 LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
200 return ret;
201 }
202
203 // Check if |slot| is marked boot successfully.
IsSlotMarkedSuccessful(int slot) const204 std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
205 TEST_NE(module_, nullptr);
206 bool ret = false;
207 const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
208 if (!status.isOk()) {
209 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
210 << status.getDescription();
211 return {};
212 }
213 return ret;
214 }
215
MarkBootSuccessful()216 CommandResult MarkBootSuccessful() override {
217 TEST_NE(module_, nullptr);
218 const auto status = module_->markBootSuccessful();
219 if (!status.isOk()) {
220 LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
221 }
222 return {.success = status.isOk(), .errMsg = status.getDescription()};
223 }
224
SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status)225 CommandResult SetSnapshotMergeStatus(
226 aidl::android::hardware::boot::MergeStatus merge_status) override {
227 TEST_NE(module_, nullptr);
228 const auto status = module_->setSnapshotMergeStatus(merge_status);
229 if (!status.isOk()) {
230 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
231 << status.getDescription();
232 }
233 return {.success = status.isOk(), .errMsg = status.getDescription()};
234 }
235
236 private:
237 std::shared_ptr<IBootControl> module_;
238 AIBinder_DeathRecipient* boot_control_death_recipient;
onBootControlServiceDied(void * client)239 static void onBootControlServiceDied(void* client) {
240 BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
241 self->onBootControlServiceDied();
242 }
243 };
244
245 using namespace android::hardware::boot;
246
247 class BootControlClientHIDL final : public BootControlClient {
248 public:
BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,android::sp<V1_1::IBootControl> module_v1_1,android::sp<V1_2::IBootControl> module_v1_2)249 BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
250 android::sp<V1_1::IBootControl> module_v1_1,
251 android::sp<V1_2::IBootControl> module_v1_2)
252 : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
253 CHECK(module_v1_ != nullptr);
254 }
GetVersion() const255 BootControlVersion GetVersion() const override {
256 if (module_v1_2_ != nullptr) {
257 return BootControlVersion::BOOTCTL_V1_2;
258 } else if (module_v1_1_ != nullptr) {
259 return BootControlVersion::BOOTCTL_V1_1;
260 } else {
261 return BootControlVersion::BOOTCTL_V1_0;
262 }
263 }
GetNumSlots() const264 int32_t GetNumSlots() const override {
265 const auto ret = module_v1_->getNumberSlots();
266 if (!ret.isOk()) {
267 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
268 }
269 return ret.withDefault(-1);
270 }
271
GetCurrentSlot() const272 int32_t GetCurrentSlot() const override {
273 const auto ret = module_v1_->getCurrentSlot();
274 if (!ret.isOk()) {
275 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
276 }
277 return ret.withDefault(-1);
278 }
279
GetSuffix(int32_t slot) const280 std::string GetSuffix(int32_t slot) const override {
281 std::string suffix;
282 const auto ret = module_v1_->getSuffix(
283 slot,
284 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
285 if (!ret.isOk()) {
286 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
287 }
288 return suffix;
289 }
290
IsSlotBootable(int32_t slot) const291 std::optional<bool> IsSlotBootable(int32_t slot) const override {
292 const auto ret = module_v1_->isSlotBootable(slot);
293 if (!ret.isOk()) {
294 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
295 return {};
296 }
297 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
298 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
299 return {};
300 }
301 return bool_result == V1_0::BoolResult::TRUE;
302 }
303
MarkSlotUnbootable(int32_t slot)304 CommandResult MarkSlotUnbootable(int32_t slot) override {
305 CommandResult result;
306 const auto ret =
307 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
308 result.success = error.success;
309 result.errMsg = error.errMsg;
310 });
311 if (!ret.isOk()) {
312 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
313 }
314 return result;
315 }
316
SetActiveBootSlot(int32_t slot)317 CommandResult SetActiveBootSlot(int32_t slot) override {
318 CommandResult result;
319 const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
320 result.success = error.success;
321 result.errMsg = error.errMsg;
322 });
323 if (!ret.isOk()) {
324 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
325 }
326 return result;
327 }
328
MarkBootSuccessful()329 CommandResult MarkBootSuccessful() override {
330 CommandResult result;
331 const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
332 result.success = error.success;
333 result.errMsg = error.errMsg;
334 });
335 if (!ret.isOk()) {
336 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
337 }
338 return result;
339 }
340
IsSlotMarkedSuccessful(int32_t slot) const341 std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
342 const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
343 if (!ret.isOk()) {
344 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
345 return {};
346 }
347 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
348 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
349 return {};
350 }
351 return bool_result == V1_0::BoolResult::TRUE;
352 }
353
getSnapshotMergeStatus() const354 MergeStatus getSnapshotMergeStatus() const override {
355 if (module_v1_1_ == nullptr) {
356 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
357 return MergeStatus::UNKNOWN;
358 }
359 const auto ret = module_v1_1_->getSnapshotMergeStatus();
360 if (!ret.isOk()) {
361 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
362 }
363 return static_cast<MergeStatus>(
364 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
365 }
366
SetSnapshotMergeStatus(MergeStatus merge_status)367 CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
368 if (module_v1_1_ == nullptr) {
369 return {.success = false,
370 .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
371 }
372 const auto ret =
373 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
374 if (!ret.isOk()) {
375 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
376 << ret.description();
377 }
378 return {.success = ret.isOk(), .errMsg = ret.description()};
379 }
380
GetActiveBootSlot() const381 int32_t GetActiveBootSlot() const override {
382 if (module_v1_2_ == nullptr) {
383 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
384 return -1;
385 }
386 const auto ret = module_v1_2_->getActiveBootSlot();
387 if (!ret.isOk()) {
388 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
389 }
390 return ret.withDefault(-1);
391 }
392
393 private:
394 android::sp<V1_0::IBootControl> module_v1_;
395 android::sp<V1_1::IBootControl> module_v1_1_;
396 android::sp<V1_2::IBootControl> module_v1_2_;
397 };
398
WaitForService()399 std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
400 const auto instance_name =
401 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
402 if (AServiceManager_isDeclared(instance_name.c_str())) {
403 auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
404 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
405 if (module == nullptr) {
406 LOG(ERROR) << "AIDL " << instance_name
407 << " is declared but waitForService returned nullptr.";
408 return nullptr;
409 }
410 LOG(INFO) << "Using AIDL version of IBootControl";
411 return std::make_unique<BootControlClientAidl>(module);
412 }
413 LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
414
415 android::sp<V1_0::IBootControl> v1_0_module;
416 android::sp<V1_1::IBootControl> v1_1_module;
417 android::sp<V1_2::IBootControl> v1_2_module;
418 v1_0_module = V1_0::IBootControl::getService();
419 if (v1_0_module == nullptr) {
420 LOG(ERROR) << "Error getting bootctrl v1.0 module.";
421 return nullptr;
422 }
423 v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
424 v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
425 if (v1_2_module != nullptr) {
426 LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
427 } else if (v1_1_module != nullptr) {
428 LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
429 } else {
430 LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
431 }
432
433 return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
434 }
435
436 } // namespace android::hal
437