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
[] = {
628 static int create_dirs(const char *esp_path
) {
632 STRV_FOREACH(i
, efi_subdirs
) {
633 r
= mkdir_one(esp_path
, *i
);
641 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
645 p
= strjoina(BOOTLIBDIR
"/", name
);
646 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
647 r
= copy_file(p
, q
, force
);
649 if (startswith(name
, "systemd-boot")) {
653 /* Create the EFI default boot loader name (specified for removable devices) */
654 v
= strjoina(esp_path
, "/EFI/BOOT/BOOT", name
+ strlen("systemd-boot"));
655 ascii_strupper(strrchr(v
, '/') + 1);
657 k
= copy_file(p
, v
, force
);
665 static int install_binaries(const char *esp_path
, bool force
) {
667 _cleanup_closedir_
DIR *d
= NULL
;
671 /* Don't create any of these directories when we are
672 * just updating. When we update we'll drop-in our
673 * files (unless there are newer ones already), but we
674 * won't create the directories for them in the first
676 r
= create_dirs(esp_path
);
681 d
= opendir(BOOTLIBDIR
);
683 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
685 FOREACH_DIRENT(de, d, break) {
688 if (!endswith_no_case(de->d_name, ".efi
"))
691 k = copy_one_file(esp_path, de->d_name, force);
699 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
700 _cleanup_free_ char *opath = NULL;
704 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
707 if (!sd_id128_equal(uuid, ouuid))
709 if (!streq_ptr(path, opath))
715 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
716 _cleanup_free_ uint16_t *options = NULL;
719 n = efi_get_boot_options(&options);
723 /* find already existing systemd-boot entry */
724 for (i = 0; i < n; i++)
725 if (same_entry(options[i], uuid, path)) {
730 /* find free slot in the sorted BootXXXX variable list */
731 for (i = 0; i < n; i++)
732 if (i != options[i]) {
737 /* use the next one */
744 static int insert_into_order(uint16_t slot, bool first) {
745 _cleanup_free_ uint16_t *order = NULL;
749 n = efi_get_boot_order(&order);
751 /* no entry, add us */
752 return efi_set_boot_order(&slot, 1);
754 /* are we the first and only one? */
755 if (n == 1 && order[0] == slot)
758 /* are we already in the boot order? */
759 for (i = 0; i < n; i++) {
760 if (order[i] != slot)
763 /* we do not require to be the first one, all is fine */
767 /* move us to the first slot */
768 memmove(order + 1, order, i * sizeof(uint16_t));
770 return efi_set_boot_order(order, n);
774 t = realloc(order, (n + 1) * sizeof(uint16_t));
779 /* add us to the top or end of the list */
781 memmove(order + 1, order, n * sizeof(uint16_t));
786 return efi_set_boot_order(order, n + 1);
789 static int remove_from_order(uint16_t slot) {
790 _cleanup_free_ uint16_t *order = NULL;
793 n = efi_get_boot_order(&order);
797 for (i = 0; i < n; i++) {
798 if (order[i] != slot)
802 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
803 return efi_set_boot_order(order, n - 1);
809 static int install_variables(const char *esp_path,
810 uint32_t part, uint64_t pstart, uint64_t psize,
811 sd_id128_t uuid, const char *path,
817 if (!is_efi_boot()) {
818 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
822 p = strjoina(esp_path, path);
823 if (access(p, F_OK) < 0) {
827 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
830 r = find_slot(uuid, path, &slot);
832 return log_error_errno(r,
834 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
835 "Failed to determine current boot order
: %m
");
837 if (first || r == 0) {
838 r = efi_add_boot_option(slot, "Linux Boot Manager
",
842 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
844 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
847 return insert_into_order(slot, first);
850 static int remove_boot_efi(const char *esp_path) {
852 _cleanup_closedir_ DIR *d = NULL;
856 p = strjoina(esp_path, "/EFI
/BOOT
");
862 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
865 FOREACH_DIRENT(de, d, break) {
866 _cleanup_close_ int fd = -1;
867 _cleanup_free_ char *v = NULL;
869 if (!endswith_no_case(de->d_name, ".efi
"))
872 if (!startswith_no_case(de->d_name, "boot
"))
875 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
877 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
879 r = get_file_version(fd, &v);
882 if (r > 0 && startswith(v, "systemd
-boot
")) {
883 r = unlinkat(dirfd(d), de->d_name, 0);
885 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
887 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
896 static int rmdir_one(const char *prefix, const char *suffix) {
899 p = strjoina(prefix, "/", suffix);
901 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
902 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
904 log_info("Removed
\"%s
\".", p);
909 static int remove_binaries(const char *esp_path) {
914 p = strjoina(esp_path, "/EFI
/systemd
");
915 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
917 q = remove_boot_efi(esp_path);
921 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
922 q = rmdir_one(esp_path, efi_subdirs[i-1]);
930 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
937 r = find_slot(uuid, path, &slot);
941 r = efi_remove_boot_option(slot);
946 return remove_from_order(slot);
951 static int install_loader_config(const char *esp_path) {
953 _cleanup_fclose_ FILE *f = NULL;
954 char machine_string[SD_ID128_STRING_MAX];
955 sd_id128_t machine_id;
959 r = sd_id128_get_machine(&machine_id);
961 return log_error_errno(r, "Failed to get machine did
: %m
");
963 p = strjoina(esp_path, "/loader
/loader
.conf
");
966 return log_error_errno(errno, "Failed to open loader
.conf
for writing
: %m
");
968 fprintf(f, "#timeout 3\n");
969 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
971 r = fflush_and_check(f);
973 return log_error_errno(r, "Failed to write \"%s\": %m", p);
978 static int help(int argc, char *argv[], void *userdata) {
980 printf("%s [COMMAND] [OPTIONS...]\n"
982 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
983 " -h --help Show this help\n"
984 " --version Print version\n"
985 " --path=PATH Path to the EFI System Partition (ESP)\n"
986 " --no-variables Don't touch EFI variables\n"
989 " status Show status of installed systemd-boot and EFI variables\n"
990 " install Install systemd-boot to the ESP and EFI variables\n"
991 " update Update systemd-boot in the ESP and EFI variables\n"
992 " remove Remove systemd-boot from the ESP and EFI variables\n",
993 program_invocation_short_name);
998 static int parse_argv(int argc, char *argv[]) {
1005 static const struct option options[] = {
1006 { "help", no_argument, NULL, 'h' },
1007 { "version", no_argument, NULL, ARG_VERSION },
1008 { "path", required_argument, NULL, ARG_PATH },
1009 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1010 { NULL, 0, NULL, 0 }
1018 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1022 help(0, NULL, NULL);
1029 r = free_and_strdup(&arg_path, optarg);
1034 case ARG_NO_VARIABLES:
1035 arg_touch_variables = false;
1042 assert_not_reached("Unknown option");
1048 static void read_loader_efi_var(const char *name, char **var) {
1051 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
1052 if (r < 0 && r != -ENOENT)
1053 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1056 static int must_be_root(void) {
1061 log_error("Need to be root.");
1065 static int verb_status(int argc, char *argv[], void *userdata) {
1067 sd_id128_t uuid = SD_ID128_NULL;
1074 r = find_esp(NULL, NULL, NULL, &uuid);
1078 if (is_efi_boot()) {
1079 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1080 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1082 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1083 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1084 read_loader_efi_var("LoaderInfo", &loader);
1085 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1088 efi_tilt_backslashes(loader_path);
1090 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1091 if (r < 0 && r != -ENOENT)
1092 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1094 printf("System:\n");
1095 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1097 r = is_efi_secure_boot();
1099 log_warning_errno(r, "Failed to query secure boot status: %m");
1101 printf(" Secure Boot: %sd\n", enable_disable(r));
1103 r = is_efi_secure_boot_setup_mode();
1105 log_warning_errno(r, "Failed to query secure boot mode: %m");
1107 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1110 printf("Loader:\n");
1111 printf(" Product: %s\n", strna(loader));
1112 if (!sd_id128_is_null(loader_part_uuid))
1113 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1114 SD_ID128_FORMAT_VAL(loader_part_uuid));
1116 printf(" Partition: n/a\n");
1117 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1120 printf("System:\n Not booted with EFI\n");
1122 r = status_binaries(arg_path, uuid);
1126 if (arg_touch_variables)
1127 r = status_variables();
1132 static int verb_install(int argc, char *argv[], void *userdata) {
1134 sd_id128_t uuid = SD_ID128_NULL;
1135 uint64_t pstart = 0, psize = 0;
1144 r = find_esp(&part, &pstart, &psize, &uuid);
1148 install = streq(argv[0], "install");
1150 RUN_WITH_UMASK(0002) {
1151 r = install_binaries(arg_path, install);
1156 r = install_loader_config(arg_path);
1162 if (arg_touch_variables)
1163 r = install_variables(arg_path,
1164 part, pstart, psize, uuid,
1165 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1171 static int verb_remove(int argc, char *argv[], void *userdata) {
1172 sd_id128_t uuid = SD_ID128_NULL;
1179 r = find_esp(NULL, NULL, NULL, &uuid);
1183 r = remove_binaries(arg_path);
1185 if (arg_touch_variables) {
1188 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1189 if (q < 0 && r == 0)
1196 static int bootctl_main(int argc, char *argv[]) {
1198 static const Verb verbs[] = {
1199 { "help", VERB_ANY, VERB_ANY, 0, help },
1200 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1201 { "install", VERB_ANY, 1, 0, verb_install },
1202 { "update", VERB_ANY, 1, 0, verb_install },
1203 { "remove", VERB_ANY, 1, 0, verb_remove },
1207 return dispatch_verb(argc, argv, verbs, NULL);
1210 int main(int argc, char *argv[]) {
1213 log_parse_environment();
1216 /* If we run in a container, automatically turn of EFI file system access */
1217 if (detect_container() > 0)
1218 arg_touch_variables = false;
1220 r = parse_argv(argc, argv);
1224 r = bootctl_main(argc, argv);
1228 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;