xref: /aosp_15_r20/system/extras/bootctl/bootctl.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include <optional>
18*288bf522SAndroid Build Coastguard Worker #include <sstream>
19*288bf522SAndroid Build Coastguard Worker 
20*288bf522SAndroid Build Coastguard Worker #include <BootControlClient.h>
21*288bf522SAndroid Build Coastguard Worker #include <android/hardware/boot/1.2/IBootControl.h>
22*288bf522SAndroid Build Coastguard Worker #include <sysexits.h>
23*288bf522SAndroid Build Coastguard Worker 
24*288bf522SAndroid Build Coastguard Worker using android::sp;
25*288bf522SAndroid Build Coastguard Worker 
26*288bf522SAndroid Build Coastguard Worker using aidl::android::hardware::boot::MergeStatus;
27*288bf522SAndroid Build Coastguard Worker 
28*288bf522SAndroid Build Coastguard Worker using android::hal::BootControlClient;
29*288bf522SAndroid Build Coastguard Worker using android::hal::BootControlVersion;
30*288bf522SAndroid Build Coastguard Worker using android::hal::CommandResult;
31*288bf522SAndroid Build Coastguard Worker 
usage(FILE * where,BootControlVersion bootVersion,int,char * argv[])32*288bf522SAndroid Build Coastguard Worker static void usage(FILE* where, BootControlVersion bootVersion, int /* argc */, char* argv[]) {
33*288bf522SAndroid Build Coastguard Worker     fprintf(where,
34*288bf522SAndroid Build Coastguard Worker             "%s - command-line wrapper for the boot HAL.\n"
35*288bf522SAndroid Build Coastguard Worker             "\n"
36*288bf522SAndroid Build Coastguard Worker             "Usage:\n"
37*288bf522SAndroid Build Coastguard Worker             "  %s COMMAND\n"
38*288bf522SAndroid Build Coastguard Worker             "\n"
39*288bf522SAndroid Build Coastguard Worker             "Commands:\n"
40*288bf522SAndroid Build Coastguard Worker             "  hal-info                       - Show info about boot_control HAL used.\n"
41*288bf522SAndroid Build Coastguard Worker             "  get-number-slots               - Prints number of slots.\n"
42*288bf522SAndroid Build Coastguard Worker             "  get-current-slot               - Prints currently running SLOT.\n"
43*288bf522SAndroid Build Coastguard Worker             "  mark-boot-successful           - Mark current slot as GOOD.\n"
44*288bf522SAndroid Build Coastguard Worker             "  get-active-boot-slot           - Prints the SLOT to load on next boot.\n"
45*288bf522SAndroid Build Coastguard Worker             "  set-active-boot-slot SLOT      - On next boot, load and execute SLOT.\n"
46*288bf522SAndroid Build Coastguard Worker             "  set-slot-as-unbootable SLOT    - Mark SLOT as invalid.\n"
47*288bf522SAndroid Build Coastguard Worker             "  is-slot-bootable SLOT          - Returns 0 only if SLOT is bootable.\n"
48*288bf522SAndroid Build Coastguard Worker             "  is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.\n"
49*288bf522SAndroid Build Coastguard Worker             "  get-suffix SLOT                - Prints suffix for SLOT.\n",
50*288bf522SAndroid Build Coastguard Worker             argv[0], argv[0]);
51*288bf522SAndroid Build Coastguard Worker     if (bootVersion >= BootControlVersion::BOOTCTL_V1_1) {
52*288bf522SAndroid Build Coastguard Worker         fprintf(where,
53*288bf522SAndroid Build Coastguard Worker                 "  set-snapshot-merge-status STAT - Sets whether a snapshot-merge of any dynamic\n"
54*288bf522SAndroid Build Coastguard Worker                 "                                   partition is in progress. Valid STAT values\n"
55*288bf522SAndroid Build Coastguard Worker                 "                                   are: none, unknown, snapshotted, merging,\n"
56*288bf522SAndroid Build Coastguard Worker                 "                                   or cancelled.\n"
57*288bf522SAndroid Build Coastguard Worker                 "  get-snapshot-merge-status      - Prints the current snapshot-merge status.\n");
58*288bf522SAndroid Build Coastguard Worker     }
59*288bf522SAndroid Build Coastguard Worker     fprintf(where,
60*288bf522SAndroid Build Coastguard Worker             "\n"
61*288bf522SAndroid Build Coastguard Worker             "SLOT parameter is the zero-based slot-number.\n");
62*288bf522SAndroid Build Coastguard Worker }
63*288bf522SAndroid Build Coastguard Worker 
ToString(BootControlVersion ver)64*288bf522SAndroid Build Coastguard Worker static constexpr auto ToString(BootControlVersion ver) {
65*288bf522SAndroid Build Coastguard Worker     switch (ver) {
66*288bf522SAndroid Build Coastguard Worker         case BootControlVersion::BOOTCTL_V1_0:
67*288bf522SAndroid Build Coastguard Worker             return "[email protected]::IBootControl";
68*288bf522SAndroid Build Coastguard Worker         case BootControlVersion::BOOTCTL_V1_1:
69*288bf522SAndroid Build Coastguard Worker             return "[email protected]::IBootControl";
70*288bf522SAndroid Build Coastguard Worker         case BootControlVersion::BOOTCTL_V1_2:
71*288bf522SAndroid Build Coastguard Worker             return "[email protected]::IBootControl";
72*288bf522SAndroid Build Coastguard Worker         case BootControlVersion::BOOTCTL_AIDL:
73*288bf522SAndroid Build Coastguard Worker             return "android.hardware.boot@aidl::IBootControl";
74*288bf522SAndroid Build Coastguard Worker     }
75*288bf522SAndroid Build Coastguard Worker }
76*288bf522SAndroid Build Coastguard Worker 
do_hal_info(const BootControlClient * module)77*288bf522SAndroid Build Coastguard Worker static int do_hal_info(const BootControlClient* module) {
78*288bf522SAndroid Build Coastguard Worker     fprintf(stdout, "HAL Version: %s\n", ToString(module->GetVersion()));
79*288bf522SAndroid Build Coastguard Worker     return EX_OK;
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker 
do_get_number_slots(BootControlClient * module)82*288bf522SAndroid Build Coastguard Worker static int do_get_number_slots(BootControlClient* module) {
83*288bf522SAndroid Build Coastguard Worker     auto numSlots = module->GetNumSlots();
84*288bf522SAndroid Build Coastguard Worker     fprintf(stdout, "%u\n", numSlots);
85*288bf522SAndroid Build Coastguard Worker     return EX_OK;
86*288bf522SAndroid Build Coastguard Worker }
87*288bf522SAndroid Build Coastguard Worker 
do_get_current_slot(BootControlClient * module)88*288bf522SAndroid Build Coastguard Worker static int do_get_current_slot(BootControlClient* module) {
89*288bf522SAndroid Build Coastguard Worker     auto curSlot = module->GetCurrentSlot();
90*288bf522SAndroid Build Coastguard Worker     fprintf(stdout, "%u\n", curSlot);
91*288bf522SAndroid Build Coastguard Worker     return EX_OK;
92*288bf522SAndroid Build Coastguard Worker }
93*288bf522SAndroid Build Coastguard Worker 
handle_return(CommandResult cr,const char * errStr)94*288bf522SAndroid Build Coastguard Worker static int handle_return(CommandResult cr, const char* errStr) {
95*288bf522SAndroid Build Coastguard Worker     if (!cr.IsOk()) {
96*288bf522SAndroid Build Coastguard Worker         fprintf(stderr, errStr, cr.errMsg.c_str());
97*288bf522SAndroid Build Coastguard Worker         return EX_SOFTWARE;
98*288bf522SAndroid Build Coastguard Worker     } else if (!cr.success) {
99*288bf522SAndroid Build Coastguard Worker         fprintf(stderr, errStr, cr.errMsg.c_str());
100*288bf522SAndroid Build Coastguard Worker         return EX_SOFTWARE;
101*288bf522SAndroid Build Coastguard Worker     }
102*288bf522SAndroid Build Coastguard Worker     return EX_OK;
103*288bf522SAndroid Build Coastguard Worker }
104*288bf522SAndroid Build Coastguard Worker 
do_mark_boot_successful(BootControlClient * module)105*288bf522SAndroid Build Coastguard Worker static int do_mark_boot_successful(BootControlClient* module) {
106*288bf522SAndroid Build Coastguard Worker     auto ret = module->MarkBootSuccessful();
107*288bf522SAndroid Build Coastguard Worker     return handle_return(ret, "Error marking as having booted successfully: %s\n");
108*288bf522SAndroid Build Coastguard Worker }
109*288bf522SAndroid Build Coastguard Worker 
do_get_active_boot_slot(BootControlClient * module)110*288bf522SAndroid Build Coastguard Worker static int do_get_active_boot_slot(BootControlClient* module) {
111*288bf522SAndroid Build Coastguard Worker     uint32_t slot = module->GetActiveBootSlot();
112*288bf522SAndroid Build Coastguard Worker     fprintf(stdout, "%u\n", slot);
113*288bf522SAndroid Build Coastguard Worker     return EX_OK;
114*288bf522SAndroid Build Coastguard Worker }
115*288bf522SAndroid Build Coastguard Worker 
do_set_active_boot_slot(BootControlClient * module,int32_t slot_number)116*288bf522SAndroid Build Coastguard Worker static int do_set_active_boot_slot(BootControlClient* module, int32_t slot_number) {
117*288bf522SAndroid Build Coastguard Worker     const auto cr = module->SetActiveBootSlot(slot_number);
118*288bf522SAndroid Build Coastguard Worker     return handle_return(cr, "Error setting active boot slot: %s\n");
119*288bf522SAndroid Build Coastguard Worker }
120*288bf522SAndroid Build Coastguard Worker 
do_set_slot_as_unbootable(BootControlClient * module,int32_t slot_number)121*288bf522SAndroid Build Coastguard Worker static int do_set_slot_as_unbootable(BootControlClient* module, int32_t slot_number) {
122*288bf522SAndroid Build Coastguard Worker     const auto cr = module->MarkSlotUnbootable(slot_number);
123*288bf522SAndroid Build Coastguard Worker     return handle_return(cr, "Error setting slot as unbootable: %s\n");
124*288bf522SAndroid Build Coastguard Worker }
125*288bf522SAndroid Build Coastguard Worker 
handle_return(const std::optional<bool> & ret,const char * errStr)126*288bf522SAndroid Build Coastguard Worker static int handle_return(const std::optional<bool>& ret, const char* errStr) {
127*288bf522SAndroid Build Coastguard Worker     if (!ret.has_value()) {
128*288bf522SAndroid Build Coastguard Worker         fprintf(stderr, errStr, "");
129*288bf522SAndroid Build Coastguard Worker         return EX_SOFTWARE;
130*288bf522SAndroid Build Coastguard Worker     }
131*288bf522SAndroid Build Coastguard Worker     if (ret.value()) {
132*288bf522SAndroid Build Coastguard Worker         printf("%d\n", ret.value());
133*288bf522SAndroid Build Coastguard Worker         return EX_OK;
134*288bf522SAndroid Build Coastguard Worker     }
135*288bf522SAndroid Build Coastguard Worker     printf("%d\n", ret.value());
136*288bf522SAndroid Build Coastguard Worker     return EX_SOFTWARE;
137*288bf522SAndroid Build Coastguard Worker }
138*288bf522SAndroid Build Coastguard Worker 
do_is_slot_bootable(BootControlClient * module,int32_t slot_number)139*288bf522SAndroid Build Coastguard Worker static int do_is_slot_bootable(BootControlClient* module, int32_t slot_number) {
140*288bf522SAndroid Build Coastguard Worker     const auto ret = module->IsSlotBootable(slot_number);
141*288bf522SAndroid Build Coastguard Worker     return handle_return(ret, "Error calling isSlotBootable()\n");
142*288bf522SAndroid Build Coastguard Worker }
143*288bf522SAndroid Build Coastguard Worker 
do_is_slot_marked_successful(BootControlClient * module,int32_t slot_number)144*288bf522SAndroid Build Coastguard Worker static int do_is_slot_marked_successful(BootControlClient* module, int32_t slot_number) {
145*288bf522SAndroid Build Coastguard Worker     const auto ret = module->IsSlotMarkedSuccessful(slot_number);
146*288bf522SAndroid Build Coastguard Worker     return handle_return(ret, "Error calling isSlotMarkedSuccessful()\n");
147*288bf522SAndroid Build Coastguard Worker }
148*288bf522SAndroid Build Coastguard Worker 
stringToMergeStatus(const std::string & status)149*288bf522SAndroid Build Coastguard Worker std::optional<MergeStatus> stringToMergeStatus(const std::string& status) {
150*288bf522SAndroid Build Coastguard Worker     if (status == "cancelled") return MergeStatus::CANCELLED;
151*288bf522SAndroid Build Coastguard Worker     if (status == "merging") return MergeStatus::MERGING;
152*288bf522SAndroid Build Coastguard Worker     if (status == "none") return MergeStatus::NONE;
153*288bf522SAndroid Build Coastguard Worker     if (status == "snapshotted") return MergeStatus::SNAPSHOTTED;
154*288bf522SAndroid Build Coastguard Worker     if (status == "unknown") return MergeStatus::UNKNOWN;
155*288bf522SAndroid Build Coastguard Worker     return {};
156*288bf522SAndroid Build Coastguard Worker }
157*288bf522SAndroid Build Coastguard Worker 
do_set_snapshot_merge_status(BootControlClient * module,BootControlVersion bootVersion,int argc,char * argv[])158*288bf522SAndroid Build Coastguard Worker static int do_set_snapshot_merge_status(BootControlClient* module, BootControlVersion bootVersion,
159*288bf522SAndroid Build Coastguard Worker                                         int argc, char* argv[]) {
160*288bf522SAndroid Build Coastguard Worker     if (argc != 3) {
161*288bf522SAndroid Build Coastguard Worker         usage(stderr, bootVersion, argc, argv);
162*288bf522SAndroid Build Coastguard Worker         exit(EX_USAGE);
163*288bf522SAndroid Build Coastguard Worker         return -1;
164*288bf522SAndroid Build Coastguard Worker     }
165*288bf522SAndroid Build Coastguard Worker 
166*288bf522SAndroid Build Coastguard Worker     auto status = stringToMergeStatus(argv[2]);
167*288bf522SAndroid Build Coastguard Worker     if (!status.has_value()) {
168*288bf522SAndroid Build Coastguard Worker         usage(stderr, bootVersion, argc, argv);
169*288bf522SAndroid Build Coastguard Worker         exit(EX_USAGE);
170*288bf522SAndroid Build Coastguard Worker         return -1;
171*288bf522SAndroid Build Coastguard Worker     }
172*288bf522SAndroid Build Coastguard Worker 
173*288bf522SAndroid Build Coastguard Worker     const auto ret = module->SetSnapshotMergeStatus(status.value());
174*288bf522SAndroid Build Coastguard Worker     return handle_return(ret, "Failed to set snapshot merge status: %s\n");
175*288bf522SAndroid Build Coastguard Worker }
176*288bf522SAndroid Build Coastguard Worker 
operator <<(std::ostream & os,MergeStatus state)177*288bf522SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, MergeStatus state) {
178*288bf522SAndroid Build Coastguard Worker     switch (state) {
179*288bf522SAndroid Build Coastguard Worker         case MergeStatus::CANCELLED:
180*288bf522SAndroid Build Coastguard Worker             return os << "cancelled";
181*288bf522SAndroid Build Coastguard Worker         case MergeStatus::MERGING:
182*288bf522SAndroid Build Coastguard Worker             return os << "merging";
183*288bf522SAndroid Build Coastguard Worker         case MergeStatus::NONE:
184*288bf522SAndroid Build Coastguard Worker             return os << "none";
185*288bf522SAndroid Build Coastguard Worker         case MergeStatus::SNAPSHOTTED:
186*288bf522SAndroid Build Coastguard Worker             return os << "snapshotted";
187*288bf522SAndroid Build Coastguard Worker         case MergeStatus::UNKNOWN:
188*288bf522SAndroid Build Coastguard Worker             return os << "unknown";
189*288bf522SAndroid Build Coastguard Worker         default:
190*288bf522SAndroid Build Coastguard Worker             return os;
191*288bf522SAndroid Build Coastguard Worker     }
192*288bf522SAndroid Build Coastguard Worker }
193*288bf522SAndroid Build Coastguard Worker 
do_get_snapshot_merge_status(BootControlClient * module)194*288bf522SAndroid Build Coastguard Worker static int do_get_snapshot_merge_status(BootControlClient* module) {
195*288bf522SAndroid Build Coastguard Worker     MergeStatus ret = module->getSnapshotMergeStatus();
196*288bf522SAndroid Build Coastguard Worker     std::stringstream ss;
197*288bf522SAndroid Build Coastguard Worker     ss << ret;
198*288bf522SAndroid Build Coastguard Worker     fprintf(stdout, "%s\n", ss.str().c_str());
199*288bf522SAndroid Build Coastguard Worker     return EX_OK;
200*288bf522SAndroid Build Coastguard Worker }
201*288bf522SAndroid Build Coastguard Worker 
do_get_suffix(BootControlClient * module,int32_t slot_number)202*288bf522SAndroid Build Coastguard Worker static int do_get_suffix(BootControlClient* module, int32_t slot_number) {
203*288bf522SAndroid Build Coastguard Worker     const auto ret = module->GetSuffix(slot_number);
204*288bf522SAndroid Build Coastguard Worker     if (ret.empty()) {
205*288bf522SAndroid Build Coastguard Worker         fprintf(stderr, "Error calling getSuffix()\n");
206*288bf522SAndroid Build Coastguard Worker         return EX_SOFTWARE;
207*288bf522SAndroid Build Coastguard Worker     }
208*288bf522SAndroid Build Coastguard Worker     printf("%s\n", ret.c_str());
209*288bf522SAndroid Build Coastguard Worker     return EX_OK;
210*288bf522SAndroid Build Coastguard Worker }
211*288bf522SAndroid Build Coastguard Worker 
parse_slot(BootControlVersion bootVersion,int pos,int argc,char * argv[])212*288bf522SAndroid Build Coastguard Worker static uint32_t parse_slot(BootControlVersion bootVersion, int pos, int argc, char* argv[]) {
213*288bf522SAndroid Build Coastguard Worker     if (pos > argc - 1) {
214*288bf522SAndroid Build Coastguard Worker         usage(stderr, bootVersion, argc, argv);
215*288bf522SAndroid Build Coastguard Worker         exit(EX_USAGE);
216*288bf522SAndroid Build Coastguard Worker         return -1;
217*288bf522SAndroid Build Coastguard Worker     }
218*288bf522SAndroid Build Coastguard Worker     errno = 0;
219*288bf522SAndroid Build Coastguard Worker     uint64_t ret = strtoul(argv[pos], NULL, 10);
220*288bf522SAndroid Build Coastguard Worker     if (errno != 0 || ret > UINT_MAX) {
221*288bf522SAndroid Build Coastguard Worker         usage(stderr, bootVersion, argc, argv);
222*288bf522SAndroid Build Coastguard Worker         exit(EX_USAGE);
223*288bf522SAndroid Build Coastguard Worker         return -1;
224*288bf522SAndroid Build Coastguard Worker     }
225*288bf522SAndroid Build Coastguard Worker     return (uint32_t)ret;
226*288bf522SAndroid Build Coastguard Worker }
227*288bf522SAndroid Build Coastguard Worker 
main(int argc,char * argv[])228*288bf522SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
229*288bf522SAndroid Build Coastguard Worker     const auto client = android::hal::BootControlClient::WaitForService();
230*288bf522SAndroid Build Coastguard Worker     if (client == nullptr) {
231*288bf522SAndroid Build Coastguard Worker         fprintf(stderr, "Failed to get bootctl module.\n");
232*288bf522SAndroid Build Coastguard Worker         return EX_SOFTWARE;
233*288bf522SAndroid Build Coastguard Worker     }
234*288bf522SAndroid Build Coastguard Worker     const auto bootVersion = client->GetVersion();
235*288bf522SAndroid Build Coastguard Worker 
236*288bf522SAndroid Build Coastguard Worker     if (argc < 2) {
237*288bf522SAndroid Build Coastguard Worker         usage(stderr, bootVersion, argc, argv);
238*288bf522SAndroid Build Coastguard Worker         return EX_USAGE;
239*288bf522SAndroid Build Coastguard Worker     }
240*288bf522SAndroid Build Coastguard Worker 
241*288bf522SAndroid Build Coastguard Worker     // Functions present from version 1.0
242*288bf522SAndroid Build Coastguard Worker     if (strcmp(argv[1], "hal-info") == 0) {
243*288bf522SAndroid Build Coastguard Worker         return do_hal_info(client.get());
244*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "get-number-slots") == 0) {
245*288bf522SAndroid Build Coastguard Worker         return do_get_number_slots(client.get());
246*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "get-current-slot") == 0) {
247*288bf522SAndroid Build Coastguard Worker         return do_get_current_slot(client.get());
248*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "mark-boot-successful") == 0) {
249*288bf522SAndroid Build Coastguard Worker         return do_mark_boot_successful(client.get());
250*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "set-active-boot-slot") == 0) {
251*288bf522SAndroid Build Coastguard Worker         return do_set_active_boot_slot(client.get(), parse_slot(bootVersion, 2, argc, argv));
252*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) {
253*288bf522SAndroid Build Coastguard Worker         return do_set_slot_as_unbootable(client.get(), parse_slot(bootVersion, 2, argc, argv));
254*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "is-slot-bootable") == 0) {
255*288bf522SAndroid Build Coastguard Worker         return do_is_slot_bootable(client.get(), parse_slot(bootVersion, 2, argc, argv));
256*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) {
257*288bf522SAndroid Build Coastguard Worker         return do_is_slot_marked_successful(client.get(), parse_slot(bootVersion, 2, argc, argv));
258*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[1], "get-suffix") == 0) {
259*288bf522SAndroid Build Coastguard Worker         return do_get_suffix(client.get(), parse_slot(bootVersion, 2, argc, argv));
260*288bf522SAndroid Build Coastguard Worker     }
261*288bf522SAndroid Build Coastguard Worker 
262*288bf522SAndroid Build Coastguard Worker     // Functions present from version 1.1
263*288bf522SAndroid Build Coastguard Worker     if (strcmp(argv[1], "set-snapshot-merge-status") == 0 ||
264*288bf522SAndroid Build Coastguard Worker         strcmp(argv[1], "get-snapshot-merge-status") == 0) {
265*288bf522SAndroid Build Coastguard Worker         if (bootVersion < BootControlVersion::BOOTCTL_V1_1) {
266*288bf522SAndroid Build Coastguard Worker             fprintf(stderr, "Error getting bootctrl v1.1 module.\n");
267*288bf522SAndroid Build Coastguard Worker             return EX_SOFTWARE;
268*288bf522SAndroid Build Coastguard Worker         }
269*288bf522SAndroid Build Coastguard Worker         if (strcmp(argv[1], "set-snapshot-merge-status") == 0) {
270*288bf522SAndroid Build Coastguard Worker             return do_set_snapshot_merge_status(client.get(), bootVersion, argc, argv);
271*288bf522SAndroid Build Coastguard Worker         } else if (strcmp(argv[1], "get-snapshot-merge-status") == 0) {
272*288bf522SAndroid Build Coastguard Worker             return do_get_snapshot_merge_status(client.get());
273*288bf522SAndroid Build Coastguard Worker         }
274*288bf522SAndroid Build Coastguard Worker     }
275*288bf522SAndroid Build Coastguard Worker 
276*288bf522SAndroid Build Coastguard Worker     if (strcmp(argv[1], "get-active-boot-slot") == 0) {
277*288bf522SAndroid Build Coastguard Worker         if (bootVersion < BootControlVersion::BOOTCTL_V1_2) {
278*288bf522SAndroid Build Coastguard Worker             fprintf(stderr, "Error getting bootctrl v1.2 module.\n");
279*288bf522SAndroid Build Coastguard Worker             return EX_SOFTWARE;
280*288bf522SAndroid Build Coastguard Worker         }
281*288bf522SAndroid Build Coastguard Worker 
282*288bf522SAndroid Build Coastguard Worker         return do_get_active_boot_slot(client.get());
283*288bf522SAndroid Build Coastguard Worker     }
284*288bf522SAndroid Build Coastguard Worker 
285*288bf522SAndroid Build Coastguard Worker     // Parameter not matched, print usage
286*288bf522SAndroid Build Coastguard Worker     usage(stderr, bootVersion, argc, argv);
287*288bf522SAndroid Build Coastguard Worker     return EX_USAGE;
288*288bf522SAndroid Build Coastguard Worker }
289