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>
46 static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
54 if (statfs(p, &sfs) < 0) {
55 fprintf(stderr, "Failed to check file system type of %s: %m\n", p);
59 if (sfs.f_type != 0x4d44) {
60 fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system.\n", p);
64 if (stat(p, &st) < 0) {
65 fprintf(stderr, "Failed to determine block device node of %s: %m\n", p);
69 if (major(st.st_dev) == 0) {
70 fprintf(stderr, "Block device node of %p is invalid.\n", p);
74 r = asprintf(&t, "%s/..", p);
76 fprintf(stderr, "Out of memory.\n");
83 fprintf(stderr, "Failed to determine block device node of parent of %s: %m\n", p);
87 if (st.st_dev == st2.st_dev) {
88 fprintf(stderr, "Directory %s is not the root of the EFI System Partition (ESP) file system.\n", p);
92 r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
94 fprintf(stderr, "Out of memory.\n");
99 b = blkid_new_probe_from_filename(t);
103 fprintf(stderr, "Failed to open file system %s: %m\n", p);
107 fprintf(stderr, "Out of memory.\n");
111 blkid_probe_enable_superblocks(b, 1);
112 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
113 blkid_probe_enable_partitions(b, 1);
114 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
117 r = blkid_do_safeprobe(b);
119 fprintf(stderr, "File system %s is ambigious.\n", p);
123 fprintf(stderr, "File system %s does not contain a label.\n", p);
127 r = errno ? -errno : -EIO;
128 fprintf(stderr, "Failed to probe file system %s: %s\n", p, strerror(-r));
133 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
135 r = errno ? -errno : -EIO;
136 fprintf(stderr, "Failed to probe file system type %s: %s\n", p, strerror(-r));
140 if (strcmp(v, "vfat") != 0) {
141 fprintf(stderr, "File system %s is not a FAT EFI System Partition (ESP) file system after all.\n", p);
147 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
149 r = errno ? -errno : -EIO;
150 fprintf(stderr, "Failed to probe partition scheme %s: %s\n", p, strerror(-r));
154 if (strcmp(v, "gpt") != 0) {
155 fprintf(stderr, "File system %s is not on a GPT partition table.\n", p);
161 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
163 r = errno ? -errno : -EIO;
164 fprintf(stderr, "Failed to probe partition type UUID %s: %s\n", p, strerror(-r));
168 if (strcmp(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b") != 0) {
170 fprintf(stderr, "File system %s is not an EFI System Partition (ESP).\n", p);
175 r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
177 r = errno ? -errno : -EIO;
178 fprintf(stderr, "Failed to probe partition entry UUID %s: %s\n", p, strerror(-r));
181 sd_id128_from_string(v, uuid);
184 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
186 r = errno ? -errno : -EIO;
187 fprintf(stderr, "Failed to probe partition number %s: %s\n", p, strerror(-r));
190 *part = strtoul(v, NULL, 10);
193 r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
195 r = errno ? -errno : -EIO;
196 fprintf(stderr, "Failed to probe partition offset %s: %s\n", p, strerror(-r));
199 *pstart = strtoul(v, NULL, 10);
202 r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
204 r = errno ? -errno : -EIO;
205 fprintf(stderr, "Failed to probe partition size %s: %s\n", p, strerror(-r));
208 *psize = strtoul(v, NULL, 10);
218 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
219 static int get_file_version(FILE *f, char **v) {
229 if (fstat(fileno(f), &st) < 0)
235 buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
236 if (buf == MAP_FAILED)
239 s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
244 e = memmem(s, st.st_size - (s - buf), " ####", 5);
245 if (!e || e - s < 3) {
246 fprintf(stderr, "Malformed version string.\n");
251 x = strndup(s, e - s);
253 fprintf(stderr, "Out of memory.\n");
260 munmap(buf, st.st_size);
265 static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
267 char *p = NULL, *q = NULL;
271 if (asprintf(&p, "%s/%s", esp_path, path) < 0) {
272 fprintf(stderr, "Out of memory.\n");
279 if (errno == ENOENT) {
284 fprintf(stderr, "Failed to read %s: %m\n", p);
289 while ((de = readdir(d))) {
294 if (de->d_name[0] == '.')
297 n = strlen(de->d_name);
298 if (n < 4 || strcasecmp(de->d_name + n - 4, ".efi") != 0)
301 if (prefix && strncasecmp(de->d_name, prefix, strlen(prefix)) != 0)
306 if (asprintf(&q, "%s/%s/%s", esp_path, path, de->d_name) < 0) {
307 fprintf(stderr, "Out of memory.\n");
314 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
319 r = get_file_version(f, &v);
326 printf(" File: └─/%s/%s (%s)\n", path, de->d_name, v);
328 printf(" File: └─/%s/%s\n", path, de->d_name);
345 static int status_binaries(const char *esp_path, sd_id128_t partition) {
348 printf("Boot Loader Binaries:\n");
350 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));
352 r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
354 fprintf(stderr, "systemd-boot not installed in ESP.\n");
358 r = enumerate_binaries(esp_path, "EFI/Boot", "boot");
360 fprintf(stderr, "No default/fallback boot loader installed in ESP.\n");
368 static int print_efi_option(uint16_t id, bool in_order) {
371 sd_id128_t partition;
375 r = efi_get_boot_option(id, &title, &partition, &path, &active);
379 /* print only configured entries with partition information */
380 if (!path || sd_id128_equal(partition, SD_ID128_NULL))
383 efi_tilt_backslashes(path);
385 printf(" Title: %s\n", strna(title));
386 printf(" ID: 0x%04X\n", id);
387 printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
388 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));
389 printf(" File: └─%s\n", path);
398 static int status_variables(void) {
399 int n_options, n_order;
400 uint16_t *options = NULL, *order = NULL;
403 if (!is_efi_boot()) {
404 fprintf(stderr, "Not booted with EFI, not showing EFI variables.\n");
408 n_options = efi_get_boot_options(&options);
410 if (n_options == -ENOENT)
411 fprintf(stderr, "Failed to access EFI variables, "
412 "efivarfs needs to be available at /sys/firmware/efi/efivars/.\n");
414 fprintf(stderr, "Failed to read EFI boot entries: %s\n", strerror(-n_options));
419 printf("Boot Loader Entries in EFI Variables:\n");
420 n_order = efi_get_boot_order(&order);
421 if (n_order == -ENOENT) {
423 } else if (n_order < 0) {
424 fprintf(stderr, "Failed to read EFI boot order.\n");
429 /* print entries in BootOrder first */
430 for (i = 0; i < n_order; i++)
431 print_efi_option(order[i], true);
433 /* print remaining entries */
434 for (i = 0; i < n_options; i++) {
438 for (j = 0; j < n_order; j++)
439 if (options[i] == order[j]) {
447 print_efi_option(options[i], false);
458 static int compare_product(const char *a, const char *b) {
467 return x < y ? -1 : x > y ? 1 : 0;
469 return strncmp(a, b, x);
472 static int compare_version(const char *a, const char *b) {
476 a += strcspn(a, " ");
478 b += strcspn(b, " ");
481 return strverscmp(a, b);
484 static int version_check(FILE *f, const char *from, const char *to) {
486 char *a = NULL, *b = NULL;
493 r = get_file_version(f, &a);
498 fprintf(stderr, "Source file %s does not carry version information!\n", from);
504 if (errno == ENOENT) {
510 fprintf(stderr, "Failed to open %s for reading: %m\n", to);
514 r = get_file_version(g, &b);
517 if (r == 0 || compare_product(a, b) != 0) {
519 fprintf(stderr, "Skipping %s, since it's owned by another boot loader.\n", to);
523 if (compare_version(a, b) < 0) {
525 fprintf(stderr, "Skipping %s, since it's a newer boot loader version already.\n", to);
539 static int copy_file(const char *from, const char *to, bool force) {
540 FILE *f = NULL, *g = NULL;
543 struct timespec t[2];
549 f = fopen(from, "re");
551 fprintf(stderr, "Failed to open %s for reading: %m\n", from);
556 /* If this is an update, then let's compare versions first */
557 r = version_check(f, from, to);
562 if (asprintf(&p, "%s~", to) < 0) {
563 fprintf(stderr, "Out of memory.\n");
570 /* Directory doesn't exist yet? Then let's skip this... */
571 if (!force && errno == ENOENT) {
576 fprintf(stderr, "Failed to open %s for writing: %m\n", to);
584 uint8_t buf[32*1024];
586 k = fread(buf, 1, sizeof(buf), f);
588 fprintf(stderr, "Failed to read %s: %m\n", from);
595 fwrite(buf, 1, k, g);
597 fprintf(stderr, "Failed to write %s: %m\n", to);
605 fprintf(stderr, "Failed to write %s: %m\n", to);
610 r = fstat(fileno(f), &st);
612 fprintf(stderr, "Failed to get file timestamps of %s: %m", from);
620 r = futimens(fileno(g), t);
622 fprintf(stderr, "Failed to change file timestamps for %s: %m", p);
627 if (rename(p, to) < 0) {
628 fprintf(stderr, "Failed to rename %s to %s: %m\n", p, to);
633 fprintf(stderr, "Copied %s to %s.\n", from, to);
651 static char* strupper(char *s) {
660 static int mkdir_one(const char *prefix, const char *suffix) {
663 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
664 fprintf(stderr, "Out of memory.\n");
668 if (mkdir(p, 0700) < 0) {
669 if (errno != EEXIST) {
670 fprintf(stderr, "Failed to create %s: %m\n", p);
675 fprintf(stderr, "Created %s.\n", p);
681 static int create_dirs(const char *esp_path) {
684 r = mkdir_one(esp_path, "EFI");
688 r = mkdir_one(esp_path, "EFI/systemd");
692 r = mkdir_one(esp_path, "EFI/Boot");
696 r = mkdir_one(esp_path, "loader");
700 r = mkdir_one(esp_path, "loader/entries");
707 static int copy_one_file(const char *esp_path, const char *name, bool force) {
708 _cleanup_free_ char *p = NULL;
709 _cleanup_free_ char *q = NULL;
710 _cleanup_free_ char *v = NULL;
713 if (asprintf(&p, BOOTLIBDIR "/%s", name) < 0) {
714 fprintf(stderr, "Out of memory.\n");
718 if (asprintf(&q, "%s/EFI/systemd/%s", esp_path, name) < 0) {
719 fprintf(stderr, "Out of memory.\n");
723 r = copy_file(p, q, force);
725 if (startswith(name, "systemd-boot")) {
728 /* Create the EFI default boot loader name (specified for removable devices) */
729 if (asprintf(&v, "%s/EFI/Boot/BOOT%s", esp_path, name + strlen("systemd-boot")) < 0) {
730 fprintf(stderr, "Out of memory.\n");
733 strupper(strrchr(v, '/') + 1);
735 k = copy_file(p, v, force);
743 static int install_binaries(const char *esp_path, bool force) {
749 /* Don't create any of these directories when we are
750 * just updating. When we update we'll drop-in our
751 * files (unless there are newer ones already), but we
752 * won't create the directories for them in the first
754 r = create_dirs(esp_path);
759 d = opendir(BOOTLIBDIR);
761 fprintf(stderr, "Failed to open "BOOTLIBDIR": %m\n");
765 while ((de = readdir(d))) {
769 if (de->d_name[0] == '.')
772 n = strlen(de->d_name);
773 if (n < 4 || strcmp(de->d_name + n - 4, ".efi") != 0)
776 k = copy_one_file(esp_path, de->d_name, force);
785 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
791 err = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
794 if (!sd_id128_equal(uuid, ouuid))
797 if (!streq_ptr(path, opath))
806 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
807 uint16_t *options = NULL;
811 bool existing = false;
813 n_options = efi_get_boot_options(&options);
817 /* find already existing systemd-boot entry */
818 for (i = 0; i < n_options; i++)
819 if (same_entry(options[i], uuid, path)) {
825 /* find free slot in the sorted BootXXXX variable list */
826 for (i = 0; i < n_options; i++)
827 if (i != options[i]) {
832 /* use the next one */
843 static int insert_into_order(uint16_t slot, bool first) {
844 uint16_t *order = NULL;
850 n_order = efi_get_boot_order(&order);
852 /* no entry, add us */
853 err = efi_set_boot_order(&slot, 1);
857 /* are we the first and only one? */
858 if (n_order == 1 && order[0] == slot)
861 /* are we already in the boot order? */
862 for (i = 0; i < n_order; i++) {
863 if (order[i] != slot)
866 /* we do not require to be the first one, all is fine */
870 /* move us to the first slot */
871 memmove(&order[1], order, i * sizeof(uint16_t));
873 efi_set_boot_order(order, n_order);
878 new_order = realloc(order, (n_order+1) * sizeof(uint16_t));
885 /* add us to the top or end of the list */
887 memmove(&order[1], order, n_order * sizeof(uint16_t));
890 order[n_order] = slot;
892 efi_set_boot_order(order, n_order+1);
899 static int remove_from_order(uint16_t slot) {
900 uint16_t *order = NULL;
905 n_order = efi_get_boot_order(&order);
911 for (i = 0; i < n_order; i++) {
912 if (order[i] != slot)
916 memmove(&order[i], &order[i+1], (n_order - i) * sizeof(uint16_t));
917 efi_set_boot_order(order, n_order-1);
925 static int install_variables(const char *esp_path,
926 uint32_t part, uint64_t pstart, uint64_t psize,
927 sd_id128_t uuid, const char *path,
930 uint16_t *options = NULL;
934 if (!is_efi_boot()) {
935 fprintf(stderr, "Not booted with EFI, skipping EFI variable setup.\n");
939 if (asprintf(&p, "%s%s", esp_path, path) < 0) {
940 fprintf(stderr, "Out of memory.\n");
944 if (access(p, F_OK) < 0) {
952 r = find_slot(uuid, path, &slot);
955 fprintf(stderr, "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?\n");
957 fprintf(stderr, "Failed to determine current boot order: %s\n", strerror(-r));
961 if (first || r == false) {
962 r = efi_add_boot_option(slot, "Linux Boot Manager",
966 fprintf(stderr, "Failed to create EFI Boot variable entry: %s\n", strerror(-r));
969 fprintf(stderr, "Created EFI boot entry \"Linux Boot Manager\".\n");
972 insert_into_order(slot, first);
980 static int remove_boot_efi(const char *esp_path) {
982 char *p = NULL, *q = NULL;
986 if (asprintf(&p, "%s/EFI/Boot", esp_path) < 0) {
987 fprintf(stderr, "Out of memory.\n");
993 if (errno == ENOENT) {
998 fprintf(stderr, "Failed to read %s: %m\n", p);
1003 while ((de = readdir(d))) {
1008 if (de->d_name[0] == '.')
1011 n = strlen(de->d_name);
1012 if (n < 4 || strcasecmp(de->d_name + n - 4, ".EFI") != 0)
1015 if (strncasecmp(de->d_name, "Boot", 4) != 0)
1020 if (asprintf(&q, "%s/%s", p, de->d_name) < 0) {
1021 fprintf(stderr, "Out of memory.\n");
1028 fprintf(stderr, "Failed to open %s for reading: %m\n", q);
1033 r = get_file_version(f, &v);
1039 if (r > 0 && strncmp(v, "systemd-boot ", 10) == 0) {
1043 fprintf(stderr, "Failed to remove %s: %m\n", q);
1048 fprintf(stderr, "Removed %s.\n", q);
1066 static int rmdir_one(const char *prefix, const char *suffix) {
1069 if (asprintf(&p, "%s/%s", prefix, suffix) < 0) {
1070 fprintf(stderr, "Out of memory.\n");
1075 if (errno != ENOENT && errno != ENOTEMPTY) {
1076 fprintf(stderr, "Failed to remove %s: %m\n", p);
1081 fprintf(stderr, "Removed %s.\n", p);
1088 static int remove_binaries(const char *esp_path) {
1092 if (asprintf(&p, "%s/EFI/systemd-boot", esp_path) < 0) {
1093 fprintf(stderr, "Out of memory.\n");
1097 r = rm_rf(p, false, false, false);
1100 q = remove_boot_efi(esp_path);
1101 if (q < 0 && r == 0)
1104 q = rmdir_one(esp_path, "loader/entries");
1105 if (q < 0 && r == 0)
1108 q = rmdir_one(esp_path, "loader");
1109 if (q < 0 && r == 0)
1112 q = rmdir_one(esp_path, "EFI/Boot");
1113 if (q < 0 && r == 0)
1116 q = rmdir_one(esp_path, "EFI/systemd-boot");
1117 if (q < 0 && r == 0)
1120 q = rmdir_one(esp_path, "EFI");
1121 if (q < 0 && r == 0)
1127 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
1134 r = find_slot(uuid, path, &slot);
1138 r = efi_remove_boot_option(slot);
1143 remove_from_order(slot);
1148 static int install_loader_config(const char *esp_path) {
1151 char *machine = NULL;
1154 f = fopen("/etc/machine-id", "re");
1158 if (fgets(line, sizeof(line), f) != NULL) {
1161 s = strchr(line, '\n');
1164 if (strlen(line) == 32)
1173 if (asprintf(&p, "%s/%s", esp_path, "loader/loader.conf") < 0) {
1174 fprintf(stderr, "Out of memory.\n");
1178 f = fopen(p, "wxe");
1180 fprintf(f, "#timeout 3\n");
1181 fprintf(f, "default %s-*\n", machine);
1189 static int help(void) {
1190 printf("%s [COMMAND] [OPTIONS...]\n"
1192 "Install, update or remove the sdboot EFI boot manager.\n\n"
1193 " -h --help Show this help\n"
1194 " --version Print version\n"
1195 " --path=PATH Path to the EFI System Partition (ESP)\n"
1196 " --no-variables Don't touch EFI variables\n"
1199 " status Show status of installed systemd-boot and EFI variables\n"
1200 " install Install systemd-boot to the ESP and EFI variables\n"
1201 " update Update systemd-boot in the ESP and EFI variables\n"
1202 " remove Remove systemd-boot from the ESP and EFI variables\n",
1203 program_invocation_short_name);
1208 static const char *arg_path = NULL;
1209 static bool arg_touch_variables = true;
1211 static int parse_argv(int argc, char *argv[]) {
1218 static const struct option options[] = {
1219 { "help", no_argument, NULL, 'h' },
1220 { "version", no_argument, NULL, ARG_VERSION },
1221 { "path", required_argument, NULL, ARG_PATH },
1222 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1223 { NULL, 0, NULL, 0 }
1231 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
1239 printf(VERSION "\n");
1246 case ARG_NO_VARIABLES:
1247 arg_touch_variables = false;
1254 fprintf(stderr, "Unknown option code '%c'.\n", c);
1262 static int bootctl_main(int argc, char*argv[]) {
1268 } arg_action = ACTION_STATUS;
1269 static const struct {
1273 { "status", ACTION_STATUS },
1274 { "install", ACTION_INSTALL },
1275 { "update", ACTION_UPDATE },
1276 { "remove", ACTION_REMOVE },
1279 sd_id128_t uuid = {};
1281 uint64_t pstart = 0;
1287 r = parse_argv(argc, argv);
1292 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1293 if (!streq(argv[optind], verbs[i].verb))
1295 arg_action = verbs[i].action;
1298 if (i >= ELEMENTSOF(verbs)) {
1299 fprintf(stderr, "Unknown operation %s\n", argv[optind]);
1308 if (geteuid() != 0) {
1309 fprintf(stderr, "Need to be root.\n");
1314 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1315 if (r == -ENODEV && !arg_path)
1316 fprintf(stderr, "You might want to use --path= to indicate the path to your ESP, in case it is not mounted to /boot.\n");
1320 switch (arg_action) {
1321 case ACTION_STATUS: {
1322 _cleanup_free_ char *fw_type = NULL;
1323 _cleanup_free_ char *fw_info = NULL;
1324 _cleanup_free_ char *loader = NULL;
1325 _cleanup_free_ char *loader_path = NULL;
1326 sd_id128_t loader_part_uuid = {};
1328 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &fw_type);
1329 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &fw_info);
1330 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &loader);
1331 efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &loader_path);
1332 efi_tilt_backslashes(loader_path);
1333 efi_loader_get_device_part_uuid(&loader_part_uuid);
1335 printf("System:\n");
1336 printf(" Firmware: %s (%s)\n", fw_type, strna(fw_info));
1337 printf(" Secure Boot: %s\n", is_efi_secure_boot() ? "enabled" : "disabled");
1338 printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
1341 printf("Loader:\n");
1342 printf(" Product: %s\n", strna(loader));
1343 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1344 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1345 SD_ID128_FORMAT_VAL(loader_part_uuid));
1347 printf(" Partition: n/a\n");
1348 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1351 r = status_binaries(arg_path, uuid);
1355 if (arg_touch_variables)
1356 r = status_variables();
1360 case ACTION_INSTALL:
1364 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1368 if (arg_action == ACTION_INSTALL)
1369 install_loader_config(arg_path);
1371 if (arg_touch_variables)
1372 r = install_variables(arg_path,
1373 part, pstart, psize, uuid,
1374 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1375 arg_action == ACTION_INSTALL);
1379 r = remove_binaries(arg_path);
1381 if (arg_touch_variables) {
1382 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1383 if (q < 0 && r == 0)
1390 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1393 int main(int argc, char *argv[]) {
1396 log_parse_environment();
1399 r = parse_argv(argc, argv);
1403 r = bootctl_main(argc, argv);
1406 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;