blob: d625ee98b420d9222eb511de816c2ae8c611d46c [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)) {
72 binder_status_t status = AIBinder_linkToDeath(module->asBinder().get(),
73 boot_control_death_recipient, nullptr);
74 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
Kelvin Zhangb66d2a02022-06-15 13:10:58 -070090 virtual int32_t GetNumSlots() const {
91 int32_t ret = -1;
92 LOG_NDK_STATUS(module_->getNumberSlots(&ret));
93 return ret;
94 }
95
96 int32_t GetCurrentSlot() const {
97 int32_t ret = -1;
98 LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
99 return ret;
100 }
101 MergeStatus getSnapshotMergeStatus() const {
102 MergeStatus status = MergeStatus::UNKNOWN;
103 LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
104 return status;
105 }
106 std::string GetSuffix(int32_t slot) const {
107 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
117 std::optional<bool> IsSlotBootable(int32_t slot) const {
118 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
128 CommandResult MarkSlotUnbootable(int32_t slot) {
129 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
137 CommandResult SetActiveBootSlot(int slot) {
138 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.
152 std::optional<bool> IsSlotMarkedSuccessful(int slot) const {
153 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
163 CommandResult MarkBootSuccessful() {
164 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
171 CommandResult SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status) {
172 const auto status = module_->setSnapshotMergeStatus(merge_status);
173 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700174 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
175 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700176 }
177 return {.success = status.isOk(), .errMsg = status.getDescription()};
178 }
179
180 private:
181 const std::shared_ptr<IBootControl> module_;
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700182 AIBinder_DeathRecipient* boot_control_death_recipient;
183 static void onBootControlServiceDied(void* client) {
184 BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
185 self->onBootControlServiceDied();
186 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700187};
188
189using namespace android::hardware::boot;
190
191class BootControlClientHIDL final : public BootControlClient {
192 public:
193 BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
194 android::sp<V1_1::IBootControl> module_v1_1,
195 android::sp<V1_2::IBootControl> module_v1_2)
196 : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
197 CHECK(module_v1_ != nullptr);
198 }
199 BootControlVersion GetVersion() const override {
200 if (module_v1_2_ != nullptr) {
201 return BootControlVersion::BOOTCTL_V1_2;
202 } else if (module_v1_1_ != nullptr) {
203 return BootControlVersion::BOOTCTL_V1_1;
204 } else {
205 return BootControlVersion::BOOTCTL_V1_0;
206 }
207 }
208 int32_t GetNumSlots() const {
209 const auto ret = module_v1_->getNumberSlots();
210 if (!ret.isOk()) {
211 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
212 }
213 return ret.withDefault(-1);
214 }
215
216 int32_t GetCurrentSlot() const {
217 const auto ret = module_v1_->getCurrentSlot();
218 if (!ret.isOk()) {
219 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
220 }
221 return ret.withDefault(-1);
222 }
223
224 std::string GetSuffix(int32_t slot) const {
225 std::string suffix;
226 const auto ret = module_v1_->getSuffix(
227 slot,
228 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
229 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700230 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700231 }
232 return suffix;
233 }
234
235 std::optional<bool> IsSlotBootable(int32_t slot) const {
236 const auto ret = module_v1_->isSlotBootable(slot);
237 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700238 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700239 return {};
240 }
241 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
242 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
243 return {};
244 }
245 return bool_result == V1_0::BoolResult::TRUE;
246 }
247
248 CommandResult MarkSlotUnbootable(int32_t slot) {
249 CommandResult result;
250 const auto ret =
251 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
252 result.success = error.success;
253 result.errMsg = error.errMsg;
254 });
255 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700256 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700257 }
258 return result;
259 }
260
261 CommandResult SetActiveBootSlot(int32_t slot) {
262 CommandResult result;
263 const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
264 result.success = error.success;
265 result.errMsg = error.errMsg;
266 });
267 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700268 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700269 }
270 return result;
271 }
272
273 CommandResult MarkBootSuccessful() {
274 CommandResult result;
275 const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
276 result.success = error.success;
277 result.errMsg = error.errMsg;
278 });
279 if (!ret.isOk()) {
280 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
281 }
282 return result;
283 }
284
285 std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const {
286 const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
287 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700288 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700289 return {};
290 }
291 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
292 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
293 return {};
294 }
295 return bool_result == V1_0::BoolResult::TRUE;
296 }
297
298 MergeStatus getSnapshotMergeStatus() const {
299 if (module_v1_1_ == nullptr) {
300 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
301 return MergeStatus::UNKNOWN;
302 }
303 const auto ret = module_v1_1_->getSnapshotMergeStatus();
304 if (!ret.isOk()) {
305 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
306 }
307 return static_cast<MergeStatus>(
308 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
309 }
310
311 CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) {
312 if (module_v1_1_ == nullptr) {
313 return {.success = false,
314 .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
315 }
316 const auto ret =
317 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
318 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700319 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
320 << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700321 }
322 return {.success = ret.isOk(), .errMsg = ret.description()};
323 }
324
325 int32_t GetActiveBootSlot() const {
326 if (module_v1_2_ == nullptr) {
327 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
328 return -1;
329 }
330 const auto ret = module_v1_2_->getActiveBootSlot();
331 if (!ret.isOk()) {
332 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
333 }
334 return ret.withDefault(-1);
335 }
336
337 private:
338 android::sp<V1_0::IBootControl> module_v1_;
339 android::sp<V1_1::IBootControl> module_v1_1_;
340 android::sp<V1_2::IBootControl> module_v1_2_;
341};
342
343std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
344 const auto instance_name =
345 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700346 if (AServiceManager_isDeclared(instance_name.c_str())) {
347 auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700348 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700349 if (module == nullptr) {
350 LOG(ERROR) << "AIDL " << instance_name
351 << " is declared but waitForService returned nullptr.";
352 return nullptr;
353 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700354 LOG(INFO) << "Using AIDL version of IBootControl";
355 return std::make_unique<BootControlClientAidl>(module);
356 }
357 LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
358
359 android::sp<V1_0::IBootControl> v1_0_module;
360 android::sp<V1_1::IBootControl> v1_1_module;
361 android::sp<V1_2::IBootControl> v1_2_module;
362 v1_0_module = V1_0::IBootControl::getService();
363 if (v1_0_module == nullptr) {
364 LOG(ERROR) << "Error getting bootctrl v1.0 module.";
365 return nullptr;
366 }
367 v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
368 v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
369 if (v1_2_module != nullptr) {
370 LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
371 } else if (v1_1_module != nullptr) {
372 LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
373 } else {
374 LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
375 }
376
377 return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
378}
379
380} // namespace android::hal