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));
181 r = sd_id128_from_string(v, uuid);
183 fprintf(stderr, "Partition %s has invalid UUID: %s\n", p, v);
189 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
191 r = errno ? -errno : -EIO;
192 fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
195 *part = strtoul(v, NULL, 10);
198 r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
200 r = errno ? -errno : -EIO;
201 fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
204 *pstart = strtoul(v, NULL, 10);
207 r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
209 r = errno ? -errno : -EIO;
210 fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r));
213 *psize = strtoul(v, NULL, 10);
223 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
224 static int get_file_version(FILE *f, char **v) {
234 if (fstat(fileno(f), &st) < 0)
240 buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
241 if (buf == MAP_FAILED)
244 s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
249 e = memmem(s, st.st_size - (s - buf), " ####", 5);
250 if (!e || e - s < 3) {
251 fprintf(stderr, "Malformed version string.\n");
256 x = strndup(s, e - s);
258 fprintf(stderr, "Out of memory.\n");
265 munmap(buf, st.st_size);
270 static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
272 char *p = NULL, *q = NULL;
276 if (asprintf(&p, "%s/%s", esp_path, path) < 0) {
277 fprintf(stderr, "Out of memory.\n");
284 if (errno == ENOENT) {
289 fprintf(stderr, "Failed to read %s: %m\n", p);
294 while ((de = readdir(d))) {
299 if (de->d_name[0] == '.')
302 n = strlen(de->d_name);
303 if (n < 4 || strcasecmp(de->d_name + n - 4, ".efi") != 0)
306 if (prefix && strncasecmp(de->d_name, prefix, strlen(prefix)) != 0)
311 if (asprintf(&q, "%s/%s/%s", esp_path, path, de->d_name) < 0) {
312 fprintf(stderr, "Out of memory.\n");
319 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
324 r = get_file_version(f, &v);
331 printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v);
333 printf(" File: └─/%s/%s\n", path, de->d_name);
350 static int status_binaries(const char *esp_path, sd_id128_t partition) {
353 printf("Boot Loader Binaries:\n");
355 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));
357 r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
359 fprintf(stderr, "systemd-boot not installed in ESP.\n");
363 r = enumerate_binaries(esp_path, "EFI/Boot", "boot");
365 fprintf(stderr, "No default/fallback boot loader installed in ESP.\n");
373 static int print_efi_option(uint16_t id, bool in_order) {
374 _cleanup_free_ char *title = NULL;
375 _cleanup_free_ char *path = NULL;
376 sd_id128_t partition;
380 r = efi_get_boot_option(id, &title, &partition, &path, &active);
384 /* print only configured entries with partition information */
385 if (!path || sd_id128_equal(partition, SD_ID128_NULL))
388 efi_tilt_backslashes(path);
390 printf(" Title: %s\n", strna(title));
391 printf(" ID: 0x%04X\n", id);
392 printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
393 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));
394 printf(" File: └─%s\n", path);
400 static int status_variables(void) {
401 int n_options, n_order;
402 uint16_t *options = NULL, *order = NULL;
405 if (!is_efi_boot()) {
406 fprintf(stderr, "Not booted with EFI, not showing EFI variables.\n");
410 n_options = efi_get_boot_options(&options);
412 if (n_options == -ENOENT)
413 fprintf(stderr, "Failed to access EFI variables, "
414 "efivarfs needs to be available at /sys/firmware/efi/efivars/.\n");
416 fprintf(stderr, "Failed to read EFI boot entries: %s\n", strerror(-n_options));
421 printf("Boot Loader Entries in EFI Variables:\n");
422 n_order = efi_get_boot_order(&order);
423 if (n_order == -ENOENT) {
425 } else if (n_order < 0) {
426 fprintf(stderr, "Failed to read EFI boot order.\n");
431 /* print entries in BootOrder first */
432 for (i = 0; i < n_order; i++)
433 print_efi_option(order[i], true);
435 /* print remaining entries */
436 for (i = 0; i < n_options; i++) {
440 for (j = 0; j < n_order; j++)
441 if (options[i] == order[j]) {
449 print_efi_option(options[i], false);
460 static int compare_product(const char *a, const char *b) {
469 return x < y ? -1 : x > y ? 1 : 0;
471 return strncmp(a, b, x);
474 static int compare_version(const char *a, const char *b) {
478 a += strcspn(a, " ");
480 b += strcspn(b, " ");
483 return strverscmp(a, b);
486 static int version_check(FILE *f, const char *from, const char *to) {
488 char *a = NULL, *b = NULL;
495 r = get_file_version(f, &a);
500 fprintf(stderr, "Source file %s does not carry version information!\n", from);
506 if (errno == ENOENT) {
512 fprintf(stderr, "Failed to open %s for reading: %m\n", to);
516 r = get_file_version(g, &b);
519 if (r == 0 || compare_product(a, b) != 0) {
521 fprintf(stderr, "Skipping %s, since it's owned by another boot loader.\n", to);
525 if (compare_version(a, b) < 0) {
527 fprintf(stderr, "Skipping %s, since it's a newer boot loader version already.\n", to);
541 static int copy_file(const char *from, const char *to, bool force) {
542 FILE *f = NULL, *g = NULL;
545 struct timespec t[2];
551 f = fopen(from, "re");
553 fprintf(stderr, "Failed to open %s for reading: %m\n", from);
558 /* If this is an update, then let's compare versions first */
559 r = version_check(f, from, to);
564 if (asprintf(&p, "%s~", to) < 0) {
565 fprintf(stderr, "Out of memory.\n");
572 /* Directory doesn't exist yet? Then let's skip this... */
573 if (!force && errno == ENOENT) {
578 fprintf(stderr, "Failed to open %s for writing: %m\n", to);
586 uint8_t buf[32*1024];
588 k = fread(buf, 1, sizeof(buf), f);
590 fprintf(stderr, "Failed to read %s: %m\n", from);
597 fwrite(buf, 1, k, g);
599 fprintf(stderr, "Failed to write %s: %m\n", to);
607 fprintf(stderr, "Failed to write %s: %m\n", to);
612 r = fstat(fileno(f), &st);
614 fprintf(stderr, "Failed to get file timestamps of %s: %m", from);
622 r = futimens(fileno(g), t);
624 fprintf(stderr, "Failed to change file timestamps for %s: %m", p);
629 if (rename(p, to) < 0) {
630 fprintf(stderr, "Failed to rename %s to %s: %m\n", p, to);
635 fprintf(stderr, "Copied %s to %s.\n", from, to);
653 static char* strupper(char *s) {
662 static int mkdir_one(const char *prefix, const char *suffix) {
665 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
666 fprintf(stderr, "Out of memory.\n");
670 if (mkdir(p, 0700) < 0) {
671 if (errno != EEXIST) {
672 fprintf(stderr, "Failed to create %s: %m\n", p);
677 fprintf(stderr, "Created %s.\n", p);
683 static int create_dirs(const char *esp_path) {
686 r = mkdir_one(esp_path, "EFI");
690 r = mkdir_one(esp_path, "EFI/systemd");
694 r = mkdir_one(esp_path, "EFI/Boot");
698 r = mkdir_one(esp_path, "loader");
702 r = mkdir_one(esp_path, "loader/entries");
709 static int copy_one_file(const char *esp_path, const char *name, bool force) {
710 _cleanup_free_ char *p = NULL;
711 _cleanup_free_ char *q = NULL;
712 _cleanup_free_ char *v = NULL;
715 if (asprintf(&p, BOOTLIBDIR "/%s", name) < 0) {
716 fprintf(stderr, "Out of memory.\n");
720 if (asprintf(&q, "%s/EFI/systemd/%s", esp_path, name) < 0) {
721 fprintf(stderr, "Out of memory.\n");
725 r = copy_file(p, q, force);
727 if (startswith(name, "systemd-boot")) {
730 /* Create the EFI default boot loader name (specified for removable devices) */
731 if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("systemd-boot")) < 0) {
732 fprintf(stderr, "Out of memory.\n");
735 strupper(strrchr(v, '/') + 1);
737 k = copy_file(p, v, force);
745 static int install_binaries(const char *esp_path, bool force) {
751 /* Don't create any of these directories when we are
752 * just updating. When we update we'll drop-in our
753 * files (unless there are newer ones already), but we
754 * won't create the directories for them in the first
756 r = create_dirs(esp_path);
761 d = opendir(BOOTLIBDIR);
763 fprintf(stderr, "Failed to open "BOOTLIBDIR": %m\n");
767 while ((de = readdir(d))) {
771 if (de->d_name[0] == '.')
774 n = strlen(de->d_name);
775 if (n < 4 || strcmp(de->d_name + n - 4, ".efi") != 0)
778 k = copy_one_file(esp_path, de->d_name, force);
787 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
793 err = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
796 if (!sd_id128_equal(uuid, ouuid))
799 if (!streq_ptr(path, opath))
808 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
809 uint16_t *options = NULL;
813 bool existing = false;
815 n_options = efi_get_boot_options(&options);
819 /* find already existing systemd-boot entry */
820 for (i = 0; i < n_options; i++)
821 if (same_entry(options[i], uuid, path)) {
827 /* find free slot in the sorted BootXXXX variable list */
828 for (i = 0; i < n_options; i++)
829 if (i != options[i]) {
834 /* use the next one */
845 static int insert_into_order(uint16_t slot, bool first) {
846 uint16_t *order = NULL;
852 n_order = efi_get_boot_order(&order);
854 /* no entry, add us */
855 err = efi_set_boot_order(&slot, 1);
859 /* are we the first and only one? */
860 if (n_order == 1 && order[0] == slot)
863 /* are we already in the boot order? */
864 for (i = 0; i < n_order; i++) {
865 if (order[i] != slot)
868 /* we do not require to be the first one, all is fine */
872 /* move us to the first slot */
873 memmove(&order[1], order, i * sizeof(uint16_t));
875 efi_set_boot_order(order, n_order);
880 new_order = realloc(order, (n_order+1) * sizeof(uint16_t));
887 /* add us to the top or end of the list */
889 memmove(&order[1], order, n_order * sizeof(uint16_t));
892 order[n_order] = slot;
894 efi_set_boot_order(order, n_order+1);
901 static int remove_from_order(uint16_t slot) {
902 _cleanup_free_ uint16_t *order = NULL;
907 n_order = efi_get_boot_order(&order);
913 for (i = 0; i < n_order; i++) {
914 if (order[i] != slot)
918 memmove(&order[i], &order[i+1], (n_order - i) * sizeof(uint16_t));
919 efi_set_boot_order(order, n_order-1);
926 static int install_variables(const char *esp_path,
927 uint32_t part, uint64_t pstart, uint64_t psize,
928 sd_id128_t uuid, const char *path,
931 uint16_t *options = NULL;
935 if (!is_efi_boot()) {
936 fprintf(stderr, "Not booted with EFI, skipping EFI variable setup.\n");
940 if (asprintf(&p, "%s%s", esp_path, path) < 0) {
941 fprintf(stderr, "Out of memory.\n");
945 if (access(p, F_OK) < 0) {
953 r = find_slot(uuid, path, &slot);
956 fprintf(stderr, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?\n");
958 fprintf(stderr, "Failed to determine current boot order: %s\n", strerror(-r));
962 if (first || r == false) {
963 r = efi_add_boot_option(slot, "Linux Boot Manager",
967 fprintf(stderr, "Failed to create EFI Boot variable entry: %s\n", strerror(-r));
970 fprintf(stderr, "Created EFI boot entry \"Linux Boot Manager\".\n");
973 insert_into_order(slot, first);
981 static int remove_boot_efi(const char *esp_path) {
983 char *p = NULL, *q = NULL;
987 if (asprintf(&p, "%s/EFI/Boot", esp_path) < 0) {
988 fprintf(stderr, "Out of memory.\n");
994 if (errno == ENOENT) {
999 fprintf(stderr, "Failed to read %s: %m\n", p);
1004 while ((de = readdir(d))) {
1009 if (de->d_name[0] == '.')
1012 n = strlen(de->d_name);
1013 if (n < 4 || strcasecmp(de->d_name + n - 4, ".EFI") != 0)
1016 if (strncasecmp(de->d_name, "Boot", 4) != 0)
1021 if (asprintf(&q, "%s/%s", p, de->d_name) < 0) {
1022 fprintf(stderr, "Out of memory.\n");
1029 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
1034 r = get_file_version(f, &v);
1040 if (r > 0 && strncmp(v, "systemd-boot ", 10) == 0) {
1044 fprintf(stderr, "Failed to remove %s: %m\n", q);
1049 fprintf(stderr, "Removed %s.\n", q);
1067 static int rmdir_one(const char *prefix, const char *suffix) {
1070 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
1071 fprintf(stderr, "Out of memory.\n");
1076 if (errno != ENOENT && errno != ENOTEMPTY) {
1077 fprintf(stderr, "Failed to remove %s: %m\n", p);
1082 fprintf(stderr, "Removed %s.\n", p);
1089 static int remove_binaries(const char *esp_path) {
1093 if (asprintf(&p, "%s/EFI/systemd-boot", esp_path) < 0) {
1094 fprintf(stderr, "Out of memory.\n");
1098 r = rm_rf(p, false, false, false);
1101 q = remove_boot_efi(esp_path);
1102 if (q < 0 && r == 0)
1105 q = rmdir_one(esp_path, "loader/entries");
1106 if (q < 0 && r == 0)
1109 q = rmdir_one(esp_path, "loader");
1110 if (q < 0 && r == 0)
1113 q = rmdir_one(esp_path, "EFI/Boot");
1114 if (q < 0 && r == 0)
1117 q = rmdir_one(esp_path, "EFI/systemd-boot");
1118 if (q < 0 && r == 0)
1121 q = rmdir_one(esp_path, "EFI");
1122 if (q < 0 && r == 0)
1128 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
1135 r = find_slot(uuid, path, &slot);
1139 r = efi_remove_boot_option(slot);
1144 remove_from_order(slot);
1149 static int install_loader_config(const char *esp_path) {
1152 char *machine = NULL;
1155 f = fopen("/etc/machine-id", "re");
1159 if (fgets(line, sizeof(line), f) != NULL) {
1162 s = strchr(line, '\n');
1165 if (strlen(line) == 32)
1174 if (asprintf(&p, "%s/%s", esp_path, "loader/loader.conf") < 0) {
1175 fprintf(stderr, "Out of memory.\n");
1179 f = fopen(p, "wxe");
1181 fprintf(f, "#timeout 3\n");
1182 fprintf(f, "default %s-*\n", machine);
1190 static int help(void) {
1191 printf("%s [COMMAND] [OPTIONS...]\n"
1193 "Install, update or remove the sdboot EFI boot manager.\n\n"
1194 " -h --help Show this help\n"
1195 " --version Print version\n"
1196 " --path=PATH Path to the EFI System Partition (ESP)\n"
1197 " --no-variables Don't touch EFI variables\n"
1200 " status Show status of installed systemd-boot and EFI variables\n"
1201 " install Install systemd-boot to the ESP and EFI variables\n"
1202 " update Update systemd-boot in the ESP and EFI variables\n"
1203 " remove Remove systemd-boot from the ESP and EFI variables\n",
1204 program_invocation_short_name);
1209 static const char *arg_path = NULL;
1210 static bool arg_touch_variables = true;
1212 static int parse_argv(int argc, char *argv[]) {
1219 static const struct option options[] = {
1220 { "help", no_argument, NULL, 'h' },
1221 { "version", no_argument, NULL, ARG_VERSION },
1222 { "path", required_argument, NULL, ARG_PATH },
1223 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1224 { NULL, 0, NULL, 0 }
1232 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1240 printf(VERSION "\n");
1247 case ARG_NO_VARIABLES:
1248 arg_touch_variables = false;
1255 fprintf(stderr, "Unknown option code '%c'.\n", c);
1263 static int bootctl_main(int argc, char*argv[]) {
1269 } arg_action = ACTION_STATUS;
1270 static const struct {
1274 { "status", ACTION_STATUS },
1275 { "install", ACTION_INSTALL },
1276 { "update", ACTION_UPDATE },
1277 { "remove", ACTION_REMOVE },
1280 sd_id128_t uuid = {};
1282 uint64_t pstart = 0;
1288 r = parse_argv(argc, argv);
1293 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1294 if (!streq(argv[optind], verbs[i].verb))
1296 arg_action = verbs[i].action;
1299 if (i >= ELEMENTSOF(verbs)) {
1300 fprintf(stderr, "Unknown operation %s\n", argv[optind]);
1309 if (geteuid() != 0) {
1310 fprintf(stderr, "Need to be root.\n");
1315 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1316 if (r == -ENODEV && !arg_path)
1317 fprintf(stderr, "You might want to use --path= to indicate the path to your ESP, in case it is not mounted to /boot.\n");
1321 switch (arg_action) {
1322 case ACTION_STATUS: {
1323 _cleanup_free_ char *fw_type = NULL;
1324 _cleanup_free_ char *fw_info = NULL;
1325 _cleanup_free_ char *loader = NULL;
1326 _cleanup_free_ char *loader_path = NULL;
1327 sd_id128_t loader_part_uuid = {};
1329 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &fw_type);
1330 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &fw_info);
1331 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &loader);
1332 if (efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &loader_path) > 0)
1333 efi_tilt_backslashes(loader_path);
1334 efi_loader_get_device_part_uuid(&loader_part_uuid);
1336 printf("System:\n");
1337 printf(" Firmware: %s (%s)\n", fw_type, strna(fw_info));
1338 printf(" Secure Boot: %s\n", is_efi_secure_boot() ? "enabled" : "disabled");
1339 printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
1342 printf("Loader:\n");
1343 printf(" Product: %s\n", strna(loader));
1344 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1345 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1346 SD_ID128_FORMAT_VAL(loader_part_uuid));
1348 printf(" Partition: n/a\n");
1349 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1352 r = status_binaries(arg_path, uuid);
1356 if (arg_touch_variables)
1357 r = status_variables();
1361 case ACTION_INSTALL:
1365 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1369 if (arg_action == ACTION_INSTALL)
1370 install_loader_config(arg_path);
1372 if (arg_touch_variables)
1373 r = install_variables(arg_path,
1374 part, pstart, psize, uuid,
1375 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1376 arg_action == ACTION_INSTALL);
1380 r = remove_binaries(arg_path);
1382 if (arg_touch_variables) {
1383 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1384 if (q < 0 && r == 0)
1391 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1394 int main(int argc, char *argv[]) {
1397 log_parse_environment();
1400 r = parse_argv(argc, argv);
1404 r = bootctl_main(argc, argv);
1407 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;