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/>.
24 #include <blkid/blkid.h>
37 #include <sys/statfs.h>
40 #include "blkid-util.h"
44 #include "string-util.h"
47 static int verify_esp(const char *p
, uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
50 _cleanup_free_
char *t
= NULL
;
51 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
55 if (statfs(p
, &sfs
) < 0)
56 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
58 if (sfs
.f_type
!= 0x4d44) {
59 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
64 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
66 if (major(st
.st_dev
) == 0) {
67 log_error("Block device node of %p is invalid.", p
);
71 t2
= strjoina(p
, "/..");
74 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
76 if (st
.st_dev
== st2
.st_dev
) {
77 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
81 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
86 b
= blkid_new_probe_from_filename(t
);
91 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
94 blkid_probe_enable_superblocks(b
, 1);
95 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
96 blkid_probe_enable_partitions(b
, 1);
97 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
100 r
= blkid_do_safeprobe(b
);
102 log_error("File system \"%s\" is ambigious.", p
);
105 log_error("File system \"%s\" does not contain a label.", p
);
108 r
= errno
? -errno
: -EIO
;
109 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
113 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
115 r
= errno
? -errno
: -EIO
;
116 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
119 if (!streq(v
, "vfat")) {
120 log_error("File system \"%s\" is not FAT.", p
);
125 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
127 r
= errno
? -errno
: -EIO
;
128 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
131 if (!streq(v
, "gpt")) {
132 log_error("File system \"%s\" is not on a GPT partition table.", p
);
137 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
139 r
= errno
? -errno
: -EIO
;
140 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
143 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
144 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
149 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
151 r
= errno
? -errno
: -EIO
;
152 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
155 r
= sd_id128_from_string(v
, uuid
);
157 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
162 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
164 r
= errno
? -errno
: -EIO
;
165 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
167 *part
= strtoul(v
, NULL
, 10);
170 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
172 r
= errno
? -errno
: -EIO
;
173 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
175 *pstart
= strtoul(v
, NULL
, 10);
178 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
180 r
= errno
? -errno
: -EIO
;
181 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
183 *psize
= strtoul(v
, NULL
, 10);
188 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
189 static int get_file_version(int fd
, char **v
) {
199 if (fstat(fd
, &st
) < 0)
205 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
206 if (buf
== MAP_FAILED
)
209 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
214 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
215 if (!e
|| e
- s
< 3) {
216 log_error("Malformed version string.");
221 x
= strndup(s
, e
- s
);
229 munmap(buf
, st
.st_size
);
234 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
236 _cleanup_closedir_
DIR *d
= NULL
;
240 p
= strjoina(esp_path
, "/", path
);
246 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
249 while ((de
= readdir(d
))) {
250 _cleanup_close_
int fd
= -1;
251 _cleanup_free_
char *v
= NULL
;
253 if (de
->d_name
[0] == '.')
256 if (!endswith_no_case(de
->d_name
, ".efi"))
259 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
262 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
264 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
266 r
= get_file_version(fd
, &v
);
270 printf(" File: └─/%s/%s (%s)\n", path
, de
->d_name
, v
);
272 printf(" File: └─/%s/%s\n", path
, de
->d_name
);
279 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
282 printf("Boot Loader Binaries:\n");
284 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
));
286 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
288 log_error("systemd-boot not installed in ESP.");
292 r
= enumerate_binaries(esp_path
, "EFI/Boot", "boot");
294 log_error("No default/fallback boot loader installed in ESP.");
303 static int print_efi_option(uint16_t id
, bool in_order
) {
304 _cleanup_free_
char *title
= NULL
;
305 _cleanup_free_
char *path
= NULL
;
306 sd_id128_t partition
;
310 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
314 /* print only configured entries with partition information */
315 if (!path
|| sd_id128_equal(partition
, SD_ID128_NULL
))
318 efi_tilt_backslashes(path
);
320 printf(" Title: %s\n", strna(title
));
321 printf(" ID: 0x%04X\n", id
);
322 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
323 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
));
324 printf(" File: └─%s\n", path
);
330 static int status_variables(void) {
331 int n_options
, n_order
;
332 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
335 if (!is_efi_boot()) {
336 log_notice("Not booted with EFI, not showing EFI variables.");
340 n_options
= efi_get_boot_options(&options
);
341 if (n_options
== -ENOENT
)
342 return log_error_errno(ENOENT
, "Failed to access EFI variables, efivarfs"
343 " needs to be available at /sys/firmware/efi/efivars/.");
344 else if (n_options
< 0)
345 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
347 n_order
= efi_get_boot_order(&order
);
348 if (n_order
== -ENOENT
)
350 else if (n_order
< 0)
351 return log_error_errno(n_order
, "Failed to read EFI boot order.");
353 /* print entries in BootOrder first */
354 printf("Boot Loader Entries in EFI Variables:\n");
355 for (i
= 0; i
< n_order
; i
++)
356 print_efi_option(order
[i
], true);
358 /* print remaining entries */
359 for (i
= 0; i
< n_options
; i
++) {
362 for (j
= 0; j
< n_order
; j
++)
363 if (options
[i
] == order
[j
])
366 print_efi_option(options
[i
], false);
374 static int compare_product(const char *a
, const char *b
) {
383 return x
< y
? -1 : x
> y
? 1 : 0;
385 return strncmp(a
, b
, x
);
388 static int compare_version(const char *a
, const char *b
) {
392 a
+= strcspn(a
, " ");
394 b
+= strcspn(b
, " ");
397 return strverscmp(a
, b
);
400 static int version_check(int fd
, const char *from
, const char *to
) {
401 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
402 _cleanup_close_
int fd2
= -1;
409 r
= get_file_version(fd
, &a
);
413 log_error("Source file \"%s\" does not carry version information!", from
);
417 fd2
= open(to
, O_RDONLY
|O_CLOEXEC
);
422 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
425 r
= get_file_version(fd2
, &b
);
428 if (r
== 0 || compare_product(a
, b
) != 0) {
429 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
433 if (compare_version(a
, b
) < 0) {
434 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
441 static int copy_file(const char *from
, const char *to
, bool force
) {
442 _cleanup_fclose_
FILE *f
= NULL
, *g
= NULL
;
445 struct timespec t
[2];
451 f
= fopen(from
, "re");
453 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
456 /* If this is an update, then let's compare versions first */
457 r
= version_check(fileno(f
), from
, to
);
462 p
= strjoina(to
, "~");
465 /* Directory doesn't exist yet? Then let's skip this... */
466 if (!force
&& errno
== ENOENT
)
469 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", to
);
475 uint8_t buf
[32*1024];
477 k
= fread(buf
, 1, sizeof(buf
), f
);
479 r
= log_error_errno(EIO
, "Failed to read \"%s\": %m", from
);
486 fwrite(buf
, 1, k
, g
);
488 r
= log_error_errno(EIO
, "Failed to write \"%s\": %m", to
);
493 r
= fflush_and_check(g
);
495 log_error_errno(r
, "Failed to write \"%s\": %m", to
);
499 r
= fstat(fileno(f
), &st
);
501 r
= log_error_errno(errno
, "Failed to get file timestamps of \"%s\": %m", from
);
508 r
= futimens(fileno(g
), t
);
510 r
= log_error_errno(errno
, "Failed to set file timestamps on \"%s\": %m", p
);
514 if (rename(p
, to
) < 0) {
515 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", p
, to
);
519 log_info("Copied \"%s\" to \"%s\".", from
, to
);
527 static char* strupper(char *s
) {
536 static int mkdir_one(const char *prefix
, const char *suffix
) {
539 p
= strjoina(prefix
, "/", suffix
);
540 if (mkdir(p
, 0700) < 0) {
542 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
544 log_info("Created \"%s\".", p
);
549 static const char *efi_subdirs
[] = {
557 static int create_dirs(const char *esp_path
) {
561 for (i
= 0; i
< ELEMENTSOF(efi_subdirs
); i
++) {
562 r
= mkdir_one(esp_path
, efi_subdirs
[i
]);
570 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
574 p
= strjoina(BOOTLIBDIR
"/", name
);
575 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
576 r
= copy_file(p
, q
, force
);
578 if (startswith(name
, "systemd-boot")) {
582 /* Create the EFI default boot loader name (specified for removable devices) */
583 v
= strjoina(esp_path
, "/EFI/Boot/BOOT", name
+ strlen("systemd-boot"));
584 strupper(strrchr(v
, '/') + 1);
586 k
= copy_file(p
, v
, force
);
594 static int install_binaries(const char *esp_path
, bool force
) {
596 _cleanup_closedir_
DIR *d
= NULL
;
600 /* Don't create any of these directories when we are
601 * just updating. When we update we'll drop-in our
602 * files (unless there are newer ones already), but we
603 * won't create the directories for them in the first
605 r
= create_dirs(esp_path
);
610 d
= opendir(BOOTLIBDIR
);
612 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
614 while ((de = readdir(d))) {
617 if (de->d_name[0] == '.')
620 if (!endswith_no_case(de->d_name, ".efi
"))
623 k = copy_one_file(esp_path, de->d_name, force);
631 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
632 _cleanup_free_ char *opath = NULL;
636 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
639 if (!sd_id128_equal(uuid, ouuid))
641 if (!streq_ptr(path, opath))
647 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
648 _cleanup_free_ uint16_t *options = NULL;
651 n = efi_get_boot_options(&options);
655 /* find already existing systemd-boot entry */
656 for (i = 0; i < n; i++)
657 if (same_entry(options[i], uuid, path)) {
662 /* find free slot in the sorted BootXXXX variable list */
663 for (i = 0; i < n; i++)
664 if (i != options[i]) {
669 /* use the next one */
676 static int insert_into_order(uint16_t slot, bool first) {
677 _cleanup_free_ uint16_t *order = NULL;
681 n = efi_get_boot_order(&order);
683 /* no entry, add us */
684 return efi_set_boot_order(&slot, 1);
686 /* are we the first and only one? */
687 if (n == 1 && order[0] == slot)
690 /* are we already in the boot order? */
691 for (i = 0; i < n; i++) {
692 if (order[i] != slot)
695 /* we do not require to be the first one, all is fine */
699 /* move us to the first slot */
700 memmove(order + 1, order, i * sizeof(uint16_t));
702 return efi_set_boot_order(order, n);
706 t = realloc(order, (n + 1) * sizeof(uint16_t));
711 /* add us to the top or end of the list */
713 memmove(order + 1, order, n * sizeof(uint16_t));
718 return efi_set_boot_order(order, n + 1);
721 static int remove_from_order(uint16_t slot) {
722 _cleanup_free_ uint16_t *order = NULL;
725 n = efi_get_boot_order(&order);
729 for (i = 0; i < n; i++) {
730 if (order[i] != slot)
734 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
735 return efi_set_boot_order(order, n - 1);
741 static int install_variables(const char *esp_path,
742 uint32_t part, uint64_t pstart, uint64_t psize,
743 sd_id128_t uuid, const char *path,
749 if (!is_efi_boot()) {
750 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
754 p = strjoina(esp_path, path);
755 if (access(p, F_OK) < 0) {
759 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
762 r = find_slot(uuid, path, &slot);
764 return log_error_errno(r,
766 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
767 "Failed to determine current boot order
: %m
");
769 if (first || r == false) {
770 r = efi_add_boot_option(slot, "Linux Boot Manager
",
774 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
776 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
779 return insert_into_order(slot, first);
782 static int remove_boot_efi(const char *esp_path) {
784 _cleanup_closedir_ DIR *d = NULL;
788 p = strjoina(esp_path, "/EFI
/Boot
");
794 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
797 while ((de = readdir(d))) {
798 _cleanup_close_ int fd = -1;
799 _cleanup_free_ char *v = NULL;
801 if (de->d_name[0] == '.')
804 if (!endswith_no_case(de->d_name, ".efi
"))
807 if (!startswith_no_case(de->d_name, "Boot
"))
810 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
812 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
814 r = get_file_version(fd, &v);
817 if (r > 0 && startswith(v, "systemd
-boot
")) {
818 r = unlinkat(dirfd(d), de->d_name, 0);
820 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
822 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
831 static int rmdir_one(const char *prefix, const char *suffix) {
834 p = strjoina(prefix, "/", suffix);
836 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
837 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
839 log_info("Removed
\"%s
\".", p);
844 static int remove_binaries(const char *esp_path) {
849 p = strjoina(esp_path, "/EFI
/systemd
");
850 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
852 q = remove_boot_efi(esp_path);
856 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
857 q = rmdir_one(esp_path, efi_subdirs[i-1]);
865 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
872 r = find_slot(uuid, path, &slot);
876 r = efi_remove_boot_option(slot);
881 return remove_from_order(slot);
886 static int install_loader_config(const char *esp_path) {
889 char *machine = NULL;
890 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
892 f = fopen("/etc
/machine
-id
", "re
");
894 return errno == ENOENT ? 0 : -errno;
896 if (fgets(line, sizeof(line), f) != NULL) {
899 s = strchr(line, '\n');
902 if (strlen(line) == 32)
909 p = strjoina(esp_path, "/loader
/loader
.conf
");
912 fprintf(g, "#timeout 3\n");
913 fprintf(g, "default %s-*\n", machine);
915 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
921 static int help(void) {
922 printf("%s [COMMAND] [OPTIONS...]\n"
924 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
925 " -h --help Show this help\n"
926 " --version Print version\n"
927 " --path=PATH Path to the EFI System Partition (ESP)\n"
928 " --no-variables Don't touch EFI variables\n"
931 " status Show status of installed systemd-boot and EFI variables\n"
932 " install Install systemd-boot to the ESP and EFI variables\n"
933 " update Update systemd-boot in the ESP and EFI variables\n"
934 " remove Remove systemd-boot from the ESP and EFI variables\n",
935 program_invocation_short_name);
940 static const char *arg_path = "/boot";
941 static bool arg_touch_variables = true;
943 static int parse_argv(int argc, char *argv[]) {
950 static const struct option options[] = {
951 { "help", no_argument, NULL, 'h' },
952 { "version", no_argument, NULL, ARG_VERSION },
953 { "path", required_argument, NULL, ARG_PATH },
954 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
963 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
977 case ARG_NO_VARIABLES:
978 arg_touch_variables = false;
985 assert_not_reached("Unknown option");
991 static void read_loader_efi_var(const char *name, char **var) {
994 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
995 if (r < 0 && r != -ENOENT)
996 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
999 static int bootctl_main(int argc, char*argv[]) {
1005 } arg_action = ACTION_STATUS;
1006 static const struct {
1010 { "status", ACTION_STATUS },
1011 { "install", ACTION_INSTALL },
1012 { "update", ACTION_UPDATE },
1013 { "remove", ACTION_REMOVE },
1016 sd_id128_t uuid = {};
1018 uint64_t pstart = 0, psize = 0;
1024 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1025 if (!streq(argv[optind], verbs[i].verb))
1027 arg_action = verbs[i].action;
1030 if (i >= ELEMENTSOF(verbs)) {
1031 log_error("Unknown operation \"%s\"", argv[optind]);
1037 return log_error_errno(EPERM, "Need to be root.");
1039 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1040 if (r == -ENODEV && !arg_path)
1041 log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
1045 switch (arg_action) {
1046 case ACTION_STATUS: {
1047 _cleanup_free_ char *fw_type = NULL;
1048 _cleanup_free_ char *fw_info = NULL;
1049 _cleanup_free_ char *loader = NULL;
1050 _cleanup_free_ char *loader_path = NULL;
1051 sd_id128_t loader_part_uuid = {};
1053 if (is_efi_boot()) {
1054 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1055 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1056 read_loader_efi_var("LoaderInfo", &loader);
1057 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1059 efi_tilt_backslashes(loader_path);
1060 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1061 if (r < 0 && r == -ENOENT)
1062 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1064 printf("System:\n");
1065 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1067 r = is_efi_secure_boot();
1069 log_warning_errno(r, "Failed to query secure boot status: %m");
1071 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1073 r = is_efi_secure_boot_setup_mode();
1075 log_warning_errno(r, "Failed to query secure boot mode: %m");
1077 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1080 printf("Loader:\n");
1081 printf(" Product: %s\n", strna(loader));
1082 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1083 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1084 SD_ID128_FORMAT_VAL(loader_part_uuid));
1086 printf(" Partition: n/a\n");
1087 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1090 printf("System:\n Not booted with EFI\n");
1092 r = status_binaries(arg_path, uuid);
1096 if (arg_touch_variables)
1097 r = status_variables();
1101 case ACTION_INSTALL:
1105 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1109 if (arg_action == ACTION_INSTALL) {
1110 r = install_loader_config(arg_path);
1115 if (arg_touch_variables)
1116 r = install_variables(arg_path,
1117 part, pstart, psize, uuid,
1118 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1119 arg_action == ACTION_INSTALL);
1123 r = remove_binaries(arg_path);
1125 if (arg_touch_variables) {
1126 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1127 if (q < 0 && r == 0)
1136 int main(int argc, char *argv[]) {
1139 log_parse_environment();
1142 r = parse_argv(argc, argv);
1146 r = bootctl_main(argc, argv);
1149 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;