2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <android/hardware/boot/1.0/IBootControl.h>
22 using android::hardware::hidl_string;
23 using android::hardware::Return;
25 using android::hardware::boot::V1_0::BoolResult;
26 using android::hardware::boot::V1_0::IBootControl;
27 using android::hardware::boot::V1_0::CommandResult;
28 using android::hardware::boot::V1_0::Slot;
30 static void usage(FILE* where, int /* argc */, char* argv[])
33 "%s - command-line wrapper for the boot HAL.\n"
39 " %s hal-info - Show info about boot_control HAL used.\n"
40 " %s get-number-slots - Prints number of slots.\n"
41 " %s get-current-slot - Prints currently running SLOT.\n"
42 " %s mark-boot-successful - Mark current slot as GOOD.\n"
43 " %s set-active-boot-slot SLOT - On next boot, load and execute SLOT.\n"
44 " %s set-slot-as-unbootable SLOT - Mark SLOT as invalid.\n"
45 " %s is-slot-bootable SLOT - Returns 0 only if SLOT is bootable.\n"
46 " %s is-slot-marked-successful SLOT - Returns 0 only if SLOT is marked GOOD.\n"
47 " %s get-suffix SLOT - Prints suffix for SLOT.\n"
49 "SLOT parameter is the zero-based slot-number.\n",
50 argv[0], argv[0], argv[0], argv[0], argv[0], argv[0],
51 argv[0], argv[0], argv[0], argv[0], argv[0]);
54 static int do_hal_info(const sp<IBootControl> module) {
56 "HAL module version: %u.%u\n",
57 module->getInterfaceVersion().get_major(),
58 module->getInterfaceVersion().get_minor());
62 static int do_get_number_slots(sp<IBootControl> module)
64 uint32_t numSlots = module->getNumberSlots();
65 fprintf(stdout, "%u\n", numSlots);
69 static int do_get_current_slot(sp<IBootControl> module)
71 Slot curSlot = module->getCurrentSlot();
72 fprintf(stdout, "%u\n", curSlot);
76 static std::function<void(CommandResult)> generate_callback(CommandResult *crp) {
77 return [=](CommandResult cr){
82 static int handle_return(Return<void> ret, CommandResult cr, const char* errStr) {
84 fprintf(stderr, errStr, ret.description().c_str());
86 } else if (!cr.success) {
87 fprintf(stderr, errStr, cr.errMsg.c_str());
93 static int do_mark_boot_successful(sp<IBootControl> module)
96 Return<void> ret = module->markBootSuccessful(generate_callback(&cr));
97 return handle_return(ret, cr, "Error marking as having booted successfully: %s\n");
100 static int do_set_active_boot_slot(sp<IBootControl> module,
104 Return<void> ret = module->setActiveBootSlot(slot_number, generate_callback(&cr));
105 return handle_return(ret, cr, "Error setting active boot slot: %s\n");
108 static int do_set_slot_as_unbootable(sp<IBootControl> module,
112 Return<void> ret = module->setSlotAsUnbootable(slot_number, generate_callback(&cr));
113 return handle_return(ret, cr, "Error setting slot as unbootable: %s\n");
116 static int handle_return(Return<BoolResult> ret, const char* errStr) {
118 fprintf(stderr, errStr, ret.description().c_str());
120 } else if (ret == BoolResult::INVALID_SLOT) {
121 fprintf(stderr, errStr, "Invalid slot");
123 } else if (ret == BoolResult::TRUE) {
129 static int do_is_slot_bootable(sp<IBootControl> module, Slot slot_number)
131 Return<BoolResult> ret = module->isSlotBootable(slot_number);
132 return handle_return(ret, "Error calling isSlotBootable(): %s\n");
135 static int do_is_slot_marked_successful(sp<IBootControl> module,
138 Return<BoolResult> ret = module->isSlotMarkedSuccessful(slot_number);
139 return handle_return(ret, "Error calling isSlotMarkedSuccessful(): %s\n");
143 static int do_get_suffix(sp<IBootControl> module, Slot slot_number) {
144 std::function<void(hidl_string)> cb = [](hidl_string suffix){
145 fprintf(stdout, "%s\n", suffix.c_str());
147 Return<void> ret = module->getSuffix(slot_number, cb);
149 fprintf(stderr, "Error calling getSuffix(): %s\n",
150 ret.description().c_str());
156 static uint32_t parse_slot(int pos, int argc, char *argv[])
158 if (pos > argc - 1) {
159 usage(stderr, argc, argv);
164 uint64_t ret = strtoul(argv[pos], NULL, 10);
165 if (errno != 0 || ret > UINT_MAX) {
166 usage(stderr, argc, argv);
170 return (uint32_t)ret;
173 int main(int argc, char *argv[])
175 sp<IBootControl> module;
179 usage(stderr, argc, argv);
183 module = IBootControl::getService("bootctrl");
184 if (module == NULL) {
185 fprintf(stderr, "Error getting bootctrl module.\n");
189 if (strcmp(argv[1], "hal-info") == 0) {
190 return do_hal_info(module);
191 } else if (strcmp(argv[1], "get-number-slots") == 0) {
192 return do_get_number_slots(module);
193 } else if (strcmp(argv[1], "get-current-slot") == 0) {
194 return do_get_current_slot(module);
195 } else if (strcmp(argv[1], "mark-boot-successful") == 0) {
196 return do_mark_boot_successful(module);
197 } else if (strcmp(argv[1], "set-active-boot-slot") == 0) {
198 return do_set_active_boot_slot(module, parse_slot(2, argc, argv));
199 } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) {
200 return do_set_slot_as_unbootable(module, parse_slot(2, argc, argv));
201 } else if (strcmp(argv[1], "is-slot-bootable") == 0) {
202 return do_is_slot_bootable(module, parse_slot(2, argc, argv));
203 } else if (strcmp(argv[1], "get-suffix") == 0) {
204 return do_get_suffix(module, parse_slot(2, argc, argv));
205 } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) {
206 return do_is_slot_marked_successful(module, parse_slot(2, argc, argv));
208 usage(stderr, argc, argv);