xref: /aosp_15_r20/system/update_engine/aosp/boot_control_android.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1 //
2 // Copyright (C) 2015 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 "update_engine/aosp/boot_control_android.h"
18 
19 #include <memory>
20 #include <utility>
21 #include <vector>
22 
23 #include <base/bind.h>
24 #include <base/logging.h>
25 #include <bootloader_message/bootloader_message.h>
26 #include <brillo/message_loops/message_loop.h>
27 
28 #include "update_engine/aosp/dynamic_partition_control_android.h"
29 
30 using std::string;
31 
32 using Slot = chromeos_update_engine::BootControlInterface::Slot;
33 
34 namespace {
35 
36 }  // namespace
37 
38 namespace chromeos_update_engine {
39 
40 namespace boot_control {
41 
42 // Factory defined in boot_control.h.
CreateBootControl()43 std::unique_ptr<BootControlInterface> CreateBootControl() {
44   auto boot_control = std::make_unique<BootControlAndroid>();
45   if (!boot_control->Init()) {
46     return nullptr;
47   }
48   return std::move(boot_control);
49 }
50 
51 }  // namespace boot_control
52 
53 using android::hal::BootControlClient;
54 using android::hal::CommandResult;
55 using android::hal::BootControlVersion;
56 
Init()57 bool BootControlAndroid::Init() {
58   module_ = BootControlClient::WaitForService();
59   if (module_ == nullptr) {
60     LOG(ERROR) << "Error getting bootctrl module.";
61     return false;
62   }
63 
64   LOG(INFO) << "Loaded boot control hal.";
65 
66   dynamic_control_ =
67       std::make_unique<DynamicPartitionControlAndroid>(GetCurrentSlot());
68 
69   return true;
70 }
71 
GetNumSlots() const72 unsigned int BootControlAndroid::GetNumSlots() const {
73   return module_->GetNumSlots();
74 }
75 
GetCurrentSlot() const76 BootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const {
77   return module_->GetCurrentSlot();
78 }
79 
GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,bool not_in_payload,std::string * device,bool * is_dynamic) const80 bool BootControlAndroid::GetPartitionDevice(const std::string& partition_name,
81                                             BootControlInterface::Slot slot,
82                                             bool not_in_payload,
83                                             std::string* device,
84                                             bool* is_dynamic) const {
85   return dynamic_control_->GetPartitionDevice(partition_name,
86                                               slot,
87                                               GetCurrentSlot(),
88                                               not_in_payload,
89                                               device,
90                                               is_dynamic);
91 }
92 
GetPartitionDevice(const string & partition_name,BootControlInterface::Slot slot,string * device) const93 bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
94                                             BootControlInterface::Slot slot,
95                                             string* device) const {
96   return GetPartitionDevice(
97       partition_name, slot, false /* not_in_payload */, device, nullptr);
98 }
99 
IsSlotBootable(Slot slot) const100 bool BootControlAndroid::IsSlotBootable(Slot slot) const {
101   const auto ret = module_->IsSlotBootable(slot);
102   if (!ret.has_value()) {
103     LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
104                << " is bootable";
105     return false;
106   }
107   return ret.value();
108 }
109 
MarkSlotUnbootable(Slot slot)110 bool BootControlAndroid::MarkSlotUnbootable(Slot slot) {
111   const auto ret = module_->MarkSlotUnbootable(slot);
112   if (!ret.IsOk()) {
113     LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot "
114                << SlotName(slot) << ": " << ret.errMsg;
115     return false;
116   }
117   return ret.success;
118 }
119 
SetActiveBootSlot(Slot slot)120 bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
121   const auto result = module_->SetActiveBootSlot(slot);
122   if (!result.IsOk()) {
123     LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot)
124                << ": " << result.errMsg;
125     return false;
126   }
127   if (!result.success) {
128     LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
129                << ": " << result.errMsg.c_str();
130   }
131   return result.success;
132 }
133 
MarkBootSuccessfulAsync(base::Callback<void (bool)> callback)134 bool BootControlAndroid::MarkBootSuccessfulAsync(
135     base::Callback<void(bool)> callback) {
136   auto ret = module_->MarkBootSuccessful();
137   if (!ret.IsOk()) {
138     LOG(ERROR) << "Unable to MarkBootSuccessful: " << ret.errMsg;
139     return false;
140   }
141   return brillo::MessageLoop::current()->PostTask(
142              FROM_HERE, base::Bind(callback, ret.success)) !=
143          brillo::MessageLoop::kTaskIdNull;
144 }
145 
IsSlotMarkedSuccessful(BootControlInterface::Slot slot) const146 bool BootControlAndroid::IsSlotMarkedSuccessful(
147     BootControlInterface::Slot slot) const {
148   const auto ret = module_->IsSlotMarkedSuccessful(slot);
149   CommandResult result;
150   if (!ret.has_value()) {
151     LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
152                << " is marked successful";
153     return false;
154   }
155   return ret.value();
156 }
157 
GetActiveBootSlot()158 Slot BootControlAndroid::GetActiveBootSlot() {
159   if (module_->GetVersion() >= android::hal::BootControlVersion::BOOTCTL_V1_2) {
160     return module_->GetActiveBootSlot();
161   }
162   LOG(WARNING) << "BootControl module version is lower than 1.2, "
163                << __FUNCTION__ << " failed";
164   return kInvalidSlot;
165 }
166 
167 DynamicPartitionControlInterface*
GetDynamicPartitionControl()168 BootControlAndroid::GetDynamicPartitionControl() {
169   return dynamic_control_.get();
170 }
171 
GetPartitionDevice(const std::string & partition_name,uint32_t slot,uint32_t current_slot,bool not_in_payload) const172 std::optional<PartitionDevice> BootControlAndroid::GetPartitionDevice(
173     const std::string& partition_name,
174     uint32_t slot,
175     uint32_t current_slot,
176     bool not_in_payload) const {
177   return dynamic_control_->GetPartitionDevice(
178       partition_name, slot, current_slot, not_in_payload);
179 }
180 }  // namespace chromeos_update_engine
181