1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Kay Sievers
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/timex.h>
35 static void help(void) {
36 printf("%s [OPTIONS...] COMMAND ...\n\n"
37 "Query or change firmware and boot manager settings.\n\n"
38 " -h --help Show this help\n"
39 " --version Show package version\n"
41 " status Show current boot settings\n"
42 , program_invocation_short_name);
45 static int parse_argv(int argc, char *argv[]) {
50 static const struct option options[] = {
51 { "help", no_argument, NULL, 'h' },
52 { "version", no_argument, NULL, ARG_VERSION },
61 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
71 puts(SYSTEMD_FEATURES);
78 assert_not_reached("Unhandled option");
84 static int boot_info_new(struct boot_info **info) {
88 in = new0(struct boot_info, 1);
92 err = sd_id128_get_machine(&in->machine_id);
96 err = sd_id128_get_boot(&in->boot_id);
100 in->fw_entry_active = -1;
101 in->loader_entry_active = -1;
110 static void boot_info_entries_free(struct boot_info_entry *entries, size_t n) {
113 for (i = 0; i < n; i++) {
114 free(entries[i].title);
115 free(entries[i].path);
120 static void boot_info_free(struct boot_info *info) {
123 boot_info_entries_free(info->fw_entries, info->fw_entries_count);
124 free(info->fw_entries_order);
126 free(info->loader_image_path);
127 free(info->loader_options_added);
128 boot_info_entries_free(info->loader_entries, info->loader_entries_count);
132 static int show_status(char **args, unsigned n) {
134 struct boot_info *info;
137 err = boot_info_new(&info);
141 err = boot_info_query(info);
144 printf(" Machine ID: %s\n", sd_id128_to_string(info->machine_id, buf));
145 printf(" Boot ID: %s\n", sd_id128_to_string(info->boot_id, buf));
147 printf(" Firmware: %s (%s)\n", info->fw_type, strna(info->fw_info));
148 if (info->fw_secure_boot >= 0)
149 printf(" Secure Boot: %s\n", info->fw_secure_boot ? "enabled" : "disabled");
150 if (info->fw_secure_boot_setup_mode >= 0)
151 printf(" Setup Mode: %s\n", info->fw_secure_boot_setup_mode ? "setup" : "user");
154 if (info->fw_entry_active >= 0) {
155 printf("Selected Firmware Entry:\n");
156 printf(" Title: %s\n", strna(info->fw_entries[info->fw_entry_active].title));
157 if (!sd_id128_equal(info->fw_entries[info->fw_entry_active].part_uuid, SD_ID128_NULL))
158 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
159 SD_ID128_FORMAT_VAL(info->fw_entries[info->fw_entry_active].part_uuid));
161 printf(" Partition: n/a\n");
162 if (info->fw_entries[info->fw_entry_active].path)
163 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), info->fw_entries[info->fw_entry_active].path);
168 printf("Boot Loader:\n");
169 printf(" Product: %s\n", info->loader);
170 if (!sd_id128_equal(info->loader_part_uuid, SD_ID128_NULL))
171 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
172 SD_ID128_FORMAT_VAL(info->loader_part_uuid));
174 printf(" Partition: n/a\n");
175 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(info->loader_image_path));
178 if (info->loader_entry_active >= 0) {
179 printf("Selected Boot Loader Entry:\n");
180 printf(" Title: %s\n", strna(info->loader_entries[info->loader_entry_active].title));
181 printf(" File: %s\n", info->loader_entries[info->loader_entry_active].path);
182 if (info->loader_options_added)
183 printf(" Options: %s\n", info->loader_options_added);
186 printf("No suitable data is provided by the boot manager. See:\n"
187 " http://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface\n"
188 " http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec\n"
192 boot_info_free(info);
196 static int bootctl_main(int argc, char *argv[]) {
197 static const struct {
205 int (* const dispatch)(char **args, unsigned n);
207 { "status", LESS, 1, show_status },
216 left = argc - optind;
219 /* Special rule: no arguments means "status" */
222 if (streq(argv[optind], "help")) {
227 for (i = 0; i < ELEMENTSOF(verbs); i++)
228 if (streq(argv[optind], verbs[i].verb))
231 if (i >= ELEMENTSOF(verbs)) {
232 log_error("Unknown operation %s", argv[optind]);
237 switch (verbs[i].argc_cmp) {
240 if (left != verbs[i].argc) {
241 log_error("Invalid number of arguments.");
247 if (left < verbs[i].argc) {
248 log_error("Too few arguments.");
254 if (left > verbs[i].argc) {
255 log_error("Too many arguments.");
261 assert_not_reached("Unknown comparison operator.");
264 return verbs[i].dispatch(argv + optind, left);
267 int main(int argc, char *argv[]) {
270 log_parse_environment();
273 r = parse_argv(argc, argv);
277 r = bootctl_main(argc, argv);
280 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;