2 This file is part of systemd.
4 Copyright 2013-2015 Kay Sievers
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <blkid/blkid.h>
35 #include <sys/statfs.h>
38 #include "alloc-util.h"
39 #include "blkid-util.h"
40 #include "dirent-util.h"
44 #include "locale-util.h"
46 #include "string-util.h"
49 static const char *arg_path
= "/boot";
50 static bool arg_touch_variables
= true;
52 static int verify_esp(const char *p
, uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
55 _cleanup_free_
char *t
= NULL
;
56 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
60 if (statfs(p
, &sfs
) < 0)
61 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
63 if (sfs
.f_type
!= 0x4d44) {
64 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
69 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
71 if (major(st
.st_dev
) == 0) {
72 log_error("Block device node of %p is invalid.", p
);
76 t2
= strjoina(p
, "/..");
79 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
81 if (st
.st_dev
== st2
.st_dev
) {
82 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
86 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
91 b
= blkid_new_probe_from_filename(t
);
96 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
99 blkid_probe_enable_superblocks(b
, 1);
100 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
101 blkid_probe_enable_partitions(b
, 1);
102 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
105 r
= blkid_do_safeprobe(b
);
107 log_error("File system \"%s\" is ambiguous.", p
);
110 log_error("File system \"%s\" does not contain a label.", p
);
113 r
= errno
? -errno
: -EIO
;
114 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
118 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
120 r
= errno
? -errno
: -EIO
;
121 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
124 if (!streq(v
, "vfat")) {
125 log_error("File system \"%s\" is not FAT.", p
);
130 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
132 r
= errno
? -errno
: -EIO
;
133 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
136 if (!streq(v
, "gpt")) {
137 log_error("File system \"%s\" is not on a GPT partition table.", p
);
142 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
144 r
= errno
? -errno
: -EIO
;
145 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
148 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
149 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
154 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
156 r
= errno
? -errno
: -EIO
;
157 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
160 r
= sd_id128_from_string(v
, uuid
);
162 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
167 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
169 r
= errno
? -errno
: -EIO
;
170 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
172 *part
= strtoul(v
, NULL
, 10);
175 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
177 r
= errno
? -errno
: -EIO
;
178 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
180 *pstart
= strtoul(v
, NULL
, 10);
183 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
185 r
= errno
? -errno
: -EIO
;
186 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
188 *psize
= strtoul(v
, NULL
, 10);
193 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
194 static int get_file_version(int fd
, char **v
) {
204 if (fstat(fd
, &st
) < 0)
210 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
211 if (buf
== MAP_FAILED
)
214 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
219 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
220 if (!e
|| e
- s
< 3) {
221 log_error("Malformed version string.");
226 x
= strndup(s
, e
- s
);
234 munmap(buf
, st
.st_size
);
239 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
241 _cleanup_closedir_
DIR *d
= NULL
;
245 p
= strjoina(esp_path
, "/", path
);
251 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
254 FOREACH_DIRENT(de
, d
, break) {
255 _cleanup_close_
int fd
= -1;
256 _cleanup_free_
char *v
= NULL
;
258 if (!endswith_no_case(de
->d_name
, ".efi"))
261 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
264 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
266 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
268 r
= get_file_version(fd
, &v
);
272 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
, v
);
274 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
);
281 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
284 printf("Boot Loader Binaries:\n");
286 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
));
288 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
290 log_error("systemd-boot not installed in ESP.");
294 r
= enumerate_binaries(esp_path
, "EFI/BOOT", "boot");
296 log_error("No default/fallback boot loader installed in ESP.");
305 static int print_efi_option(uint16_t id
, bool in_order
) {
306 _cleanup_free_
char *title
= NULL
;
307 _cleanup_free_
char *path
= NULL
;
308 sd_id128_t partition
;
312 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
316 /* print only configured entries with partition information */
317 if (!path
|| sd_id128_equal(partition
, SD_ID128_NULL
))
320 efi_tilt_backslashes(path
);
322 printf(" Title: %s\n", strna(title
));
323 printf(" ID: 0x%04X\n", id
);
324 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
325 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
));
326 printf(" File: %s%s\n", special_glyph(TREE_RIGHT
), path
);
332 static int status_variables(void) {
333 int n_options
, n_order
;
334 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
337 if (!is_efi_boot()) {
338 log_notice("Not booted with EFI, not showing EFI variables.");
342 n_options
= efi_get_boot_options(&options
);
343 if (n_options
== -ENOENT
)
344 return log_error_errno(ENOENT
, "Failed to access EFI variables, efivarfs"
345 " needs to be available at /sys/firmware/efi/efivars/.");
346 else if (n_options
< 0)
347 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
349 n_order
= efi_get_boot_order(&order
);
350 if (n_order
== -ENOENT
)
352 else if (n_order
< 0)
353 return log_error_errno(n_order
, "Failed to read EFI boot order.");
355 /* print entries in BootOrder first */
356 printf("Boot Loader Entries in EFI Variables:\n");
357 for (i
= 0; i
< n_order
; i
++)
358 print_efi_option(order
[i
], true);
360 /* print remaining entries */
361 for (i
= 0; i
< n_options
; i
++) {
364 for (j
= 0; j
< n_order
; j
++)
365 if (options
[i
] == order
[j
])
368 print_efi_option(options
[i
], false);
376 static int compare_product(const char *a
, const char *b
) {
385 return x
< y
? -1 : x
> y
? 1 : 0;
387 return strncmp(a
, b
, x
);
390 static int compare_version(const char *a
, const char *b
) {
394 a
+= strcspn(a
, " ");
396 b
+= strcspn(b
, " ");
399 return strverscmp(a
, b
);
402 static int version_check(int fd
, const char *from
, const char *to
) {
403 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
404 _cleanup_close_
int fd2
= -1;
411 r
= get_file_version(fd
, &a
);
415 log_error("Source file \"%s\" does not carry version information!", from
);
419 fd2
= open(to
, O_RDONLY
|O_CLOEXEC
);
424 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
427 r
= get_file_version(fd2
, &b
);
430 if (r
== 0 || compare_product(a
, b
) != 0) {
431 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
435 if (compare_version(a
, b
) < 0) {
436 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
443 static int copy_file(const char *from
, const char *to
, bool force
) {
444 _cleanup_fclose_
FILE *f
= NULL
, *g
= NULL
;
447 struct timespec t
[2];
453 f
= fopen(from
, "re");
455 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
458 /* If this is an update, then let's compare versions first */
459 r
= version_check(fileno(f
), from
, to
);
464 p
= strjoina(to
, "~");
467 /* Directory doesn't exist yet? Then let's skip this... */
468 if (!force
&& errno
== ENOENT
)
471 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", to
);
477 uint8_t buf
[32*1024];
479 k
= fread(buf
, 1, sizeof(buf
), f
);
481 r
= log_error_errno(EIO
, "Failed to read \"%s\": %m", from
);
488 fwrite(buf
, 1, k
, g
);
490 r
= log_error_errno(EIO
, "Failed to write \"%s\": %m", to
);
495 r
= fflush_and_check(g
);
497 log_error_errno(r
, "Failed to write \"%s\": %m", to
);
501 r
= fstat(fileno(f
), &st
);
503 r
= log_error_errno(errno
, "Failed to get file timestamps of \"%s\": %m", from
);
510 r
= futimens(fileno(g
), t
);
512 r
= log_error_errno(errno
, "Failed to set file timestamps on \"%s\": %m", p
);
516 if (rename(p
, to
) < 0) {
517 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", p
, to
);
521 log_info("Copied \"%s\" to \"%s\".", from
, to
);
529 static char* strupper(char *s
) {
538 static int mkdir_one(const char *prefix
, const char *suffix
) {
541 p
= strjoina(prefix
, "/", suffix
);
542 if (mkdir(p
, 0700) < 0) {
544 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
546 log_info("Created \"%s\".", p
);
551 static const char *efi_subdirs
[] = {
559 static int create_dirs(const char *esp_path
) {
563 for (i
= 0; i
< ELEMENTSOF(efi_subdirs
); i
++) {
564 r
= mkdir_one(esp_path
, efi_subdirs
[i
]);
572 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
576 p
= strjoina(BOOTLIBDIR
"/", name
);
577 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
578 r
= copy_file(p
, q
, force
);
580 if (startswith(name
, "systemd-boot")) {
584 /* Create the EFI default boot loader name (specified for removable devices) */
585 v
= strjoina(esp_path
, "/EFI/BOOT/BOOT", name
+ strlen("systemd-boot"));
586 strupper(strrchr(v
, '/') + 1);
588 k
= copy_file(p
, v
, force
);
596 static int install_binaries(const char *esp_path
, bool force
) {
598 _cleanup_closedir_
DIR *d
= NULL
;
602 /* Don't create any of these directories when we are
603 * just updating. When we update we'll drop-in our
604 * files (unless there are newer ones already), but we
605 * won't create the directories for them in the first
607 r
= create_dirs(esp_path
);
612 d
= opendir(BOOTLIBDIR
);
614 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
616 FOREACH_DIRENT(de, d, break) {
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 FOREACH_DIRENT(de, d, break) {
797 _cleanup_close_ int fd = -1;
798 _cleanup_free_ char *v = NULL;
800 if (!endswith_no_case(de->d_name, ".efi
"))
803 if (!startswith_no_case(de->d_name, "boot
"))
806 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
808 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
810 r = get_file_version(fd, &v);
813 if (r > 0 && startswith(v, "systemd
-boot
")) {
814 r = unlinkat(dirfd(d), de->d_name, 0);
816 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
818 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
827 static int rmdir_one(const char *prefix, const char *suffix) {
830 p = strjoina(prefix, "/", suffix);
832 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
833 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
835 log_info("Removed
\"%s
\".", p);
840 static int remove_binaries(const char *esp_path) {
845 p = strjoina(esp_path, "/EFI
/systemd
");
846 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
848 q = remove_boot_efi(esp_path);
852 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
853 q = rmdir_one(esp_path, efi_subdirs[i-1]);
861 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
868 r = find_slot(uuid, path, &slot);
872 r = efi_remove_boot_option(slot);
877 return remove_from_order(slot);
882 static int install_loader_config(const char *esp_path) {
885 char *machine = NULL;
886 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
888 f = fopen("/etc
/machine
-id
", "re
");
890 return errno == ENOENT ? 0 : -errno;
892 if (fgets(line, sizeof(line), f) != NULL) {
895 s = strchr(line, '\n');
898 if (strlen(line) == 32)
905 p = strjoina(esp_path, "/loader
/loader
.conf
");
908 fprintf(g, "#timeout 3\n");
909 fprintf(g, "default %s-*\n", machine);
911 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
917 static int help(void) {
918 printf("%s [COMMAND] [OPTIONS...]\n"
920 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
921 " -h --help Show this help\n"
922 " --version Print version\n"
923 " --path=PATH Path to the EFI System Partition (ESP)\n"
924 " --no-variables Don't touch EFI variables\n"
927 " status Show status of installed systemd-boot and EFI variables\n"
928 " install Install systemd-boot to the ESP and EFI variables\n"
929 " update Update systemd-boot in the ESP and EFI variables\n"
930 " remove Remove systemd-boot from the ESP and EFI variables\n",
931 program_invocation_short_name);
936 static int parse_argv(int argc, char *argv[]) {
943 static const struct option options[] = {
944 { "help", no_argument, NULL, 'h' },
945 { "version", no_argument, NULL, ARG_VERSION },
946 { "path", required_argument, NULL, ARG_PATH },
947 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
956 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
970 case ARG_NO_VARIABLES:
971 arg_touch_variables = false;
978 assert_not_reached("Unknown option");
984 static void read_loader_efi_var(const char *name, char **var) {
987 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
988 if (r < 0 && r != -ENOENT)
989 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
992 static int bootctl_main(int argc, char*argv[]) {
998 } arg_action = ACTION_STATUS;
999 static const struct {
1003 { "status", ACTION_STATUS },
1004 { "install", ACTION_INSTALL },
1005 { "update", ACTION_UPDATE },
1006 { "remove", ACTION_REMOVE },
1009 sd_id128_t uuid = {};
1011 uint64_t pstart = 0, psize = 0;
1017 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1018 if (!streq(argv[optind], verbs[i].verb))
1020 arg_action = verbs[i].action;
1023 if (i >= ELEMENTSOF(verbs)) {
1024 log_error("Unknown operation \"%s\"", argv[optind]);
1030 return log_error_errno(EPERM, "Need to be root.");
1032 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1033 if (r == -ENODEV && !arg_path)
1034 log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
1038 switch (arg_action) {
1040 case ACTION_STATUS: {
1041 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1042 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1044 if (is_efi_boot()) {
1045 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1046 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1047 read_loader_efi_var("LoaderInfo", &loader);
1048 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1050 efi_tilt_backslashes(loader_path);
1051 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1052 if (r < 0 && r != -ENOENT)
1053 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1055 printf("System:\n");
1056 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1058 r = is_efi_secure_boot();
1060 log_warning_errno(r, "Failed to query secure boot status: %m");
1062 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1064 r = is_efi_secure_boot_setup_mode();
1066 log_warning_errno(r, "Failed to query secure boot mode: %m");
1068 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1071 printf("Loader:\n");
1072 printf(" Product: %s\n", strna(loader));
1073 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1074 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1075 SD_ID128_FORMAT_VAL(loader_part_uuid));
1077 printf(" Partition: n/a\n");
1078 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1081 printf("System:\n Not booted with EFI\n");
1083 r = status_binaries(arg_path, uuid);
1087 if (arg_touch_variables)
1088 r = status_variables();
1092 case ACTION_INSTALL:
1096 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1100 if (arg_action == ACTION_INSTALL) {
1101 r = install_loader_config(arg_path);
1106 if (arg_touch_variables)
1107 r = install_variables(arg_path,
1108 part, pstart, psize, uuid,
1109 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1110 arg_action == ACTION_INSTALL);
1114 r = remove_binaries(arg_path);
1116 if (arg_touch_variables) {
1117 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1118 if (q < 0 && r == 0)
1127 int main(int argc, char *argv[]) {
1130 log_parse_environment();
1133 r = parse_argv(argc, argv);
1137 r = bootctl_main(argc, argv);
1140 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;