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"
43 #include "string-util.h"
46 static int verify_esp(const char *p
, uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
49 _cleanup_free_
char *t
= NULL
;
50 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
54 if (statfs(p
, &sfs
) < 0)
55 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
57 if (sfs
.f_type
!= 0x4d44) {
58 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
63 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
65 if (major(st
.st_dev
) == 0) {
66 log_error("Block device node of %p is invalid.", p
);
70 t2
= strjoina(p
, "/..");
73 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
75 if (st
.st_dev
== st2
.st_dev
) {
76 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
80 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
85 b
= blkid_new_probe_from_filename(t
);
90 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
93 blkid_probe_enable_superblocks(b
, 1);
94 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
95 blkid_probe_enable_partitions(b
, 1);
96 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
99 r
= blkid_do_safeprobe(b
);
101 log_error("File system \"%s\" is ambigious.", p
);
104 log_error("File system \"%s\" does not contain a label.", p
);
107 r
= errno
? -errno
: -EIO
;
108 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
112 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
114 r
= errno
? -errno
: -EIO
;
115 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
118 if (!streq(v
, "vfat")) {
119 log_error("File system \"%s\" is not FAT.", p
);
124 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
126 r
= errno
? -errno
: -EIO
;
127 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
130 if (!streq(v
, "gpt")) {
131 log_error("File system \"%s\" is not on a GPT partition table.", p
);
136 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
138 r
= errno
? -errno
: -EIO
;
139 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
142 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
143 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
148 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
150 r
= errno
? -errno
: -EIO
;
151 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
154 r
= sd_id128_from_string(v
, uuid
);
156 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
161 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
163 r
= errno
? -errno
: -EIO
;
164 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
166 *part
= strtoul(v
, NULL
, 10);
169 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
171 r
= errno
? -errno
: -EIO
;
172 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
174 *pstart
= strtoul(v
, NULL
, 10);
177 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
179 r
= errno
? -errno
: -EIO
;
180 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
182 *psize
= strtoul(v
, NULL
, 10);
187 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
188 static int get_file_version(int fd
, char **v
) {
198 if (fstat(fd
, &st
) < 0)
204 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
205 if (buf
== MAP_FAILED
)
208 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
213 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
214 if (!e
|| e
- s
< 3) {
215 log_error("Malformed version string.");
220 x
= strndup(s
, e
- s
);
228 munmap(buf
, st
.st_size
);
233 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
235 _cleanup_closedir_
DIR *d
= NULL
;
239 p
= strjoina(esp_path
, "/", path
);
245 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
248 while ((de
= readdir(d
))) {
249 _cleanup_close_
int fd
= -1;
250 _cleanup_free_
char *v
= NULL
;
252 if (de
->d_name
[0] == '.')
255 if (!endswith_no_case(de
->d_name
, ".efi"))
258 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
261 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
263 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
265 r
= get_file_version(fd
, &v
);
269 printf(" File: └─/%s/%s (%s)\n", path
, de
->d_name
, v
);
271 printf(" File: └─/%s/%s\n", path
, de
->d_name
);
278 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
281 printf("Boot Loader Binaries:\n");
283 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
));
285 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
287 log_error("systemd-boot not installed in ESP.");
291 r
= enumerate_binaries(esp_path
, "EFI/Boot", "boot");
293 log_error("No default/fallback boot loader installed in ESP.");
302 static int print_efi_option(uint16_t id
, bool in_order
) {
303 _cleanup_free_
char *title
= NULL
;
304 _cleanup_free_
char *path
= NULL
;
305 sd_id128_t partition
;
309 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
313 /* print only configured entries with partition information */
314 if (!path
|| sd_id128_equal(partition
, SD_ID128_NULL
))
317 efi_tilt_backslashes(path
);
319 printf(" Title: %s\n", strna(title
));
320 printf(" ID: 0x%04X\n", id
);
321 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
322 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
));
323 printf(" File: └─%s\n", path
);
329 static int status_variables(void) {
330 int n_options
, n_order
;
331 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
334 if (!is_efi_boot()) {
335 log_notice("Not booted with EFI, not showing EFI variables.");
339 n_options
= efi_get_boot_options(&options
);
340 if (n_options
== -ENOENT
)
341 return log_error_errno(ENOENT
, "Failed to access EFI variables, efivarfs"
342 " needs to be available at /sys/firmware/efi/efivars/.");
343 else if (n_options
< 0)
344 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
346 n_order
= efi_get_boot_order(&order
);
347 if (n_order
== -ENOENT
)
349 else if (n_order
< 0)
350 return log_error_errno(n_order
, "Failed to read EFI boot order.");
352 /* print entries in BootOrder first */
353 printf("Boot Loader Entries in EFI Variables:\n");
354 for (i
= 0; i
< n_order
; i
++)
355 print_efi_option(order
[i
], true);
357 /* print remaining entries */
358 for (i
= 0; i
< n_options
; i
++) {
361 for (j
= 0; j
< n_order
; j
++)
362 if (options
[i
] == order
[j
])
365 print_efi_option(options
[i
], false);
373 static int compare_product(const char *a
, const char *b
) {
382 return x
< y
? -1 : x
> y
? 1 : 0;
384 return strncmp(a
, b
, x
);
387 static int compare_version(const char *a
, const char *b
) {
391 a
+= strcspn(a
, " ");
393 b
+= strcspn(b
, " ");
396 return strverscmp(a
, b
);
399 static int version_check(int fd
, const char *from
, const char *to
) {
400 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
401 _cleanup_close_
int fd2
= -1;
408 r
= get_file_version(fd
, &a
);
412 log_error("Source file \"%s\" does not carry version information!", from
);
416 fd2
= open(to
, O_RDONLY
|O_CLOEXEC
);
421 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
424 r
= get_file_version(fd2
, &b
);
427 if (r
== 0 || compare_product(a
, b
) != 0) {
428 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
432 if (compare_version(a
, b
) < 0) {
433 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
440 static int copy_file(const char *from
, const char *to
, bool force
) {
441 _cleanup_fclose_
FILE *f
= NULL
, *g
= NULL
;
444 struct timespec t
[2];
450 f
= fopen(from
, "re");
452 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
455 /* If this is an update, then let's compare versions first */
456 r
= version_check(fileno(f
), from
, to
);
461 p
= strjoina(to
, "~");
464 /* Directory doesn't exist yet? Then let's skip this... */
465 if (!force
&& errno
== ENOENT
)
468 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", to
);
474 uint8_t buf
[32*1024];
476 k
= fread(buf
, 1, sizeof(buf
), f
);
478 r
= log_error_errno(EIO
, "Failed to read \"%s\": %m", from
);
485 fwrite(buf
, 1, k
, g
);
487 r
= log_error_errno(EIO
, "Failed to write \"%s\": %m", to
);
492 r
= fflush_and_check(g
);
494 log_error_errno(r
, "Failed to write \"%s\": %m", to
);
498 r
= fstat(fileno(f
), &st
);
500 r
= log_error_errno(errno
, "Failed to get file timestamps of \"%s\": %m", from
);
507 r
= futimens(fileno(g
), t
);
509 r
= log_error_errno(errno
, "Failed to set file timestamps on \"%s\": %m", p
);
513 if (rename(p
, to
) < 0) {
514 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", p
, to
);
518 log_info("Copied \"%s\" to \"%s\".", from
, to
);
526 static char* strupper(char *s
) {
535 static int mkdir_one(const char *prefix
, const char *suffix
) {
538 p
= strjoina(prefix
, "/", suffix
);
539 if (mkdir(p
, 0700) < 0) {
541 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
543 log_info("Created \"%s\".", p
);
548 static const char *efi_subdirs
[] = {
556 static int create_dirs(const char *esp_path
) {
560 for (i
= 0; i
< ELEMENTSOF(efi_subdirs
); i
++) {
561 r
= mkdir_one(esp_path
, efi_subdirs
[i
]);
569 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
573 p
= strjoina(BOOTLIBDIR
"/", name
);
574 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
575 r
= copy_file(p
, q
, force
);
577 if (startswith(name
, "systemd-boot")) {
581 /* Create the EFI default boot loader name (specified for removable devices) */
582 v
= strjoina(esp_path
, "/EFI/Boot/BOOT", name
+ strlen("systemd-boot"));
583 strupper(strrchr(v
, '/') + 1);
585 k
= copy_file(p
, v
, force
);
593 static int install_binaries(const char *esp_path
, bool force
) {
595 _cleanup_closedir_
DIR *d
= NULL
;
599 /* Don't create any of these directories when we are
600 * just updating. When we update we'll drop-in our
601 * files (unless there are newer ones already), but we
602 * won't create the directories for them in the first
604 r
= create_dirs(esp_path
);
609 d
= opendir(BOOTLIBDIR
);
611 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
613 while ((de = readdir(d))) {
616 if (de->d_name[0] == '.')
619 if (!endswith_no_case(de->d_name, ".efi
"))
622 k = copy_one_file(esp_path, de->d_name, force);
630 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
631 _cleanup_free_ char *opath = NULL;
635 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
638 if (!sd_id128_equal(uuid, ouuid))
640 if (!streq_ptr(path, opath))
646 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
647 _cleanup_free_ uint16_t *options = NULL;
650 n = efi_get_boot_options(&options);
654 /* find already existing systemd-boot entry */
655 for (i = 0; i < n; i++)
656 if (same_entry(options[i], uuid, path)) {
661 /* find free slot in the sorted BootXXXX variable list */
662 for (i = 0; i < n; i++)
663 if (i != options[i]) {
668 /* use the next one */
675 static int insert_into_order(uint16_t slot, bool first) {
676 _cleanup_free_ uint16_t *order = NULL;
680 n = efi_get_boot_order(&order);
682 /* no entry, add us */
683 return efi_set_boot_order(&slot, 1);
685 /* are we the first and only one? */
686 if (n == 1 && order[0] == slot)
689 /* are we already in the boot order? */
690 for (i = 0; i < n; i++) {
691 if (order[i] != slot)
694 /* we do not require to be the first one, all is fine */
698 /* move us to the first slot */
699 memmove(order + 1, order, i * sizeof(uint16_t));
701 return efi_set_boot_order(order, n);
705 t = realloc(order, (n + 1) * sizeof(uint16_t));
710 /* add us to the top or end of the list */
712 memmove(order + 1, order, n * sizeof(uint16_t));
717 return efi_set_boot_order(order, n + 1);
720 static int remove_from_order(uint16_t slot) {
721 _cleanup_free_ uint16_t *order = NULL;
724 n = efi_get_boot_order(&order);
728 for (i = 0; i < n; i++) {
729 if (order[i] != slot)
733 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
734 return efi_set_boot_order(order, n - 1);
740 static int install_variables(const char *esp_path,
741 uint32_t part, uint64_t pstart, uint64_t psize,
742 sd_id128_t uuid, const char *path,
748 if (!is_efi_boot()) {
749 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
753 p = strjoina(esp_path, path);
754 if (access(p, F_OK) < 0) {
758 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
761 r = find_slot(uuid, path, &slot);
763 return log_error_errno(r,
765 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
766 "Failed to determine current boot order
: %m
");
768 if (first || r == false) {
769 r = efi_add_boot_option(slot, "Linux Boot Manager
",
773 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
775 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
778 return insert_into_order(slot, first);
781 static int remove_boot_efi(const char *esp_path) {
783 _cleanup_closedir_ DIR *d = NULL;
787 p = strjoina(esp_path, "/EFI
/Boot
");
793 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
796 while ((de = readdir(d))) {
797 _cleanup_close_ int fd = -1;
798 _cleanup_free_ char *v = NULL;
800 if (de->d_name[0] == '.')
803 if (!endswith_no_case(de->d_name, ".efi
"))
806 if (!startswith_no_case(de->d_name, "Boot
"))
809 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
811 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
813 r = get_file_version(fd, &v);
816 if (r > 0 && startswith(v, "systemd
-boot
")) {
817 r = unlinkat(dirfd(d), de->d_name, 0);
819 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
821 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
830 static int rmdir_one(const char *prefix, const char *suffix) {
833 p = strjoina(prefix, "/", suffix);
835 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
836 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
838 log_info("Removed
\"%s
\".", p);
843 static int remove_binaries(const char *esp_path) {
848 p = strjoina(esp_path, "/EFI
/systemd
");
849 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
851 q = remove_boot_efi(esp_path);
855 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
856 q = rmdir_one(esp_path, efi_subdirs[i-1]);
864 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
871 r = find_slot(uuid, path, &slot);
875 r = efi_remove_boot_option(slot);
880 return remove_from_order(slot);
885 static int install_loader_config(const char *esp_path) {
888 char *machine = NULL;
889 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
891 f = fopen("/etc
/machine
-id
", "re
");
893 return errno == ENOENT ? 0 : -errno;
895 if (fgets(line, sizeof(line), f) != NULL) {
898 s = strchr(line, '\n');
901 if (strlen(line) == 32)
908 p = strjoina(esp_path, "/loader
/loader
.conf
");
911 fprintf(g, "#timeout 3\n");
912 fprintf(g, "default %s-*\n", machine);
914 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
920 static int help(void) {
921 printf("%s [COMMAND] [OPTIONS...]\n"
923 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
924 " -h --help Show this help\n"
925 " --version Print version\n"
926 " --path=PATH Path to the EFI System Partition (ESP)\n"
927 " --no-variables Don't touch EFI variables\n"
930 " status Show status of installed systemd-boot and EFI variables\n"
931 " install Install systemd-boot to the ESP and EFI variables\n"
932 " update Update systemd-boot in the ESP and EFI variables\n"
933 " remove Remove systemd-boot from the ESP and EFI variables\n",
934 program_invocation_short_name);
939 static const char *arg_path = "/boot";
940 static bool arg_touch_variables = true;
942 static int parse_argv(int argc, char *argv[]) {
949 static const struct option options[] = {
950 { "help", no_argument, NULL, 'h' },
951 { "version", no_argument, NULL, ARG_VERSION },
952 { "path", required_argument, NULL, ARG_PATH },
953 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
962 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
976 case ARG_NO_VARIABLES:
977 arg_touch_variables = false;
984 assert_not_reached("Unknown option");
990 static void read_loader_efi_var(const char *name, char **var) {
993 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
994 if (r < 0 && r != -ENOENT)
995 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
998 static int bootctl_main(int argc, char*argv[]) {
1004 } arg_action = ACTION_STATUS;
1005 static const struct {
1009 { "status", ACTION_STATUS },
1010 { "install", ACTION_INSTALL },
1011 { "update", ACTION_UPDATE },
1012 { "remove", ACTION_REMOVE },
1015 sd_id128_t uuid = {};
1017 uint64_t pstart = 0, psize = 0;
1023 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1024 if (!streq(argv[optind], verbs[i].verb))
1026 arg_action = verbs[i].action;
1029 if (i >= ELEMENTSOF(verbs)) {
1030 log_error("Unknown operation \"%s\"", argv[optind]);
1036 return log_error_errno(EPERM, "Need to be root.");
1038 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1039 if (r == -ENODEV && !arg_path)
1040 log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
1044 switch (arg_action) {
1045 case ACTION_STATUS: {
1046 _cleanup_free_ char *fw_type = NULL;
1047 _cleanup_free_ char *fw_info = NULL;
1048 _cleanup_free_ char *loader = NULL;
1049 _cleanup_free_ char *loader_path = NULL;
1050 sd_id128_t loader_part_uuid = {};
1052 if (is_efi_boot()) {
1053 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1054 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1055 read_loader_efi_var("LoaderInfo", &loader);
1056 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1058 efi_tilt_backslashes(loader_path);
1059 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1060 if (r < 0 && r == -ENOENT)
1061 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1063 printf("System:\n");
1064 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1066 r = is_efi_secure_boot();
1068 log_warning_errno(r, "Failed to query secure boot status: %m");
1070 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1072 r = is_efi_secure_boot_setup_mode();
1074 log_warning_errno(r, "Failed to query secure boot mode: %m");
1076 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1079 printf("Loader:\n");
1080 printf(" Product: %s\n", strna(loader));
1081 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1082 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1083 SD_ID128_FORMAT_VAL(loader_part_uuid));
1085 printf(" Partition: n/a\n");
1086 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1089 printf("System:\n Not booted with EFI\n");
1091 r = status_binaries(arg_path, uuid);
1095 if (arg_touch_variables)
1096 r = status_variables();
1100 case ACTION_INSTALL:
1104 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1108 if (arg_action == ACTION_INSTALL) {
1109 r = install_loader_config(arg_path);
1114 if (arg_touch_variables)
1115 r = install_variables(arg_path,
1116 part, pstart, psize, uuid,
1117 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1118 arg_action == ACTION_INSTALL);
1122 r = remove_binaries(arg_path);
1124 if (arg_touch_variables) {
1125 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1126 if (q < 0 && r == 0)
1135 int main(int argc, char *argv[]) {
1138 log_parse_environment();
1141 r = parse_argv(argc, argv);
1145 r = bootctl_main(argc, argv);
1148 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;