1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013-2015 Kay Sievers
7 Copyright 2013 Lennart Poettering
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/statfs.h>
39 #include <blkid/blkid.h>
45 static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
53 if (statfs(p, &sfs) < 0) {
54 fprintf(stderr, "Failed to check file system type of %s: %m\n", p);
58 if (sfs.f_type != 0x4d44) {
59 fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p);
63 if (stat(p, &st) < 0) {
64 fprintf(stderr, "Failed to determine block device node of %s: %m\n", p);
68 if (major(st.st_dev) == 0) {
69 fprintf(stderr, "Block device node of %p is invalid.\n", p);
73 r = asprintf(&t, "%s/..", p);
75 fprintf(stderr, "Out of memory.\n");
82 fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p);
86 if (st.st_dev == st2.st_dev) {
87 fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p);
91 r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
93 fprintf(stderr, "Out of memory.\n");
98 b = blkid_new_probe_from_filename(t);
102 fprintf(stderr, "Failed to open file system %s: %m\n", p);
106 fprintf(stderr, "Out of memory.\n");
110 blkid_probe_enable_superblocks(b, 1);
111 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
112 blkid_probe_enable_partitions(b, 1);
113 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
116 r = blkid_do_safeprobe(b);
118 fprintf(stderr, "File system %s is ambigious.\n", p);
122 fprintf(stderr, "File system %s does not contain a label.\n", p);
126 r = errno ? -errno : -EIO;
127 fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r));
132 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
134 r = errno ? -errno : -EIO;
135 fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r));
139 if (strcmp(v, "vfat") != 0) {
140 fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p);
146 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
148 r = errno ? -errno : -EIO;
149 fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r));
153 if (strcmp(v, "gpt") != 0) {
154 fprintf(stderr, "File system %s is not on a GPT partition table.\n", p);
160 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
162 r = errno ? -errno : -EIO;
163 fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r));
167 if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) {
169 fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p);
174 r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
176 r = errno ? -errno : -EIO;
177 fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r));
180 sd_id128_from_string(v, uuid);
183 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
185 r = errno ? -errno : -EIO;
186 fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
189 *part = strtoul(v, NULL, 10);
192 r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
194 r = errno ? -errno : -EIO;
195 fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
198 *pstart = strtoul(v, NULL, 10);
201 r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
203 r = errno ? -errno : -EIO;
204 fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r));
207 *psize = strtoul(v, NULL, 10);
217 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
218 static int get_file_version(FILE *f, char **v) {
228 if (fstat(fileno(f), &st) < 0)
234 buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
235 if (buf == MAP_FAILED)
238 s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
243 e = memmem(s, st.st_size - (s - buf), " ####", 5);
244 if (!e || e - s < 3) {
245 fprintf(stderr, "Malformed version string.\n");
250 x = strndup(s, e - s);
252 fprintf(stderr, "Out of memory.\n");
259 munmap(buf, st.st_size);
264 static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
266 char *p = NULL, *q = NULL;
270 if (asprintf(&p, "%s/%s", esp_path, path) < 0) {
271 fprintf(stderr, "Out of memory.\n");
278 if (errno == ENOENT) {
283 fprintf(stderr, "Failed to read %s: %m\n", p);
288 while ((de = readdir(d))) {
293 if (de->d_name[0] == '.')
296 n = strlen(de->d_name);
297 if (n < 4 || strcasecmp(de->d_name + n - 4, ".efi") != 0)
300 if (prefix && strncasecmp(de->d_name, prefix, strlen(prefix)) != 0)
305 if (asprintf(&q, "%s/%s/%s", esp_path, path, de->d_name) < 0) {
306 fprintf(stderr, "Out of memory.\n");
313 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
318 r = get_file_version(f, &v);
325 printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v);
327 printf(" File: └─/%s/%s\n", path, de->d_name);
344 static int status_binaries(const char *esp_path, sd_id128_t partition) {
347 printf("Boot Loader Binaries:\n");
349 printf(" ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition));
351 r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
353 fprintf(stderr, "systemd-boot not installed in ESP.\n");
357 r = enumerate_binaries(esp_path, "EFI/Boot", "boot");
359 fprintf(stderr, "No default/fallback boot loader installed in ESP.\n");
367 static int print_efi_option(uint16_t id, bool in_order) {
368 _cleanup_free_ char *title = NULL;
369 _cleanup_free_ char *path = NULL;
370 sd_id128_t partition;
374 r = efi_get_boot_option(id, &title, &partition, &path, &active);
378 /* print only configured entries with partition information */
379 if (!path || sd_id128_equal(partition, SD_ID128_NULL))
382 efi_tilt_backslashes(path);
384 printf(" Title: %s\n", strna(title));
385 printf(" ID: 0x%04X\n", id);
386 printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
387 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition));
388 printf(" File: └─%s\n", path);
394 static int status_variables(void) {
395 int n_options, n_order;
396 uint16_t *options = NULL, *order = NULL;
399 if (!is_efi_boot()) {
400 fprintf(stderr, "Not booted with EFI, not showing EFI variables.\n");
404 n_options = efi_get_boot_options(&options);
406 if (n_options == -ENOENT)
407 fprintf(stderr, "Failed to access EFI variables, "
408 "efivarfs needs to be available at /sys/firmware/efi/efivars/.\n");
410 fprintf(stderr, "Failed to read EFI boot entries: %s\n", strerror(-n_options));
415 printf("Boot Loader Entries in EFI Variables:\n");
416 n_order = efi_get_boot_order(&order);
417 if (n_order == -ENOENT) {
419 } else if (n_order < 0) {
420 fprintf(stderr, "Failed to read EFI boot order.\n");
425 /* print entries in BootOrder first */
426 for (i = 0; i < n_order; i++)
427 print_efi_option(order[i], true);
429 /* print remaining entries */
430 for (i = 0; i < n_options; i++) {
434 for (j = 0; j < n_order; j++)
435 if (options[i] == order[j]) {
443 print_efi_option(options[i], false);
454 static int compare_product(const char *a, const char *b) {
463 return x < y ? -1 : x > y ? 1 : 0;
465 return strncmp(a, b, x);
468 static int compare_version(const char *a, const char *b) {
472 a += strcspn(a, " ");
474 b += strcspn(b, " ");
477 return strverscmp(a, b);
480 static int version_check(FILE *f, const char *from, const char *to) {
482 char *a = NULL, *b = NULL;
489 r = get_file_version(f, &a);
494 fprintf(stderr, "Source file %s does not carry version information!\n", from);
500 if (errno == ENOENT) {
506 fprintf(stderr, "Failed to open %s for reading: %m\n", to);
510 r = get_file_version(g, &b);
513 if (r == 0 || compare_product(a, b) != 0) {
515 fprintf(stderr, "Skipping %s, since it's owned by another boot loader.\n", to);
519 if (compare_version(a, b) < 0) {
521 fprintf(stderr, "Skipping %s, since it's a newer boot loader version already.\n", to);
535 static int copy_file(const char *from, const char *to, bool force) {
536 FILE *f = NULL, *g = NULL;
539 struct timespec t[2];
545 f = fopen(from, "re");
547 fprintf(stderr, "Failed to open %s for reading: %m\n", from);
552 /* If this is an update, then let's compare versions first */
553 r = version_check(f, from, to);
558 if (asprintf(&p, "%s~", to) < 0) {
559 fprintf(stderr, "Out of memory.\n");
566 /* Directory doesn't exist yet? Then let's skip this... */
567 if (!force && errno == ENOENT) {
572 fprintf(stderr, "Failed to open %s for writing: %m\n", to);
580 uint8_t buf[32*1024];
582 k = fread(buf, 1, sizeof(buf), f);
584 fprintf(stderr, "Failed to read %s: %m\n", from);
591 fwrite(buf, 1, k, g);
593 fprintf(stderr, "Failed to write %s: %m\n", to);
601 fprintf(stderr, "Failed to write %s: %m\n", to);
606 r = fstat(fileno(f), &st);
608 fprintf(stderr, "Failed to get file timestamps of %s: %m", from);
616 r = futimens(fileno(g), t);
618 fprintf(stderr, "Failed to change file timestamps for %s: %m", p);
623 if (rename(p, to) < 0) {
624 fprintf(stderr, "Failed to rename %s to %s: %m\n", p, to);
629 fprintf(stderr, "Copied %s to %s.\n", from, to);
647 static char* strupper(char *s) {
656 static int mkdir_one(const char *prefix, const char *suffix) {
659 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
660 fprintf(stderr, "Out of memory.\n");
664 if (mkdir(p, 0700) < 0) {
665 if (errno != EEXIST) {
666 fprintf(stderr, "Failed to create %s: %m\n", p);
671 fprintf(stderr, "Created %s.\n", p);
677 static int create_dirs(const char *esp_path) {
680 r = mkdir_one(esp_path, "EFI");
684 r = mkdir_one(esp_path, "EFI/systemd");
688 r = mkdir_one(esp_path, "EFI/Boot");
692 r = mkdir_one(esp_path, "loader");
696 r = mkdir_one(esp_path, "loader/entries");
703 static int copy_one_file(const char *esp_path, const char *name, bool force) {
704 _cleanup_free_ char *p = NULL;
705 _cleanup_free_ char *q = NULL;
706 _cleanup_free_ char *v = NULL;
709 if (asprintf(&p, BOOTLIBDIR "/%s", name) < 0) {
710 fprintf(stderr, "Out of memory.\n");
714 if (asprintf(&q, "%s/EFI/systemd/%s", esp_path, name) < 0) {
715 fprintf(stderr, "Out of memory.\n");
719 r = copy_file(p, q, force);
721 if (startswith(name, "systemd-boot")) {
724 /* Create the EFI default boot loader name (specified for removable devices) */
725 if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("systemd-boot")) < 0) {
726 fprintf(stderr, "Out of memory.\n");
729 strupper(strrchr(v, '/') + 1);
731 k = copy_file(p, v, force);
739 static int install_binaries(const char *esp_path, bool force) {
745 /* Don't create any of these directories when we are
746 * just updating. When we update we'll drop-in our
747 * files (unless there are newer ones already), but we
748 * won't create the directories for them in the first
750 r = create_dirs(esp_path);
755 d = opendir(BOOTLIBDIR);
757 fprintf(stderr, "Failed to open "BOOTLIBDIR": %m\n");
761 while ((de = readdir(d))) {
765 if (de->d_name[0] == '.')
768 n = strlen(de->d_name);
769 if (n < 4 || strcmp(de->d_name + n - 4, ".efi") != 0)
772 k = copy_one_file(esp_path, de->d_name, force);
781 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
787 err = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
790 if (!sd_id128_equal(uuid, ouuid))
793 if (!streq_ptr(path, opath))
802 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
803 uint16_t *options = NULL;
807 bool existing = false;
809 n_options = efi_get_boot_options(&options);
813 /* find already existing systemd-boot entry */
814 for (i = 0; i < n_options; i++)
815 if (same_entry(options[i], uuid, path)) {
821 /* find free slot in the sorted BootXXXX variable list */
822 for (i = 0; i < n_options; i++)
823 if (i != options[i]) {
828 /* use the next one */
839 static int insert_into_order(uint16_t slot, bool first) {
840 uint16_t *order = NULL;
846 n_order = efi_get_boot_order(&order);
848 /* no entry, add us */
849 err = efi_set_boot_order(&slot, 1);
853 /* are we the first and only one? */
854 if (n_order == 1 && order[0] == slot)
857 /* are we already in the boot order? */
858 for (i = 0; i < n_order; i++) {
859 if (order[i] != slot)
862 /* we do not require to be the first one, all is fine */
866 /* move us to the first slot */
867 memmove(&order[1], order, i * sizeof(uint16_t));
869 efi_set_boot_order(order, n_order);
874 new_order = realloc(order, (n_order+1) * sizeof(uint16_t));
881 /* add us to the top or end of the list */
883 memmove(&order[1], order, n_order * sizeof(uint16_t));
886 order[n_order] = slot;
888 efi_set_boot_order(order, n_order+1);
895 static int remove_from_order(uint16_t slot) {
896 _cleanup_free_ uint16_t *order = NULL;
901 n_order = efi_get_boot_order(&order);
907 for (i = 0; i < n_order; i++) {
908 if (order[i] != slot)
912 memmove(&order[i], &order[i+1], (n_order - i) * sizeof(uint16_t));
913 efi_set_boot_order(order, n_order-1);
920 static int install_variables(const char *esp_path,
921 uint32_t part, uint64_t pstart, uint64_t psize,
922 sd_id128_t uuid, const char *path,
925 uint16_t *options = NULL;
929 if (!is_efi_boot()) {
930 fprintf(stderr, "Not booted with EFI, skipping EFI variable setup.\n");
934 if (asprintf(&p, "%s%s", esp_path, path) < 0) {
935 fprintf(stderr, "Out of memory.\n");
939 if (access(p, F_OK) < 0) {
947 r = find_slot(uuid, path, &slot);
950 fprintf(stderr, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?\n");
952 fprintf(stderr, "Failed to determine current boot order: %s\n", strerror(-r));
956 if (first || r == false) {
957 r = efi_add_boot_option(slot, "Linux Boot Manager",
961 fprintf(stderr, "Failed to create EFI Boot variable entry: %s\n", strerror(-r));
964 fprintf(stderr, "Created EFI boot entry \"Linux Boot Manager\".\n");
967 insert_into_order(slot, first);
975 static int remove_boot_efi(const char *esp_path) {
977 char *p = NULL, *q = NULL;
981 if (asprintf(&p, "%s/EFI/Boot", esp_path) < 0) {
982 fprintf(stderr, "Out of memory.\n");
988 if (errno == ENOENT) {
993 fprintf(stderr, "Failed to read %s: %m\n", p);
998 while ((de = readdir(d))) {
1003 if (de->d_name[0] == '.')
1006 n = strlen(de->d_name);
1007 if (n < 4 || strcasecmp(de->d_name + n - 4, ".EFI") != 0)
1010 if (strncasecmp(de->d_name, "Boot", 4) != 0)
1015 if (asprintf(&q, "%s/%s", p, de->d_name) < 0) {
1016 fprintf(stderr, "Out of memory.\n");
1023 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
1028 r = get_file_version(f, &v);
1034 if (r > 0 && strncmp(v, "systemd-boot ", 10) == 0) {
1038 fprintf(stderr, "Failed to remove %s: %m\n", q);
1043 fprintf(stderr, "Removed %s.\n", q);
1061 static int rmdir_one(const char *prefix, const char *suffix) {
1064 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
1065 fprintf(stderr, "Out of memory.\n");
1070 if (errno != ENOENT && errno != ENOTEMPTY) {
1071 fprintf(stderr, "Failed to remove %s: %m\n", p);
1076 fprintf(stderr, "Removed %s.\n", p);
1083 static int remove_binaries(const char *esp_path) {
1087 if (asprintf(&p, "%s/EFI/systemd-boot", esp_path) < 0) {
1088 fprintf(stderr, "Out of memory.\n");
1092 r = rm_rf(p, false, false, false);
1095 q = remove_boot_efi(esp_path);
1096 if (q < 0 && r == 0)
1099 q = rmdir_one(esp_path, "loader/entries");
1100 if (q < 0 && r == 0)
1103 q = rmdir_one(esp_path, "loader");
1104 if (q < 0 && r == 0)
1107 q = rmdir_one(esp_path, "EFI/Boot");
1108 if (q < 0 && r == 0)
1111 q = rmdir_one(esp_path, "EFI/systemd-boot");
1112 if (q < 0 && r == 0)
1115 q = rmdir_one(esp_path, "EFI");
1116 if (q < 0 && r == 0)
1122 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
1129 r = find_slot(uuid, path, &slot);
1133 r = efi_remove_boot_option(slot);
1138 remove_from_order(slot);
1143 static int install_loader_config(const char *esp_path) {
1146 char *machine = NULL;
1149 f = fopen("/etc/machine-id", "re");
1153 if (fgets(line, sizeof(line), f) != NULL) {
1156 s = strchr(line, '\n');
1159 if (strlen(line) == 32)
1168 if (asprintf(&p, "%s/%s", esp_path, "loader/loader.conf") < 0) {
1169 fprintf(stderr, "Out of memory.\n");
1173 f = fopen(p, "wxe");
1175 fprintf(f, "#timeout 3\n");
1176 fprintf(f, "default %s-*\n", machine);
1184 static int help(void) {
1185 printf("%s [COMMAND] [OPTIONS...]\n"
1187 "Install, update or remove the sdboot EFI boot manager.\n\n"
1188 " -h --help Show this help\n"
1189 " --version Print version\n"
1190 " --path=PATH Path to the EFI System Partition (ESP)\n"
1191 " --no-variables Don't touch EFI variables\n"
1194 " status Show status of installed systemd-boot and EFI variables\n"
1195 " install Install systemd-boot to the ESP and EFI variables\n"
1196 " update Update systemd-boot in the ESP and EFI variables\n"
1197 " remove Remove systemd-boot from the ESP and EFI variables\n",
1198 program_invocation_short_name);
1203 static const char *arg_path = NULL;
1204 static bool arg_touch_variables = true;
1206 static int parse_argv(int argc, char *argv[]) {
1213 static const struct option options[] = {
1214 { "help", no_argument, NULL, 'h' },
1215 { "version", no_argument, NULL, ARG_VERSION },
1216 { "path", required_argument, NULL, ARG_PATH },
1217 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1218 { NULL, 0, NULL, 0 }
1226 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1234 printf(VERSION "\n");
1241 case ARG_NO_VARIABLES:
1242 arg_touch_variables = false;
1249 fprintf(stderr, "Unknown option code '%c'.\n", c);
1257 static int bootctl_main(int argc, char*argv[]) {
1263 } arg_action = ACTION_STATUS;
1264 static const struct {
1268 { "status", ACTION_STATUS },
1269 { "install", ACTION_INSTALL },
1270 { "update", ACTION_UPDATE },
1271 { "remove", ACTION_REMOVE },
1274 sd_id128_t uuid = {};
1276 uint64_t pstart = 0;
1282 r = parse_argv(argc, argv);
1287 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1288 if (!streq(argv[optind], verbs[i].verb))
1290 arg_action = verbs[i].action;
1293 if (i >= ELEMENTSOF(verbs)) {
1294 fprintf(stderr, "Unknown operation %s\n", argv[optind]);
1303 if (geteuid() != 0) {
1304 fprintf(stderr, "Need to be root.\n");
1309 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1310 if (r == -ENODEV && !arg_path)
1311 fprintf(stderr, "You might want to use --path= to indicate the path to your ESP, in case it is not mounted to /boot.\n");
1315 switch (arg_action) {
1316 case ACTION_STATUS: {
1317 _cleanup_free_ char *fw_type = NULL;
1318 _cleanup_free_ char *fw_info = NULL;
1319 _cleanup_free_ char *loader = NULL;
1320 _cleanup_free_ char *loader_path = NULL;
1321 sd_id128_t loader_part_uuid = {};
1323 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &fw_type);
1324 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &fw_info);
1325 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &loader);
1326 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &loader_path);
1327 efi_tilt_backslashes(loader_path);
1328 efi_loader_get_device_part_uuid(&loader_part_uuid);
1330 printf("System:\n");
1331 printf(" Firmware: %s (%s)\n", fw_type, strna(fw_info));
1332 printf(" Secure Boot: %s\n", is_efi_secure_boot() ? "enabled" : "disabled");
1333 printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
1336 printf("Loader:\n");
1337 printf(" Product: %s\n", strna(loader));
1338 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1339 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1340 SD_ID128_FORMAT_VAL(loader_part_uuid));
1342 printf(" Partition: n/a\n");
1343 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1346 r = status_binaries(arg_path, uuid);
1350 if (arg_touch_variables)
1351 r = status_variables();
1355 case ACTION_INSTALL:
1359 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1363 if (arg_action == ACTION_INSTALL)
1364 install_loader_config(arg_path);
1366 if (arg_touch_variables)
1367 r = install_variables(arg_path,
1368 part, pstart, psize, uuid,
1369 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1370 arg_action == ACTION_INSTALL);
1374 r = remove_binaries(arg_path);
1376 if (arg_touch_variables) {
1377 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1378 if (q < 0 && r == 0)
1385 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1388 int main(int argc, char *argv[]) {
1391 log_parse_environment();
1394 r = parse_argv(argc, argv);
1398 r = bootctl_main(argc, argv);
1401 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;