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 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 ambiguous.", 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 FOREACH_DIRENT(de
, d
, break) {
252 _cleanup_close_
int fd
= -1;
253 _cleanup_free_
char *v
= NULL
;
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 (%s)\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
, v
);
271 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT
), 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%s\n", special_glyph(TREE_RIGHT
), 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 FOREACH_DIRENT(de, d, break) {
616 if (!endswith_no_case(de->d_name, ".efi
"))
619 k = copy_one_file(esp_path, de->d_name, force);
627 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
628 _cleanup_free_ char *opath = NULL;
632 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
635 if (!sd_id128_equal(uuid, ouuid))
637 if (!streq_ptr(path, opath))
643 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
644 _cleanup_free_ uint16_t *options = NULL;
647 n = efi_get_boot_options(&options);
651 /* find already existing systemd-boot entry */
652 for (i = 0; i < n; i++)
653 if (same_entry(options[i], uuid, path)) {
658 /* find free slot in the sorted BootXXXX variable list */
659 for (i = 0; i < n; i++)
660 if (i != options[i]) {
665 /* use the next one */
672 static int insert_into_order(uint16_t slot, bool first) {
673 _cleanup_free_ uint16_t *order = NULL;
677 n = efi_get_boot_order(&order);
679 /* no entry, add us */
680 return efi_set_boot_order(&slot, 1);
682 /* are we the first and only one? */
683 if (n == 1 && order[0] == slot)
686 /* are we already in the boot order? */
687 for (i = 0; i < n; i++) {
688 if (order[i] != slot)
691 /* we do not require to be the first one, all is fine */
695 /* move us to the first slot */
696 memmove(order + 1, order, i * sizeof(uint16_t));
698 return efi_set_boot_order(order, n);
702 t = realloc(order, (n + 1) * sizeof(uint16_t));
707 /* add us to the top or end of the list */
709 memmove(order + 1, order, n * sizeof(uint16_t));
714 return efi_set_boot_order(order, n + 1);
717 static int remove_from_order(uint16_t slot) {
718 _cleanup_free_ uint16_t *order = NULL;
721 n = efi_get_boot_order(&order);
725 for (i = 0; i < n; i++) {
726 if (order[i] != slot)
730 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
731 return efi_set_boot_order(order, n - 1);
737 static int install_variables(const char *esp_path,
738 uint32_t part, uint64_t pstart, uint64_t psize,
739 sd_id128_t uuid, const char *path,
745 if (!is_efi_boot()) {
746 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
750 p = strjoina(esp_path, path);
751 if (access(p, F_OK) < 0) {
755 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
758 r = find_slot(uuid, path, &slot);
760 return log_error_errno(r,
762 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
763 "Failed to determine current boot order
: %m
");
765 if (first || r == false) {
766 r = efi_add_boot_option(slot, "Linux Boot Manager
",
770 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
772 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
775 return insert_into_order(slot, first);
778 static int remove_boot_efi(const char *esp_path) {
780 _cleanup_closedir_ DIR *d = NULL;
784 p = strjoina(esp_path, "/EFI
/BOOT
");
790 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
793 FOREACH_DIRENT(de, d, break) {
794 _cleanup_close_ int fd = -1;
795 _cleanup_free_ char *v = NULL;
797 if (!endswith_no_case(de->d_name, ".efi
"))
800 if (!startswith_no_case(de->d_name, "boot
"))
803 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
805 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
807 r = get_file_version(fd, &v);
810 if (r > 0 && startswith(v, "systemd
-boot
")) {
811 r = unlinkat(dirfd(d), de->d_name, 0);
813 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
815 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
824 static int rmdir_one(const char *prefix, const char *suffix) {
827 p = strjoina(prefix, "/", suffix);
829 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
830 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
832 log_info("Removed
\"%s
\".", p);
837 static int remove_binaries(const char *esp_path) {
842 p = strjoina(esp_path, "/EFI
/systemd
");
843 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
845 q = remove_boot_efi(esp_path);
849 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
850 q = rmdir_one(esp_path, efi_subdirs[i-1]);
858 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
865 r = find_slot(uuid, path, &slot);
869 r = efi_remove_boot_option(slot);
874 return remove_from_order(slot);
879 static int install_loader_config(const char *esp_path) {
882 char *machine = NULL;
883 _cleanup_fclose_ FILE *f = NULL, *g = NULL;
885 f = fopen("/etc
/machine
-id
", "re
");
887 return errno == ENOENT ? 0 : -errno;
889 if (fgets(line, sizeof(line), f) != NULL) {
892 s = strchr(line, '\n');
895 if (strlen(line) == 32)
902 p = strjoina(esp_path, "/loader
/loader
.conf
");
905 fprintf(g, "#timeout 3\n");
906 fprintf(g, "default %s-*\n", machine);
908 return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
914 static int help(void) {
915 printf("%s [COMMAND] [OPTIONS...]\n"
917 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
918 " -h --help Show this help\n"
919 " --version Print version\n"
920 " --path=PATH Path to the EFI System Partition (ESP)\n"
921 " --no-variables Don't touch EFI variables\n"
924 " status Show status of installed systemd-boot and EFI variables\n"
925 " install Install systemd-boot to the ESP and EFI variables\n"
926 " update Update systemd-boot in the ESP and EFI variables\n"
927 " remove Remove systemd-boot from the ESP and EFI variables\n",
928 program_invocation_short_name);
933 static const char *arg_path = "/boot";
934 static bool arg_touch_variables = true;
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) {
1039 case ACTION_STATUS: {
1040 _cleanup_free_ char *fw_type = NULL;
1041 _cleanup_free_ char *fw_info = NULL;
1042 _cleanup_free_ char *loader = NULL;
1043 _cleanup_free_ char *loader_path = NULL;
1044 sd_id128_t loader_part_uuid = {};
1046 if (is_efi_boot()) {
1047 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1048 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1049 read_loader_efi_var("LoaderInfo", &loader);
1050 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1052 efi_tilt_backslashes(loader_path);
1053 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1054 if (r < 0 && r == -ENOENT)
1055 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1057 printf("System:\n");
1058 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1060 r = is_efi_secure_boot();
1062 log_warning_errno(r, "Failed to query secure boot status: %m");
1064 printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
1066 r = is_efi_secure_boot_setup_mode();
1068 log_warning_errno(r, "Failed to query secure boot mode: %m");
1070 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1073 printf("Loader:\n");
1074 printf(" Product: %s\n", strna(loader));
1075 if (!sd_id128_equal(loader_part_uuid, SD_ID128_NULL))
1076 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1077 SD_ID128_FORMAT_VAL(loader_part_uuid));
1079 printf(" Partition: n/a\n");
1080 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1083 printf("System:\n Not booted with EFI\n");
1085 r = status_binaries(arg_path, uuid);
1089 if (arg_touch_variables)
1090 r = status_variables();
1094 case ACTION_INSTALL:
1098 r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
1102 if (arg_action == ACTION_INSTALL) {
1103 r = install_loader_config(arg_path);
1108 if (arg_touch_variables)
1109 r = install_variables(arg_path,
1110 part, pstart, psize, uuid,
1111 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1112 arg_action == ACTION_INSTALL);
1116 r = remove_binaries(arg_path);
1118 if (arg_touch_variables) {
1119 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1120 if (q < 0 && r == 0)
1129 int main(int argc, char *argv[]) {
1132 log_parse_environment();
1135 r = parse_argv(argc, argv);
1139 r = bootctl_main(argc, argv);
1142 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;