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>
29 #include <linux/magic.h>
36 #include <sys/statfs.h>
39 #include "alloc-util.h"
40 #include "blkid-util.h"
41 #include "dirent-util.h"
45 #include "locale-util.h"
46 #include "parse-util.h"
48 #include "string-util.h"
50 #include "umask-util.h"
54 #include "stat-util.h"
56 static char *arg_path
= NULL
;
57 static bool arg_touch_variables
= true;
59 static int verify_esp(
65 sd_id128_t
*ret_uuid
) {
67 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
68 _cleanup_free_
char *t
= NULL
;
69 uint64_t pstart
= 0, psize
= 0;
73 sd_id128_t uuid
= SD_ID128_NULL
;
79 if (statfs(p
, &sfs
) < 0) {
81 /* If we are searching for the mount point, don't generate a log message if we can't find the path */
82 if (errno
== ENOENT
&& searching
)
85 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
88 if (!F_TYPE_EQUAL(sfs
.f_type
, MSDOS_SUPER_MAGIC
)) {
91 return -EADDRNOTAVAIL
;
93 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
98 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
100 if (major(st
.st_dev
) == 0) {
101 log_error("Block device node of %p is invalid.", p
);
105 t2
= strjoina(p
, "/..");
108 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
110 if (st
.st_dev
== st2
.st_dev
) {
111 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
115 /* In a container we don't have access to block devices, skip this part of the verification, we trust the
116 * container manager set everything up correctly on its own. */
117 if (detect_container() > 0)
120 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
125 b
= blkid_new_probe_from_filename(t
);
130 return log_error_errno(errno
, "Failed to open file system \"%s\": %m", p
);
133 blkid_probe_enable_superblocks(b
, 1);
134 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
135 blkid_probe_enable_partitions(b
, 1);
136 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
139 r
= blkid_do_safeprobe(b
);
141 log_error("File system \"%s\" is ambiguous.", p
);
144 log_error("File system \"%s\" does not contain a label.", p
);
147 r
= errno
? -errno
: -EIO
;
148 return log_error_errno(r
, "Failed to probe file system \"%s\": %m", p
);
152 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
154 r
= errno
? -errno
: -EIO
;
155 return log_error_errno(r
, "Failed to probe file system type \"%s\": %m", p
);
157 if (!streq(v
, "vfat")) {
158 log_error("File system \"%s\" is not FAT.", p
);
163 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
165 r
= errno
? -errno
: -EIO
;
166 return log_error_errno(r
, "Failed to probe partition scheme \"%s\": %m", p
);
168 if (!streq(v
, "gpt")) {
169 log_error("File system \"%s\" is not on a GPT partition table.", p
);
174 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
176 r
= errno
? -errno
: -EIO
;
177 return log_error_errno(r
, "Failed to probe partition type UUID \"%s\": %m", p
);
179 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
180 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
185 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
187 r
= errno
? -errno
: -EIO
;
188 return log_error_errno(r
, "Failed to probe partition entry UUID \"%s\": %m", p
);
190 r
= sd_id128_from_string(v
, &uuid
);
192 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
197 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
199 r
= errno
? -errno
: -EIO
;
200 return log_error_errno(r
, "Failed to probe partition number \"%s\": m", p
);
202 r
= safe_atou32(v
, &part
);
204 return log_error_errno(r
, "Failed to parse PART_ENTRY_NUMBER field.");
207 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
209 r
= errno
? -errno
: -EIO
;
210 return log_error_errno(r
, "Failed to probe partition offset \"%s\": %m", p
);
212 r
= safe_atou64(v
, &pstart
);
214 return log_error_errno(r
, "Failed to parse PART_ENTRY_OFFSET field.");
217 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
219 r
= errno
? -errno
: -EIO
;
220 return log_error_errno(r
, "Failed to probe partition size \"%s\": %m", p
);
222 r
= safe_atou64(v
, &psize
);
224 return log_error_errno(r
, "Failed to parse PART_ENTRY_SIZE field.");
230 *ret_pstart
= pstart
;
239 static int find_esp(uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
244 return verify_esp(false, arg_path
, part
, pstart
, psize
, uuid
);
246 FOREACH_STRING(path
, "/efi", "/boot", "/boot/efi") {
248 r
= verify_esp(true, path
, part
, pstart
, psize
, uuid
);
249 if (IN_SET(r
, -ENOENT
, -EADDRNOTAVAIL
)) /* This one is not it */
254 arg_path
= strdup(path
);
258 log_info("Using EFI System Parition at %s.", path
);
262 log_error("Couldn't find EFI system partition. It is recommended to mount it to /boot. Alternatively, use --path= to specify path to mount point.");
266 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
267 static int get_file_version(int fd
, char **v
) {
277 if (fstat(fd
, &st
) < 0)
278 return log_error_errno(errno
, "Failed to stat EFI binary: %m");
280 if (st
.st_size
< 27) {
285 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
286 if (buf
== MAP_FAILED
)
287 return log_error_errno(errno
, "Failed to memory map EFI binary: %m");
289 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
294 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
295 if (!e
|| e
- s
< 3) {
296 log_error("Malformed version string.");
301 x
= strndup(s
, e
- s
);
309 (void) munmap(buf
, st
.st_size
);
314 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
316 _cleanup_closedir_
DIR *d
= NULL
;
320 p
= strjoina(esp_path
, "/", path
);
326 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
329 FOREACH_DIRENT(de
, d
, break) {
330 _cleanup_close_
int fd
= -1;
331 _cleanup_free_
char *v
= NULL
;
333 if (!endswith_no_case(de
->d_name
, ".efi"))
336 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
339 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
341 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
343 r
= get_file_version(fd
, &v
);
347 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
, v
);
349 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
);
356 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
359 printf("Boot Loader Binaries:\n");
361 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
));
363 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
365 log_error("systemd-boot not installed in ESP.");
369 r
= enumerate_binaries(esp_path
, "EFI/BOOT", "boot");
371 log_error("No default/fallback boot loader installed in ESP.");
380 static int print_efi_option(uint16_t id
, bool in_order
) {
381 _cleanup_free_
char *title
= NULL
;
382 _cleanup_free_
char *path
= NULL
;
383 sd_id128_t partition
;
387 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
391 /* print only configured entries with partition information */
392 if (!path
|| sd_id128_is_null(partition
))
395 efi_tilt_backslashes(path
);
397 printf(" Title: %s\n", strna(title
));
398 printf(" ID: 0x%04X\n", id
);
399 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
400 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
));
401 printf(" File: %s%s\n", special_glyph(TREE_RIGHT
), path
);
407 static int status_variables(void) {
408 int n_options
, n_order
;
409 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
412 if (!is_efi_boot()) {
413 log_notice("Not booted with EFI, not showing EFI variables.");
417 n_options
= efi_get_boot_options(&options
);
418 if (n_options
== -ENOENT
)
419 return log_error_errno(n_options
,
420 "Failed to access EFI variables, efivarfs"
421 " needs to be available at /sys/firmware/efi/efivars/.");
423 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
425 n_order
= efi_get_boot_order(&order
);
426 if (n_order
== -ENOENT
)
428 else if (n_order
< 0)
429 return log_error_errno(n_order
, "Failed to read EFI boot order.");
431 /* print entries in BootOrder first */
432 printf("Boot Loader Entries in EFI Variables:\n");
433 for (i
= 0; i
< n_order
; i
++)
434 print_efi_option(order
[i
], true);
436 /* print remaining entries */
437 for (i
= 0; i
< n_options
; i
++) {
440 for (j
= 0; j
< n_order
; j
++)
441 if (options
[i
] == order
[j
])
444 print_efi_option(options
[i
], false);
453 static int compare_product(const char *a
, const char *b
) {
462 return x
< y
? -1 : x
> y
? 1 : 0;
464 return strncmp(a
, b
, x
);
467 static int compare_version(const char *a
, const char *b
) {
471 a
+= strcspn(a
, " ");
473 b
+= strcspn(b
, " ");
476 return strverscmp(a
, b
);
479 static int version_check(int fd
, const char *from
, const char *to
) {
480 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
481 _cleanup_close_
int fd2
= -1;
488 r
= get_file_version(fd
, &a
);
492 log_error("Source file \"%s\" does not carry version information!", from
);
496 fd2
= open(to
, O_RDONLY
|O_CLOEXEC
);
501 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
504 r
= get_file_version(fd2
, &b
);
507 if (r
== 0 || compare_product(a
, b
) != 0) {
508 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
512 if (compare_version(a
, b
) < 0) {
513 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
520 static int copy_file(const char *from
, const char *to
, bool force
) {
521 _cleanup_fclose_
FILE *f
= NULL
, *g
= NULL
;
524 struct timespec t
[2];
530 f
= fopen(from
, "re");
532 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
535 /* If this is an update, then let's compare versions first */
536 r
= version_check(fileno(f
), from
, to
);
541 p
= strjoina(to
, "~");
544 /* Directory doesn't exist yet? Then let's skip this... */
545 if (!force
&& errno
== ENOENT
)
548 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", to
);
554 uint8_t buf
[32*1024];
556 k
= fread(buf
, 1, sizeof(buf
), f
);
558 r
= log_error_errno(EIO
, "Failed to read \"%s\": %m", from
);
565 fwrite(buf
, 1, k
, g
);
567 r
= log_error_errno(EIO
, "Failed to write \"%s\": %m", to
);
572 r
= fflush_and_check(g
);
574 log_error_errno(r
, "Failed to write \"%s\": %m", to
);
578 r
= fstat(fileno(f
), &st
);
580 r
= log_error_errno(errno
, "Failed to get file timestamps of \"%s\": %m", from
);
587 r
= futimens(fileno(g
), t
);
589 r
= log_error_errno(errno
, "Failed to set file timestamps on \"%s\": %m", p
);
593 if (rename(p
, to
) < 0) {
594 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", p
, to
);
598 log_info("Copied \"%s\" to \"%s\".", from
, to
);
606 static int mkdir_one(const char *prefix
, const char *suffix
) {
609 p
= strjoina(prefix
, "/", suffix
);
610 if (mkdir(p
, 0700) < 0) {
612 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
614 log_info("Created \"%s\".", p
);
619 static const char *efi_subdirs
[] = {
627 static int create_dirs(const char *esp_path
) {
631 STRV_FOREACH(i
, efi_subdirs
) {
632 r
= mkdir_one(esp_path
, *i
);
640 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
644 p
= strjoina(BOOTLIBDIR
"/", name
);
645 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
646 r
= copy_file(p
, q
, force
);
648 if (startswith(name
, "systemd-boot")) {
652 /* Create the EFI default boot loader name (specified for removable devices) */
653 v
= strjoina(esp_path
, "/EFI/BOOT/BOOT", name
+ strlen("systemd-boot"));
654 ascii_strupper(strrchr(v
, '/') + 1);
656 k
= copy_file(p
, v
, force
);
664 static int install_binaries(const char *esp_path
, bool force
) {
666 _cleanup_closedir_
DIR *d
= NULL
;
670 /* Don't create any of these directories when we are
671 * just updating. When we update we'll drop-in our
672 * files (unless there are newer ones already), but we
673 * won't create the directories for them in the first
675 r
= create_dirs(esp_path
);
680 d
= opendir(BOOTLIBDIR
);
682 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
684 FOREACH_DIRENT(de, d, break) {
687 if (!endswith_no_case(de->d_name, ".efi
"))
690 k = copy_one_file(esp_path, de->d_name, force);
698 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
699 _cleanup_free_ char *opath = NULL;
703 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
706 if (!sd_id128_equal(uuid, ouuid))
708 if (!streq_ptr(path, opath))
714 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
715 _cleanup_free_ uint16_t *options = NULL;
718 n = efi_get_boot_options(&options);
722 /* find already existing systemd-boot entry */
723 for (i = 0; i < n; i++)
724 if (same_entry(options[i], uuid, path)) {
729 /* find free slot in the sorted BootXXXX variable list */
730 for (i = 0; i < n; i++)
731 if (i != options[i]) {
736 /* use the next one */
743 static int insert_into_order(uint16_t slot, bool first) {
744 _cleanup_free_ uint16_t *order = NULL;
748 n = efi_get_boot_order(&order);
750 /* no entry, add us */
751 return efi_set_boot_order(&slot, 1);
753 /* are we the first and only one? */
754 if (n == 1 && order[0] == slot)
757 /* are we already in the boot order? */
758 for (i = 0; i < n; i++) {
759 if (order[i] != slot)
762 /* we do not require to be the first one, all is fine */
766 /* move us to the first slot */
767 memmove(order + 1, order, i * sizeof(uint16_t));
769 return efi_set_boot_order(order, n);
773 t = realloc(order, (n + 1) * sizeof(uint16_t));
778 /* add us to the top or end of the list */
780 memmove(order + 1, order, n * sizeof(uint16_t));
785 return efi_set_boot_order(order, n + 1);
788 static int remove_from_order(uint16_t slot) {
789 _cleanup_free_ uint16_t *order = NULL;
792 n = efi_get_boot_order(&order);
796 for (i = 0; i < n; i++) {
797 if (order[i] != slot)
801 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
802 return efi_set_boot_order(order, n - 1);
808 static int install_variables(const char *esp_path,
809 uint32_t part, uint64_t pstart, uint64_t psize,
810 sd_id128_t uuid, const char *path,
816 if (!is_efi_boot()) {
817 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
821 p = strjoina(esp_path, path);
822 if (access(p, F_OK) < 0) {
826 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
829 r = find_slot(uuid, path, &slot);
831 return log_error_errno(r,
833 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
834 "Failed to determine current boot order
: %m
");
836 if (first || r == 0) {
837 r = efi_add_boot_option(slot, "Linux Boot Manager
",
841 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
843 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
846 return insert_into_order(slot, first);
849 static int remove_boot_efi(const char *esp_path) {
851 _cleanup_closedir_ DIR *d = NULL;
855 p = strjoina(esp_path, "/EFI
/BOOT
");
861 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
864 FOREACH_DIRENT(de, d, break) {
865 _cleanup_close_ int fd = -1;
866 _cleanup_free_ char *v = NULL;
868 if (!endswith_no_case(de->d_name, ".efi
"))
871 if (!startswith_no_case(de->d_name, "boot
"))
874 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
876 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
878 r = get_file_version(fd, &v);
881 if (r > 0 && startswith(v, "systemd
-boot
")) {
882 r = unlinkat(dirfd(d), de->d_name, 0);
884 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
886 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
895 static int rmdir_one(const char *prefix, const char *suffix) {
898 p = strjoina(prefix, "/", suffix);
900 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
901 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
903 log_info("Removed
\"%s
\".", p);
908 static int remove_binaries(const char *esp_path) {
913 p = strjoina(esp_path, "/EFI
/systemd
");
914 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
916 q = remove_boot_efi(esp_path);
920 for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
921 q = rmdir_one(esp_path, efi_subdirs[i-1]);
929 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
936 r = find_slot(uuid, path, &slot);
940 r = efi_remove_boot_option(slot);
945 return remove_from_order(slot);
950 static int install_loader_config(const char *esp_path) {
952 _cleanup_fclose_ FILE *f = NULL;
953 char machine_string[SD_ID128_STRING_MAX];
954 sd_id128_t machine_id;
958 r = sd_id128_get_machine(&machine_id);
960 return log_error_errno(r, "Failed to get machine did
: %m
");
962 p = strjoina(esp_path, "/loader
/loader
.conf
");
965 return log_error_errno(errno, "Failed to open loader
.conf
for writing
: %m
");
967 fprintf(f, "#timeout 3\n");
968 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
970 r = fflush_and_check(f);
972 return log_error_errno(r, "Failed to write \"%s\": %m", p);
977 static int help(int argc, char *argv[], void *userdata) {
979 printf("%s [COMMAND] [OPTIONS...]\n"
981 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
982 " -h --help Show this help\n"
983 " --version Print version\n"
984 " --path=PATH Path to the EFI System Partition (ESP)\n"
985 " --no-variables Don't touch EFI variables\n"
988 " status Show status of installed systemd-boot and EFI variables\n"
989 " install Install systemd-boot to the ESP and EFI variables\n"
990 " update Update systemd-boot in the ESP and EFI variables\n"
991 " remove Remove systemd-boot from the ESP and EFI variables\n",
992 program_invocation_short_name);
997 static int parse_argv(int argc, char *argv[]) {
1004 static const struct option options[] = {
1005 { "help", no_argument, NULL, 'h' },
1006 { "version", no_argument, NULL, ARG_VERSION },
1007 { "path", required_argument, NULL, ARG_PATH },
1008 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1009 { NULL, 0, NULL, 0 }
1017 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1021 help(0, NULL, NULL);
1028 r = free_and_strdup(&arg_path, optarg);
1033 case ARG_NO_VARIABLES:
1034 arg_touch_variables = false;
1041 assert_not_reached("Unknown option");
1047 static void read_loader_efi_var(const char *name, char **var) {
1050 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
1051 if (r < 0 && r != -ENOENT)
1052 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1055 static int must_be_root(void) {
1060 log_error("Need to be root.");
1064 static int verb_status(int argc, char *argv[], void *userdata) {
1066 sd_id128_t uuid = SD_ID128_NULL;
1073 r = find_esp(NULL, NULL, NULL, &uuid);
1077 if (is_efi_boot()) {
1078 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1079 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1081 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1082 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1083 read_loader_efi_var("LoaderInfo", &loader);
1084 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1087 efi_tilt_backslashes(loader_path);
1089 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1090 if (r < 0 && r != -ENOENT)
1091 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1093 printf("System:\n");
1094 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1096 r = is_efi_secure_boot();
1098 log_warning_errno(r, "Failed to query secure boot status: %m");
1100 printf(" Secure Boot: %sd\n", enable_disable(r));
1102 r = is_efi_secure_boot_setup_mode();
1104 log_warning_errno(r, "Failed to query secure boot mode: %m");
1106 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1109 printf("Loader:\n");
1110 printf(" Product: %s\n", strna(loader));
1111 if (!sd_id128_is_null(loader_part_uuid))
1112 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1113 SD_ID128_FORMAT_VAL(loader_part_uuid));
1115 printf(" Partition: n/a\n");
1116 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1119 printf("System:\n Not booted with EFI\n");
1121 r = status_binaries(arg_path, uuid);
1125 if (arg_touch_variables)
1126 r = status_variables();
1131 static int verb_install(int argc, char *argv[], void *userdata) {
1133 sd_id128_t uuid = SD_ID128_NULL;
1134 uint64_t pstart = 0, psize = 0;
1143 r = find_esp(&part, &pstart, &psize, &uuid);
1147 install = streq(argv[0], "install");
1149 RUN_WITH_UMASK(0002) {
1150 r = install_binaries(arg_path, install);
1155 r = install_loader_config(arg_path);
1161 if (arg_touch_variables)
1162 r = install_variables(arg_path,
1163 part, pstart, psize, uuid,
1164 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1170 static int verb_remove(int argc, char *argv[], void *userdata) {
1171 sd_id128_t uuid = SD_ID128_NULL;
1178 r = find_esp(NULL, NULL, NULL, &uuid);
1182 r = remove_binaries(arg_path);
1184 if (arg_touch_variables) {
1187 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1188 if (q < 0 && r == 0)
1195 static int bootctl_main(int argc, char *argv[]) {
1197 static const Verb verbs[] = {
1198 { "help", VERB_ANY, VERB_ANY, 0, help },
1199 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1200 { "install", VERB_ANY, 1, 0, verb_install },
1201 { "update", VERB_ANY, 1, 0, verb_install },
1202 { "remove", VERB_ANY, 1, 0, verb_remove },
1206 return dispatch_verb(argc, argv, verbs, NULL);
1209 int main(int argc, char *argv[]) {
1212 log_parse_environment();
1215 /* If we run in a container, automatically turn of EFI file system access */
1216 if (detect_container() > 0)
1217 arg_touch_variables = false;
1219 r = parse_argv(argc, argv);
1223 r = bootctl_main(argc, argv);
1227 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;