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/>.
28 #include <linux/magic.h>
35 #include <sys/statfs.h>
38 #include "alloc-util.h"
39 #include "blkid-util.h"
41 #include "dirent-util.h"
46 #include "locale-util.h"
47 #include "parse-util.h"
49 #include "stat-util.h"
50 #include "string-util.h"
52 #include "umask-util.h"
57 static char *arg_path
= NULL
;
58 static bool arg_touch_variables
= true;
60 static int verify_esp(
66 sd_id128_t
*ret_uuid
) {
68 _cleanup_blkid_free_probe_ blkid_probe b
= NULL
;
69 _cleanup_free_
char *t
= NULL
;
70 uint64_t pstart
= 0, psize
= 0;
74 sd_id128_t uuid
= SD_ID128_NULL
;
80 if (statfs(p
, &sfs
) < 0) {
82 /* If we are searching for the mount point, don't generate a log message if we can't find the path */
83 if (errno
== ENOENT
&& searching
)
86 return log_error_errno(errno
, "Failed to check file system type of \"%s\": %m", p
);
89 if (!F_TYPE_EQUAL(sfs
.f_type
, MSDOS_SUPER_MAGIC
)) {
92 return -EADDRNOTAVAIL
;
94 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p
);
99 return log_error_errno(errno
, "Failed to determine block device node of \"%s\": %m", p
);
101 if (major(st
.st_dev
) == 0) {
102 log_error("Block device node of %p is invalid.", p
);
106 t2
= strjoina(p
, "/..");
109 return log_error_errno(errno
, "Failed to determine block device node of parent of \"%s\": %m", p
);
111 if (st
.st_dev
== st2
.st_dev
) {
112 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p
);
116 /* In a container we don't have access to block devices, skip this part of the verification, we trust the
117 * container manager set everything up correctly on its own. */
118 if (detect_container() > 0)
121 r
= asprintf(&t
, "/dev/block/%u:%u", major(st
.st_dev
), minor(st
.st_dev
));
126 b
= blkid_new_probe_from_filename(t
);
128 return log_error_errno(errno
?: ENOMEM
, "Failed to open file system \"%s\": %m", p
);
130 blkid_probe_enable_superblocks(b
, 1);
131 blkid_probe_set_superblocks_flags(b
, BLKID_SUBLKS_TYPE
);
132 blkid_probe_enable_partitions(b
, 1);
133 blkid_probe_set_partitions_flags(b
, BLKID_PARTS_ENTRY_DETAILS
);
136 r
= blkid_do_safeprobe(b
);
138 log_error("File system \"%s\" is ambiguous.", p
);
141 log_error("File system \"%s\" does not contain a label.", p
);
144 return log_error_errno(errno
?: EIO
, "Failed to probe file system \"%s\": %m", p
);
147 r
= blkid_probe_lookup_value(b
, "TYPE", &v
, NULL
);
149 return log_error_errno(errno
?: EIO
, "Failed to probe file system type \"%s\": %m", p
);
150 if (!streq(v
, "vfat")) {
151 log_error("File system \"%s\" is not FAT.", p
);
156 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SCHEME", &v
, NULL
);
158 return log_error_errno(errno
?: EIO
, "Failed to probe partition scheme \"%s\": %m", p
);
159 if (!streq(v
, "gpt")) {
160 log_error("File system \"%s\" is not on a GPT partition table.", p
);
165 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_TYPE", &v
, NULL
);
167 return log_error_errno(errno
?: EIO
, "Failed to probe partition type UUID \"%s\": %m", p
);
168 if (!streq(v
, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
169 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p
);
174 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_UUID", &v
, NULL
);
176 return log_error_errno(errno
?: EIO
, "Failed to probe partition entry UUID \"%s\": %m", p
);
177 r
= sd_id128_from_string(v
, &uuid
);
179 log_error("Partition \"%s\" has invalid UUID \"%s\".", p
, v
);
184 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_NUMBER", &v
, NULL
);
186 return log_error_errno(errno
?: EIO
, "Failed to probe partition number \"%s\": m", p
);
187 r
= safe_atou32(v
, &part
);
189 return log_error_errno(r
, "Failed to parse PART_ENTRY_NUMBER field.");
192 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_OFFSET", &v
, NULL
);
194 return log_error_errno(errno
?: EIO
, "Failed to probe partition offset \"%s\": %m", p
);
195 r
= safe_atou64(v
, &pstart
);
197 return log_error_errno(r
, "Failed to parse PART_ENTRY_OFFSET field.");
200 r
= blkid_probe_lookup_value(b
, "PART_ENTRY_SIZE", &v
, NULL
);
202 return log_error_errno(errno
?: EIO
, "Failed to probe partition size \"%s\": %m", p
);
203 r
= safe_atou64(v
, &psize
);
205 return log_error_errno(r
, "Failed to parse PART_ENTRY_SIZE field.");
211 *ret_pstart
= pstart
;
220 static int find_esp(uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
225 return verify_esp(false, arg_path
, part
, pstart
, psize
, uuid
);
227 FOREACH_STRING(path
, "/efi", "/boot", "/boot/efi") {
229 r
= verify_esp(true, path
, part
, pstart
, psize
, uuid
);
230 if (IN_SET(r
, -ENOENT
, -EADDRNOTAVAIL
)) /* This one is not it */
235 arg_path
= strdup(path
);
239 log_info("Using EFI System Partition at %s.", path
);
243 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.");
247 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
248 static int get_file_version(int fd
, char **v
) {
258 if (fstat(fd
, &st
) < 0)
259 return log_error_errno(errno
, "Failed to stat EFI binary: %m");
261 if (st
.st_size
< 27) {
266 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
267 if (buf
== MAP_FAILED
)
268 return log_error_errno(errno
, "Failed to memory map EFI binary: %m");
270 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
275 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
276 if (!e
|| e
- s
< 3) {
277 log_error("Malformed version string.");
282 x
= strndup(s
, e
- s
);
290 (void) munmap(buf
, st
.st_size
);
295 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
297 _cleanup_closedir_
DIR *d
= NULL
;
301 p
= strjoina(esp_path
, "/", path
);
307 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
310 FOREACH_DIRENT(de
, d
, break) {
311 _cleanup_close_
int fd
= -1;
312 _cleanup_free_
char *v
= NULL
;
314 if (!endswith_no_case(de
->d_name
, ".efi"))
317 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
320 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
322 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
324 r
= get_file_version(fd
, &v
);
328 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
, v
);
330 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
);
337 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
340 printf("Boot Loader Binaries:\n");
342 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
));
344 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
346 log_error("systemd-boot not installed in ESP.");
350 r
= enumerate_binaries(esp_path
, "EFI/BOOT", "boot");
352 log_error("No default/fallback boot loader installed in ESP.");
361 static int print_efi_option(uint16_t id
, bool in_order
) {
362 _cleanup_free_
char *title
= NULL
;
363 _cleanup_free_
char *path
= NULL
;
364 sd_id128_t partition
;
368 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
372 /* print only configured entries with partition information */
373 if (!path
|| sd_id128_is_null(partition
))
376 efi_tilt_backslashes(path
);
378 printf(" Title: %s\n", strna(title
));
379 printf(" ID: 0x%04X\n", id
);
380 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
381 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
));
382 printf(" File: %s%s\n", special_glyph(TREE_RIGHT
), path
);
388 static int status_variables(void) {
389 int n_options
, n_order
;
390 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
393 if (!is_efi_boot()) {
394 log_notice("Not booted with EFI, not showing EFI variables.");
398 n_options
= efi_get_boot_options(&options
);
399 if (n_options
== -ENOENT
)
400 return log_error_errno(n_options
,
401 "Failed to access EFI variables, efivarfs"
402 " needs to be available at /sys/firmware/efi/efivars/.");
404 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
406 n_order
= efi_get_boot_order(&order
);
407 if (n_order
== -ENOENT
)
409 else if (n_order
< 0)
410 return log_error_errno(n_order
, "Failed to read EFI boot order.");
412 /* print entries in BootOrder first */
413 printf("Boot Loader Entries in EFI Variables:\n");
414 for (i
= 0; i
< n_order
; i
++)
415 print_efi_option(order
[i
], true);
417 /* print remaining entries */
418 for (i
= 0; i
< n_options
; i
++) {
421 for (j
= 0; j
< n_order
; j
++)
422 if (options
[i
] == order
[j
])
425 print_efi_option(options
[i
], false);
434 static int compare_product(const char *a
, const char *b
) {
443 return x
< y
? -1 : x
> y
? 1 : 0;
445 return strncmp(a
, b
, x
);
448 static int compare_version(const char *a
, const char *b
) {
452 a
+= strcspn(a
, " ");
454 b
+= strcspn(b
, " ");
457 return strverscmp(a
, b
);
460 static int version_check(int fd_from
, const char *from
, int fd_to
, const char *to
) {
461 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
464 assert(fd_from
>= 0);
469 r
= get_file_version(fd_from
, &a
);
473 log_error("Source file \"%s\" does not carry version information!", from
);
477 r
= get_file_version(fd_to
, &b
);
480 if (r
== 0 || compare_product(a
, b
) != 0) {
481 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
485 if (compare_version(a
, b
) < 0) {
486 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
493 static int copy_file_with_version_check(const char *from
, const char *to
, bool force
) {
494 _cleanup_close_
int fd_from
= -1, fd_to
= -1;
495 _cleanup_free_
char *t
= NULL
;
498 fd_from
= open(from
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
500 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
503 fd_to
= open(to
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
505 if (errno
!= -ENOENT
)
506 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
508 r
= version_check(fd_from
, from
, fd_to
, to
);
512 if (lseek(fd_from
, 0, SEEK_SET
) == (off_t
) -1)
513 return log_error_errno(errno
, "Failed to seek in \%s\": %m", from
);
515 fd_to
= safe_close(fd_to
);
519 r
= tempfn_random(to
, NULL
, &t
);
523 RUN_WITH_UMASK(0000) {
524 fd_to
= open(t
, O_WRONLY
|O_CREAT
|O_CLOEXEC
|O_EXCL
|O_NOFOLLOW
, 0644);
526 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", t
);
529 r
= copy_bytes(fd_from
, fd_to
, (uint64_t) -1, COPY_REFLINK
);
532 return log_error_errno(errno
, "Failed to copy data from \"%s\" to \"%s\": %m", from
, t
);
535 (void) copy_times(fd_from
, fd_to
);
537 r
= renameat(AT_FDCWD
, t
, AT_FDCWD
, to
);
539 (void) unlink_noerrno(t
);
540 return log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", t
, to
);
543 log_info("Copied \"%s\" to \"%s\".", from
, to
);
548 static int mkdir_one(const char *prefix
, const char *suffix
) {
551 p
= strjoina(prefix
, "/", suffix
);
552 if (mkdir(p
, 0700) < 0) {
554 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
556 log_info("Created \"%s\".", p
);
561 static const char *efi_subdirs
[] = {
570 static int create_dirs(const char *esp_path
) {
574 STRV_FOREACH(i
, efi_subdirs
) {
575 r
= mkdir_one(esp_path
, *i
);
583 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
587 p
= strjoina(BOOTLIBDIR
"/", name
);
588 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
589 r
= copy_file_with_version_check(p
, q
, force
);
591 if (startswith(name
, "systemd-boot")) {
595 /* Create the EFI default boot loader name (specified for removable devices) */
596 v
= strjoina(esp_path
, "/EFI/BOOT/BOOT", name
+ strlen("systemd-boot"));
597 ascii_strupper(strrchr(v
, '/') + 1);
599 k
= copy_file_with_version_check(p
, v
, force
);
607 static int install_binaries(const char *esp_path
, bool force
) {
609 _cleanup_closedir_
DIR *d
= NULL
;
613 /* Don't create any of these directories when we are
614 * just updating. When we update we'll drop-in our
615 * files (unless there are newer ones already), but we
616 * won't create the directories for them in the first
618 r
= create_dirs(esp_path
);
623 d
= opendir(BOOTLIBDIR
);
625 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
627 FOREACH_DIRENT(de, d, break) {
630 if (!endswith_no_case(de->d_name, ".efi
"))
633 k = copy_one_file(esp_path, de->d_name, force);
641 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
642 _cleanup_free_ char *opath = NULL;
646 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
649 if (!sd_id128_equal(uuid, ouuid))
651 if (!streq_ptr(path, opath))
657 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
658 _cleanup_free_ uint16_t *options = NULL;
661 n = efi_get_boot_options(&options);
665 /* find already existing systemd-boot entry */
666 for (i = 0; i < n; i++)
667 if (same_entry(options[i], uuid, path)) {
672 /* find free slot in the sorted BootXXXX variable list */
673 for (i = 0; i < n; i++)
674 if (i != options[i]) {
679 /* use the next one */
686 static int insert_into_order(uint16_t slot, bool first) {
687 _cleanup_free_ uint16_t *order = NULL;
691 n = efi_get_boot_order(&order);
693 /* no entry, add us */
694 return efi_set_boot_order(&slot, 1);
696 /* are we the first and only one? */
697 if (n == 1 && order[0] == slot)
700 /* are we already in the boot order? */
701 for (i = 0; i < n; i++) {
702 if (order[i] != slot)
705 /* we do not require to be the first one, all is fine */
709 /* move us to the first slot */
710 memmove(order + 1, order, i * sizeof(uint16_t));
712 return efi_set_boot_order(order, n);
716 t = realloc(order, (n + 1) * sizeof(uint16_t));
721 /* add us to the top or end of the list */
723 memmove(order + 1, order, n * sizeof(uint16_t));
728 return efi_set_boot_order(order, n + 1);
731 static int remove_from_order(uint16_t slot) {
732 _cleanup_free_ uint16_t *order = NULL;
735 n = efi_get_boot_order(&order);
739 for (i = 0; i < n; i++) {
740 if (order[i] != slot)
744 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
745 return efi_set_boot_order(order, n - 1);
751 static int install_variables(const char *esp_path,
752 uint32_t part, uint64_t pstart, uint64_t psize,
753 sd_id128_t uuid, const char *path,
759 if (!is_efi_boot()) {
760 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
764 p = strjoina(esp_path, path);
765 if (access(p, F_OK) < 0) {
769 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
772 r = find_slot(uuid, path, &slot);
774 return log_error_errno(r,
776 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
777 "Failed to determine current boot order
: %m
");
779 if (first || r == 0) {
780 r = efi_add_boot_option(slot, "Linux Boot Manager
",
784 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
786 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
789 return insert_into_order(slot, first);
792 static int remove_boot_efi(const char *esp_path) {
794 _cleanup_closedir_ DIR *d = NULL;
798 p = strjoina(esp_path, "/EFI
/BOOT
");
804 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
807 FOREACH_DIRENT(de, d, break) {
808 _cleanup_close_ int fd = -1;
809 _cleanup_free_ char *v = NULL;
811 if (!endswith_no_case(de->d_name, ".efi
"))
814 if (!startswith_no_case(de->d_name, "boot
"))
817 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
819 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
821 r = get_file_version(fd, &v);
824 if (r > 0 && startswith(v, "systemd
-boot
")) {
825 r = unlinkat(dirfd(d), de->d_name, 0);
827 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
829 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
838 static int rmdir_one(const char *prefix, const char *suffix) {
841 p = strjoina(prefix, "/", suffix);
843 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
844 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
846 log_info("Removed
\"%s
\".", p);
851 static int remove_binaries(const char *esp_path) {
856 p = strjoina(esp_path, "/EFI
/systemd
");
857 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
859 q = remove_boot_efi(esp_path);
863 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
864 q = rmdir_one(esp_path, efi_subdirs[i-1]);
872 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
879 r = find_slot(uuid, path, &slot);
883 r = efi_remove_boot_option(slot);
888 return remove_from_order(slot);
893 static int install_loader_config(const char *esp_path) {
895 char machine_string[SD_ID128_STRING_MAX];
896 _cleanup_(unlink_and_freep) char *t = NULL;
897 _cleanup_fclose_ FILE *f = NULL;
898 sd_id128_t machine_id;
902 r = sd_id128_get_machine(&machine_id);
904 return log_error_errno(r, "Failed to get machine did
: %m
");
906 p = strjoina(esp_path, "/loader
/loader
.conf
");
908 if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
911 fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
913 return log_error_errno(fd, "Failed to open
\"%s
\" for writing
: %m
", p);
915 f = fdopen(fd, "we
");
921 fprintf(f, "#timeout 3\n");
922 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
924 r = fflush_and_check(f);
926 return log_error_errno(r, "Failed to write \"%s\": %m", p);
928 r = link_tmpfile(fd, t, p);
930 return 0; /* Silently skip creation if the file exists now (recheck) */
932 return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
939 static int help(int argc, char *argv[], void *userdata) {
941 printf("%s [COMMAND] [OPTIONS...]\n"
943 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
944 " -h --help Show this help\n"
945 " --version Print version\n"
946 " --path=PATH Path to the EFI System Partition (ESP)\n"
947 " --no-variables Don't touch EFI variables\n"
950 " status Show status of installed systemd-boot and EFI variables\n"
951 " install Install systemd-boot to the ESP and EFI variables\n"
952 " update Update systemd-boot in the ESP and EFI variables\n"
953 " remove Remove systemd-boot from the ESP and EFI variables\n",
954 program_invocation_short_name);
959 static int parse_argv(int argc, char *argv[]) {
966 static const struct option options[] = {
967 { "help", no_argument, NULL, 'h' },
968 { "version", no_argument, NULL, ARG_VERSION },
969 { "path", required_argument, NULL, ARG_PATH },
970 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
979 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
990 r = free_and_strdup(&arg_path, optarg);
995 case ARG_NO_VARIABLES:
996 arg_touch_variables = false;
1003 assert_not_reached("Unknown option");
1009 static void read_loader_efi_var(const char *name, char **var) {
1012 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
1013 if (r < 0 && r != -ENOENT)
1014 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1017 static int must_be_root(void) {
1022 log_error("Need to be root.");
1026 static int verb_status(int argc, char *argv[], void *userdata) {
1028 sd_id128_t uuid = SD_ID128_NULL;
1035 r = find_esp(NULL, NULL, NULL, &uuid);
1039 if (is_efi_boot()) {
1040 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1041 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1043 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1044 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1045 read_loader_efi_var("LoaderInfo", &loader);
1046 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1049 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: %sd\n", enable_disable(r));
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_is_null(loader_part_uuid))
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();
1093 static int verb_install(int argc, char *argv[], void *userdata) {
1095 sd_id128_t uuid = SD_ID128_NULL;
1096 uint64_t pstart = 0, psize = 0;
1105 r = find_esp(&part, &pstart, &psize, &uuid);
1109 install = streq(argv[0], "install");
1111 RUN_WITH_UMASK(0002) {
1112 r = install_binaries(arg_path, install);
1117 r = install_loader_config(arg_path);
1123 if (arg_touch_variables)
1124 r = install_variables(arg_path,
1125 part, pstart, psize, uuid,
1126 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1132 static int verb_remove(int argc, char *argv[], void *userdata) {
1133 sd_id128_t uuid = SD_ID128_NULL;
1140 r = find_esp(NULL, NULL, NULL, &uuid);
1144 r = remove_binaries(arg_path);
1146 if (arg_touch_variables) {
1149 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1150 if (q < 0 && r == 0)
1157 static int bootctl_main(int argc, char *argv[]) {
1159 static const Verb verbs[] = {
1160 { "help", VERB_ANY, VERB_ANY, 0, help },
1161 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1162 { "install", VERB_ANY, 1, 0, verb_install },
1163 { "update", VERB_ANY, 1, 0, verb_install },
1164 { "remove", VERB_ANY, 1, 0, verb_remove },
1168 return dispatch_verb(argc, argv, verbs, NULL);
1171 int main(int argc, char *argv[]) {
1174 log_parse_environment();
1177 /* If we run in a container, automatically turn of EFI file system access */
1178 if (detect_container() > 0)
1179 arg_touch_variables = false;
1181 r = parse_argv(argc, argv);
1185 r = bootctl_main(argc, argv);
1189 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;