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