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_manager.h>
22 #include <android/hardware/boot/1.0/IBootControl.h>
23 #include <android/hardware/boot/1.1/IBootControl.h>
24 #include <android/hardware/boot/1.2/IBootControl.h>
25 #include "utils/StrongPointer.h"
26
27 #define CONCAT(x, y) x##y
28
29 #define LOG_NDK_STATUS(x) \
30 do { \
31 const auto CONCAT(status, __COUNTER__) = x; \
32 if (!CONCAT(status, __COUNTER__).isOk()) { \
33 LOG(ERROR) << #x << " failed " << CONCAT(status, __COUNTER__).getDescription(); \
34 } \
35 } while (0)
36
37 using aidl::android::hardware::boot::MergeStatus;
38
operator <<(std::ostream & os,MergeStatus status)39 std::ostream& operator<<(std::ostream& os, MergeStatus status) {
40 switch (status) {
41 case MergeStatus::NONE:
42 os << "MergeStatus::NONE";
43 break;
44 case MergeStatus::UNKNOWN:
45 os << "MergeStatus::UNKNOWN";
46 break;
47 case MergeStatus::SNAPSHOTTED:
48 os << "MergeStatus::SNAPSHOTTED";
49 break;
50 case MergeStatus::MERGING:
51 os << "MergeStatus::MERGING";
52 break;
53 case MergeStatus::CANCELLED:
54 os << "MergeStatus::CANCELLED";
55 break;
56 default:
57 os << static_cast<int>(status);
58 break;
59 }
60 return os;
61 }
62
63 namespace android::hal {
64 class BootControlClientAidl final : public BootControlClient {
65 using IBootControl = ::aidl::android::hardware::boot::IBootControl;
66
67 public:
BootControlClientAidl(std::shared_ptr<IBootControl> module)68 BootControlClientAidl(std::shared_ptr<IBootControl> module) : module_(module) {}
69
GetVersion() const70 BootControlVersion GetVersion() const override { return BootControlVersion::BOOTCTL_AIDL; }
71
72 ~BootControlClientAidl() = default;
GetNumSlots() const73 virtual int32_t GetNumSlots() const {
74 int32_t ret = -1;
75 LOG_NDK_STATUS(module_->getNumberSlots(&ret));
76 return ret;
77 }
78
GetCurrentSlot() const79 int32_t GetCurrentSlot() const {
80 int32_t ret = -1;
81 LOG_NDK_STATUS(module_->getCurrentSlot(&ret));
82 return ret;
83 }
getSnapshotMergeStatus() const84 MergeStatus getSnapshotMergeStatus() const {
85 MergeStatus status = MergeStatus::UNKNOWN;
86 LOG_NDK_STATUS(module_->getSnapshotMergeStatus(&status));
87 return status;
88 }
GetSuffix(int32_t slot) const89 std::string GetSuffix(int32_t slot) const {
90 std::string ret;
91 const auto status = module_->getSuffix(slot, &ret);
92 if (!status.isOk()) {
93 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
94 << " failed " << status.getDescription();
95 return {};
96 }
97 return ret;
98 }
99
IsSlotBootable(int32_t slot) const100 std::optional<bool> IsSlotBootable(int32_t slot) const {
101 bool ret = false;
102 const auto status = module_->isSlotBootable(slot, &ret);
103 if (!status.isOk()) {
104 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
105 << " failed " << status.getDescription();
106 return {};
107 }
108 return ret;
109 }
110
MarkSlotUnbootable(int32_t slot)111 CommandResult MarkSlotUnbootable(int32_t slot) {
112 const auto status = module_->setSlotAsUnbootable(slot);
113 if (!status.isOk()) {
114 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
115 << " failed " << status.getDescription();
116 }
117 return {.success = status.isOk(), .errMsg = status.getDescription()};
118 }
119
SetActiveBootSlot(int slot)120 CommandResult SetActiveBootSlot(int slot) {
121 const auto status = module_->setActiveBootSlot(slot);
122 if (!status.isOk()) {
123 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
124 << " failed " << status.getDescription();
125 }
126 return {.success = status.isOk(), .errMsg = status.getDescription()};
127 }
GetActiveBootSlot() const128 int GetActiveBootSlot() const {
129 int ret = -1;
130 LOG_NDK_STATUS(module_->getActiveBootSlot(&ret));
131 return ret;
132 }
133
134 // Check if |slot| is marked boot successfully.
IsSlotMarkedSuccessful(int slot) const135 std::optional<bool> IsSlotMarkedSuccessful(int slot) const {
136 bool ret = false;
137 const auto status = module_->isSlotMarkedSuccessful(slot, &ret);
138 if (!status.isOk()) {
139 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
140 << " failed " << status.getDescription();
141 return {};
142 }
143 return ret;
144 }
145
MarkBootSuccessful()146 CommandResult MarkBootSuccessful() {
147 const auto status = module_->markBootSuccessful();
148 if (!status.isOk()) {
149 LOG(ERROR) << __FUNCTION__ << " failed " << status.getDescription();
150 }
151 return {.success = status.isOk(), .errMsg = status.getDescription()};
152 }
153
SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status)154 CommandResult SetSnapshotMergeStatus(aidl::android::hardware::boot::MergeStatus merge_status) {
155 const auto status = module_->setSnapshotMergeStatus(merge_status);
156 if (!status.isOk()) {
157 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
158 << " failed " << status.getDescription();
159 }
160 return {.success = status.isOk(), .errMsg = status.getDescription()};
161 }
162
163 private:
164 const std::shared_ptr<IBootControl> module_;
165 };
166
167 using namespace android::hardware::boot;
168
169 class BootControlClientHIDL final : public BootControlClient {
170 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)171 BootControlClientHIDL(android::sp<V1_0::IBootControl> module_v1,
172 android::sp<V1_1::IBootControl> module_v1_1,
173 android::sp<V1_2::IBootControl> module_v1_2)
174 : module_v1_(module_v1), module_v1_1_(module_v1_1), module_v1_2_(module_v1_2) {
175 CHECK(module_v1_ != nullptr);
176 }
GetVersion() const177 BootControlVersion GetVersion() const override {
178 if (module_v1_2_ != nullptr) {
179 return BootControlVersion::BOOTCTL_V1_2;
180 } else if (module_v1_1_ != nullptr) {
181 return BootControlVersion::BOOTCTL_V1_1;
182 } else {
183 return BootControlVersion::BOOTCTL_V1_0;
184 }
185 }
GetNumSlots() const186 int32_t GetNumSlots() const {
187 const auto ret = module_v1_->getNumberSlots();
188 if (!ret.isOk()) {
189 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
190 }
191 return ret.withDefault(-1);
192 }
193
GetCurrentSlot() const194 int32_t GetCurrentSlot() const {
195 const auto ret = module_v1_->getCurrentSlot();
196 if (!ret.isOk()) {
197 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
198 }
199 return ret.withDefault(-1);
200 }
201
GetSuffix(int32_t slot) const202 std::string GetSuffix(int32_t slot) const {
203 std::string suffix;
204 const auto ret = module_v1_->getSuffix(
205 slot,
206 [&](const ::android::hardware::hidl_string& slotSuffix) { suffix = slotSuffix; });
207 if (!ret.isOk()) {
208 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
209 << " failed " << ret.description();
210 }
211 return suffix;
212 }
213
IsSlotBootable(int32_t slot) const214 std::optional<bool> IsSlotBootable(int32_t slot) const {
215 const auto ret = module_v1_->isSlotBootable(slot);
216 if (!ret.isOk()) {
217 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
218 << " failed " << ret.description();
219 return {};
220 }
221 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
222 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
223 return {};
224 }
225 return bool_result == V1_0::BoolResult::TRUE;
226 }
227
MarkSlotUnbootable(int32_t slot)228 CommandResult MarkSlotUnbootable(int32_t slot) {
229 CommandResult result;
230 const auto ret =
231 module_v1_->setSlotAsUnbootable(slot, [&](const V1_0::CommandResult& error) {
232 result.success = error.success;
233 result.errMsg = error.errMsg;
234 });
235 if (!ret.isOk()) {
236 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
237 << " failed " << ret.description();
238 }
239 return result;
240 }
241
SetActiveBootSlot(int32_t slot)242 CommandResult SetActiveBootSlot(int32_t slot) {
243 CommandResult result;
244 const auto ret = module_v1_->setActiveBootSlot(slot, [&](const V1_0::CommandResult& error) {
245 result.success = error.success;
246 result.errMsg = error.errMsg;
247 });
248 if (!ret.isOk()) {
249 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
250 << " failed " << ret.description();
251 }
252 return result;
253 }
254
MarkBootSuccessful()255 CommandResult MarkBootSuccessful() {
256 CommandResult result;
257 const auto ret = module_v1_->markBootSuccessful([&](const V1_0::CommandResult& error) {
258 result.success = error.success;
259 result.errMsg = error.errMsg;
260 });
261 if (!ret.isOk()) {
262 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
263 }
264 return result;
265 }
266
IsSlotMarkedSuccessful(int32_t slot) const267 std::optional<bool> IsSlotMarkedSuccessful(int32_t slot) const {
268 const auto ret = module_v1_->isSlotMarkedSuccessful(slot);
269 if (!ret.isOk()) {
270 LOG(ERROR) << __FUNCTION__ << "(" << slot << ")"
271 << " failed " << ret.description();
272 return {};
273 }
274 const auto bool_result = ret.withDefault(V1_0::BoolResult::INVALID_SLOT);
275 if (bool_result == V1_0::BoolResult::INVALID_SLOT) {
276 return {};
277 }
278 return bool_result == V1_0::BoolResult::TRUE;
279 }
280
getSnapshotMergeStatus() const281 MergeStatus getSnapshotMergeStatus() const {
282 if (module_v1_1_ == nullptr) {
283 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.1";
284 return MergeStatus::UNKNOWN;
285 }
286 const auto ret = module_v1_1_->getSnapshotMergeStatus();
287 if (!ret.isOk()) {
288 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
289 }
290 return static_cast<MergeStatus>(
291 ret.withDefault(static_cast<V1_1::MergeStatus>(MergeStatus::UNKNOWN)));
292 }
293
SetSnapshotMergeStatus(MergeStatus merge_status)294 CommandResult SetSnapshotMergeStatus(MergeStatus merge_status) {
295 if (module_v1_1_ == nullptr) {
296 return {.success = false,
297 .errMsg = "setSnapshotMergeStatus is unsupported, requires at least boot v1.1"};
298 }
299 const auto ret =
300 module_v1_1_->setSnapshotMergeStatus(static_cast<V1_1::MergeStatus>(merge_status));
301 if (!ret.isOk()) {
302 LOG(ERROR) << __FUNCTION__ << "(" << merge_status << ")"
303 << " failed " << ret.description();
304 }
305 return {.success = ret.isOk(), .errMsg = ret.description()};
306 }
307
GetActiveBootSlot() const308 int32_t GetActiveBootSlot() const {
309 if (module_v1_2_ == nullptr) {
310 LOG(ERROR) << __FUNCTION__ << " is unsupported, requires at least boot v1.2";
311 return -1;
312 }
313 const auto ret = module_v1_2_->getActiveBootSlot();
314 if (!ret.isOk()) {
315 LOG(ERROR) << __FUNCTION__ << " failed " << ret.description();
316 }
317 return ret.withDefault(-1);
318 }
319
320 private:
321 android::sp<V1_0::IBootControl> module_v1_;
322 android::sp<V1_1::IBootControl> module_v1_1_;
323 android::sp<V1_2::IBootControl> module_v1_2_;
324 };
325
WaitForService()326 std::unique_ptr<BootControlClient> BootControlClient::WaitForService() {
327 const auto instance_name =
328 std::string(::aidl::android::hardware::boot::IBootControl::descriptor) + "/default";
329
330 if (AServiceManager_isDeclared(instance_name.c_str())) {
331 auto module = ::aidl::android::hardware::boot::IBootControl::fromBinder(
332 ndk::SpAIBinder(AServiceManager_waitForService(instance_name.c_str())));
333 if (module == nullptr) {
334 LOG(ERROR) << "AIDL " << instance_name
335 << " is declared but waitForService returned nullptr.";
336 return nullptr;
337 }
338 LOG(INFO) << "Using AIDL version of IBootControl";
339 return std::make_unique<BootControlClientAidl>(module);
340 }
341 LOG(INFO) << "AIDL IBootControl not available, falling back to HIDL.";
342
343 android::sp<V1_0::IBootControl> v1_0_module;
344 android::sp<V1_1::IBootControl> v1_1_module;
345 android::sp<V1_2::IBootControl> v1_2_module;
346 v1_0_module = V1_0::IBootControl::getService();
347 if (v1_0_module == nullptr) {
348 LOG(ERROR) << "Error getting bootctrl v1.0 module.";
349 return nullptr;
350 }
351 v1_1_module = V1_1::IBootControl::castFrom(v1_0_module);
352 v1_2_module = V1_2::IBootControl::castFrom(v1_0_module);
353 if (v1_2_module != nullptr) {
354 LOG(INFO) << "Using HIDL version 1.2 of IBootControl";
355 } else if (v1_1_module != nullptr) {
356 LOG(INFO) << "Using HIDL version 1.1 of IBootControl";
357 } else {
358 LOG(INFO) << "Using HIDL version 1.0 of IBootControl";
359 }
360
361 return std::make_unique<BootControlClientHIDL>(v1_0_module, v1_1_module, v1_2_module);
362 }
363
364 } // namespace android::hal
365