xref: /aosp_15_r20/system/update_engine/aosp/boot_control_android.cc (revision 5a9231315b4521097b8dc3750bc806fcafe0c72f)
1*5a923131SAndroid Build Coastguard Worker //
2*5a923131SAndroid Build Coastguard Worker // Copyright (C) 2015 The Android Open Source Project
3*5a923131SAndroid Build Coastguard Worker //
4*5a923131SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*5a923131SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*5a923131SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*5a923131SAndroid Build Coastguard Worker //
8*5a923131SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*5a923131SAndroid Build Coastguard Worker //
10*5a923131SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*5a923131SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*5a923131SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5a923131SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*5a923131SAndroid Build Coastguard Worker // limitations under the License.
15*5a923131SAndroid Build Coastguard Worker //
16*5a923131SAndroid Build Coastguard Worker 
17*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/boot_control_android.h"
18*5a923131SAndroid Build Coastguard Worker 
19*5a923131SAndroid Build Coastguard Worker #include <memory>
20*5a923131SAndroid Build Coastguard Worker #include <utility>
21*5a923131SAndroid Build Coastguard Worker #include <vector>
22*5a923131SAndroid Build Coastguard Worker 
23*5a923131SAndroid Build Coastguard Worker #include <base/bind.h>
24*5a923131SAndroid Build Coastguard Worker #include <base/logging.h>
25*5a923131SAndroid Build Coastguard Worker #include <bootloader_message/bootloader_message.h>
26*5a923131SAndroid Build Coastguard Worker #include <brillo/message_loops/message_loop.h>
27*5a923131SAndroid Build Coastguard Worker 
28*5a923131SAndroid Build Coastguard Worker #include "update_engine/aosp/dynamic_partition_control_android.h"
29*5a923131SAndroid Build Coastguard Worker 
30*5a923131SAndroid Build Coastguard Worker using std::string;
31*5a923131SAndroid Build Coastguard Worker 
32*5a923131SAndroid Build Coastguard Worker using Slot = chromeos_update_engine::BootControlInterface::Slot;
33*5a923131SAndroid Build Coastguard Worker 
34*5a923131SAndroid Build Coastguard Worker namespace {
35*5a923131SAndroid Build Coastguard Worker 
36*5a923131SAndroid Build Coastguard Worker }  // namespace
37*5a923131SAndroid Build Coastguard Worker 
38*5a923131SAndroid Build Coastguard Worker namespace chromeos_update_engine {
39*5a923131SAndroid Build Coastguard Worker 
40*5a923131SAndroid Build Coastguard Worker namespace boot_control {
41*5a923131SAndroid Build Coastguard Worker 
42*5a923131SAndroid Build Coastguard Worker // Factory defined in boot_control.h.
CreateBootControl()43*5a923131SAndroid Build Coastguard Worker std::unique_ptr<BootControlInterface> CreateBootControl() {
44*5a923131SAndroid Build Coastguard Worker   auto boot_control = std::make_unique<BootControlAndroid>();
45*5a923131SAndroid Build Coastguard Worker   if (!boot_control->Init()) {
46*5a923131SAndroid Build Coastguard Worker     return nullptr;
47*5a923131SAndroid Build Coastguard Worker   }
48*5a923131SAndroid Build Coastguard Worker   return std::move(boot_control);
49*5a923131SAndroid Build Coastguard Worker }
50*5a923131SAndroid Build Coastguard Worker 
51*5a923131SAndroid Build Coastguard Worker }  // namespace boot_control
52*5a923131SAndroid Build Coastguard Worker 
53*5a923131SAndroid Build Coastguard Worker using android::hal::BootControlClient;
54*5a923131SAndroid Build Coastguard Worker using android::hal::CommandResult;
55*5a923131SAndroid Build Coastguard Worker using android::hal::BootControlVersion;
56*5a923131SAndroid Build Coastguard Worker 
Init()57*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::Init() {
58*5a923131SAndroid Build Coastguard Worker   module_ = BootControlClient::WaitForService();
59*5a923131SAndroid Build Coastguard Worker   if (module_ == nullptr) {
60*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Error getting bootctrl module.";
61*5a923131SAndroid Build Coastguard Worker     return false;
62*5a923131SAndroid Build Coastguard Worker   }
63*5a923131SAndroid Build Coastguard Worker 
64*5a923131SAndroid Build Coastguard Worker   LOG(INFO) << "Loaded boot control hal.";
65*5a923131SAndroid Build Coastguard Worker 
66*5a923131SAndroid Build Coastguard Worker   dynamic_control_ =
67*5a923131SAndroid Build Coastguard Worker       std::make_unique<DynamicPartitionControlAndroid>(GetCurrentSlot());
68*5a923131SAndroid Build Coastguard Worker 
69*5a923131SAndroid Build Coastguard Worker   return true;
70*5a923131SAndroid Build Coastguard Worker }
71*5a923131SAndroid Build Coastguard Worker 
GetNumSlots() const72*5a923131SAndroid Build Coastguard Worker unsigned int BootControlAndroid::GetNumSlots() const {
73*5a923131SAndroid Build Coastguard Worker   return module_->GetNumSlots();
74*5a923131SAndroid Build Coastguard Worker }
75*5a923131SAndroid Build Coastguard Worker 
GetCurrentSlot() const76*5a923131SAndroid Build Coastguard Worker BootControlInterface::Slot BootControlAndroid::GetCurrentSlot() const {
77*5a923131SAndroid Build Coastguard Worker   return module_->GetCurrentSlot();
78*5a923131SAndroid Build Coastguard Worker }
79*5a923131SAndroid Build Coastguard Worker 
GetPartitionDevice(const std::string & partition_name,BootControlInterface::Slot slot,bool not_in_payload,std::string * device,bool * is_dynamic) const80*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::GetPartitionDevice(const std::string& partition_name,
81*5a923131SAndroid Build Coastguard Worker                                             BootControlInterface::Slot slot,
82*5a923131SAndroid Build Coastguard Worker                                             bool not_in_payload,
83*5a923131SAndroid Build Coastguard Worker                                             std::string* device,
84*5a923131SAndroid Build Coastguard Worker                                             bool* is_dynamic) const {
85*5a923131SAndroid Build Coastguard Worker   return dynamic_control_->GetPartitionDevice(partition_name,
86*5a923131SAndroid Build Coastguard Worker                                               slot,
87*5a923131SAndroid Build Coastguard Worker                                               GetCurrentSlot(),
88*5a923131SAndroid Build Coastguard Worker                                               not_in_payload,
89*5a923131SAndroid Build Coastguard Worker                                               device,
90*5a923131SAndroid Build Coastguard Worker                                               is_dynamic);
91*5a923131SAndroid Build Coastguard Worker }
92*5a923131SAndroid Build Coastguard Worker 
GetPartitionDevice(const string & partition_name,BootControlInterface::Slot slot,string * device) const93*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::GetPartitionDevice(const string& partition_name,
94*5a923131SAndroid Build Coastguard Worker                                             BootControlInterface::Slot slot,
95*5a923131SAndroid Build Coastguard Worker                                             string* device) const {
96*5a923131SAndroid Build Coastguard Worker   return GetPartitionDevice(
97*5a923131SAndroid Build Coastguard Worker       partition_name, slot, false /* not_in_payload */, device, nullptr);
98*5a923131SAndroid Build Coastguard Worker }
99*5a923131SAndroid Build Coastguard Worker 
IsSlotBootable(Slot slot) const100*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::IsSlotBootable(Slot slot) const {
101*5a923131SAndroid Build Coastguard Worker   const auto ret = module_->IsSlotBootable(slot);
102*5a923131SAndroid Build Coastguard Worker   if (!ret.has_value()) {
103*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
104*5a923131SAndroid Build Coastguard Worker                << " is bootable";
105*5a923131SAndroid Build Coastguard Worker     return false;
106*5a923131SAndroid Build Coastguard Worker   }
107*5a923131SAndroid Build Coastguard Worker   return ret.value();
108*5a923131SAndroid Build Coastguard Worker }
109*5a923131SAndroid Build Coastguard Worker 
MarkSlotUnbootable(Slot slot)110*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::MarkSlotUnbootable(Slot slot) {
111*5a923131SAndroid Build Coastguard Worker   const auto ret = module_->MarkSlotUnbootable(slot);
112*5a923131SAndroid Build Coastguard Worker   if (!ret.IsOk()) {
113*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to call MarkSlotUnbootable for slot "
114*5a923131SAndroid Build Coastguard Worker                << SlotName(slot) << ": " << ret.errMsg;
115*5a923131SAndroid Build Coastguard Worker     return false;
116*5a923131SAndroid Build Coastguard Worker   }
117*5a923131SAndroid Build Coastguard Worker   return ret.success;
118*5a923131SAndroid Build Coastguard Worker }
119*5a923131SAndroid Build Coastguard Worker 
SetActiveBootSlot(Slot slot)120*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
121*5a923131SAndroid Build Coastguard Worker   const auto result = module_->SetActiveBootSlot(slot);
122*5a923131SAndroid Build Coastguard Worker   if (!result.IsOk()) {
123*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to call SetActiveBootSlot for slot " << SlotName(slot)
124*5a923131SAndroid Build Coastguard Worker                << ": " << result.errMsg;
125*5a923131SAndroid Build Coastguard Worker     return false;
126*5a923131SAndroid Build Coastguard Worker   }
127*5a923131SAndroid Build Coastguard Worker   if (!result.success) {
128*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to set the active slot to slot " << SlotName(slot)
129*5a923131SAndroid Build Coastguard Worker                << ": " << result.errMsg.c_str();
130*5a923131SAndroid Build Coastguard Worker   }
131*5a923131SAndroid Build Coastguard Worker   return result.success;
132*5a923131SAndroid Build Coastguard Worker }
133*5a923131SAndroid Build Coastguard Worker 
MarkBootSuccessfulAsync(base::Callback<void (bool)> callback)134*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::MarkBootSuccessfulAsync(
135*5a923131SAndroid Build Coastguard Worker     base::Callback<void(bool)> callback) {
136*5a923131SAndroid Build Coastguard Worker   auto ret = module_->MarkBootSuccessful();
137*5a923131SAndroid Build Coastguard Worker   if (!ret.IsOk()) {
138*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to MarkBootSuccessful: " << ret.errMsg;
139*5a923131SAndroid Build Coastguard Worker     return false;
140*5a923131SAndroid Build Coastguard Worker   }
141*5a923131SAndroid Build Coastguard Worker   return brillo::MessageLoop::current()->PostTask(
142*5a923131SAndroid Build Coastguard Worker              FROM_HERE, base::Bind(callback, ret.success)) !=
143*5a923131SAndroid Build Coastguard Worker          brillo::MessageLoop::kTaskIdNull;
144*5a923131SAndroid Build Coastguard Worker }
145*5a923131SAndroid Build Coastguard Worker 
IsSlotMarkedSuccessful(BootControlInterface::Slot slot) const146*5a923131SAndroid Build Coastguard Worker bool BootControlAndroid::IsSlotMarkedSuccessful(
147*5a923131SAndroid Build Coastguard Worker     BootControlInterface::Slot slot) const {
148*5a923131SAndroid Build Coastguard Worker   const auto ret = module_->IsSlotMarkedSuccessful(slot);
149*5a923131SAndroid Build Coastguard Worker   CommandResult result;
150*5a923131SAndroid Build Coastguard Worker   if (!ret.has_value()) {
151*5a923131SAndroid Build Coastguard Worker     LOG(ERROR) << "Unable to determine if slot " << SlotName(slot)
152*5a923131SAndroid Build Coastguard Worker                << " is marked successful";
153*5a923131SAndroid Build Coastguard Worker     return false;
154*5a923131SAndroid Build Coastguard Worker   }
155*5a923131SAndroid Build Coastguard Worker   return ret.value();
156*5a923131SAndroid Build Coastguard Worker }
157*5a923131SAndroid Build Coastguard Worker 
GetActiveBootSlot()158*5a923131SAndroid Build Coastguard Worker Slot BootControlAndroid::GetActiveBootSlot() {
159*5a923131SAndroid Build Coastguard Worker   if (module_->GetVersion() >= android::hal::BootControlVersion::BOOTCTL_V1_2) {
160*5a923131SAndroid Build Coastguard Worker     return module_->GetActiveBootSlot();
161*5a923131SAndroid Build Coastguard Worker   }
162*5a923131SAndroid Build Coastguard Worker   LOG(WARNING) << "BootControl module version is lower than 1.2, "
163*5a923131SAndroid Build Coastguard Worker                << __FUNCTION__ << " failed";
164*5a923131SAndroid Build Coastguard Worker   return kInvalidSlot;
165*5a923131SAndroid Build Coastguard Worker }
166*5a923131SAndroid Build Coastguard Worker 
167*5a923131SAndroid Build Coastguard Worker DynamicPartitionControlInterface*
GetDynamicPartitionControl()168*5a923131SAndroid Build Coastguard Worker BootControlAndroid::GetDynamicPartitionControl() {
169*5a923131SAndroid Build Coastguard Worker   return dynamic_control_.get();
170*5a923131SAndroid Build Coastguard Worker }
171*5a923131SAndroid Build Coastguard Worker 
GetPartitionDevice(const std::string & partition_name,uint32_t slot,uint32_t current_slot,bool not_in_payload) const172*5a923131SAndroid Build Coastguard Worker std::optional<PartitionDevice> BootControlAndroid::GetPartitionDevice(
173*5a923131SAndroid Build Coastguard Worker     const std::string& partition_name,
174*5a923131SAndroid Build Coastguard Worker     uint32_t slot,
175*5a923131SAndroid Build Coastguard Worker     uint32_t current_slot,
176*5a923131SAndroid Build Coastguard Worker     bool not_in_payload) const {
177*5a923131SAndroid Build Coastguard Worker   return dynamic_control_->GetPartitionDevice(
178*5a923131SAndroid Build Coastguard Worker       partition_name, slot, current_slot, not_in_payload);
179*5a923131SAndroid Build Coastguard Worker }
180*5a923131SAndroid Build Coastguard Worker }  // namespace chromeos_update_engine
181