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) {
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);
397 static int status_variables(void) {
398 int n_options, n_order;
399 uint16_t *options = NULL, *order = NULL;
402 if (!is_efi_boot()) {
403 fprintf(stderr, "Not booted with EFI, not showing EFI variables.\n");
407 n_options = efi_get_boot_options(&options);
409 if (n_options == -ENOENT)
410 fprintf(stderr, "Failed to access EFI variables, "
411 "efivarfs needs to be available at /sys/firmware/efi/efivars/.\n");
413 fprintf(stderr, "Failed to read EFI boot entries: %s\n", strerror(-n_options));
418 printf("Boot Loader Entries in EFI Variables:\n");
419 n_order = efi_get_boot_order(&order);
420 if (n_order == -ENOENT) {
422 } else if (n_order < 0) {
423 fprintf(stderr, "Failed to read EFI boot order.\n");
428 /* print entries in BootOrder first */
429 for (i = 0; i < n_order; i++)
430 print_efi_option(order[i], true);
432 /* print remaining entries */
433 for (i = 0; i < n_options; i++) {
437 for (j = 0; j < n_order; j++)
438 if (options[i] == order[j]) {
446 print_efi_option(options[i], false);
457 static int compare_product(const char *a, const char *b) {
466 return x < y ? -1 : x > y ? 1 : 0;
468 return strncmp(a, b, x);
471 static int compare_version(const char *a, const char *b) {
475 a += strcspn(a, " ");
477 b += strcspn(b, " ");
480 return strverscmp(a, b);
483 static int version_check(FILE *f, const char *from, const char *to) {
485 char *a = NULL, *b = NULL;
492 r = get_file_version(f, &a);
497 fprintf(stderr, "Source file %s does not carry version information!\n", from);
503 if (errno == ENOENT) {
509 fprintf(stderr, "Failed to open %s for reading: %m\n", to);
513 r = get_file_version(g, &b);
516 if (r == 0 || compare_product(a, b) != 0) {
518 fprintf(stderr, "Skipping %s, since it's owned by another boot loader.\n", to);
522 if (compare_version(a, b) < 0) {
524 fprintf(stderr, "Skipping %s, since it's a newer boot loader version already.\n", to);
538 static int copy_file(const char *from, const char *to, bool force) {
539 FILE *f = NULL, *g = NULL;
542 struct timespec t[2];
548 f = fopen(from, "re");
550 fprintf(stderr, "Failed to open %s for reading: %m\n", from);
555 /* If this is an update, then let's compare versions first */
556 r = version_check(f, from, to);
561 if (asprintf(&p, "%s~", to) < 0) {
562 fprintf(stderr, "Out of memory.\n");
569 /* Directory doesn't exist yet? Then let's skip this... */
570 if (!force && errno == ENOENT) {
575 fprintf(stderr, "Failed to open %s for writing: %m\n", to);
583 uint8_t buf[32*1024];
585 k = fread(buf, 1, sizeof(buf), f);
587 fprintf(stderr, "Failed to read %s: %m\n", from);
594 fwrite(buf, 1, k, g);
596 fprintf(stderr, "Failed to write %s: %m\n", to);
604 fprintf(stderr, "Failed to write %s: %m\n", to);
609 r = fstat(fileno(f), &st);
611 fprintf(stderr, "Failed to get file timestamps of %s: %m", from);
619 r = futimens(fileno(g), t);
621 fprintf(stderr, "Failed to change file timestamps for %s: %m", p);
626 if (rename(p, to) < 0) {
627 fprintf(stderr, "Failed to rename %s to %s: %m\n", p, to);
632 fprintf(stderr, "Copied %s to %s.\n", from, to);
650 static char* strupper(char *s) {
659 static int mkdir_one(const char *prefix, const char *suffix) {
662 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
663 fprintf(stderr, "Out of memory.\n");
667 if (mkdir(p, 0700) < 0) {
668 if (errno != EEXIST) {
669 fprintf(stderr, "Failed to create %s: %m\n", p);
674 fprintf(stderr, "Created %s.\n", p);
680 static int create_dirs(const char *esp_path) {
683 r = mkdir_one(esp_path, "EFI");
687 r = mkdir_one(esp_path, "EFI/systemd");
691 r = mkdir_one(esp_path, "EFI/Boot");
695 r = mkdir_one(esp_path, "loader");
699 r = mkdir_one(esp_path, "loader/entries");
706 static int copy_one_file(const char *esp_path, const char *name, bool force) {
707 _cleanup_free_ char *p = NULL;
708 _cleanup_free_ char *q = NULL;
709 _cleanup_free_ char *v = NULL;
712 if (asprintf(&p, BOOTLIBDIR "/%s", name) < 0) {
713 fprintf(stderr, "Out of memory.\n");
717 if (asprintf(&q, "%s/EFI/systemd/%s", esp_path, name) < 0) {
718 fprintf(stderr, "Out of memory.\n");
722 r = copy_file(p, q, force);
724 if (startswith(name, "systemd-boot")) {
727 /* Create the EFI default boot loader name (specified for removable devices) */
728 if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("systemd-boot")) < 0) {
729 fprintf(stderr, "Out of memory.\n");
732 strupper(strrchr(v, '/') + 1);
734 k = copy_file(p, v, force);
742 static int install_binaries(const char *esp_path, bool force) {
748 /* Don't create any of these directories when we are
749 * just updating. When we update we'll drop-in our
750 * files (unless there are newer ones already), but we
751 * won't create the directories for them in the first
753 r = create_dirs(esp_path);
758 d = opendir(BOOTLIBDIR);
760 fprintf(stderr, "Failed to open "BOOTLIBDIR": %m\n");
764 while ((de = readdir(d))) {
768 if (de->d_name[0] == '.')
771 n = strlen(de->d_name);
772 if (n < 4 || strcmp(de->d_name + n - 4, ".efi") != 0)
775 k = copy_one_file(esp_path, de->d_name, force);
784 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
790 err = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
793 if (!sd_id128_equal(uuid, ouuid))
796 if (!streq_ptr(path, opath))
805 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
806 uint16_t *options = NULL;
810 bool existing = false;
812 n_options = efi_get_boot_options(&options);
816 /* find already existing systemd-boot entry */
817 for (i = 0; i < n_options; i++)
818 if (same_entry(options[i], uuid, path)) {
824 /* find free slot in the sorted BootXXXX variable list */
825 for (i = 0; i < n_options; i++)
826 if (i != options[i]) {
831 /* use the next one */
842 static int insert_into_order(uint16_t slot, bool first) {
843 uint16_t *order = NULL;
849 n_order = efi_get_boot_order(&order);
851 /* no entry, add us */
852 err = efi_set_boot_order(&slot, 1);
856 /* are we the first and only one? */
857 if (n_order == 1 && order[0] == slot)
860 /* are we already in the boot order? */
861 for (i = 0; i < n_order; i++) {
862 if (order[i] != slot)
865 /* we do not require to be the first one, all is fine */
869 /* move us to the first slot */
870 memmove(&order[1], order, i * sizeof(uint16_t));
872 efi_set_boot_order(order, n_order);
877 new_order = realloc(order, (n_order+1) * sizeof(uint16_t));
884 /* add us to the top or end of the list */
886 memmove(&order[1], order, n_order * sizeof(uint16_t));
889 order[n_order] = slot;
891 efi_set_boot_order(order, n_order+1);
898 static int remove_from_order(uint16_t slot) {
899 uint16_t *order = NULL;
904 n_order = efi_get_boot_order(&order);
910 for (i = 0; i < n_order; i++) {
911 if (order[i] != slot)
915 memmove(&order[i], &order[i+1], (n_order - i) * sizeof(uint16_t));
916 efi_set_boot_order(order, n_order-1);
924 static int install_variables(const char *esp_path,
925 uint32_t part, uint64_t pstart, uint64_t psize,
926 sd_id128_t uuid, const char *path,
929 uint16_t *options = NULL;
933 if (!is_efi_boot()) {
934 fprintf(stderr, "Not booted with EFI, skipping EFI variable setup.\n");
938 if (asprintf(&p, "%s%s", esp_path, path) < 0) {
939 fprintf(stderr, "Out of memory.\n");
943 if (access(p, F_OK) < 0) {
951 r = find_slot(uuid, path, &slot);
954 fprintf(stderr, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?\n");
956 fprintf(stderr, "Failed to determine current boot order: %s\n", strerror(-r));
960 if (first || r == false) {
961 r = efi_add_boot_option(slot, "Linux Boot Manager",
965 fprintf(stderr, "Failed to create EFI Boot variable entry: %s\n", strerror(-r));
968 fprintf(stderr, "Created EFI boot entry \"Linux Boot Manager\".\n");
971 insert_into_order(slot, first);
979 static int remove_boot_efi(const char *esp_path) {
981 char *p = NULL, *q = NULL;
985 if (asprintf(&p, "%s/EFI/Boot", esp_path) < 0) {
986 fprintf(stderr, "Out of memory.\n");
992 if (errno == ENOENT) {
997 fprintf(stderr, "Failed to read %s: %m\n", p);
1002 while ((de = readdir(d))) {
1007 if (de->d_name[0] == '.')
1010 n = strlen(de->d_name);
1011 if (n < 4 || strcasecmp(de->d_name + n - 4, ".EFI") != 0)
1014 if (strncasecmp(de->d_name, "Boot", 4) != 0)
1019 if (asprintf(&q, "%s/%s", p, de->d_name) < 0) {
1020 fprintf(stderr, "Out of memory.\n");
1027 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
1032 r = get_file_version(f, &v);
1038 if (r > 0 && strncmp(v, "systemd-boot ", 10) == 0) {
1042 fprintf(stderr, "Failed to remove %s: %m\n", q);
1047 fprintf(stderr, "Removed %s.\n", q);
1065 static int rmdir_one(const char *prefix, const char *suffix) {
1068 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
1069 fprintf(stderr, "Out of memory.\n");
1074 if (errno != ENOENT && errno != ENOTEMPTY) {
1075 fprintf(stderr, "Failed to remove %s: %m\n", p);
1080 fprintf(stderr, "Removed %s.\n", p);
1087 static int remove_binaries(const char *esp_path) {
1091 if (asprintf(&p, "%s/EFI/systemd-boot", esp_path) < 0) {
1092 fprintf(stderr, "Out of memory.\n");
1096 r = rm_rf(p, false, false, false);
1099 q = remove_boot_efi(esp_path);
1100 if (q < 0 && r == 0)
1103 q = rmdir_one(esp_path, "loader/entries");
1104 if (q < 0 && r == 0)
1107 q = rmdir_one(esp_path, "loader");
1108 if (q < 0 && r == 0)
1111 q = rmdir_one(esp_path, "EFI/Boot");
1112 if (q < 0 && r == 0)
1115 q = rmdir_one(esp_path, "EFI/systemd-boot");
1116 if (q < 0 && r == 0)
1119 q = rmdir_one(esp_path, "EFI");
1120 if (q < 0 && r == 0)
1126 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
1133 r = find_slot(uuid, path, &slot);
1137 r = efi_remove_boot_option(slot);
1142 remove_from_order(slot);
1147 static int install_loader_config(const char *esp_path) {
1150 char *machine = NULL;
1153 f = fopen("/etc/machine-id", "re");
1157 if (fgets(line, sizeof(line), f) != NULL) {
1160 s = strchr(line, '\n');
1163 if (strlen(line) == 32)
1172 if (asprintf(&p, "%s/%s", esp_path, "loader/loader.conf") < 0) {
1173 fprintf(stderr, "Out of memory.\n");
1177 f = fopen(p, "wxe");
1179 fprintf(f, "#timeout 3\n");
1180 fprintf(f, "default %s-*\n", machine);
1188 static int help(void) {
1189 printf("%s [COMMAND] [OPTIONS...]\n"
1191 "Install, update or remove the sdboot EFI boot manager.\n\n"
1192 " -h --help Show this help\n"
1193 " --version Print version\n"
1194 " --path=PATH Path to the EFI System Partition (ESP)\n"
1195 " --no-variables Don't touch EFI variables\n"
1198 " status Show status of installed systemd-boot and EFI variables\n"
1199 " install Install systemd-boot to the ESP and EFI variables\n"
1200 " update Update systemd-boot in the ESP and EFI variables\n"
1201 " remove Remove systemd-boot from the ESP and EFI variables\n",
1202 program_invocation_short_name);
1207 static const char *arg_path = NULL;
1208 static bool arg_touch_variables = true;
1210 static int parse_argv(int argc, char *argv[]) {
1217 static const struct option options[] = {
1218 { "help", no_argument, NULL, 'h' },
1219 { "version", no_argument, NULL, ARG_VERSION },
1220 { "path", required_argument, NULL, ARG_PATH },
1221 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1222 { NULL, 0, NULL, 0 }
1230 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1238 printf(VERSION "\n");
1245 case ARG_NO_VARIABLES:
1246 arg_touch_variables = false;
1253 fprintf(stderr, "Unknown option code '%c'.\n", c);
1261 static int bootctl_main(int argc, char*argv[]) {
1267 } arg_action = ACTION_STATUS;
1268 static const struct {
1272 { "status", ACTION_STATUS },
1273 { "install", ACTION_INSTALL },
1274 { "update", ACTION_UPDATE },
1275 { "remove", ACTION_REMOVE },
1278 sd_id128_t uuid = {};
1280 uint64_t pstart = 0;
1286 r = parse_argv(argc, argv);
1291 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1292 if (!streq(argv[optind], verbs[i].verb))
1294 arg_action = verbs[i].action;
1297 if (i >= ELEMENTSOF(verbs)) {
1298 fprintf(stderr, "Unknown operation %s\n", argv[optind]);
1307 if (geteuid() != 0) {
1308 fprintf(stderr, "Need to be root.\n");
1313 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1314 if (r == -ENODEV && !arg_path)
1315 fprintf(stderr, "You might want to use --path= to indicate the path to your ESP, in case it is not mounted to /boot.\n");
1319 switch (arg_action) {
1320 case ACTION_STATUS: {
1321 _cleanup_free_ char *fw_type = NULL;
1322 _cleanup_free_ char *fw_info = NULL;
1323 _cleanup_free_ char *loader = NULL;
1324 _cleanup_free_ char *loader_path = NULL;
1325 sd_id128_t loader_part_uuid = {};
1327 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &fw_type);
1328 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &fw_info);
1329 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &loader);
1330 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &loader_path);
1331 efi_tilt_backslashes(loader_path);
1332 efi_loader_get_device_part_uuid(&loader_part_uuid);
1334 printf("System:\n");
1335 printf(" Firmware: %s (%s)\n", fw_type, strna(fw_info));
1336 printf(" Secure Boot: %s\n", is_efi_secure_boot() ? "enabled" : "disabled");
1337 printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
1340 printf("Loader:\n");
1341 printf(" Product: %s\n", strna(loader));
1342 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1343 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1344 SD_ID128_FORMAT_VAL(loader_part_uuid));
1346 printf(" Partition: n/a\n");
1347 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1350 r = status_binaries(arg_path, uuid);
1354 if (arg_touch_variables)
1355 r = status_variables();
1359 case ACTION_INSTALL:
1363 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1367 if (arg_action == ACTION_INSTALL)
1368 install_loader_config(arg_path);
1370 if (arg_touch_variables)
1371 r = install_variables(arg_path,
1372 part, pstart, psize, uuid,
1373 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1374 arg_action == ACTION_INSTALL);
1378 r = remove_binaries(arg_path);
1380 if (arg_touch_variables) {
1381 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1382 if (q < 0 && r == 0)
1389 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1392 int main(int argc, char *argv[]) {
1395 log_parse_environment();
1398 r = parse_argv(argc, argv);
1402 r = bootctl_main(argc, argv);
1405 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;