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 "locale-util.h"
46 #include "string-util.h"
49 static int verify_esp(const char *p
, uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
52 _cleanup_free_
char *t
= NULL
;
53 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
57 if (statfs(p
, &sfs
) < 0)
58 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
60 if (sfs
.f_type
!= 0x4d44) {
61 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
66 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
68 if (major(st
.st_dev
) == 0) {
69 log_error("Block device node of %p is invalid.", p
);
73 t2
= strjoina(p
, "/..");
76 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
78 if (st
.st_dev
== st2
.st_dev
) {
79 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
83 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
88 b
= blkid_new_probe_from_filename(t
);
93 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
96 blkid_probe_enable_superblocks(b
, 1);
97 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
98 blkid_probe_enable_partitions(b
, 1);
99 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
102 r
= blkid_do_safeprobe(b
);
104 log_error("File system \"%s\" is ambigious.", p
);
107 log_error("File system \"%s\" does not contain a label.", p
);
110 r
= errno
? -errno
: -EIO
;
111 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
115 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
117 r
= errno
? -errno
: -EIO
;
118 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
121 if (!streq(v
, "vfat")) {
122 log_error("File system \"%s\" is not FAT.", p
);
127 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
129 r
= errno
? -errno
: -EIO
;
130 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
133 if (!streq(v
, "gpt")) {
134 log_error("File system \"%s\" is not on a GPT partition table.", p
);
139 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
141 r
= errno
? -errno
: -EIO
;
142 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
145 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
146 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
151 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
153 r
= errno
? -errno
: -EIO
;
154 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
157 r
= sd_id128_from_string(v
, uuid
);
159 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
164 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
166 r
= errno
? -errno
: -EIO
;
167 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
169 *part
= strtoul(v
, NULL
, 10);
172 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
174 r
= errno
? -errno
: -EIO
;
175 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
177 *pstart
= strtoul(v
, NULL
, 10);
180 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
182 r
= errno
? -errno
: -EIO
;
183 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
185 *psize
= strtoul(v
, NULL
, 10);
190 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
191 static int get_file_version(int fd
, char **v
) {
201 if (fstat(fd
, &st
) < 0)
207 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
208 if (buf
== MAP_FAILED
)
211 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
216 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
217 if (!e
|| e
- s
< 3) {
218 log_error("Malformed version string.");
223 x
= strndup(s
, e
- s
);
231 munmap(buf
, st
.st_size
);
236 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
238 _cleanup_closedir_
DIR *d
= NULL
;
242 p
= strjoina(esp_path
, "/", path
);
248 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
251 while ((de
= readdir(d
))) {
252 _cleanup_close_
int fd
= -1;
253 _cleanup_free_
char *v
= NULL
;
255 if (de
->d_name
[0] == '.')
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)\n", path
, de
->d_name
, v
);
274 printf(" File: └─/%s/%s\n", 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\n", 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 while ((de = readdir(d))) {
619 if (de->d_name[0] == '.')
622 if (!endswith_no_case(de->d_name, ".efi
"))
625 k = copy_one_file(esp_path, de->d_name, force);
633 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
634 _cleanup_free_ char *opath = NULL;
638 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
641 if (!sd_id128_equal(uuid, ouuid))
643 if (!streq_ptr(path, opath))
649 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
650 _cleanup_free_ uint16_t *options = NULL;
653 n = efi_get_boot_options(&options);
657 /* find already existing systemd-boot entry */
658 for (i = 0; i < n; i++)
659 if (same_entry(options[i], uuid, path)) {
664 /* find free slot in the sorted BootXXXX variable list */
665 for (i = 0; i < n; i++)
666 if (i != options[i]) {
671 /* use the next one */
678 static int insert_into_order(uint16_t slot, bool first) {
679 _cleanup_free_ uint16_t *order = NULL;
683 n = efi_get_boot_order(&order);
685 /* no entry, add us */
686 return efi_set_boot_order(&slot, 1);
688 /* are we the first and only one? */
689 if (n == 1 && order[0] == slot)
692 /* are we already in the boot order? */
693 for (i = 0; i < n; i++) {
694 if (order[i] != slot)
697 /* we do not require to be the first one, all is fine */
701 /* move us to the first slot */
702 memmove(order + 1, order, i * sizeof(uint16_t));
704 return efi_set_boot_order(order, n);
708 t = realloc(order, (n + 1) * sizeof(uint16_t));
713 /* add us to the top or end of the list */
715 memmove(order + 1, order, n * sizeof(uint16_t));
720 return efi_set_boot_order(order, n + 1);
723 static int remove_from_order(uint16_t slot) {
724 _cleanup_free_ uint16_t *order = NULL;
727 n = efi_get_boot_order(&order);
731 for (i = 0; i < n; i++) {
732 if (order[i] != slot)
736 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
737 return efi_set_boot_order(order, n - 1);
743 static int install_variables(const char *esp_path,
744 uint32_t part, uint64_t pstart, uint64_t psize,
745 sd_id128_t uuid, const char *path,
751 if (!is_efi_boot()) {
752 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
756 p = strjoina(esp_path, path);
757 if (access(p, F_OK) < 0) {
761 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
764 r = find_slot(uuid, path, &slot);
766 return log_error_errno(r,
768 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
769 "Failed to determine current boot order
: %m
");
771 if (first || r == false) {
772 r = efi_add_boot_option(slot, "Linux Boot Manager
",
776 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
778 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
781 return insert_into_order(slot, first);
784 static int remove_boot_efi(const char *esp_path) {
786 _cleanup_closedir_ DIR *d = NULL;
790 p = strjoina(esp_path, "/EFI
/Boot
");
796 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
799 while ((de = readdir(d))) {
800 _cleanup_close_ int fd = -1;
801 _cleanup_free_ char *v = NULL;
803 if (de->d_name[0] == '.')
806 if (!endswith_no_case(de->d_name, ".efi
"))
809 if (!startswith_no_case(de->d_name, "Boot
"))
812 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
814 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
816 r = get_file_version(fd, &v);
819 if (r > 0 && startswith(v, "systemd
-boot
")) {
820 r = unlinkat(dirfd(d), de->d_name, 0);
822 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
824 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
833 static int rmdir_one(const char *prefix, const char *suffix) {
836 p = strjoina(prefix, "/", suffix);
838 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
839 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
841 log_info("Removed
\"%s
\".", p);
846 static int remove_binaries(const char *esp_path) {
851 p = strjoina(esp_path, "/EFI
/systemd
");
852 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
854 q = remove_boot_efi(esp_path);
858 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
859 q = rmdir_one(esp_path, efi_subdirs[i-1]);
867 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
874 r = find_slot(uuid, path, &slot);
878 r = efi_remove_boot_option(slot);
883 return remove_from_order(slot);
888 static int install_loader_config(const char *esp_path) {
891 char *machine = NULL;
892 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
894 f = fopen("/etc
/machine
-id
", "re
");
896 return errno == ENOENT ? 0 : -errno;
898 if (fgets(line, sizeof(line), f) != NULL) {
901 s = strchr(line, '\n');
904 if (strlen(line) == 32)
911 p = strjoina(esp_path, "/loader
/loader
.conf
");
914 fprintf(g, "#timeout 3\n");
915 fprintf(g, "default %s-*\n", machine);
917 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
923 static int help(void) {
924 printf("%s [COMMAND] [OPTIONS...]\n"
926 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
927 " -h --help Show this help\n"
928 " --version Print version\n"
929 " --path=PATH Path to the EFI System Partition (ESP)\n"
930 " --no-variables Don't touch EFI variables\n"
933 " status Show status of installed systemd-boot and EFI variables\n"
934 " install Install systemd-boot to the ESP and EFI variables\n"
935 " update Update systemd-boot in the ESP and EFI variables\n"
936 " remove Remove systemd-boot from the ESP and EFI variables\n",
937 program_invocation_short_name);
942 static const char *arg_path = "/boot";
943 static bool arg_touch_variables = true;
945 static int parse_argv(int argc, char *argv[]) {
952 static const struct option options[] = {
953 { "help", no_argument, NULL, 'h' },
954 { "version", no_argument, NULL, ARG_VERSION },
955 { "path", required_argument, NULL, ARG_PATH },
956 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
965 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
979 case ARG_NO_VARIABLES:
980 arg_touch_variables = false;
987 assert_not_reached("Unknown option");
993 static void read_loader_efi_var(const char *name, char **var) {
996 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
997 if (r < 0 && r != -ENOENT)
998 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1001 static int bootctl_main(int argc, char*argv[]) {
1007 } arg_action = ACTION_STATUS;
1008 static const struct {
1012 { "status", ACTION_STATUS },
1013 { "install", ACTION_INSTALL },
1014 { "update", ACTION_UPDATE },
1015 { "remove", ACTION_REMOVE },
1018 sd_id128_t uuid = {};
1020 uint64_t pstart = 0, psize = 0;
1026 for (i = 0; i < ELEMENTSOF(verbs); i++) {
1027 if (!streq(argv[optind], verbs[i].verb))
1029 arg_action = verbs[i].action;
1032 if (i >= ELEMENTSOF(verbs)) {
1033 log_error("Unknown operation \"%s\"", argv[optind]);
1039 return log_error_errno(EPERM, "Need to be root.");
1041 r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
1042 if (r == -ENODEV && !arg_path)
1043 log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
1047 switch (arg_action) {
1048 case ACTION_STATUS: {
1049 _cleanup_free_ char *fw_type = NULL;
1050 _cleanup_free_ char *fw_info = NULL;
1051 _cleanup_free_ char *loader = NULL;
1052 _cleanup_free_ char *loader_path = NULL;
1053 sd_id128_t loader_part_uuid = {};
1055 if (is_efi_boot()) {
1056 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1057 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1058 read_loader_efi_var("LoaderInfo", &loader);
1059 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1061 efi_tilt_backslashes(loader_path);
1062 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1063 if (r < 0 && r == -ENOENT)
1064 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1066 printf("System:\n");
1067 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1069 r = is_efi_secure_boot();
1071 log_warning_errno(r, "Failed to query secure boot status: %m");
1073 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1075 r = is_efi_secure_boot_setup_mode();
1077 log_warning_errno(r, "Failed to query secure boot mode: %m");
1079 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1082 printf("Loader:\n");
1083 printf(" Product: %s\n", strna(loader));
1084 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1085 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1086 SD_ID128_FORMAT_VAL(loader_part_uuid));
1088 printf(" Partition: n/a\n");
1089 printf(" File: %s%s\n", draw_special_char(DRAW_TREE_RIGHT), strna(loader_path));
1092 printf("System:\n Not booted with EFI\n");
1094 r = status_binaries(arg_path, uuid);
1098 if (arg_touch_variables)
1099 r = status_variables();
1103 case ACTION_INSTALL:
1107 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1111 if (arg_action == ACTION_INSTALL) {
1112 r = install_loader_config(arg_path);
1117 if (arg_touch_variables)
1118 r = install_variables(arg_path,
1119 part, pstart, psize, uuid,
1120 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1121 arg_action == ACTION_INSTALL);
1125 r = remove_binaries(arg_path);
1127 if (arg_touch_variables) {
1128 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1129 if (q < 0 && r == 0)
1138 int main(int argc, char *argv[]) {
1141 log_parse_environment();
1144 r = parse_argv(argc, argv);
1148 r = bootctl_main(argc, argv);
1151 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;