• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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