]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/bootctl.c
bootctl: move find_esp() to shared
[thirdparty/systemd.git] / src / boot / bootctl.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2013-2015 Kay Sievers
5 Copyright 2013 Lennart Poettering
6
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.
11
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.
16
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/>.
19 ***/
20
21 #include <blkid.h>
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <ftw.h>
26 #include <getopt.h>
27 #include <limits.h>
28 #include <linux/magic.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/mman.h>
34 #include <sys/stat.h>
35 #include <sys/statfs.h>
36 #include <unistd.h>
37
38 #include "alloc-util.h"
39 #include "blkid-util.h"
40 #include "bootspec.h"
41 #include "copy.h"
42 #include "dirent-util.h"
43 #include "efivars.h"
44 #include "fd-util.h"
45 #include "fileio.h"
46 #include "fs-util.h"
47 #include "locale-util.h"
48 #include "parse-util.h"
49 #include "rm-rf.h"
50 #include "stat-util.h"
51 #include "string-util.h"
52 #include "strv.h"
53 #include "terminal-util.h"
54 #include "umask-util.h"
55 #include "util.h"
56 #include "verbs.h"
57 #include "virt.h"
58
59 static char *arg_path = NULL;
60 static bool arg_touch_variables = true;
61
62 static int find_esp_and_warn(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
63 int r;
64
65 r = find_esp(&arg_path, part, pstart, psize, uuid);
66 if (r == -ENOENT)
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.");
70 else if (r < 0)
71 return log_error_errno(r,
72 "Couldn't find EFI system partition: %m");
73
74 log_info("Using EFI System Partition at %s.", arg_path);
75 return 0;
76 }
77
78 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
79 static int get_file_version(int fd, char **v) {
80 struct stat st;
81 char *buf;
82 const char *s, *e;
83 char *x = NULL;
84 int r = 0;
85
86 assert(fd >= 0);
87 assert(v);
88
89 if (fstat(fd, &st) < 0)
90 return log_error_errno(errno, "Failed to stat EFI binary: %m");
91
92 if (st.st_size < 27) {
93 *v = NULL;
94 return 0;
95 }
96
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");
100
101 s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
102 if (!s)
103 goto finish;
104 s += 17;
105
106 e = memmem(s, st.st_size - (s - buf), " ####", 5);
107 if (!e || e - s < 3) {
108 log_error("Malformed version string.");
109 r = -EINVAL;
110 goto finish;
111 }
112
113 x = strndup(s, e - s);
114 if (!x) {
115 r = log_oom();
116 goto finish;
117 }
118 r = 1;
119
120 finish:
121 (void) munmap(buf, st.st_size);
122 *v = x;
123 return r;
124 }
125
126 static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
127 char *p;
128 _cleanup_closedir_ DIR *d = NULL;
129 struct dirent *de;
130 int r = 0, c = 0;
131
132 p = strjoina(esp_path, "/", path);
133 d = opendir(p);
134 if (!d) {
135 if (errno == ENOENT)
136 return 0;
137
138 return log_error_errno(errno, "Failed to read \"%s\": %m", p);
139 }
140
141 FOREACH_DIRENT(de, d, break) {
142 _cleanup_close_ int fd = -1;
143 _cleanup_free_ char *v = NULL;
144
145 if (!endswith_no_case(de->d_name, ".efi"))
146 continue;
147
148 if (prefix && !startswith_no_case(de->d_name, prefix))
149 continue;
150
151 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
152 if (fd < 0)
153 return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);
154
155 r = get_file_version(fd, &v);
156 if (r < 0)
157 return r;
158 if (r > 0)
159 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT), path, de->d_name, v);
160 else
161 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT), path, de->d_name);
162 c++;
163 }
164
165 return c;
166 }
167
168 static int status_binaries(const char *esp_path, sd_id128_t partition) {
169 int r;
170
171 printf("Boot Loader Binaries:\n");
172
173 if (!esp_path) {
174 printf(" ESP: Cannot find or access mount point of ESP.\n\n");
175 return -ENOENT;
176 }
177
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));
181 printf("\n");
182
183 r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
184 if (r == 0)
185 log_error("systemd-boot not installed in ESP.");
186 else if (r < 0)
187 return r;
188
189 r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
190 if (r == 0)
191 log_error("No default/fallback boot loader installed in ESP.");
192 else if (r < 0)
193 return r;
194
195 printf("\n");
196
197 return 0;
198 }
199
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;
204 bool active;
205 int r = 0;
206
207 r = efi_get_boot_option(id, &title, &partition, &path, &active);
208 if (r < 0)
209 return r;
210
211 /* print only configured entries with partition information */
212 if (!path || sd_id128_is_null(partition))
213 return 0;
214
215 efi_tilt_backslashes(path);
216
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);
222 printf("\n");
223
224 return 0;
225 }
226
227 static int status_variables(void) {
228 int n_options, n_order;
229 _cleanup_free_ uint16_t *options = NULL, *order = NULL;
230 int i;
231
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/.");
237 if (n_options < 0)
238 return log_error_errno(n_options, "Failed to read EFI boot entries: %m");
239
240 n_order = efi_get_boot_order(&order);
241 if (n_order == -ENOENT)
242 n_order = 0;
243 else if (n_order < 0)
244 return log_error_errno(n_order, "Failed to read EFI boot order.");
245
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);
250
251 /* print remaining entries */
252 for (i = 0; i < n_options; i++) {
253 int j;
254
255 for (j = 0; j < n_order; j++)
256 if (options[i] == order[j])
257 goto next_option;
258
259 print_efi_option(options[i], false);
260
261 next_option:
262 continue;
263 }
264
265 return 0;
266 }
267
268 static int status_entries(const char *esp_path, sd_id128_t partition) {
269 int r;
270
271 _cleanup_(boot_config_free) BootConfig config = {};
272
273 printf("Default Boot Entry:\n");
274
275 r = boot_entries_load_config(esp_path, &config);
276 if (r < 0)
277 return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
278 esp_path);
279
280 if (config.default_entry < 0)
281 printf("%zu entries, no entry suitable as default", config.n_entries);
282 else {
283 const BootEntry *e = &config.entries[config.default_entry];
284
285 printf(" title: %s\n", boot_entry_title(e));
286 if (e->version)
287 printf(" version: %s\n", e->version);
288 if (e->kernel)
289 printf(" linux: %s\n", e->kernel);
290 if (!strv_isempty(e->initrd)) {
291 _cleanup_free_ char *t;
292
293 t = strv_join(e->initrd, " ");
294 if (!t)
295 return log_oom();
296
297 printf(" initrd: %s\n", t);
298 }
299 if (!strv_isempty(e->options)) {
300 _cleanup_free_ char *t;
301
302 t = strv_join(e->options, " ");
303 if (!t)
304 return log_oom();
305
306 printf(" options: %s\n", t);
307 }
308 if (e->device_tree)
309 printf(" devicetree: %s\n", e->device_tree);
310 puts("");
311 }
312
313 return 0;
314 }
315
316 static int compare_product(const char *a, const char *b) {
317 size_t x, y;
318
319 assert(a);
320 assert(b);
321
322 x = strcspn(a, " ");
323 y = strcspn(b, " ");
324 if (x != y)
325 return x < y ? -1 : x > y ? 1 : 0;
326
327 return strncmp(a, b, x);
328 }
329
330 static int compare_version(const char *a, const char *b) {
331 assert(a);
332 assert(b);
333
334 a += strcspn(a, " ");
335 a += strspn(a, " ");
336 b += strcspn(b, " ");
337 b += strspn(b, " ");
338
339 return strverscmp(a, b);
340 }
341
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;
344 int r;
345
346 assert(fd_from >= 0);
347 assert(from);
348 assert(fd_to >= 0);
349 assert(to);
350
351 r = get_file_version(fd_from, &a);
352 if (r < 0)
353 return r;
354 if (r == 0) {
355 log_error("Source file \"%s\" does not carry version information!", from);
356 return -EINVAL;
357 }
358
359 r = get_file_version(fd_to, &b);
360 if (r < 0)
361 return r;
362 if (r == 0 || compare_product(a, b) != 0) {
363 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to);
364 return -EEXIST;
365 }
366
367 if (compare_version(a, b) < 0) {
368 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to);
369 return -ESTALE;
370 }
371
372 return 0;
373 }
374
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;
378 int r;
379
380 fd_from = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
381 if (fd_from < 0)
382 return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", from);
383
384 if (!force) {
385 fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY);
386 if (fd_to < 0) {
387 if (errno != -ENOENT)
388 return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to);
389 } else {
390 r = version_check(fd_from, from, fd_to, to);
391 if (r < 0)
392 return r;
393
394 if (lseek(fd_from, 0, SEEK_SET) == (off_t) -1)
395 return log_error_errno(errno, "Failed to seek in \%s\": %m", from);
396
397 fd_to = safe_close(fd_to);
398 }
399 }
400
401 r = tempfn_random(to, NULL, &t);
402 if (r < 0)
403 return log_oom();
404
405 RUN_WITH_UMASK(0000) {
406 fd_to = open(t, O_WRONLY|O_CREAT|O_CLOEXEC|O_EXCL|O_NOFOLLOW, 0644);
407 if (fd_to < 0)
408 return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", t);
409 }
410
411 r = copy_bytes(fd_from, fd_to, (uint64_t) -1, COPY_REFLINK);
412 if (r < 0) {
413 (void) unlink(t);
414 return log_error_errno(r, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
415 }
416
417 (void) copy_times(fd_from, fd_to);
418
419 r = fsync(fd_to);
420 if (r < 0) {
421 (void) unlink_noerrno(t);
422 return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
423 }
424
425 r = renameat(AT_FDCWD, t, AT_FDCWD, to);
426 if (r < 0) {
427 (void) unlink_noerrno(t);
428 return log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", t, to);
429 }
430
431 log_info("Copied \"%s\" to \"%s\".", from, to);
432
433 return 0;
434 }
435
436 static int mkdir_one(const char *prefix, const char *suffix) {
437 char *p;
438
439 p = strjoina(prefix, "/", suffix);
440 if (mkdir(p, 0700) < 0) {
441 if (errno != EEXIST)
442 return log_error_errno(errno, "Failed to create \"%s\": %m", p);
443 } else
444 log_info("Created \"%s\".", p);
445
446 return 0;
447 }
448
449 static const char *efi_subdirs[] = {
450 "EFI",
451 "EFI/systemd",
452 "EFI/BOOT",
453 "loader",
454 "loader/entries",
455 NULL
456 };
457
458 static int create_dirs(const char *esp_path) {
459 const char **i;
460 int r;
461
462 STRV_FOREACH(i, efi_subdirs) {
463 r = mkdir_one(esp_path, *i);
464 if (r < 0)
465 return r;
466 }
467
468 return 0;
469 }
470
471 static int copy_one_file(const char *esp_path, const char *name, bool force) {
472 char *p, *q;
473 int r;
474
475 p = strjoina(BOOTLIBDIR "/", name);
476 q = strjoina(esp_path, "/EFI/systemd/", name);
477 r = copy_file_with_version_check(p, q, force);
478
479 if (startswith(name, "systemd-boot")) {
480 int k;
481 char *v;
482
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);
486
487 k = copy_file_with_version_check(p, v, force);
488 if (k < 0 && r == 0)
489 r = k;
490 }
491
492 return r;
493 }
494
495 static int install_binaries(const char *esp_path, bool force) {
496 struct dirent *de;
497 _cleanup_closedir_ DIR *d = NULL;
498 int r = 0;
499
500 if (force) {
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
505 * place. */
506 r = create_dirs(esp_path);
507 if (r < 0)
508 return r;
509 }
510
511 d = opendir(BOOTLIBDIR);
512 if (!d)
513 return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
514
515 FOREACH_DIRENT(de, d, break) {
516 int k;
517
518 if (!endswith_no_case(de->d_name, ".efi"))
519 continue;
520
521 k = copy_one_file(esp_path, de->d_name, force);
522 if (k < 0 && r == 0)
523 r = k;
524 }
525
526 return r;
527 }
528
529 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
530 _cleanup_free_ char *opath = NULL;
531 sd_id128_t ouuid;
532 int r;
533
534 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
535 if (r < 0)
536 return false;
537 if (!sd_id128_equal(uuid, ouuid))
538 return false;
539 if (!streq_ptr(path, opath))
540 return false;
541
542 return true;
543 }
544
545 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
546 _cleanup_free_ uint16_t *options = NULL;
547 int n, i;
548
549 n = efi_get_boot_options(&options);
550 if (n < 0)
551 return n;
552
553 /* find already existing systemd-boot entry */
554 for (i = 0; i < n; i++)
555 if (same_entry(options[i], uuid, path)) {
556 *id = options[i];
557 return 1;
558 }
559
560 /* find free slot in the sorted BootXXXX variable list */
561 for (i = 0; i < n; i++)
562 if (i != options[i]) {
563 *id = i;
564 return 1;
565 }
566
567 /* use the next one */
568 if (i == 0xffff)
569 return -ENOSPC;
570 *id = i;
571 return 0;
572 }
573
574 static int insert_into_order(uint16_t slot, bool first) {
575 _cleanup_free_ uint16_t *order = NULL;
576 uint16_t *t;
577 int n, i;
578
579 n = efi_get_boot_order(&order);
580 if (n <= 0)
581 /* no entry, add us */
582 return efi_set_boot_order(&slot, 1);
583
584 /* are we the first and only one? */
585 if (n == 1 && order[0] == slot)
586 return 0;
587
588 /* are we already in the boot order? */
589 for (i = 0; i < n; i++) {
590 if (order[i] != slot)
591 continue;
592
593 /* we do not require to be the first one, all is fine */
594 if (!first)
595 return 0;
596
597 /* move us to the first slot */
598 memmove(order + 1, order, i * sizeof(uint16_t));
599 order[0] = slot;
600 return efi_set_boot_order(order, n);
601 }
602
603 /* extend array */
604 t = realloc(order, (n + 1) * sizeof(uint16_t));
605 if (!t)
606 return -ENOMEM;
607 order = t;
608
609 /* add us to the top or end of the list */
610 if (first) {
611 memmove(order + 1, order, n * sizeof(uint16_t));
612 order[0] = slot;
613 } else
614 order[n] = slot;
615
616 return efi_set_boot_order(order, n + 1);
617 }
618
619 static int remove_from_order(uint16_t slot) {
620 _cleanup_free_ uint16_t *order = NULL;
621 int n, i;
622
623 n = efi_get_boot_order(&order);
624 if (n <= 0)
625 return n;
626
627 for (i = 0; i < n; i++) {
628 if (order[i] != slot)
629 continue;
630
631 if (i + 1 < n)
632 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
633 return efi_set_boot_order(order, n - 1);
634 }
635
636 return 0;
637 }
638
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,
642 bool first) {
643 char *p;
644 uint16_t slot;
645 int r;
646
647 if (!is_efi_boot()) {
648 log_warning("Not booted with EFI, skipping EFI variable setup.");
649 return 0;
650 }
651
652 p = strjoina(esp_path, path);
653 if (access(p, F_OK) < 0) {
654 if (errno == ENOENT)
655 return 0;
656
657 return log_error_errno(errno, "Cannot access \"%s\": %m", p);
658 }
659
660 r = find_slot(uuid, path, &slot);
661 if (r < 0)
662 return log_error_errno(r,
663 r == -ENOENT ?
664 "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" :
665 "Failed to determine current boot order: %m");
666
667 if (first || r == 0) {
668 r = efi_add_boot_option(slot, "Linux Boot Manager",
669 part, pstart, psize,
670 uuid, path);
671 if (r < 0)
672 return log_error_errno(r, "Failed to create EFI Boot variable entry: %m");
673
674 log_info("Created EFI boot entry \"Linux Boot Manager\".");
675 }
676
677 return insert_into_order(slot, first);
678 }
679
680 static int remove_boot_efi(const char *esp_path) {
681 char *p;
682 _cleanup_closedir_ DIR *d = NULL;
683 struct dirent *de;
684 int r, c = 0;
685
686 p = strjoina(esp_path, "/EFI/BOOT");
687 d = opendir(p);
688 if (!d) {
689 if (errno == ENOENT)
690 return 0;
691
692 return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
693 }
694
695 FOREACH_DIRENT(de, d, break) {
696 _cleanup_close_ int fd = -1;
697 _cleanup_free_ char *v = NULL;
698
699 if (!endswith_no_case(de->d_name, ".efi"))
700 continue;
701
702 if (!startswith_no_case(de->d_name, "boot"))
703 continue;
704
705 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
706 if (fd < 0)
707 return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);
708
709 r = get_file_version(fd, &v);
710 if (r < 0)
711 return r;
712 if (r > 0 && startswith(v, "systemd-boot ")) {
713 r = unlinkat(dirfd(d), de->d_name, 0);
714 if (r < 0)
715 return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name);
716
717 log_info("Removed \"%s/%s\".", p, de->d_name);
718 }
719
720 c++;
721 }
722
723 return c;
724 }
725
726 static int rmdir_one(const char *prefix, const char *suffix) {
727 char *p;
728
729 p = strjoina(prefix, "/", suffix);
730 if (rmdir(p) < 0) {
731 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
732 return log_error_errno(errno, "Failed to remove \"%s\": %m", p);
733 } else
734 log_info("Removed \"%s\".", p);
735
736 return 0;
737 }
738
739 static int remove_binaries(const char *esp_path) {
740 char *p;
741 int r, q;
742 unsigned i;
743
744 p = strjoina(esp_path, "/EFI/systemd");
745 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
746
747 q = remove_boot_efi(esp_path);
748 if (q < 0 && r == 0)
749 r = q;
750
751 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
752 q = rmdir_one(esp_path, efi_subdirs[i-1]);
753 if (q < 0 && r == 0)
754 r = q;
755 }
756
757 return r;
758 }
759
760 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
761 uint16_t slot;
762 int r;
763
764 if (!is_efi_boot())
765 return 0;
766
767 r = find_slot(uuid, path, &slot);
768 if (r != 1)
769 return 0;
770
771 r = efi_remove_boot_option(slot);
772 if (r < 0)
773 return r;
774
775 if (in_order)
776 return remove_from_order(slot);
777
778 return 0;
779 }
780
781 static int install_loader_config(const char *esp_path) {
782
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;
787 const char *p;
788 int r, fd;
789
790 r = sd_id128_get_machine(&machine_id);
791 if (r < 0)
792 return log_error_errno(r, "Failed to get machine id: %m");
793
794 p = strjoina(esp_path, "/loader/loader.conf");
795
796 if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
797 return 0;
798
799 fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
800 if (fd < 0)
801 return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p);
802
803 f = fdopen(fd, "we");
804 if (!f) {
805 safe_close(fd);
806 return log_oom();
807 }
808
809 fprintf(f, "#timeout 3\n");
810 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
811
812 r = fflush_sync_and_check(f);
813 if (r < 0)
814 return log_error_errno(r, "Failed to write \"%s\": %m", p);
815
816 r = link_tmpfile(fd, t, p);
817 if (r == -EEXIST)
818 return 0; /* Silently skip creation if the file exists now (recheck) */
819 if (r < 0)
820 return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
821
822 t = mfree(t);
823
824 return 1;
825 }
826
827 static int help(int argc, char *argv[], void *userdata) {
828
829 printf("%s [COMMAND] [OPTIONS...]\n"
830 "\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"
836 "\n"
837 "Commands:\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);
844
845 return 0;
846 }
847
848 static int parse_argv(int argc, char *argv[]) {
849 enum {
850 ARG_PATH = 0x100,
851 ARG_VERSION,
852 ARG_NO_VARIABLES,
853 };
854
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 },
860 { NULL, 0, NULL, 0 }
861 };
862
863 int c, r;
864
865 assert(argc >= 0);
866 assert(argv);
867
868 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
869 switch (c) {
870
871 case 'h':
872 help(0, NULL, NULL);
873 return 0;
874
875 case ARG_VERSION:
876 return version();
877
878 case ARG_PATH:
879 r = free_and_strdup(&arg_path, optarg);
880 if (r < 0)
881 return log_oom();
882 break;
883
884 case ARG_NO_VARIABLES:
885 arg_touch_variables = false;
886 break;
887
888 case '?':
889 return -EINVAL;
890
891 default:
892 assert_not_reached("Unknown option");
893 }
894
895 return 1;
896 }
897
898 static void read_loader_efi_var(const char *name, char **var) {
899 int r;
900
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);
904 }
905
906 static int must_be_root(void) {
907
908 if (geteuid() == 0)
909 return 0;
910
911 log_error("Need to be root.");
912 return -EPERM;
913 }
914
915 static int verb_status(int argc, char *argv[], void *userdata) {
916
917 sd_id128_t uuid = SD_ID128_NULL;
918 int r, r2;
919
920 r2 = find_esp_and_warn(NULL, NULL, NULL, &uuid);
921
922 if (is_efi_boot()) {
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;
925
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);
930
931 if (loader_path)
932 efi_tilt_backslashes(loader_path);
933
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");
937
938 printf("System:\n");
939 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
940
941 r = is_efi_secure_boot();
942 if (r < 0)
943 r2 = log_warning_errno(r, "Failed to query secure boot status: %m");
944 else
945 printf(" Secure Boot: %sd\n", enable_disable(r));
946
947 r = is_efi_secure_boot_setup_mode();
948 if (r < 0)
949 r2 = log_warning_errno(r, "Failed to query secure boot mode: %m");
950 else
951 printf(" Setup Mode: %s\n", r ? "setup" : "user");
952 printf("\n");
953
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));
959 else
960 printf(" ESP: n/a\n");
961 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
962 printf("\n");
963 } else
964 printf("System:\n Not booted with EFI\n\n");
965
966 r = status_binaries(arg_path, uuid);
967 if (r < 0)
968 r2 = r;
969
970 if (is_efi_boot()) {
971 r = status_variables();
972 if (r < 0)
973 r2 = r;
974 }
975
976 r = status_entries(arg_path, uuid);
977 if (r < 0)
978 r2 = r;
979
980 return r2;
981 }
982
983 static int verb_list(int argc, char *argv[], void *userdata) {
984 sd_id128_t uuid = SD_ID128_NULL;
985 int r;
986 unsigned n;
987
988 _cleanup_(boot_config_free) BootConfig config = {};
989
990 r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
991 if (r < 0)
992 return r;
993
994 r = boot_entries_load_config(arg_path, &config);
995 if (r < 0)
996 return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
997 arg_path);
998
999 printf("Available boot entries:\n");
1000
1001 for (n = 0; n < config.n_entries; n++) {
1002 const BootEntry *e = &config.entries[n];
1003
1004 printf(" title: %s%s%s%s%s%s\n",
1005 ansi_highlight(),
1006 boot_entry_title(e),
1007 ansi_normal(),
1008 ansi_highlight_green(),
1009 n == config.default_entry ? " (default)" : "",
1010 ansi_normal());
1011 if (e->version)
1012 printf(" version: %s\n", e->version);
1013 if (e->machine_id)
1014 printf(" machine-id: %s\n", e->machine_id);
1015 if (e->architecture)
1016 printf(" architecture: %s\n", e->architecture);
1017 if (e->kernel)
1018 printf(" linux: %s\n", e->kernel);
1019 if (!strv_isempty(e->initrd)) {
1020 _cleanup_free_ char *t;
1021
1022 t = strv_join(e->initrd, " ");
1023 if (!t)
1024 return log_oom();
1025
1026 printf(" initrd: %s\n", t);
1027 }
1028 if (!strv_isempty(e->options)) {
1029 _cleanup_free_ char *t;
1030
1031 t = strv_join(e->options, " ");
1032 if (!t)
1033 return log_oom();
1034
1035 printf(" options: %s\n", t);
1036 }
1037 if (e->device_tree)
1038 printf(" devicetree: %s\n", e->device_tree);
1039
1040 puts("");
1041 }
1042
1043 return 0;
1044 }
1045
1046 static int verb_install(int argc, char *argv[], void *userdata) {
1047
1048 sd_id128_t uuid = SD_ID128_NULL;
1049 uint64_t pstart = 0, psize = 0;
1050 uint32_t part = 0;
1051 bool install;
1052 int r;
1053
1054 r = must_be_root();
1055 if (r < 0)
1056 return r;
1057
1058 r = find_esp_and_warn(&part, &pstart, &psize, &uuid);
1059 if (r < 0)
1060 return r;
1061
1062 install = streq(argv[0], "install");
1063
1064 RUN_WITH_UMASK(0002) {
1065 r = install_binaries(arg_path, install);
1066 if (r < 0)
1067 return r;
1068
1069 if (install) {
1070 r = install_loader_config(arg_path);
1071 if (r < 0)
1072 return r;
1073 }
1074 }
1075
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",
1080 install);
1081
1082 return r;
1083 }
1084
1085 static int verb_remove(int argc, char *argv[], void *userdata) {
1086 sd_id128_t uuid = SD_ID128_NULL;
1087 int r;
1088
1089 r = must_be_root();
1090 if (r < 0)
1091 return r;
1092
1093 r = find_esp_and_warn(NULL, NULL, NULL, &uuid);
1094 if (r < 0)
1095 return r;
1096
1097 r = remove_binaries(arg_path);
1098
1099 if (arg_touch_variables) {
1100 int q;
1101
1102 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1103 if (q < 0 && r == 0)
1104 r = q;
1105 }
1106
1107 return r;
1108 }
1109
1110 static int bootctl_main(int argc, char *argv[]) {
1111
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 },
1119 {}
1120 };
1121
1122 return dispatch_verb(argc, argv, verbs, NULL);
1123 }
1124
1125 int main(int argc, char *argv[]) {
1126 int r;
1127
1128 log_parse_environment();
1129 log_open();
1130
1131 /* If we run in a container, automatically turn of EFI file system access */
1132 if (detect_container() > 0)
1133 arg_touch_variables = false;
1134
1135 r = parse_argv(argc, argv);
1136 if (r <= 0)
1137 goto finish;
1138
1139 r = bootctl_main(argc, argv);
1140
1141 finish:
1142 free(arg_path);
1143 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1144 }