1 /*
2 * Copyright (C) 2016 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 <sysexits.h>
18 #include <android/hardware/boot/1.0/IBootControl.h>
19
20 using android::sp;
21
22 using android::hardware::hidl_string;
23 using android::hardware::Return;
24
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;
29
usage(FILE * where,int,char * argv[])30 static void usage(FILE* where, int /* argc */, char* argv[])
31 {
32 fprintf(where,
33 "%s - command-line wrapper for the boot HAL.\n"
34 "\n"
35 "Usage:\n"
36 " %s COMMAND\n"
37 "\n"
38 "Commands:\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"
48 "\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]);
52 }
53
do_hal_info(const sp<IBootControl> module)54 static int do_hal_info(const sp<IBootControl> module) {
55 module->interfaceDescriptor([&](const auto& descriptor) {
56 fprintf(stdout,
57 "HAL Version: %s\n",
58 descriptor.c_str());
59 });
60 return EX_OK;
61 }
62
do_get_number_slots(sp<IBootControl> module)63 static int do_get_number_slots(sp<IBootControl> module)
64 {
65 uint32_t numSlots = module->getNumberSlots();
66 fprintf(stdout, "%u\n", numSlots);
67 return EX_OK;
68 }
69
do_get_current_slot(sp<IBootControl> module)70 static int do_get_current_slot(sp<IBootControl> module)
71 {
72 Slot curSlot = module->getCurrentSlot();
73 fprintf(stdout, "%u\n", curSlot);
74 return EX_OK;
75 }
76
generate_callback(CommandResult * crp)77 static std::function<void(CommandResult)> generate_callback(CommandResult *crp) {
78 return [=](CommandResult cr){
79 *crp = cr;
80 };
81 }
82
handle_return(const Return<void> & ret,CommandResult cr,const char * errStr)83 static int handle_return(const Return<void> &ret, CommandResult cr, const char* errStr) {
84 if (!ret.isOk()) {
85 fprintf(stderr, errStr, ret.description().c_str());
86 return EX_SOFTWARE;
87 } else if (!cr.success) {
88 fprintf(stderr, errStr, cr.errMsg.c_str());
89 return EX_SOFTWARE;
90 }
91 return EX_OK;
92 }
93
do_mark_boot_successful(sp<IBootControl> module)94 static int do_mark_boot_successful(sp<IBootControl> module)
95 {
96 CommandResult cr;
97 Return<void> ret = module->markBootSuccessful(generate_callback(&cr));
98 return handle_return(ret, cr, "Error marking as having booted successfully: %s\n");
99 }
100
do_set_active_boot_slot(sp<IBootControl> module,Slot slot_number)101 static int do_set_active_boot_slot(sp<IBootControl> module,
102 Slot slot_number)
103 {
104 CommandResult cr;
105 Return<void> ret = module->setActiveBootSlot(slot_number, generate_callback(&cr));
106 return handle_return(ret, cr, "Error setting active boot slot: %s\n");
107 }
108
do_set_slot_as_unbootable(sp<IBootControl> module,Slot slot_number)109 static int do_set_slot_as_unbootable(sp<IBootControl> module,
110 Slot slot_number)
111 {
112 CommandResult cr;
113 Return<void> ret = module->setSlotAsUnbootable(slot_number, generate_callback(&cr));
114 return handle_return(ret, cr, "Error setting slot as unbootable: %s\n");
115 }
116
handle_return(const Return<BoolResult> & ret,const char * errStr)117 static int handle_return(const Return<BoolResult> &ret, const char* errStr) {
118 if (!ret.isOk()) {
119 fprintf(stderr, errStr, ret.description().c_str());
120 return EX_SOFTWARE;
121 } else if (ret == BoolResult::INVALID_SLOT) {
122 fprintf(stderr, errStr, "Invalid slot");
123 return EX_SOFTWARE;
124 } else if (ret == BoolResult::TRUE) {
125 return EX_OK;
126 }
127 return EX_SOFTWARE;
128 }
129
do_is_slot_bootable(sp<IBootControl> module,Slot slot_number)130 static int do_is_slot_bootable(sp<IBootControl> module, Slot slot_number)
131 {
132 Return<BoolResult> ret = module->isSlotBootable(slot_number);
133 return handle_return(ret, "Error calling isSlotBootable(): %s\n");
134 }
135
do_is_slot_marked_successful(sp<IBootControl> module,Slot slot_number)136 static int do_is_slot_marked_successful(sp<IBootControl> module,
137 Slot slot_number)
138 {
139 Return<BoolResult> ret = module->isSlotMarkedSuccessful(slot_number);
140 return handle_return(ret, "Error calling isSlotMarkedSuccessful(): %s\n");
141 }
142
143
do_get_suffix(sp<IBootControl> module,Slot slot_number)144 static int do_get_suffix(sp<IBootControl> module, Slot slot_number) {
145 std::function<void(hidl_string)> cb = [](hidl_string suffix){
146 fprintf(stdout, "%s\n", suffix.c_str());
147 };
148 Return<void> ret = module->getSuffix(slot_number, cb);
149 if (!ret.isOk()) {
150 fprintf(stderr, "Error calling getSuffix(): %s\n",
151 ret.description().c_str());
152 return EX_SOFTWARE;
153 }
154 return EX_OK;
155 }
156
parse_slot(int pos,int argc,char * argv[])157 static uint32_t parse_slot(int pos, int argc, char *argv[])
158 {
159 if (pos > argc - 1) {
160 usage(stderr, argc, argv);
161 exit(EX_USAGE);
162 return -1;
163 }
164 errno = 0;
165 uint64_t ret = strtoul(argv[pos], NULL, 10);
166 if (errno != 0 || ret > UINT_MAX) {
167 usage(stderr, argc, argv);
168 exit(EX_USAGE);
169 return -1;
170 }
171 return (uint32_t)ret;
172 }
173
main(int argc,char * argv[])174 int main(int argc, char *argv[])
175 {
176 sp<IBootControl> module;
177 int ret;
178
179 if (argc < 2) {
180 usage(stderr, argc, argv);
181 return EX_USAGE;
182 }
183
184 module = IBootControl::getService();
185 if (module == NULL) {
186 fprintf(stderr, "Error getting bootctrl module.\n");
187 return EX_SOFTWARE;
188 }
189
190 if (strcmp(argv[1], "hal-info") == 0) {
191 return do_hal_info(module);
192 } else if (strcmp(argv[1], "get-number-slots") == 0) {
193 return do_get_number_slots(module);
194 } else if (strcmp(argv[1], "get-current-slot") == 0) {
195 return do_get_current_slot(module);
196 } else if (strcmp(argv[1], "mark-boot-successful") == 0) {
197 return do_mark_boot_successful(module);
198 } else if (strcmp(argv[1], "set-active-boot-slot") == 0) {
199 return do_set_active_boot_slot(module, parse_slot(2, argc, argv));
200 } else if (strcmp(argv[1], "set-slot-as-unbootable") == 0) {
201 return do_set_slot_as_unbootable(module, parse_slot(2, argc, argv));
202 } else if (strcmp(argv[1], "is-slot-bootable") == 0) {
203 return do_is_slot_bootable(module, parse_slot(2, argc, argv));
204 } else if (strcmp(argv[1], "get-suffix") == 0) {
205 return do_get_suffix(module, parse_slot(2, argc, argv));
206 } else if (strcmp(argv[1], "is-slot-marked-successful") == 0) {
207 return do_is_slot_marked_successful(module, parse_slot(2, argc, argv));
208 } else {
209 usage(stderr, argc, argv);
210 return EX_USAGE;
211 }
212
213 return 0;
214 }
215