]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/bootctl.c
Merge pull request #5449 from keszybz/blkd-error-handling
[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 <assert.h>
22 #include <blkid/blkid.h>
23 #include <ctype.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <ftw.h>
27 #include <getopt.h>
28 #include <limits.h>
29 #include <linux/magic.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 #include <sys/statfs.h>
37 #include <unistd.h>
38
39 #include "alloc-util.h"
40 #include "blkid-util.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 "umask-util.h"
54 #include "util.h"
55 #include "verbs.h"
56 #include "virt.h"
57
58 static char *arg_path = NULL;
59 static bool arg_touch_variables = true;
60
61 static int verify_esp(
62 bool searching,
63 const char *p,
64 uint32_t *ret_part,
65 uint64_t *ret_pstart,
66 uint64_t *ret_psize,
67 sd_id128_t *ret_uuid) {
68
69 _cleanup_blkid_free_probe_ blkid_probe b = NULL;
70 _cleanup_free_ char *t = NULL;
71 uint64_t pstart = 0, psize = 0;
72 struct stat st, st2;
73 const char *v, *t2;
74 struct statfs sfs;
75 sd_id128_t uuid = SD_ID128_NULL;
76 uint32_t part = 0;
77 int r;
78
79 assert(p);
80
81 if (statfs(p, &sfs) < 0) {
82
83 /* If we are searching for the mount point, don't generate a log message if we can't find the path */
84 if (errno == ENOENT && searching)
85 return -ENOENT;
86
87 return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p);
88 }
89
90 if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) {
91
92 if (searching)
93 return -EADDRNOTAVAIL;
94
95 log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
96 return -ENODEV;
97 }
98
99 if (stat(p, &st) < 0)
100 return log_error_errno(errno, "Failed to determine block device node of \"%s\": %m", p);
101
102 if (major(st.st_dev) == 0) {
103 log_error("Block device node of %p is invalid.", p);
104 return -ENODEV;
105 }
106
107 t2 = strjoina(p, "/..");
108 r = stat(t2, &st2);
109 if (r < 0)
110 return log_error_errno(errno, "Failed to determine block device node of parent of \"%s\": %m", p);
111
112 if (st.st_dev == st2.st_dev) {
113 log_error("Directory \"%s\" is not the root of the EFI System Partition (ESP) file system.", p);
114 return -ENODEV;
115 }
116
117 /* In a container we don't have access to block devices, skip this part of the verification, we trust the
118 * container manager set everything up correctly on its own. */
119 if (detect_container() > 0)
120 goto finish;
121
122 r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
123 if (r < 0)
124 return log_oom();
125
126 errno = 0;
127 b = blkid_new_probe_from_filename(t);
128 if (!b)
129 return log_error_errno(errno ?: ENOMEM, "Failed to open file system \"%s\": %m", p);
130
131 blkid_probe_enable_superblocks(b, 1);
132 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
133 blkid_probe_enable_partitions(b, 1);
134 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
135
136 errno = 0;
137 r = blkid_do_safeprobe(b);
138 if (r == -2) {
139 log_error("File system \"%s\" is ambiguous.", p);
140 return -ENODEV;
141 } else if (r == 1) {
142 log_error("File system \"%s\" does not contain a label.", p);
143 return -ENODEV;
144 } else if (r != 0)
145 return log_error_errno(errno ?: EIO, "Failed to probe file system \"%s\": %m", p);
146
147 errno = 0;
148 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
149 if (r != 0)
150 return log_error_errno(errno ?: EIO, "Failed to probe file system type \"%s\": %m", p);
151 if (!streq(v, "vfat")) {
152 log_error("File system \"%s\" is not FAT.", p);
153 return -ENODEV;
154 }
155
156 errno = 0;
157 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
158 if (r != 0)
159 return log_error_errno(errno ?: EIO, "Failed to probe partition scheme \"%s\": %m", p);
160 if (!streq(v, "gpt")) {
161 log_error("File system \"%s\" is not on a GPT partition table.", p);
162 return -ENODEV;
163 }
164
165 errno = 0;
166 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
167 if (r != 0)
168 return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID \"%s\": %m", p);
169 if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
170 log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p);
171 return -ENODEV;
172 }
173
174 errno = 0;
175 r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL);
176 if (r != 0)
177 return log_error_errno(errno ?: EIO, "Failed to probe partition entry UUID \"%s\": %m", p);
178 r = sd_id128_from_string(v, &uuid);
179 if (r < 0) {
180 log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v);
181 return -EIO;
182 }
183
184 errno = 0;
185 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
186 if (r != 0)
187 return log_error_errno(errno ?: EIO, "Failed to probe partition number \"%s\": m", p);
188 r = safe_atou32(v, &part);
189 if (r < 0)
190 return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.");
191
192 errno = 0;
193 r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
194 if (r != 0)
195 return log_error_errno(errno ?: EIO, "Failed to probe partition offset \"%s\": %m", p);
196 r = safe_atou64(v, &pstart);
197 if (r < 0)
198 return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.");
199
200 errno = 0;
201 r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
202 if (r != 0)
203 return log_error_errno(errno ?: EIO, "Failed to probe partition size \"%s\": %m", p);
204 r = safe_atou64(v, &psize);
205 if (r < 0)
206 return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.");
207
208 finish:
209 if (ret_part)
210 *ret_part = part;
211 if (ret_pstart)
212 *ret_pstart = pstart;
213 if (ret_psize)
214 *ret_psize = psize;
215 if (ret_uuid)
216 *ret_uuid = uuid;
217
218 return 0;
219 }
220
221 static int find_esp(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
222 const char *path;
223 int r;
224
225 if (arg_path)
226 return verify_esp(false, arg_path, part, pstart, psize, uuid);
227
228 FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
229
230 r = verify_esp(true, path, part, pstart, psize, uuid);
231 if (IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
232 continue;
233 if (r < 0)
234 return r;
235
236 arg_path = strdup(path);
237 if (!arg_path)
238 return log_oom();
239
240 log_info("Using EFI System Partition at %s.", path);
241 return 0;
242 }
243
244 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.");
245 return -ENOENT;
246 }
247
248 /* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
249 static int get_file_version(int fd, char **v) {
250 struct stat st;
251 char *buf;
252 const char *s, *e;
253 char *x = NULL;
254 int r = 0;
255
256 assert(fd >= 0);
257 assert(v);
258
259 if (fstat(fd, &st) < 0)
260 return log_error_errno(errno, "Failed to stat EFI binary: %m");
261
262 if (st.st_size < 27) {
263 *v = NULL;
264 return 0;
265 }
266
267 buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
268 if (buf == MAP_FAILED)
269 return log_error_errno(errno, "Failed to memory map EFI binary: %m");
270
271 s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
272 if (!s)
273 goto finish;
274 s += 17;
275
276 e = memmem(s, st.st_size - (s - buf), " ####", 5);
277 if (!e || e - s < 3) {
278 log_error("Malformed version string.");
279 r = -EINVAL;
280 goto finish;
281 }
282
283 x = strndup(s, e - s);
284 if (!x) {
285 r = log_oom();
286 goto finish;
287 }
288 r = 1;
289
290 finish:
291 (void) munmap(buf, st.st_size);
292 *v = x;
293 return r;
294 }
295
296 static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
297 char *p;
298 _cleanup_closedir_ DIR *d = NULL;
299 struct dirent *de;
300 int r = 0, c = 0;
301
302 p = strjoina(esp_path, "/", path);
303 d = opendir(p);
304 if (!d) {
305 if (errno == ENOENT)
306 return 0;
307
308 return log_error_errno(errno, "Failed to read \"%s\": %m", p);
309 }
310
311 FOREACH_DIRENT(de, d, break) {
312 _cleanup_close_ int fd = -1;
313 _cleanup_free_ char *v = NULL;
314
315 if (!endswith_no_case(de->d_name, ".efi"))
316 continue;
317
318 if (prefix && !startswith_no_case(de->d_name, prefix))
319 continue;
320
321 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
322 if (fd < 0)
323 return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);
324
325 r = get_file_version(fd, &v);
326 if (r < 0)
327 return r;
328 if (r > 0)
329 printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT), path, de->d_name, v);
330 else
331 printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT), path, de->d_name);
332 c++;
333 }
334
335 return c;
336 }
337
338 static int status_binaries(const char *esp_path, sd_id128_t partition) {
339 int r;
340
341 printf("Boot Loader Binaries:\n");
342
343 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
345 r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
346 if (r == 0)
347 log_error("systemd-boot not installed in ESP.");
348 else if (r < 0)
349 return r;
350
351 r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
352 if (r == 0)
353 log_error("No default/fallback boot loader installed in ESP.");
354 else if (r < 0)
355 return r;
356
357 printf("\n");
358
359 return 0;
360 }
361
362 static int print_efi_option(uint16_t id, bool in_order) {
363 _cleanup_free_ char *title = NULL;
364 _cleanup_free_ char *path = NULL;
365 sd_id128_t partition;
366 bool active;
367 int r = 0;
368
369 r = efi_get_boot_option(id, &title, &partition, &path, &active);
370 if (r < 0)
371 return r;
372
373 /* print only configured entries with partition information */
374 if (!path || sd_id128_is_null(partition))
375 return 0;
376
377 efi_tilt_backslashes(path);
378
379 printf(" Title: %s\n", strna(title));
380 printf(" ID: 0x%04X\n", id);
381 printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
382 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));
383 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), path);
384 printf("\n");
385
386 return 0;
387 }
388
389 static int status_variables(void) {
390 int n_options, n_order;
391 _cleanup_free_ uint16_t *options = NULL, *order = NULL;
392 int i;
393
394 if (!is_efi_boot()) {
395 log_notice("Not booted with EFI, not showing EFI variables.");
396 return 0;
397 }
398
399 n_options = efi_get_boot_options(&options);
400 if (n_options == -ENOENT)
401 return log_error_errno(n_options,
402 "Failed to access EFI variables, efivarfs"
403 " needs to be available at /sys/firmware/efi/efivars/.");
404 if (n_options < 0)
405 return log_error_errno(n_options, "Failed to read EFI boot entries: %m");
406
407 n_order = efi_get_boot_order(&order);
408 if (n_order == -ENOENT)
409 n_order = 0;
410 else if (n_order < 0)
411 return log_error_errno(n_order, "Failed to read EFI boot order.");
412
413 /* print entries in BootOrder first */
414 printf("Boot Loader Entries in EFI Variables:\n");
415 for (i = 0; i < n_order; i++)
416 print_efi_option(order[i], true);
417
418 /* print remaining entries */
419 for (i = 0; i < n_options; i++) {
420 int j;
421
422 for (j = 0; j < n_order; j++)
423 if (options[i] == order[j])
424 goto next_option;
425
426 print_efi_option(options[i], false);
427
428 next_option:
429 continue;
430 }
431
432 return 0;
433 }
434
435 static int compare_product(const char *a, const char *b) {
436 size_t x, y;
437
438 assert(a);
439 assert(b);
440
441 x = strcspn(a, " ");
442 y = strcspn(b, " ");
443 if (x != y)
444 return x < y ? -1 : x > y ? 1 : 0;
445
446 return strncmp(a, b, x);
447 }
448
449 static int compare_version(const char *a, const char *b) {
450 assert(a);
451 assert(b);
452
453 a += strcspn(a, " ");
454 a += strspn(a, " ");
455 b += strcspn(b, " ");
456 b += strspn(b, " ");
457
458 return strverscmp(a, b);
459 }
460
461 static int version_check(int fd_from, const char *from, int fd_to, const char *to) {
462 _cleanup_free_ char *a = NULL, *b = NULL;
463 int r;
464
465 assert(fd_from >= 0);
466 assert(from);
467 assert(fd_to >= 0);
468 assert(to);
469
470 r = get_file_version(fd_from, &a);
471 if (r < 0)
472 return r;
473 if (r == 0) {
474 log_error("Source file \"%s\" does not carry version information!", from);
475 return -EINVAL;
476 }
477
478 r = get_file_version(fd_to, &b);
479 if (r < 0)
480 return r;
481 if (r == 0 || compare_product(a, b) != 0) {
482 log_notice("Skipping \"%s\", since it's owned by another boot loader.", to);
483 return -EEXIST;
484 }
485
486 if (compare_version(a, b) < 0) {
487 log_warning("Skipping \"%s\", since a newer boot loader version exists already.", to);
488 return -ESTALE;
489 }
490
491 return 0;
492 }
493
494 static int copy_file_with_version_check(const char *from, const char *to, bool force) {
495 _cleanup_close_ int fd_from = -1, fd_to = -1;
496 _cleanup_free_ char *t = NULL;
497 int r;
498
499 fd_from = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
500 if (fd_from < 0)
501 return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", from);
502
503 if (!force) {
504 fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY);
505 if (fd_to < 0) {
506 if (errno != -ENOENT)
507 return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to);
508 } else {
509 r = version_check(fd_from, from, fd_to, to);
510 if (r < 0)
511 return r;
512
513 if (lseek(fd_from, 0, SEEK_SET) == (off_t) -1)
514 return log_error_errno(errno, "Failed to seek in \%s\": %m", from);
515
516 fd_to = safe_close(fd_to);
517 }
518 }
519
520 r = tempfn_random(to, NULL, &t);
521 if (r < 0)
522 return log_oom();
523
524 RUN_WITH_UMASK(0000) {
525 fd_to = open(t, O_WRONLY|O_CREAT|O_CLOEXEC|O_EXCL|O_NOFOLLOW, 0644);
526 if (fd_to < 0)
527 return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", t);
528 }
529
530 r = copy_bytes(fd_from, fd_to, (uint64_t) -1, COPY_REFLINK);
531 if (r < 0) {
532 unlink(t);
533 return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t);
534 }
535
536 (void) copy_times(fd_from, fd_to);
537
538 r = renameat(AT_FDCWD, t, AT_FDCWD, to);
539 if (r < 0) {
540 (void) unlink_noerrno(t);
541 return log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", t, to);
542 }
543
544 log_info("Copied \"%s\" to \"%s\".", from, to);
545
546 return 0;
547 }
548
549 static int mkdir_one(const char *prefix, const char *suffix) {
550 char *p;
551
552 p = strjoina(prefix, "/", suffix);
553 if (mkdir(p, 0700) < 0) {
554 if (errno != EEXIST)
555 return log_error_errno(errno, "Failed to create \"%s\": %m", p);
556 } else
557 log_info("Created \"%s\".", p);
558
559 return 0;
560 }
561
562 static const char *efi_subdirs[] = {
563 "EFI",
564 "EFI/systemd",
565 "EFI/BOOT",
566 "loader",
567 "loader/entries",
568 NULL
569 };
570
571 static int create_dirs(const char *esp_path) {
572 const char **i;
573 int r;
574
575 STRV_FOREACH(i, efi_subdirs) {
576 r = mkdir_one(esp_path, *i);
577 if (r < 0)
578 return r;
579 }
580
581 return 0;
582 }
583
584 static int copy_one_file(const char *esp_path, const char *name, bool force) {
585 char *p, *q;
586 int r;
587
588 p = strjoina(BOOTLIBDIR "/", name);
589 q = strjoina(esp_path, "/EFI/systemd/", name);
590 r = copy_file_with_version_check(p, q, force);
591
592 if (startswith(name, "systemd-boot")) {
593 int k;
594 char *v;
595
596 /* Create the EFI default boot loader name (specified for removable devices) */
597 v = strjoina(esp_path, "/EFI/BOOT/BOOT", name + strlen("systemd-boot"));
598 ascii_strupper(strrchr(v, '/') + 1);
599
600 k = copy_file_with_version_check(p, v, force);
601 if (k < 0 && r == 0)
602 r = k;
603 }
604
605 return r;
606 }
607
608 static int install_binaries(const char *esp_path, bool force) {
609 struct dirent *de;
610 _cleanup_closedir_ DIR *d = NULL;
611 int r = 0;
612
613 if (force) {
614 /* Don't create any of these directories when we are
615 * just updating. When we update we'll drop-in our
616 * files (unless there are newer ones already), but we
617 * won't create the directories for them in the first
618 * place. */
619 r = create_dirs(esp_path);
620 if (r < 0)
621 return r;
622 }
623
624 d = opendir(BOOTLIBDIR);
625 if (!d)
626 return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
627
628 FOREACH_DIRENT(de, d, break) {
629 int k;
630
631 if (!endswith_no_case(de->d_name, ".efi"))
632 continue;
633
634 k = copy_one_file(esp_path, de->d_name, force);
635 if (k < 0 && r == 0)
636 r = k;
637 }
638
639 return r;
640 }
641
642 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
643 _cleanup_free_ char *opath = NULL;
644 sd_id128_t ouuid;
645 int r;
646
647 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
648 if (r < 0)
649 return false;
650 if (!sd_id128_equal(uuid, ouuid))
651 return false;
652 if (!streq_ptr(path, opath))
653 return false;
654
655 return true;
656 }
657
658 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
659 _cleanup_free_ uint16_t *options = NULL;
660 int n, i;
661
662 n = efi_get_boot_options(&options);
663 if (n < 0)
664 return n;
665
666 /* find already existing systemd-boot entry */
667 for (i = 0; i < n; i++)
668 if (same_entry(options[i], uuid, path)) {
669 *id = options[i];
670 return 1;
671 }
672
673 /* find free slot in the sorted BootXXXX variable list */
674 for (i = 0; i < n; i++)
675 if (i != options[i]) {
676 *id = i;
677 return 1;
678 }
679
680 /* use the next one */
681 if (i == 0xffff)
682 return -ENOSPC;
683 *id = i;
684 return 0;
685 }
686
687 static int insert_into_order(uint16_t slot, bool first) {
688 _cleanup_free_ uint16_t *order = NULL;
689 uint16_t *t;
690 int n, i;
691
692 n = efi_get_boot_order(&order);
693 if (n <= 0)
694 /* no entry, add us */
695 return efi_set_boot_order(&slot, 1);
696
697 /* are we the first and only one? */
698 if (n == 1 && order[0] == slot)
699 return 0;
700
701 /* are we already in the boot order? */
702 for (i = 0; i < n; i++) {
703 if (order[i] != slot)
704 continue;
705
706 /* we do not require to be the first one, all is fine */
707 if (!first)
708 return 0;
709
710 /* move us to the first slot */
711 memmove(order + 1, order, i * sizeof(uint16_t));
712 order[0] = slot;
713 return efi_set_boot_order(order, n);
714 }
715
716 /* extend array */
717 t = realloc(order, (n + 1) * sizeof(uint16_t));
718 if (!t)
719 return -ENOMEM;
720 order = t;
721
722 /* add us to the top or end of the list */
723 if (first) {
724 memmove(order + 1, order, n * sizeof(uint16_t));
725 order[0] = slot;
726 } else
727 order[n] = slot;
728
729 return efi_set_boot_order(order, n + 1);
730 }
731
732 static int remove_from_order(uint16_t slot) {
733 _cleanup_free_ uint16_t *order = NULL;
734 int n, i;
735
736 n = efi_get_boot_order(&order);
737 if (n <= 0)
738 return n;
739
740 for (i = 0; i < n; i++) {
741 if (order[i] != slot)
742 continue;
743
744 if (i + 1 < n)
745 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
746 return efi_set_boot_order(order, n - 1);
747 }
748
749 return 0;
750 }
751
752 static int install_variables(const char *esp_path,
753 uint32_t part, uint64_t pstart, uint64_t psize,
754 sd_id128_t uuid, const char *path,
755 bool first) {
756 char *p;
757 uint16_t slot;
758 int r;
759
760 if (!is_efi_boot()) {
761 log_warning("Not booted with EFI, skipping EFI variable setup.");
762 return 0;
763 }
764
765 p = strjoina(esp_path, path);
766 if (access(p, F_OK) < 0) {
767 if (errno == ENOENT)
768 return 0;
769
770 return log_error_errno(errno, "Cannot access \"%s\": %m", p);
771 }
772
773 r = find_slot(uuid, path, &slot);
774 if (r < 0)
775 return log_error_errno(r,
776 r == -ENOENT ?
777 "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" :
778 "Failed to determine current boot order: %m");
779
780 if (first || r == 0) {
781 r = efi_add_boot_option(slot, "Linux Boot Manager",
782 part, pstart, psize,
783 uuid, path);
784 if (r < 0)
785 return log_error_errno(r, "Failed to create EFI Boot variable entry: %m");
786
787 log_info("Created EFI boot entry \"Linux Boot Manager\".");
788 }
789
790 return insert_into_order(slot, first);
791 }
792
793 static int remove_boot_efi(const char *esp_path) {
794 char *p;
795 _cleanup_closedir_ DIR *d = NULL;
796 struct dirent *de;
797 int r, c = 0;
798
799 p = strjoina(esp_path, "/EFI/BOOT");
800 d = opendir(p);
801 if (!d) {
802 if (errno == ENOENT)
803 return 0;
804
805 return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
806 }
807
808 FOREACH_DIRENT(de, d, break) {
809 _cleanup_close_ int fd = -1;
810 _cleanup_free_ char *v = NULL;
811
812 if (!endswith_no_case(de->d_name, ".efi"))
813 continue;
814
815 if (!startswith_no_case(de->d_name, "boot"))
816 continue;
817
818 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
819 if (fd < 0)
820 return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);
821
822 r = get_file_version(fd, &v);
823 if (r < 0)
824 return r;
825 if (r > 0 && startswith(v, "systemd-boot ")) {
826 r = unlinkat(dirfd(d), de->d_name, 0);
827 if (r < 0)
828 return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name);
829
830 log_info("Removed \"%s/%s\".", p, de->d_name);
831 }
832
833 c++;
834 }
835
836 return c;
837 }
838
839 static int rmdir_one(const char *prefix, const char *suffix) {
840 char *p;
841
842 p = strjoina(prefix, "/", suffix);
843 if (rmdir(p) < 0) {
844 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
845 return log_error_errno(errno, "Failed to remove \"%s\": %m", p);
846 } else
847 log_info("Removed \"%s\".", p);
848
849 return 0;
850 }
851
852 static int remove_binaries(const char *esp_path) {
853 char *p;
854 int r, q;
855 unsigned i;
856
857 p = strjoina(esp_path, "/EFI/systemd");
858 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
859
860 q = remove_boot_efi(esp_path);
861 if (q < 0 && r == 0)
862 r = q;
863
864 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
865 q = rmdir_one(esp_path, efi_subdirs[i-1]);
866 if (q < 0 && r == 0)
867 r = q;
868 }
869
870 return r;
871 }
872
873 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
874 uint16_t slot;
875 int r;
876
877 if (!is_efi_boot())
878 return 0;
879
880 r = find_slot(uuid, path, &slot);
881 if (r != 1)
882 return 0;
883
884 r = efi_remove_boot_option(slot);
885 if (r < 0)
886 return r;
887
888 if (in_order)
889 return remove_from_order(slot);
890
891 return 0;
892 }
893
894 static int install_loader_config(const char *esp_path) {
895
896 char machine_string[SD_ID128_STRING_MAX];
897 _cleanup_(unlink_and_freep) char *t = NULL;
898 _cleanup_fclose_ FILE *f = NULL;
899 sd_id128_t machine_id;
900 const char *p;
901 int r, fd;
902
903 r = sd_id128_get_machine(&machine_id);
904 if (r < 0)
905 return log_error_errno(r, "Failed to get machine did: %m");
906
907 p = strjoina(esp_path, "/loader/loader.conf");
908
909 if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
910 return 0;
911
912 fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
913 if (fd < 0)
914 return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p);
915
916 f = fdopen(fd, "we");
917 if (!f) {
918 safe_close(fd);
919 return log_oom();
920 }
921
922 fprintf(f, "#timeout 3\n");
923 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
924
925 r = fflush_and_check(f);
926 if (r < 0)
927 return log_error_errno(r, "Failed to write \"%s\": %m", p);
928
929 r = link_tmpfile(fd, t, p);
930 if (r == -EEXIST)
931 return 0; /* Silently skip creation if the file exists now (recheck) */
932 if (r < 0)
933 return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
934
935 t = mfree(t);
936
937 return 1;
938 }
939
940 static int help(int argc, char *argv[], void *userdata) {
941
942 printf("%s [COMMAND] [OPTIONS...]\n"
943 "\n"
944 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
945 " -h --help Show this help\n"
946 " --version Print version\n"
947 " --path=PATH Path to the EFI System Partition (ESP)\n"
948 " --no-variables Don't touch EFI variables\n"
949 "\n"
950 "Commands:\n"
951 " status Show status of installed systemd-boot and EFI variables\n"
952 " install Install systemd-boot to the ESP and EFI variables\n"
953 " update Update systemd-boot in the ESP and EFI variables\n"
954 " remove Remove systemd-boot from the ESP and EFI variables\n",
955 program_invocation_short_name);
956
957 return 0;
958 }
959
960 static int parse_argv(int argc, char *argv[]) {
961 enum {
962 ARG_PATH = 0x100,
963 ARG_VERSION,
964 ARG_NO_VARIABLES,
965 };
966
967 static const struct option options[] = {
968 { "help", no_argument, NULL, 'h' },
969 { "version", no_argument, NULL, ARG_VERSION },
970 { "path", required_argument, NULL, ARG_PATH },
971 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
972 { NULL, 0, NULL, 0 }
973 };
974
975 int c, r;
976
977 assert(argc >= 0);
978 assert(argv);
979
980 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
981 switch (c) {
982
983 case 'h':
984 help(0, NULL, NULL);
985 return 0;
986
987 case ARG_VERSION:
988 return version();
989
990 case ARG_PATH:
991 r = free_and_strdup(&arg_path, optarg);
992 if (r < 0)
993 return log_oom();
994 break;
995
996 case ARG_NO_VARIABLES:
997 arg_touch_variables = false;
998 break;
999
1000 case '?':
1001 return -EINVAL;
1002
1003 default:
1004 assert_not_reached("Unknown option");
1005 }
1006
1007 return 1;
1008 }
1009
1010 static void read_loader_efi_var(const char *name, char **var) {
1011 int r;
1012
1013 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
1014 if (r < 0 && r != -ENOENT)
1015 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1016 }
1017
1018 static int must_be_root(void) {
1019
1020 if (geteuid() == 0)
1021 return 0;
1022
1023 log_error("Need to be root.");
1024 return -EPERM;
1025 }
1026
1027 static int verb_status(int argc, char *argv[], void *userdata) {
1028
1029 sd_id128_t uuid = SD_ID128_NULL;
1030 int r;
1031
1032 r = must_be_root();
1033 if (r < 0)
1034 return r;
1035
1036 r = find_esp(NULL, NULL, NULL, &uuid);
1037 if (r < 0)
1038 return r;
1039
1040 if (is_efi_boot()) {
1041 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1042 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1043
1044 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1045 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1046 read_loader_efi_var("LoaderInfo", &loader);
1047 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1048
1049 if (loader_path)
1050 efi_tilt_backslashes(loader_path);
1051
1052 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1053 if (r < 0 && r != -ENOENT)
1054 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1055
1056 printf("System:\n");
1057 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1058
1059 r = is_efi_secure_boot();
1060 if (r < 0)
1061 log_warning_errno(r, "Failed to query secure boot status: %m");
1062 else
1063 printf(" Secure Boot: %sd\n", enable_disable(r));
1064
1065 r = is_efi_secure_boot_setup_mode();
1066 if (r < 0)
1067 log_warning_errno(r, "Failed to query secure boot mode: %m");
1068 else
1069 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1070 printf("\n");
1071
1072 printf("Loader:\n");
1073 printf(" Product: %s\n", strna(loader));
1074 if (!sd_id128_is_null(loader_part_uuid))
1075 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1076 SD_ID128_FORMAT_VAL(loader_part_uuid));
1077 else
1078 printf(" Partition: n/a\n");
1079 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1080 printf("\n");
1081 } else
1082 printf("System:\n Not booted with EFI\n");
1083
1084 r = status_binaries(arg_path, uuid);
1085 if (r < 0)
1086 return r;
1087
1088 if (arg_touch_variables)
1089 r = status_variables();
1090
1091 return r;
1092 }
1093
1094 static int verb_install(int argc, char *argv[], void *userdata) {
1095
1096 sd_id128_t uuid = SD_ID128_NULL;
1097 uint64_t pstart = 0, psize = 0;
1098 uint32_t part = 0;
1099 bool install;
1100 int r;
1101
1102 r = must_be_root();
1103 if (r < 0)
1104 return r;
1105
1106 r = find_esp(&part, &pstart, &psize, &uuid);
1107 if (r < 0)
1108 return r;
1109
1110 install = streq(argv[0], "install");
1111
1112 RUN_WITH_UMASK(0002) {
1113 r = install_binaries(arg_path, install);
1114 if (r < 0)
1115 return r;
1116
1117 if (install) {
1118 r = install_loader_config(arg_path);
1119 if (r < 0)
1120 return r;
1121 }
1122 }
1123
1124 if (arg_touch_variables)
1125 r = install_variables(arg_path,
1126 part, pstart, psize, uuid,
1127 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1128 install);
1129
1130 return r;
1131 }
1132
1133 static int verb_remove(int argc, char *argv[], void *userdata) {
1134 sd_id128_t uuid = SD_ID128_NULL;
1135 int r;
1136
1137 r = must_be_root();
1138 if (r < 0)
1139 return r;
1140
1141 r = find_esp(NULL, NULL, NULL, &uuid);
1142 if (r < 0)
1143 return r;
1144
1145 r = remove_binaries(arg_path);
1146
1147 if (arg_touch_variables) {
1148 int q;
1149
1150 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1151 if (q < 0 && r == 0)
1152 r = q;
1153 }
1154
1155 return r;
1156 }
1157
1158 static int bootctl_main(int argc, char *argv[]) {
1159
1160 static const Verb verbs[] = {
1161 { "help", VERB_ANY, VERB_ANY, 0, help },
1162 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1163 { "install", VERB_ANY, 1, 0, verb_install },
1164 { "update", VERB_ANY, 1, 0, verb_install },
1165 { "remove", VERB_ANY, 1, 0, verb_remove },
1166 {}
1167 };
1168
1169 return dispatch_verb(argc, argv, verbs, NULL);
1170 }
1171
1172 int main(int argc, char *argv[]) {
1173 int r;
1174
1175 log_parse_environment();
1176 log_open();
1177
1178 /* If we run in a container, automatically turn of EFI file system access */
1179 if (detect_container() > 0)
1180 arg_touch_variables = false;
1181
1182 r = parse_argv(argc, argv);
1183 if (r <= 0)
1184 goto finish;
1185
1186 r = bootctl_main(argc, argv);
1187
1188 finish:
1189 free(arg_path);
1190 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1191 }