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"
42 #include "dirent-util.h"
47 #include "locale-util.h"
48 #include "parse-util.h"
50 #include "stat-util.h"
51 #include "string-util.h"
53 #include "terminal-util.h"
54 #include "umask-util.h"
59 static char *arg_path
= NULL
;
60 static bool arg_touch_variables
= true;
62 static int find_esp_and_warn(uint32_t *part
, uint64_t *pstart
, uint64_t *psize
, sd_id128_t
*uuid
) {
65 r
= find_esp(&arg_path
, part
, pstart
, psize
, uuid
);
67 return log_error_errno(r
,
68 "Couldn't find EFI system partition. It is recommended to mount it to /boot.\n"
69 "Alternatively, use --path= to specify path to mount point.");
71 return log_error_errno(r
,
72 "Couldn't find EFI system partition: %m");
74 log_info("Using EFI System Partition at %s.", arg_path
);
78 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
79 static int get_file_version(int fd
, char **v
) {
89 if (fstat(fd
, &st
) < 0)
90 return log_error_errno(errno
, "Failed to stat EFI binary: %m");
92 if (st
.st_size
< 27) {
97 buf
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
98 if (buf
== MAP_FAILED
)
99 return log_error_errno(errno
, "Failed to memory map EFI binary: %m");
101 s
= memmem(buf
, st
.st_size
- 8, "#### LoaderInfo: ", 17);
106 e
= memmem(s
, st
.st_size
- (s
- buf
), " ####", 5);
107 if (!e
|| e
- s
< 3) {
108 log_error("Malformed version string.");
113 x
= strndup(s
, e
- s
);
121 (void) munmap(buf
, st
.st_size
);
126 static int enumerate_binaries(const char *esp_path
, const char *path
, const char *prefix
) {
128 _cleanup_closedir_
DIR *d
= NULL
;
132 p
= strjoina(esp_path
, "/", path
);
138 return log_error_errno(errno
, "Failed to read \"%s\": %m", p
);
141 FOREACH_DIRENT(de
, d
, break) {
142 _cleanup_close_
int fd
= -1;
143 _cleanup_free_
char *v
= NULL
;
145 if (!endswith_no_case(de
->d_name
, ".efi"))
148 if (prefix
&& !startswith_no_case(de
->d_name
, prefix
))
151 fd
= openat(dirfd(d
), de
->d_name
, O_RDONLY
|O_CLOEXEC
);
153 return log_error_errno(errno
, "Failed to open \"%s/%s\" for reading: %m", p
, de
->d_name
);
155 r
= get_file_version(fd
, &v
);
159 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
, v
);
161 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT
), path
, de
->d_name
);
168 static int status_binaries(const char *esp_path
, sd_id128_t partition
) {
171 printf("Boot Loader Binaries:\n");
174 printf(" ESP: Cannot find or access mount point of ESP.\n\n");
178 printf(" ESP: %s", esp_path
);
179 if (!sd_id128_is_null(partition
))
180 printf(" (/dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x)", SD_ID128_FORMAT_VAL(partition
));
183 r
= enumerate_binaries(esp_path
, "EFI/systemd", NULL
);
185 log_error("systemd-boot not installed in ESP.");
189 r
= enumerate_binaries(esp_path
, "EFI/BOOT", "boot");
191 log_error("No default/fallback boot loader installed in ESP.");
200 static int print_efi_option(uint16_t id
, bool in_order
) {
201 _cleanup_free_
char *title
= NULL
;
202 _cleanup_free_
char *path
= NULL
;
203 sd_id128_t partition
;
207 r
= efi_get_boot_option(id
, &title
, &partition
, &path
, &active
);
211 /* print only configured entries with partition information */
212 if (!path
|| sd_id128_is_null(partition
))
215 efi_tilt_backslashes(path
);
217 printf(" Title: %s\n", strna(title
));
218 printf(" ID: 0x%04X\n", id
);
219 printf(" Status: %sactive%s\n", active
? "" : "in", in_order
? ", boot-order" : "");
220 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
));
221 printf(" File: %s%s\n", special_glyph(TREE_RIGHT
), path
);
227 static int status_variables(void) {
228 int n_options
, n_order
;
229 _cleanup_free_
uint16_t *options
= NULL
, *order
= NULL
;
232 n_options
= efi_get_boot_options(&options
);
233 if (n_options
== -ENOENT
)
234 return log_error_errno(n_options
,
235 "Failed to access EFI variables, efivarfs"
236 " needs to be available at /sys/firmware/efi/efivars/.");
238 return log_error_errno(n_options
, "Failed to read EFI boot entries: %m");
240 n_order
= efi_get_boot_order(&order
);
241 if (n_order
== -ENOENT
)
243 else if (n_order
< 0)
244 return log_error_errno(n_order
, "Failed to read EFI boot order.");
246 /* print entries in BootOrder first */
247 printf("Boot Loader Entries in EFI Variables:\n");
248 for (i
= 0; i
< n_order
; i
++)
249 print_efi_option(order
[i
], true);
251 /* print remaining entries */
252 for (i
= 0; i
< n_options
; i
++) {
255 for (j
= 0; j
< n_order
; j
++)
256 if (options
[i
] == order
[j
])
259 print_efi_option(options
[i
], false);
268 static int status_entries(const char *esp_path
, sd_id128_t partition
) {
271 _cleanup_(boot_config_free
) BootConfig config
= {};
273 printf("Default Boot Entry:\n");
275 r
= boot_entries_load_config(esp_path
, &config
);
277 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m",
280 if (config
.default_entry
< 0)
281 printf("%zu entries, no entry suitable as default", config
.n_entries
);
283 const BootEntry
*e
= &config
.entries
[config
.default_entry
];
285 printf(" title: %s\n", boot_entry_title(e
));
287 printf(" version: %s\n", e
->version
);
289 printf(" linux: %s\n", e
->kernel
);
290 if (!strv_isempty(e
->initrd
)) {
291 _cleanup_free_
char *t
;
293 t
= strv_join(e
->initrd
, " ");
297 printf(" initrd: %s\n", t
);
299 if (!strv_isempty(e
->options
)) {
300 _cleanup_free_
char *t
;
302 t
= strv_join(e
->options
, " ");
306 printf(" options: %s\n", t
);
309 printf(" devicetree: %s\n", e
->device_tree
);
316 static int compare_product(const char *a
, const char *b
) {
325 return x
< y
? -1 : x
> y
? 1 : 0;
327 return strncmp(a
, b
, x
);
330 static int compare_version(const char *a
, const char *b
) {
334 a
+= strcspn(a
, " ");
336 b
+= strcspn(b
, " ");
339 return strverscmp(a
, b
);
342 static int version_check(int fd_from
, const char *from
, int fd_to
, const char *to
) {
343 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
346 assert(fd_from
>= 0);
351 r
= get_file_version(fd_from
, &a
);
355 log_error("Source file \"%s\" does not carry version information!", from
);
359 r
= get_file_version(fd_to
, &b
);
362 if (r
== 0 || compare_product(a
, b
) != 0) {
363 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to
);
367 if (compare_version(a
, b
) < 0) {
368 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to
);
375 static int copy_file_with_version_check(const char *from
, const char *to
, bool force
) {
376 _cleanup_close_
int fd_from
= -1, fd_to
= -1;
377 _cleanup_free_
char *t
= NULL
;
380 fd_from
= open(from
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
382 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", from
);
385 fd_to
= open(to
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
387 if (errno
!= -ENOENT
)
388 return log_error_errno(errno
, "Failed to open \"%s\" for reading: %m", to
);
390 r
= version_check(fd_from
, from
, fd_to
, to
);
394 if (lseek(fd_from
, 0, SEEK_SET
) == (off_t
) -1)
395 return log_error_errno(errno
, "Failed to seek in \%s\": %m", from
);
397 fd_to
= safe_close(fd_to
);
401 r
= tempfn_random(to
, NULL
, &t
);
405 RUN_WITH_UMASK(0000) {
406 fd_to
= open(t
, O_WRONLY
|O_CREAT
|O_CLOEXEC
|O_EXCL
|O_NOFOLLOW
, 0644);
408 return log_error_errno(errno
, "Failed to open \"%s\" for writing: %m", t
);
411 r
= copy_bytes(fd_from
, fd_to
, (uint64_t) -1, COPY_REFLINK
);
414 return log_error_errno(r
, "Failed to copy data from \"%s\" to \"%s\": %m", from
, t
);
417 (void) copy_times(fd_from
, fd_to
);
421 (void) unlink_noerrno(t
);
422 return log_error_errno(errno
, "Failed to copy data from \"%s\" to \"%s\": %m", from
, t
);
425 r
= renameat(AT_FDCWD
, t
, AT_FDCWD
, to
);
427 (void) unlink_noerrno(t
);
428 return log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", t
, to
);
431 log_info("Copied \"%s\" to \"%s\".", from
, to
);
436 static int mkdir_one(const char *prefix
, const char *suffix
) {
439 p
= strjoina(prefix
, "/", suffix
);
440 if (mkdir(p
, 0700) < 0) {
442 return log_error_errno(errno
, "Failed to create \"%s\": %m", p
);
444 log_info("Created \"%s\".", p
);
449 static const char *efi_subdirs
[] = {
458 static int create_dirs(const char *esp_path
) {
462 STRV_FOREACH(i
, efi_subdirs
) {
463 r
= mkdir_one(esp_path
, *i
);
471 static int copy_one_file(const char *esp_path
, const char *name
, bool force
) {
475 p
= strjoina(BOOTLIBDIR
"/", name
);
476 q
= strjoina(esp_path
, "/EFI/systemd/", name
);
477 r
= copy_file_with_version_check(p
, q
, force
);
479 if (startswith(name
, "systemd-boot")) {
483 /* Create the EFI default boot loader name (specified for removable devices) */
484 v
= strjoina(esp_path
, "/EFI/BOOT/BOOT", name
+ strlen("systemd-boot"));
485 ascii_strupper(strrchr(v
, '/') + 1);
487 k
= copy_file_with_version_check(p
, v
, force
);
495 static int install_binaries(const char *esp_path
, bool force
) {
497 _cleanup_closedir_
DIR *d
= NULL
;
501 /* Don't create any of these directories when we are
502 * just updating. When we update we'll drop-in our
503 * files (unless there are newer ones already), but we
504 * won't create the directories for them in the first
506 r
= create_dirs(esp_path
);
511 d
= opendir(BOOTLIBDIR
);
513 return log_error_errno(errno
, "Failed to open \""BOOTLIBDIR
"\": %m
");
515 FOREACH_DIRENT(de, d, break) {
518 if (!endswith_no_case(de->d_name, ".efi
"))
521 k = copy_one_file(esp_path, de->d_name, force);
529 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
530 _cleanup_free_ char *opath = NULL;
534 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
537 if (!sd_id128_equal(uuid, ouuid))
539 if (!streq_ptr(path, opath))
545 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
546 _cleanup_free_ uint16_t *options = NULL;
549 n = efi_get_boot_options(&options);
553 /* find already existing systemd-boot entry */
554 for (i = 0; i < n; i++)
555 if (same_entry(options[i], uuid, path)) {
560 /* find free slot in the sorted BootXXXX variable list */
561 for (i = 0; i < n; i++)
562 if (i != options[i]) {
567 /* use the next one */
574 static int insert_into_order(uint16_t slot, bool first) {
575 _cleanup_free_ uint16_t *order = NULL;
579 n = efi_get_boot_order(&order);
581 /* no entry, add us */
582 return efi_set_boot_order(&slot, 1);
584 /* are we the first and only one? */
585 if (n == 1 && order[0] == slot)
588 /* are we already in the boot order? */
589 for (i = 0; i < n; i++) {
590 if (order[i] != slot)
593 /* we do not require to be the first one, all is fine */
597 /* move us to the first slot */
598 memmove(order + 1, order, i * sizeof(uint16_t));
600 return efi_set_boot_order(order, n);
604 t = realloc(order, (n + 1) * sizeof(uint16_t));
609 /* add us to the top or end of the list */
611 memmove(order + 1, order, n * sizeof(uint16_t));
616 return efi_set_boot_order(order, n + 1);
619 static int remove_from_order(uint16_t slot) {
620 _cleanup_free_ uint16_t *order = NULL;
623 n = efi_get_boot_order(&order);
627 for (i = 0; i < n; i++) {
628 if (order[i] != slot)
632 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
633 return efi_set_boot_order(order, n - 1);
639 static int install_variables(const char *esp_path,
640 uint32_t part, uint64_t pstart, uint64_t psize,
641 sd_id128_t uuid, const char *path,
647 if (!is_efi_boot()) {
648 log_warning("Not booted with EFI
, skipping EFI variable setup
.");
652 p = strjoina(esp_path, path);
653 if (access(p, F_OK) < 0) {
657 return log_error_errno(errno, "Cannot access
\"%s
\": %m
", p);
660 r = find_slot(uuid, path, &slot);
662 return log_error_errno(r,
664 "Failed to access EFI variables
. Is the
\"efivarfs
\" filesystem mounted
?" :
665 "Failed to determine current boot order
: %m
");
667 if (first || r == 0) {
668 r = efi_add_boot_option(slot, "Linux Boot Manager
",
672 return log_error_errno(r, "Failed to create EFI Boot variable entry
: %m
");
674 log_info("Created EFI boot entry
\"Linux Boot Manager
\".");
677 return insert_into_order(slot, first);
680 static int remove_boot_efi(const char *esp_path) {
682 _cleanup_closedir_ DIR *d = NULL;
686 p = strjoina(esp_path, "/EFI
/BOOT
");
692 return log_error_errno(errno, "Failed to open directory
\"%s
\": %m
", p);
695 FOREACH_DIRENT(de, d, break) {
696 _cleanup_close_ int fd = -1;
697 _cleanup_free_ char *v = NULL;
699 if (!endswith_no_case(de->d_name, ".efi
"))
702 if (!startswith_no_case(de->d_name, "boot
"))
705 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
707 return log_error_errno(errno, "Failed to open
\"%s
/%s
\" for reading
: %m
", p, de->d_name);
709 r = get_file_version(fd, &v);
712 if (r > 0 && startswith(v, "systemd
-boot
")) {
713 r = unlinkat(dirfd(d), de->d_name, 0);
715 return log_error_errno(errno, "Failed to remove
\"%s
/%s
\": %m
", p, de->d_name);
717 log_info("Removed
\"%s
/%s
\".", p, de->d_name);
726 static int rmdir_one(const char *prefix, const char *suffix) {
729 p = strjoina(prefix, "/", suffix);
731 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
732 return log_error_errno(errno, "Failed to remove
\"%s
\": %m
", p);
734 log_info("Removed
\"%s
\".", p);
739 static int remove_binaries(const char *esp_path) {
744 p = strjoina(esp_path, "/EFI
/systemd
");
745 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
747 q = remove_boot_efi(esp_path);
751 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
752 q = rmdir_one(esp_path, efi_subdirs[i-1]);
760 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
767 r = find_slot(uuid, path, &slot);
771 r = efi_remove_boot_option(slot);
776 return remove_from_order(slot);
781 static int install_loader_config(const char *esp_path) {
783 char machine_string[SD_ID128_STRING_MAX];
784 _cleanup_(unlink_and_freep) char *t = NULL;
785 _cleanup_fclose_ FILE *f = NULL;
786 sd_id128_t machine_id;
790 r = sd_id128_get_machine(&machine_id);
792 return log_error_errno(r, "Failed to get machine id
: %m
");
794 p = strjoina(esp_path, "/loader
/loader
.conf
");
796 if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
799 fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
801 return log_error_errno(fd, "Failed to open
\"%s
\" for writing
: %m
", p);
803 f = fdopen(fd, "we
");
809 fprintf(f, "#timeout 3\n");
810 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
812 r = fflush_sync_and_check(f);
814 return log_error_errno(r, "Failed to write \"%s\": %m", p);
816 r = link_tmpfile(fd, t, p);
818 return 0; /* Silently skip creation if the file exists now (recheck) */
820 return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
827 static int help(int argc, char *argv[], void *userdata) {
829 printf("%s [COMMAND] [OPTIONS...]\n"
831 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
832 " -h --help Show this help\n"
833 " --version Print version\n"
834 " --path=PATH Path to the EFI System Partition (ESP)\n"
835 " --no-variables Don't touch EFI variables\n"
838 " status Show status of installed systemd-boot and EFI variables\n"
839 " list List boot entries\n"
840 " install Install systemd-boot to the ESP and EFI variables\n"
841 " update Update systemd-boot in the ESP and EFI variables\n"
842 " remove Remove systemd-boot from the ESP and EFI variables\n",
843 program_invocation_short_name);
848 static int parse_argv(int argc, char *argv[]) {
855 static const struct option options[] = {
856 { "help", no_argument, NULL, 'h' },
857 { "version", no_argument, NULL, ARG_VERSION },
858 { "path", required_argument, NULL, ARG_PATH },
859 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
868 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
879 r = free_and_strdup(&arg_path, optarg);
884 case ARG_NO_VARIABLES:
885 arg_touch_variables = false;
892 assert_not_reached("Unknown option");
898 static void read_loader_efi_var(const char *name, char **var) {
901 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
902 if (r < 0 && r != -ENOENT)
903 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
906 static int must_be_root(void) {
911 log_error("Need to be root.");
915 static int verb_status(int argc, char *argv[], void *userdata) {
917 sd_id128_t uuid = SD_ID128_NULL;
920 r2 = find_esp_and_warn(NULL, NULL, NULL, &uuid);
923 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
924 sd_id128_t loader_part_uuid = SD_ID128_NULL;
926 read_loader_efi_var("LoaderFirmwareType", &fw_type);
927 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
928 read_loader_efi_var("LoaderInfo", &loader);
929 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
932 efi_tilt_backslashes(loader_path);
934 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
935 if (r < 0 && r != -ENOENT)
936 r2 = log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
939 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
941 r = is_efi_secure_boot();
943 r2 = log_warning_errno(r, "Failed to query secure boot status: %m");
945 printf(" Secure Boot: %sd\n", enable_disable(r));
947 r = is_efi_secure_boot_setup_mode();
949 r2 = log_warning_errno(r, "Failed to query secure boot mode: %m");
951 printf(" Setup Mode: %s\n", r ? "setup" : "user");
954 printf("Current Loader:\n");
955 printf(" Product: %s\n", strna(loader));
956 if (!sd_id128_is_null(loader_part_uuid))
957 printf(" ESP: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
958 SD_ID128_FORMAT_VAL(loader_part_uuid));
960 printf(" ESP: n/a\n");
961 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
964 printf("System:\n Not booted with EFI\n\n");
966 r = status_binaries(arg_path, uuid);
971 r = status_variables();
976 r = status_entries(arg_path, uuid);
983 static int verb_list(int argc, char *argv[], void *userdata) {
984 sd_id128_t uuid = SD_ID128_NULL;
988 _cleanup_(boot_config_free) BootConfig config = {};
990 r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
994 r = boot_entries_load_config(arg_path, &config);
996 return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
999 printf("Available boot entries:\n");
1001 for (n = 0; n < config.n_entries; n++) {
1002 const BootEntry *e = &config.entries[n];
1004 printf(" title: %s%s%s%s%s%s\n",
1006 boot_entry_title(e),
1008 ansi_highlight_green(),
1009 n == config.default_entry ? " (default)" : "",
1012 printf(" version: %s\n", e->version);
1014 printf(" machine-id: %s\n", e->machine_id);
1015 if (e->architecture)
1016 printf(" architecture: %s\n", e->architecture);
1018 printf(" linux: %s\n", e->kernel);
1019 if (!strv_isempty(e->initrd)) {
1020 _cleanup_free_ char *t;
1022 t = strv_join(e->initrd, " ");
1026 printf(" initrd: %s\n", t);
1028 if (!strv_isempty(e->options)) {
1029 _cleanup_free_ char *t;
1031 t = strv_join(e->options, " ");
1035 printf(" options: %s\n", t);
1038 printf(" devicetree: %s\n", e->device_tree);
1046 static int verb_install(int argc, char *argv[], void *userdata) {
1048 sd_id128_t uuid = SD_ID128_NULL;
1049 uint64_t pstart = 0, psize = 0;
1058 r = find_esp_and_warn(&part, &pstart, &psize, &uuid);
1062 install = streq(argv[0], "install");
1064 RUN_WITH_UMASK(0002) {
1065 r = install_binaries(arg_path, install);
1070 r = install_loader_config(arg_path);
1076 if (arg_touch_variables)
1077 r = install_variables(arg_path,
1078 part, pstart, psize, uuid,
1079 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1085 static int verb_remove(int argc, char *argv[], void *userdata) {
1086 sd_id128_t uuid = SD_ID128_NULL;
1093 r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
1097 r = remove_binaries(arg_path);
1099 if (arg_touch_variables) {
1102 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1103 if (q < 0 && r == 0)
1110 static int bootctl_main(int argc, char *argv[]) {
1112 static const Verb verbs[] = {
1113 { "help", VERB_ANY, VERB_ANY, 0, help },
1114 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1115 { "list", VERB_ANY, 1, 0, verb_list },
1116 { "install", VERB_ANY, 1, 0, verb_install },
1117 { "update", VERB_ANY, 1, 0, verb_install },
1118 { "remove", VERB_ANY, 1, 0, verb_remove },
1122 return dispatch_verb(argc, argv, verbs, NULL);
1125 int main(int argc, char *argv[]) {
1128 log_parse_environment();
1131 /* If we run in a container, automatically turn of EFI file system access */
1132 if (detect_container() > 0)
1133 arg_touch_variables = false;
1135 r = parse_argv(argc, argv);
1139 r = bootctl_main(argc, argv);
1143 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;