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