blob: 090d62416a4274a2caf09847dd64987bfa08866a [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 Zheng01d5a1d2024-10-16 14:09:50 -070082 void onBootControlServiceDied() {
83 LOG(ERROR) << "boot control service AIDL died. Attempting to reconnect...";
84 const auto instance_name =
85 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
86 if (AServiceManager_isDeclared(instance_name.c_str())) {
87 module_ = ::aidl::android::hardware::boot::IBootControl::fromBinder(
88 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
89 if (module_ == nullptr) {
90 LOG(ERROR) << "AIDL " << instance_name
91 << " is declared but waitForService returned nullptr when trying to "
92 "reconnect boot control service";
93 return;
94 }
95 LOG(INFO) << "Reconnected to AIDL version of IBootControl";
96 binder_status_t status = AIBinder_linkToDeath(module_->asBinder().get(),
97 boot_control_death_recipient, this);
98 if (status != STATUS_OK) {
99 LOG(ERROR) << "Could not link to binder death";
100 return;
101 }
102
103 } else {
104 LOG(ERROR) << "Failed to get service manager for: " << instance_name;
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700105 }
106 }
107
Daniel Zhengcba98612024-10-10 09:54:33 -0700108 int32_t GetNumSlots() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700109 int32_t ret = -1;
110 LOG_NDK_STATUS(module_->getNumberSlots(&ret));
111 return ret;
112 }
113
Daniel Zhengcba98612024-10-10 09:54:33 -0700114 int32_t GetCurrentSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700115 int32_t ret = -1;
116 LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
117 return ret;
118 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700119 MergeStatus getSnapshotMergeStatus() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700120 MergeStatus status = MergeStatus::UNKNOWN;
121 LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
122 return status;
123 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700124 std::string GetSuffix(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700125 std::string ret;
126 const auto status = module_->getSuffix(slot, &ret);
127 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700128 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
129 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700130 return {};
131 }
132 return ret;
133 }
134
Daniel Zhengcba98612024-10-10 09:54:33 -0700135 std::optional<bool> IsSlotBootable(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700136 bool ret = false;
137 const auto status = module_->isSlotBootable(slot, &ret);
138 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700139 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
140 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700141 return {};
142 }
143 return ret;
144 }
145
Daniel Zhengcba98612024-10-10 09:54:33 -0700146 CommandResult MarkSlotUnbootable(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700147 const auto status = module_->setSlotAsUnbootable(slot);
148 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700149 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
150 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700151 }
152 return {.success = status.isOk(), .errMsg = status.getDescription()};
153 }
154
Daniel Zhengcba98612024-10-10 09:54:33 -0700155 CommandResult SetActiveBootSlot(int slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700156 const auto status = module_->setActiveBootSlot(slot);
157 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700158 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
159 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700160 }
161 return {.success = status.isOk(), .errMsg = status.getDescription()};
162 }
163 int GetActiveBootSlot() const {
164 int ret = -1;
165 LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
166 return ret;
167 }
168
169 // Check if |slot| is marked boot successfully.
Daniel Zhengcba98612024-10-10 09:54:33 -0700170 std::optional<bool> IsSlotMarkedSuccessful(int slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700171 bool ret = false;
172 const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
173 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700174 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed "
175 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700176 return {};
177 }
178 return ret;
179 }
180
Daniel Zhengcba98612024-10-10 09:54:33 -0700181 CommandResult MarkBootSuccessful() override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700182 const auto status = module_->markBootSuccessful();
183 if (!status.isOk()) {
184 LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
185 }
186 return {.success = status.isOk(), .errMsg = status.getDescription()};
187 }
188
Daniel Zhengcba98612024-10-10 09:54:33 -0700189 CommandResult SetSnapshotMergeStatus(
190 aidl::android::hardware::boot::MergeStatus merge_status) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700191 const auto status = module_->setSnapshotMergeStatus(merge_status);
192 if (!status.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700193 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
194 << status.getDescription();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700195 }
196 return {.success = status.isOk(), .errMsg = status.getDescription()};
197 }
198
199 private:
Daniel Zheng01d5a1d2024-10-16 14:09:50 -0700200 std::shared_ptr<IBootControl> module_;
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700201 AIBinder_DeathRecipient* boot_control_death_recipient;
202 static void onBootControlServiceDied(void* client) {
203 BootControlClientAidl* self = static_cast<BootControlClientAidl*>(client);
204 self->onBootControlServiceDied();
205 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700206};
207
208using namespace android::hardware::boot;
209
210class BootControlClientHIDL final : public BootControlClient {
211 public:
212 BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
213 android::sp<V1_1::IBootControl> module_v1_1,
214 android::sp<V1_2::IBootControl> module_v1_2)
215 : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
216 CHECK(module_v1_ != nullptr);
217 }
218 BootControlVersion GetVersion() const override {
219 if (module_v1_2_ != nullptr) {
220 return BootControlVersion::BOOTCTL_V1_2;
221 } else if (module_v1_1_ != nullptr) {
222 return BootControlVersion::BOOTCTL_V1_1;
223 } else {
224 return BootControlVersion::BOOTCTL_V1_0;
225 }
226 }
Daniel Zhengcba98612024-10-10 09:54:33 -0700227 int32_t GetNumSlots() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700228 const auto ret = module_v1_->getNumberSlots();
229 if (!ret.isOk()) {
230 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
231 }
232 return ret.withDefault(-1);
233 }
234
Daniel Zhengcba98612024-10-10 09:54:33 -0700235 int32_t GetCurrentSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700236 const auto ret = module_v1_->getCurrentSlot();
237 if (!ret.isOk()) {
238 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
239 }
240 return ret.withDefault(-1);
241 }
242
Daniel Zhengcba98612024-10-10 09:54:33 -0700243 std::string GetSuffix(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700244 std::string suffix;
245 const auto ret = module_v1_->getSuffix(
246 slot,
247 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
248 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700249 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700250 }
251 return suffix;
252 }
253
Daniel Zhengcba98612024-10-10 09:54:33 -0700254 std::optional<bool> IsSlotBootable(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700255 const auto ret = module_v1_->isSlotBootable(slot);
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 return {};
259 }
260 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
261 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
262 return {};
263 }
264 return bool_result == V1_0::BoolResult::TRUE;
265 }
266
Daniel Zhengcba98612024-10-10 09:54:33 -0700267 CommandResult MarkSlotUnbootable(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700268 CommandResult result;
269 const auto ret =
270 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
271 result.success = error.success;
272 result.errMsg = error.errMsg;
273 });
274 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700275 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700276 }
277 return result;
278 }
279
Daniel Zhengcba98612024-10-10 09:54:33 -0700280 CommandResult SetActiveBootSlot(int32_t slot) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700281 CommandResult result;
282 const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
283 result.success = error.success;
284 result.errMsg = error.errMsg;
285 });
286 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700287 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700288 }
289 return result;
290 }
291
Daniel Zhengcba98612024-10-10 09:54:33 -0700292 CommandResult MarkBootSuccessful() override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700293 CommandResult result;
294 const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
295 result.success = error.success;
296 result.errMsg = error.errMsg;
297 });
298 if (!ret.isOk()) {
299 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
300 }
301 return result;
302 }
303
Daniel Zhengcba98612024-10-10 09:54:33 -0700304 std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700305 const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
306 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700307 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")" << " failed " << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700308 return {};
309 }
310 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
311 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
312 return {};
313 }
314 return bool_result == V1_0::BoolResult::TRUE;
315 }
316
Daniel Zhengcba98612024-10-10 09:54:33 -0700317 MergeStatus getSnapshotMergeStatus() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700318 if (module_v1_1_ == nullptr) {
319 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
320 return MergeStatus::UNKNOWN;
321 }
322 const auto ret = module_v1_1_->getSnapshotMergeStatus();
323 if (!ret.isOk()) {
324 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
325 }
326 return static_cast<MergeStatus>(
327 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
328 }
329
Daniel Zhengcba98612024-10-10 09:54:33 -0700330 CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700331 if (module_v1_1_ == nullptr) {
332 return {.success = false,
333 .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
334 }
335 const auto ret =
336 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
337 if (!ret.isOk()) {
Daniel Zheng28b6b2b2024-10-08 12:39:17 -0700338 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")" << " failed "
339 << ret.description();
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700340 }
341 return {.success = ret.isOk(), .errMsg = ret.description()};
342 }
343
Daniel Zhengcba98612024-10-10 09:54:33 -0700344 int32_t GetActiveBootSlot() const override {
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700345 if (module_v1_2_ == nullptr) {
346 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
347 return -1;
348 }
349 const auto ret = module_v1_2_->getActiveBootSlot();
350 if (!ret.isOk()) {
351 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
352 }
353 return ret.withDefault(-1);
354 }
355
356 private:
357 android::sp<V1_0::IBootControl> module_v1_;
358 android::sp<V1_1::IBootControl> module_v1_1_;
359 android::sp<V1_2::IBootControl> module_v1_2_;
360};
361
362std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
363 const auto instance_name =
364 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700365 if (AServiceManager_isDeclared(instance_name.c_str())) {
366 auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700367 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
Kelvin Zhang781b4ff2022-06-27 16:29:53 -0700368 if (module == nullptr) {
369 LOG(ERROR) << "AIDL " << instance_name
370 << " is declared but waitForService returned nullptr.";
371 return nullptr;
372 }
Kelvin Zhangb66d2a02022-06-15 13:10:58 -0700373 LOG(INFO) << "Using AIDL version of IBootControl";
374 return std::make_unique<BootControlClientAidl>(module);
375 }
376 LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
377
378 android::sp<V1_0::IBootControl> v1_0_module;
379 android::sp<V1_1::IBootControl> v1_1_module;
380 android::sp<V1_2::IBootControl> v1_2_module;
381 v1_0_module = V1_0::IBootControl::getService();
382 if (v1_0_module == nullptr) {
383 LOG(ERROR) << "Error getting bootctrl v1.0 module.";
384 return nullptr;
385 }
386 v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
387 v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
388 if (v1_2_module != nullptr) {
389 LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
390 } else if (v1_1_module != nullptr) {
391 LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
392 } else {
393 LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
394 }
395
396 return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
397}
398
399} // namespace android::hal