1a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien/*
2a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * Copyright (C) 2016 The Android Open Source Project
3a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien *
4a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * Licensed under the Apache License, Version 2.0 (the "License");
5a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * you may not use this file except in compliance with the License.
6a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * You may obtain a copy of the License at
7a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien *
8a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien *      http://www.apache.org/licenses/LICENSE-2.0
9a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien *
10a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * Unless required by applicable law or agreed to in writing, software
11a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * distributed under the License is distributed on an "AS IS" BASIS,
12a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * See the License for the specific language governing permissions and
14a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien * limitations under the License.
15a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien */
16a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
17a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien#include <sysexits.h>
18a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien#include <android/hardware/boot/1.0/IBootControl.h>
19a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
20a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::sp;
21a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
22a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::hidl_string;
23a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::Return;
24a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
25a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::boot::V1_0::BoolResult;
26a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::boot::V1_0::IBootControl;
27a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::boot::V1_0::CommandResult;
28a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienusing android::hardware::boot::V1_0::Slot;
29a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
30a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic void usage(FILE* where, int /* argc */, char* argv[])
31a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
32a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    fprintf(where,
33a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "%s - command-line wrapper for the boot HAL.\n"
34a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "\n"
35a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "Usage:\n"
36a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s COMMAND\n"
37a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "\n"
38a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "Commands:\n"
39a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s hal-info                       - Show info about boot_control HAL used.\n"
40a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s get-number-slots               - Prints number of slots.\n"
41a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s get-current-slot               - Prints currently running SLOT.\n"
42a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s mark-boot-successful           - Mark current slot as GOOD.\n"
43a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s set-active-boot-slot SLOT      - On next boot, load and execute SLOT.\n"
44a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s set-slot-as-unbootable SLOT    - Mark SLOT as invalid.\n"
45a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s is-slot-bootable SLOT          - Returns 0 only if SLOT is bootable.\n"
46a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.\n"
47a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "  %s get-suffix SLOT                - Prints suffix for SLOT.\n"
48a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "\n"
49a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            "SLOT parameter is the zero-based slot-number.\n",
50a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            argv[0], argv[0], argv[0], argv[0], argv[0], argv[0],
51a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien            argv[0], argv[0], argv[0], argv[0], argv[0]);
52a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
53a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
54a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_hal_info(const sp<IBootControl> module) {
552e3024fca9693ab1655fa0863b4ba885d10e2094Yifan Hong    module->interfaceDescriptor([&](const auto& descriptor) {
566b8d033d22c93516d0edafaf80cf725e4f1cf324Steven Moreland        fprintf(stdout,
576b8d033d22c93516d0edafaf80cf725e4f1cf324Steven Moreland                "HAL Version: %s\n",
582e3024fca9693ab1655fa0863b4ba885d10e2094Yifan Hong                descriptor.c_str());
596b8d033d22c93516d0edafaf80cf725e4f1cf324Steven Moreland    });
60a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_OK;
61a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
62a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
63a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_get_number_slots(sp<IBootControl> module)
64a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
65a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    uint32_t numSlots = module->getNumberSlots();
66a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    fprintf(stdout, "%u\n", numSlots);
67a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_OK;
68a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
69a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
70a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_get_current_slot(sp<IBootControl> module)
71a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
72a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Slot curSlot = module->getCurrentSlot();
73a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    fprintf(stdout, "%u\n", curSlot);
74a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_OK;
75a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
76a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
77a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic std::function<void(CommandResult)> generate_callback(CommandResult *crp) {
78a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return [=](CommandResult cr){
79a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        *crp = cr;
80a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    };
81a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
82a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
8383a2fdb4e10b9c308d470fd3bc99f483fc0af2bdYifan Hongstatic int handle_return(const Return<void> &ret, CommandResult cr, const char* errStr) {
8487d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong    if (!ret.isOk()) {
8587d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong        fprintf(stderr, errStr, ret.description().c_str());
86a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
87a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (!cr.success) {
88a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        fprintf(stderr, errStr, cr.errMsg.c_str());
89a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
90a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
91a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_OK;
92a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
93a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
94a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_mark_boot_successful(sp<IBootControl> module)
95a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
96a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    CommandResult cr;
97a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<void> ret = module->markBootSuccessful(generate_callback(&cr));
98a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return handle_return(ret, cr, "Error marking as having booted successfully: %s\n");
99a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
100a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
101a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_set_active_boot_slot(sp<IBootControl> module,
102a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien                                   Slot slot_number)
103a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
104a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    CommandResult cr;
105a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<void> ret = module->setActiveBootSlot(slot_number, generate_callback(&cr));
106a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return handle_return(ret, cr, "Error setting active boot slot: %s\n");
107a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
108a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
109a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_set_slot_as_unbootable(sp<IBootControl> module,
110a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien                                     Slot slot_number)
111a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
112a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    CommandResult cr;
113a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<void> ret = module->setSlotAsUnbootable(slot_number, generate_callback(&cr));
114a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return handle_return(ret, cr, "Error setting slot as unbootable: %s\n");
115a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
116a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
11783a2fdb4e10b9c308d470fd3bc99f483fc0af2bdYifan Hongstatic int handle_return(const Return<BoolResult> &ret, const char* errStr) {
11887d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong    if (!ret.isOk()) {
11987d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong        fprintf(stderr, errStr, ret.description().c_str());
120a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
121a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (ret == BoolResult::INVALID_SLOT) {
122a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        fprintf(stderr, errStr, "Invalid slot");
123a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
124a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (ret == BoolResult::TRUE) {
125a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_OK;
126a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
127a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_SOFTWARE;
128a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
129a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
130a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_is_slot_bootable(sp<IBootControl> module, Slot slot_number)
131a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
132a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<BoolResult> ret = module->isSlotBootable(slot_number);
133a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return handle_return(ret, "Error calling isSlotBootable(): %s\n");
134a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
135a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
136a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_is_slot_marked_successful(sp<IBootControl> module,
137a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien                                        Slot slot_number)
138a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
139a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<BoolResult> ret = module->isSlotMarkedSuccessful(slot_number);
140a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return handle_return(ret, "Error calling isSlotMarkedSuccessful(): %s\n");
141a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
142a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
143a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
144a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic int do_get_suffix(sp<IBootControl> module, Slot slot_number) {
145a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    std::function<void(hidl_string)> cb = [](hidl_string suffix){
146a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        fprintf(stdout, "%s\n", suffix.c_str());
147a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    };
148a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    Return<void> ret = module->getSuffix(slot_number, cb);
14987d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong    if (!ret.isOk()) {
150a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        fprintf(stderr, "Error calling getSuffix(): %s\n",
15187d71f3586812c485c90bf16b57f7d3a55dfbf32Yifan Hong                ret.description().c_str());
152a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
153a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
154a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return EX_OK;
155a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
156a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
157a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienstatic uint32_t parse_slot(int pos, int argc, char *argv[])
158a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
159a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    if (pos > argc - 1) {
160a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        usage(stderr, argc, argv);
161a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        exit(EX_USAGE);
162a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return -1;
163a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
164a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    errno = 0;
165a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    uint64_t ret = strtoul(argv[pos], NULL, 10);
166a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    if (errno != 0 || ret > UINT_MAX) {
167a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        usage(stderr, argc, argv);
168a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        exit(EX_USAGE);
169a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return -1;
170a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
171a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return (uint32_t)ret;
172a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
173a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
174a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brienint main(int argc, char *argv[])
175a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien{
176a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    sp<IBootControl> module;
177a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
178a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    if (argc < 2) {
179a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        usage(stderr, argc, argv);
180a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_USAGE;
181a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
182a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
1833659fcdc0c26dfe19a996f4b986fa45cdd15037fChris Phoenix    module = IBootControl::getService();
184a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    if (module == NULL) {
185a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        fprintf(stderr, "Error getting bootctrl module.\n");
186a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_SOFTWARE;
187a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
188a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
189a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    if (strcmp(argv[1], "hal-info") == 0) {
190a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_hal_info(module);
191a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "get-number-slots") == 0) {
192a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_get_number_slots(module);
193a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "get-current-slot") == 0) {
194a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_get_current_slot(module);
195a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "mark-boot-successful") == 0) {
196a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_mark_boot_successful(module);
197a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "set-active-boot-slot") == 0) {
198a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_set_active_boot_slot(module, parse_slot(2, argc, argv));
199a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) {
200a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_set_slot_as_unbootable(module, parse_slot(2, argc, argv));
201a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "is-slot-bootable") == 0) {
202a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_is_slot_bootable(module, parse_slot(2, argc, argv));
203a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "get-suffix") == 0) {
204a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_get_suffix(module, parse_slot(2, argc, argv));
205a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) {
206a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return do_is_slot_marked_successful(module, parse_slot(2, argc, argv));
207a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    } else {
208a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        usage(stderr, argc, argv);
209a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien        return EX_USAGE;
210a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    }
211a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien
212a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien    return 0;
213a4fbed759a1eecd978fe2f8d426e68cff49fec77Connor O'Brien}
214