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 int help(void) {
36 printf("%s [OPTIONS...] COMMAND ...\n\n"
37 "Query or change firmware and boot mananger 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);
47 static int parse_argv(int argc, char *argv[]) {
52 static const struct option options[] = {
53 { "help", no_argument, NULL, 'h' },
54 { "version", no_argument, NULL, ARG_VERSION },
62 while ((c = getopt_long(argc, argv, "+hH:P", options, NULL)) >= 0) {
72 puts(SYSTEMD_FEATURES);
79 log_error("Unknown option code %c", c);
87 static int boot_info_new(struct boot_info **info) {
91 in = new0(struct boot_info, 1);
95 err = sd_id128_get_machine(&in->machine_id);
99 err = sd_id128_get_boot(&in->boot_id);
103 in->fw_entry_active = -1;
104 in->loader_entry_active = -1;
113 static void boot_info_entries_free(struct boot_info_entry *entries, size_t n) {
116 for (i = 0; i < n; i++) {
117 free(entries[i].title);
118 free(entries[i].path);
123 static void boot_info_free(struct boot_info *info) {
126 boot_info_entries_free(info->fw_entries, info->fw_entries_count);
127 free(info->fw_entries_order);
129 free(info->loader_image_path);
130 free(info->loader_options_added);
131 boot_info_entries_free(info->loader_entries, info->loader_entries_count);
135 static int show_status(char **args, unsigned n) {
137 struct boot_info *info;
140 err = boot_info_new(&info);
144 err = boot_info_query(info);
147 printf(" Machine ID: %s\n", sd_id128_to_string(info->machine_id, buf));
148 printf(" Boot ID: %s\n", sd_id128_to_string(info->boot_id, buf));
150 printf(" Firmware: %s (%s)\n", info->fw_type, strna(info->fw_info));
151 if (info->fw_secure_boot >= 0)
152 printf(" Secure Boot: %s\n", info->fw_secure_boot ? "enabled" : "disabled");
153 if (info->fw_secure_boot_setup_mode >= 0)
154 printf(" Setup Mode: %s\n", info->fw_secure_boot_setup_mode ? "setup" : "user");
157 if (info->fw_entry_active >= 0) {
158 printf("Selected Firmware Entry:\n");
159 printf(" Title: %s\n", strna(info->fw_entries[info->fw_entry_active].title));
160 if (!sd_id128_equal(info->fw_entries[info->fw_entry_active].part_uuid, SD_ID128_NULL))
161 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
162 SD_ID128_FORMAT_VAL(info->fw_entries[info->fw_entry_active].part_uuid));
164 printf(" Partition: n/a\n");
165 if (info->fw_entries[info->fw_entry_active].path)
166 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), info->fw_entries[info->fw_entry_active].path);
171 printf("Boot Loader:\n");
172 printf(" Product: %s\n", info->loader);
173 if (!sd_id128_equal(info->loader_part_uuid, SD_ID128_NULL))
174 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
175 SD_ID128_FORMAT_VAL(info->loader_part_uuid));
177 printf(" Partition: n/a\n");
178 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(info->loader_image_path));
181 if (info->loader_entry_active >= 0) {
182 printf("Selected Boot Loader Entry:\n");
183 printf(" Title: %s\n", strna(info->loader_entries[info->loader_entry_active].title));
184 printf(" File: %s\n", info->loader_entries[info->loader_entry_active].path);
185 if (info->loader_options_added)
186 printf(" Options: %s\n", info->loader_options_added);
189 printf("No suitable data is provided by the boot manager. See:\n"
190 " http://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface\n"
191 " http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec\n"
195 boot_info_free(info);
199 static int bootctl_main(int argc, char *argv[]) {
200 static const struct {
208 int (* const dispatch)(char **args, unsigned n);
210 { "status", LESS, 1, show_status },
219 left = argc - optind;
222 /* Special rule: no arguments means "status" */
225 if (streq(argv[optind], "help")) {
230 for (i = 0; i < ELEMENTSOF(verbs); i++)
231 if (streq(argv[optind], verbs[i].verb))
234 if (i >= ELEMENTSOF(verbs)) {
235 log_error("Unknown operation %s", argv[optind]);
240 switch (verbs[i].argc_cmp) {
243 if (left != verbs[i].argc) {
244 log_error("Invalid number of arguments.");
250 if (left < verbs[i].argc) {
251 log_error("Too few arguments.");
257 if (left > verbs[i].argc) {
258 log_error("Too many arguments.");
264 assert_not_reached("Unknown comparison operator.");
267 return verbs[i].dispatch(argv + optind, left);
270 int main(int argc, char *argv[]) {
271 int r, retval = EXIT_FAILURE;
273 log_parse_environment();
276 r = parse_argv(argc, argv);
280 retval = EXIT_SUCCESS;
284 r = bootctl_main(argc, argv);
285 retval = r < 0 ? EXIT_FAILURE : r;