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"
45 static int verify_esp(const char *p
, uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
48 _cleanup_free_
char *t
= NULL
;
49 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
53 if (statfs(p
, &sfs
) < 0)
54 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
56 if (sfs
.f_type
!= 0x4d44) {
57 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
62 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
64 if (major(st
.st_dev
) == 0) {
65 log_error("Block device node of %p is invalid.", p
);
69 t2
= strjoina(p
, "/..");
72 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
74 if (st
.st_dev
== st2
.st_dev
) {
75 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
79 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
84 b
= blkid_new_probe_from_filename(t
);
89 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
92 blkid_probe_enable_superblocks(b
, 1);
93 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
94 blkid_probe_enable_partitions(b
, 1);
95 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
98 r
= blkid_do_safeprobe(b
);
100 log_error("File system \"%s\" is ambigious.", p
);
103 log_error("File system \"%s\" does not contain a label.", p
);
106 r
= errno
? -errno
: -EIO
;
107 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
111 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
113 r
= errno
? -errno
: -EIO
;
114 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
117 if (!streq(v
, "vfat")) {
118 log_error("File system \"%s\" is not FAT.", p
);
123 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
125 r
= errno
? -errno
: -EIO
;
126 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
129 if (!streq(v
, "gpt")) {
130 log_error("File system \"%s\" is not on a GPT partition table.", p
);
135 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
137 r
= errno
? -errno
: -EIO
;
138 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
141 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
142 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
147 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
149 r
= errno
? -errno
: -EIO
;
150 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
153 r
= sd_id128_from_string(v
, uuid
);
155 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
160 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
162 r
= errno
? -errno
: -EIO
;
163 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
165 *part
= strtoul(v
, NULL
, 10);
168 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
170 r
= errno
? -errno
: -EIO
;
171 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
173 *pstart
= strtoul(v
, NULL
, 10);
176 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
178 r
= errno
? -errno
: -EIO
;
179 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
181 *psize
= strtoul(v
, NULL
, 10);
186 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
187 static int get_file_version(int fd
, char **v
) {
197 if (fstat(fd
, &st
) < 0)
203 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
204 if (buf
== MAP_FAILED
)
207 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
212 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
213 if (!e
|| e
- s
< 3) {
214 log_error("Malformed version string.");
219 x
= strndup(s
, e
- s
);
227 munmap(buf
, st
.st_size
);
232 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
234 _cleanup_closedir_
DIR *d
= NULL
;
238 p
= strjoina(esp_path
, "/", path
);
244 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
247 while ((de
= readdir(d
))) {
248 _cleanup_close_
int fd
= -1;
249 _cleanup_free_
char *v
= NULL
;
251 if (de
->d_name
[0] == '.')
254 if (!endswith_no_case(de
->d_name
, ".efi"))
257 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
260 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
262 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
264 r
= get_file_version(fd
, &v
);
268 printf(" File: └─/%s/%s (%s)\n", path
, de
->d_name
, v
);
270 printf(" File: └─/%s/%s\n", path
, de
->d_name
);
277 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
280 printf("Boot Loader Binaries:\n");
282 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
));
284 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
286 log_error("systemd-boot not installed in ESP.");
290 r
= enumerate_binaries(esp_path
, "EFI/Boot", "boot");
292 log_error("No default/fallback boot loader installed in ESP.");
301 static int print_efi_option(uint16_t id
, bool in_order
) {
302 _cleanup_free_
char *title
= NULL
;
303 _cleanup_free_
char *path
= NULL
;
304 sd_id128_t partition
;
308 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
312 /* print only configured entries with partition information */
313 if (!path
|| sd_id128_equal(partition
, SD_ID128_NULL
))
316 efi_tilt_backslashes(path
);
318 printf(" Title: %s\n", strna(title
));
319 printf(" ID: 0x%04X\n", id
);
320 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
321 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
));
322 printf(" File: └─%s\n", path
);
328 static int status_variables(void) {
329 int n_options
, n_order
;
330 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
333 if (!is_efi_boot()) {
334 log_notice("Not booted with EFI, not showing EFI variables.");
338 n_options
= efi_get_boot_options(&options
);
339 if (n_options
== -ENOENT
)
340 return log_error_errno(ENOENT
, "Failed to access EFI variables, efivarfs"
341 " needs to be available at /sys/firmware/efi/efivars/.");
342 else if (n_options
< 0)
343 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
345 n_order
= efi_get_boot_order(&order
);
346 if (n_order
== -ENOENT
)
348 else if (n_order
< 0)
349 return log_error_errno(n_order
, "Failed to read EFI boot order.");
351 /* print entries in BootOrder first */
352 printf("Boot Loader Entries in EFI Variables:\n");
353 for (i
= 0; i
< n_order
; i
++)
354 print_efi_option(order
[i
], true);
356 /* print remaining entries */
357 for (i
= 0; i
< n_options
; i
++) {
360 for (j
= 0; j
< n_order
; j
++)
361 if (options
[i
] == order
[j
])
364 print_efi_option(options
[i
], false);
372 static int compare_product(const char *a
, const char *b
) {
381 return x
< y
? -1 : x
> y
? 1 : 0;
383 return strncmp(a
, b
, x
);
386 static int compare_version(const char *a
, const char *b
) {
390 a
+= strcspn(a
, " ");
392 b
+= strcspn(b
, " ");
395 return strverscmp(a
, b
);
398 static int version_check(int fd
, const char *from
, const char *to
) {
399 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
400 _cleanup_close_
int fd2
= -1;
407 r
= get_file_version(fd
, &a
);
411 log_error("Source file \"%s\" does not carry version information!", from
);
415 fd2
= open(to
, O_RDONLY
|O_CLOEXEC
);
420 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
423 r
= get_file_version(fd2
, &b
);
426 if (r
== 0 || compare_product(a
, b
) != 0) {
427 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
431 if (compare_version(a
, b
) < 0) {
432 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
439 static int copy_file(const char *from
, const char *to
, bool force
) {
440 _cleanup_fclose_
FILE *f
= NULL
, *g
= NULL
;
443 struct timespec t
[2];
449 f
= fopen(from
, "re");
451 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
454 /* If this is an update, then let's compare versions first */
455 r
= version_check(fileno(f
), from
, to
);
460 p
= strjoina(to
, "~");
463 /* Directory doesn't exist yet? Then let's skip this... */
464 if (!force
&& errno
== ENOENT
)
467 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", to
);
473 uint8_t buf
[32*1024];
475 k
= fread(buf
, 1, sizeof(buf
), f
);
477 r
= log_error_errno(EIO
, "Failed to read \"%s\": %m", from
);
484 fwrite(buf
, 1, k
, g
);
486 r
= log_error_errno(EIO
, "Failed to write \"%s\": %m", to
);
491 r
= fflush_and_check(g
);
493 log_error_errno(r
, "Failed to write \"%s\": %m", to
);
497 r
= fstat(fileno(f
), &st
);
499 r
= log_error_errno(errno
, "Failed to get file timestamps of \"%s\": %m", from
);
506 r
= futimens(fileno(g
), t
);
508 r
= log_error_errno(errno
, "Failed to set file timestamps on \"%s\": %m", p
);
512 if (rename(p
, to
) < 0) {
513 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", p
, to
);
517 log_info("Copied \"%s\" to \"%s\".", from
, to
);
525 static char* strupper(char *s
) {
534 static int mkdir_one(const char *prefix
, const char *suffix
) {
537 p
= strjoina(prefix
, "/", suffix
);
538 if (mkdir(p
, 0700) < 0) {
540 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
542 log_info("Created \"%s\".", p
);
547 static const char *efi_subdirs
[] = {
555 static int create_dirs(const char *esp_path
) {
559 for (i
= 0; i
< ELEMENTSOF(efi_subdirs
); i
++) {
560 r
= mkdir_one(esp_path
, efi_subdirs
[i
]);
568 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
572 p
= strjoina(BOOTLIBDIR
"/", name
);
573 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
574 r
= copy_file(p
, q
, force
);
576 if (startswith(name
, "systemd-boot")) {
580 /* Create the EFI default boot loader name (specified for removable devices) */
581 v
= strjoina(esp_path
, "/EFI/Boot/BOOT", name
+ strlen("systemd-boot"));
582 strupper(strrchr(v
, '/') + 1);
584 k
= copy_file(p
, v
, force
);
592 static int install_binaries(const char *esp_path
, bool force
) {
594 _cleanup_closedir_
DIR *d
= NULL
;
598 /* Don't create any of these directories when we are
599 * just updating. When we update we'll drop-in our
600 * files (unless there are newer ones already), but we
601 * won't create the directories for them in the first
603 r
= create_dirs(esp_path
);
608 d
= opendir(BOOTLIBDIR
);
610 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
612 while ((de = readdir(d))) {
615 if (de->d_name[0] == '.')
618 if (!endswith_no_case(de->d_name, ".efi
"))
621 k = copy_one_file(esp_path, de->d_name, force);
629 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
630 _cleanup_free_ char *opath = NULL;
634 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
637 if (!sd_id128_equal(uuid, ouuid))
639 if (!streq_ptr(path, opath))
645 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
646 _cleanup_free_ uint16_t *options = NULL;
649 n = efi_get_boot_options(&options);
653 /* find already existing systemd-boot entry */
654 for (i = 0; i < n; i++)
655 if (same_entry(options[i], uuid, path)) {
660 /* find free slot in the sorted BootXXXX variable list */
661 for (i = 0; i < n; i++)
662 if (i != options[i]) {
667 /* use the next one */
674 static int insert_into_order(uint16_t slot, bool first) {
675 _cleanup_free_ uint16_t *order = NULL;
679 n = efi_get_boot_order(&order);
681 /* no entry, add us */
682 return efi_set_boot_order(&slot, 1);
684 /* are we the first and only one? */
685 if (n == 1 && order[0] == slot)
688 /* are we already in the boot order? */
689 for (i = 0; i < n; i++) {
690 if (order[i] != slot)
693 /* we do not require to be the first one, all is fine */
697 /* move us to the first slot */
698 memmove(order + 1, order, i * sizeof(uint16_t));
700 return efi_set_boot_order(order, n);
704 t = realloc(order, (n + 1) * sizeof(uint16_t));
709 /* add us to the top or end of the list */
711 memmove(order + 1, order, n * sizeof(uint16_t));
716 return efi_set_boot_order(order, n + 1);
719 static int remove_from_order(uint16_t slot) {
720 _cleanup_free_ uint16_t *order = NULL;
723 n = efi_get_boot_order(&order);
727 for (i = 0; i < n; i++) {
728 if (order[i] != slot)
732 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
733 return efi_set_boot_order(order, n - 1);
739 static int install_variables(const char *esp_path,
740 uint32_t part, uint64_t pstart, uint64_t psize,
741 sd_id128_t uuid, const char *path,
747 if (!is_efi_boot()) {
748 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
752 p = strjoina(esp_path, path);
753 if (access(p, F_OK) < 0) {
757 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
760 r = find_slot(uuid, path, &slot);
762 return log_error_errno(r,
764 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
765 "Failed to determine current boot order
: %m
");
767 if (first || r == false) {
768 r = efi_add_boot_option(slot, "Linux Boot Manager
",
772 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
774 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
777 return insert_into_order(slot, first);
780 static int remove_boot_efi(const char *esp_path) {
782 _cleanup_closedir_ DIR *d = NULL;
786 p = strjoina(esp_path, "/EFI
/Boot
");
792 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
795 while ((de = readdir(d))) {
796 _cleanup_close_ int fd = -1;
797 _cleanup_free_ char *v = NULL;
799 if (de->d_name[0] == '.')
802 if (!endswith_no_case(de->d_name, ".efi
"))
805 if (!startswith_no_case(de->d_name, "Boot
"))
808 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
810 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
812 r = get_file_version(fd, &v);
815 if (r > 0 && startswith(v, "systemd
-boot
")) {
816 r = unlinkat(dirfd(d), de->d_name, 0);
818 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
820 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
829 static int rmdir_one(const char *prefix, const char *suffix) {
832 p = strjoina(prefix, "/", suffix);
834 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
835 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
837 log_info("Removed
\"%s
\".", p);
842 static int remove_binaries(const char *esp_path) {
847 p = strjoina(esp_path, "/EFI
/systemd
");
848 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
850 q = remove_boot_efi(esp_path);
854 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
855 q = rmdir_one(esp_path, efi_subdirs[i-1]);
863 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
870 r = find_slot(uuid, path, &slot);
874 r = efi_remove_boot_option(slot);
879 return remove_from_order(slot);
884 static int install_loader_config(const char *esp_path) {
887 char *machine = NULL;
888 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
890 f = fopen("/etc
/machine
-id
", "re
");
892 return errno == ENOENT ? 0 : -errno;
894 if (fgets(line, sizeof(line), f) != NULL) {
897 s = strchr(line, '\n');
900 if (strlen(line) == 32)
907 p = strjoina(esp_path, "/loader
/loader
.conf
");
910 fprintf(g, "#timeout 3\n");
911 fprintf(g, "default %s-*\n", machine);
913 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
919 static int help(void) {
920 printf("%s [COMMAND] [OPTIONS...]\n"
922 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
923 " -h --help Show this help\n"
924 " --version Print version\n"
925 " --path=PATH Path to the EFI System Partition (ESP)\n"
926 " --no-variables Don't touch EFI variables\n"
929 " status Show status of installed systemd-boot and EFI variables\n"
930 " install Install systemd-boot to the ESP and EFI variables\n"
931 " update Update systemd-boot in the ESP and EFI variables\n"
932 " remove Remove systemd-boot from the ESP and EFI variables\n",
933 program_invocation_short_name);
938 static const char *arg_path = "/boot";
939 static bool arg_touch_variables = true;
941 static int parse_argv(int argc, char *argv[]) {
948 static const struct option options[] = {
949 { "help", no_argument, NULL, 'h' },
950 { "version", no_argument, NULL, ARG_VERSION },
951 { "path", required_argument, NULL, ARG_PATH },
952 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
961 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
975 case ARG_NO_VARIABLES:
976 arg_touch_variables = false;
983 assert_not_reached("Unknown option");
989 static void read_loader_efi_var(const char *name, char **var) {
992 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
993 if (r < 0 && r != -ENOENT)
994 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
997 static int bootctl_main(int argc, char*argv[]) {
1003 } arg_action = ACTION_STATUS;
1004 static const struct {
1008 { "status", ACTION_STATUS },
1009 { "install", ACTION_INSTALL },
1010 { "update", ACTION_UPDATE },
1011 { "remove", ACTION_REMOVE },
1014 sd_id128_t uuid = {};
1016 uint64_t pstart = 0, psize = 0;
1022 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1023 if (!streq(argv[optind], verbs[i].verb))
1025 arg_action = verbs[i].action;
1028 if (i >= ELEMENTSOF(verbs)) {
1029 log_error("Unknown operation \"%s\"", argv[optind]);
1035 return log_error_errno(EPERM, "Need to be root.");
1037 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1038 if (r == -ENODEV && !arg_path)
1039 log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
1043 switch (arg_action) {
1044 case ACTION_STATUS: {
1045 _cleanup_free_ char *fw_type = NULL;
1046 _cleanup_free_ char *fw_info = NULL;
1047 _cleanup_free_ char *loader = NULL;
1048 _cleanup_free_ char *loader_path = NULL;
1049 sd_id128_t loader_part_uuid = {};
1051 if (is_efi_boot()) {
1052 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1053 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1054 read_loader_efi_var("LoaderInfo", &loader);
1055 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1057 efi_tilt_backslashes(loader_path);
1058 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1059 if (r < 0 && r == -ENOENT)
1060 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1062 printf("System:\n");
1063 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1065 r = is_efi_secure_boot();
1067 log_warning_errno(r, "Failed to query secure boot status: %m");
1069 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1071 r = is_efi_secure_boot_setup_mode();
1073 log_warning_errno(r, "Failed to query secure boot mode: %m");
1075 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1078 printf("Loader:\n");
1079 printf(" Product: %s\n", strna(loader));
1080 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1081 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1082 SD_ID128_FORMAT_VAL(loader_part_uuid));
1084 printf(" Partition: n/a\n");
1085 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1088 printf("System:\n Not booted with EFI\n");
1090 r = status_binaries(arg_path, uuid);
1094 if (arg_touch_variables)
1095 r = status_variables();
1099 case ACTION_INSTALL:
1103 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1107 if (arg_action == ACTION_INSTALL) {
1108 r = install_loader_config(arg_path);
1113 if (arg_touch_variables)
1114 r = install_variables(arg_path,
1115 part, pstart, psize, uuid,
1116 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1117 arg_action == ACTION_INSTALL);
1121 r = remove_binaries(arg_path);
1123 if (arg_touch_variables) {
1124 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1125 if (q < 0 && r == 0)
1134 int main(int argc, char *argv[]) {
1137 log_parse_environment();
1140 r = parse_argv(argc, argv);
1144 r = bootctl_main(argc, argv);
1147 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;