OSDN Git Service

Merge "Use shared lib of libselinux in runconuid instead of static one."
[android-x86/system-extras.git] / bootctl / bootctl.cpp
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
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
54 static int do_hal_info(const sp<IBootControl> module) {
55     fprintf(stdout,
56             "HAL module version: %u.%u\n",
57             module->getInterfaceVersion().get_major(),
58             module->getInterfaceVersion().get_minor());
59     return EX_OK;
60 }
61
62 static int do_get_number_slots(sp<IBootControl> module)
63 {
64     uint32_t numSlots = module->getNumberSlots();
65     fprintf(stdout, "%u\n", numSlots);
66     return EX_OK;
67 }
68
69 static int do_get_current_slot(sp<IBootControl> module)
70 {
71     Slot curSlot = module->getCurrentSlot();
72     fprintf(stdout, "%u\n", curSlot);
73     return EX_OK;
74 }
75
76 static std::function<void(CommandResult)> generate_callback(CommandResult *crp) {
77     return [=](CommandResult cr){
78         *crp = cr;
79     };
80 }
81
82 static int handle_return(Return<void> ret, CommandResult cr, const char* errStr) {
83     if (!ret.isOk()) {
84         fprintf(stderr, errStr, ret.description().c_str());
85         return EX_SOFTWARE;
86     } else if (!cr.success) {
87         fprintf(stderr, errStr, cr.errMsg.c_str());
88         return EX_SOFTWARE;
89     }
90     return EX_OK;
91 }
92
93 static int do_mark_boot_successful(sp<IBootControl> module)
94 {
95     CommandResult cr;
96     Return<void> ret = module->markBootSuccessful(generate_callback(&cr));
97     return handle_return(ret, cr, "Error marking as having booted successfully: %s\n");
98 }
99
100 static int do_set_active_boot_slot(sp<IBootControl> module,
101                                    Slot slot_number)
102 {
103     CommandResult cr;
104     Return<void> ret = module->setActiveBootSlot(slot_number, generate_callback(&cr));
105     return handle_return(ret, cr, "Error setting active boot slot: %s\n");
106 }
107
108 static int do_set_slot_as_unbootable(sp<IBootControl> module,
109                                      Slot slot_number)
110 {
111     CommandResult cr;
112     Return<void> ret = module->setSlotAsUnbootable(slot_number, generate_callback(&cr));
113     return handle_return(ret, cr, "Error setting slot as unbootable: %s\n");
114 }
115
116 static int handle_return(Return<BoolResult> ret, const char* errStr) {
117     if (!ret.isOk()) {
118         fprintf(stderr, errStr, ret.description().c_str());
119         return EX_SOFTWARE;
120     } else if (ret == BoolResult::INVALID_SLOT) {
121         fprintf(stderr, errStr, "Invalid slot");
122         return EX_SOFTWARE;
123     } else if (ret == BoolResult::TRUE) {
124         return EX_OK;
125     }
126     return EX_SOFTWARE;
127 }
128
129 static int do_is_slot_bootable(sp<IBootControl> module, Slot slot_number)
130 {
131     Return<BoolResult> ret = module->isSlotBootable(slot_number);
132     return handle_return(ret, "Error calling isSlotBootable(): %s\n");
133 }
134
135 static int do_is_slot_marked_successful(sp<IBootControl> module,
136                                         Slot slot_number)
137 {
138     Return<BoolResult> ret = module->isSlotMarkedSuccessful(slot_number);
139     return handle_return(ret, "Error calling isSlotMarkedSuccessful(): %s\n");
140 }
141
142
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());
146     };
147     Return<void> ret = module->getSuffix(slot_number, cb);
148     if (!ret.isOk()) {
149         fprintf(stderr, "Error calling getSuffix(): %s\n",
150                 ret.description().c_str());
151         return EX_SOFTWARE;
152     }
153     return EX_OK;
154 }
155
156 static uint32_t parse_slot(int pos, int argc, char *argv[])
157 {
158     if (pos > argc - 1) {
159         usage(stderr, argc, argv);
160         exit(EX_USAGE);
161         return -1;
162     }
163     errno = 0;
164     uint64_t ret = strtoul(argv[pos], NULL, 10);
165     if (errno != 0 || ret > UINT_MAX) {
166         usage(stderr, argc, argv);
167         exit(EX_USAGE);
168         return -1;
169     }
170     return (uint32_t)ret;
171 }
172
173 int main(int argc, char *argv[])
174 {
175     sp<IBootControl> module;
176     int ret;
177
178     if (argc < 2) {
179         usage(stderr, argc, argv);
180         return EX_USAGE;
181     }
182
183     module = IBootControl::getService("bootctrl");
184     if (module == NULL) {
185         fprintf(stderr, "Error getting bootctrl module.\n");
186         return EX_SOFTWARE;
187     }
188
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));
207     } else {
208         usage(stderr, argc, argv);
209         return EX_USAGE;
210     }
211
212     return 0;
213 }