]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/bootctl.c
Merge pull request #4390 from keszybz/install-specifiers
[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 NULL
626 };
627
628 static int create_dirs(const char *esp_path) {
629 const char **i;
630 int r;
631
632 STRV_FOREACH(i, efi_subdirs) {
633 r = mkdir_one(esp_path, *i);
634 if (r < 0)
635 return r;
636 }
637
638 return 0;
639 }
640
641 static int copy_one_file(const char *esp_path, const char *name, bool force) {
642 char *p, *q;
643 int r;
644
645 p = strjoina(BOOTLIBDIR "/", name);
646 q = strjoina(esp_path, "/EFI/systemd/", name);
647 r = copy_file(p, q, force);
648
649 if (startswith(name, "systemd-boot")) {
650 int k;
651 char *v;
652
653 /* Create the EFI default boot loader name (specified for removable devices) */
654 v = strjoina(esp_path, "/EFI/BOOT/BOOT", name + strlen("systemd-boot"));
655 ascii_strupper(strrchr(v, '/') + 1);
656
657 k = copy_file(p, v, force);
658 if (k < 0 && r == 0)
659 r = k;
660 }
661
662 return r;
663 }
664
665 static int install_binaries(const char *esp_path, bool force) {
666 struct dirent *de;
667 _cleanup_closedir_ DIR *d = NULL;
668 int r = 0;
669
670 if (force) {
671 /* Don't create any of these directories when we are
672 * just updating. When we update we'll drop-in our
673 * files (unless there are newer ones already), but we
674 * won't create the directories for them in the first
675 * place. */
676 r = create_dirs(esp_path);
677 if (r < 0)
678 return r;
679 }
680
681 d = opendir(BOOTLIBDIR);
682 if (!d)
683 return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
684
685 FOREACH_DIRENT(de, d, break) {
686 int k;
687
688 if (!endswith_no_case(de->d_name, ".efi"))
689 continue;
690
691 k = copy_one_file(esp_path, de->d_name, force);
692 if (k < 0 && r == 0)
693 r = k;
694 }
695
696 return r;
697 }
698
699 static bool same_entry(uint16_t id, const sd_id128_t uuid, const char *path) {
700 _cleanup_free_ char *opath = NULL;
701 sd_id128_t ouuid;
702 int r;
703
704 r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL);
705 if (r < 0)
706 return false;
707 if (!sd_id128_equal(uuid, ouuid))
708 return false;
709 if (!streq_ptr(path, opath))
710 return false;
711
712 return true;
713 }
714
715 static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
716 _cleanup_free_ uint16_t *options = NULL;
717 int n, i;
718
719 n = efi_get_boot_options(&options);
720 if (n < 0)
721 return n;
722
723 /* find already existing systemd-boot entry */
724 for (i = 0; i < n; i++)
725 if (same_entry(options[i], uuid, path)) {
726 *id = options[i];
727 return 1;
728 }
729
730 /* find free slot in the sorted BootXXXX variable list */
731 for (i = 0; i < n; i++)
732 if (i != options[i]) {
733 *id = i;
734 return 1;
735 }
736
737 /* use the next one */
738 if (i == 0xffff)
739 return -ENOSPC;
740 *id = i;
741 return 0;
742 }
743
744 static int insert_into_order(uint16_t slot, bool first) {
745 _cleanup_free_ uint16_t *order = NULL;
746 uint16_t *t;
747 int n, i;
748
749 n = efi_get_boot_order(&order);
750 if (n <= 0)
751 /* no entry, add us */
752 return efi_set_boot_order(&slot, 1);
753
754 /* are we the first and only one? */
755 if (n == 1 && order[0] == slot)
756 return 0;
757
758 /* are we already in the boot order? */
759 for (i = 0; i < n; i++) {
760 if (order[i] != slot)
761 continue;
762
763 /* we do not require to be the first one, all is fine */
764 if (!first)
765 return 0;
766
767 /* move us to the first slot */
768 memmove(order + 1, order, i * sizeof(uint16_t));
769 order[0] = slot;
770 return efi_set_boot_order(order, n);
771 }
772
773 /* extend array */
774 t = realloc(order, (n + 1) * sizeof(uint16_t));
775 if (!t)
776 return -ENOMEM;
777 order = t;
778
779 /* add us to the top or end of the list */
780 if (first) {
781 memmove(order + 1, order, n * sizeof(uint16_t));
782 order[0] = slot;
783 } else
784 order[n] = slot;
785
786 return efi_set_boot_order(order, n + 1);
787 }
788
789 static int remove_from_order(uint16_t slot) {
790 _cleanup_free_ uint16_t *order = NULL;
791 int n, i;
792
793 n = efi_get_boot_order(&order);
794 if (n <= 0)
795 return n;
796
797 for (i = 0; i < n; i++) {
798 if (order[i] != slot)
799 continue;
800
801 if (i + 1 < n)
802 memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t));
803 return efi_set_boot_order(order, n - 1);
804 }
805
806 return 0;
807 }
808
809 static int install_variables(const char *esp_path,
810 uint32_t part, uint64_t pstart, uint64_t psize,
811 sd_id128_t uuid, const char *path,
812 bool first) {
813 char *p;
814 uint16_t slot;
815 int r;
816
817 if (!is_efi_boot()) {
818 log_warning("Not booted with EFI, skipping EFI variable setup.");
819 return 0;
820 }
821
822 p = strjoina(esp_path, path);
823 if (access(p, F_OK) < 0) {
824 if (errno == ENOENT)
825 return 0;
826
827 return log_error_errno(errno, "Cannot access \"%s\": %m", p);
828 }
829
830 r = find_slot(uuid, path, &slot);
831 if (r < 0)
832 return log_error_errno(r,
833 r == -ENOENT ?
834 "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" :
835 "Failed to determine current boot order: %m");
836
837 if (first || r == 0) {
838 r = efi_add_boot_option(slot, "Linux Boot Manager",
839 part, pstart, psize,
840 uuid, path);
841 if (r < 0)
842 return log_error_errno(r, "Failed to create EFI Boot variable entry: %m");
843
844 log_info("Created EFI boot entry \"Linux Boot Manager\".");
845 }
846
847 return insert_into_order(slot, first);
848 }
849
850 static int remove_boot_efi(const char *esp_path) {
851 char *p;
852 _cleanup_closedir_ DIR *d = NULL;
853 struct dirent *de;
854 int r, c = 0;
855
856 p = strjoina(esp_path, "/EFI/BOOT");
857 d = opendir(p);
858 if (!d) {
859 if (errno == ENOENT)
860 return 0;
861
862 return log_error_errno(errno, "Failed to open directory \"%s\": %m", p);
863 }
864
865 FOREACH_DIRENT(de, d, break) {
866 _cleanup_close_ int fd = -1;
867 _cleanup_free_ char *v = NULL;
868
869 if (!endswith_no_case(de->d_name, ".efi"))
870 continue;
871
872 if (!startswith_no_case(de->d_name, "boot"))
873 continue;
874
875 fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC);
876 if (fd < 0)
877 return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name);
878
879 r = get_file_version(fd, &v);
880 if (r < 0)
881 return r;
882 if (r > 0 && startswith(v, "systemd-boot ")) {
883 r = unlinkat(dirfd(d), de->d_name, 0);
884 if (r < 0)
885 return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name);
886
887 log_info("Removed \"%s/%s\".", p, de->d_name);
888 }
889
890 c++;
891 }
892
893 return c;
894 }
895
896 static int rmdir_one(const char *prefix, const char *suffix) {
897 char *p;
898
899 p = strjoina(prefix, "/", suffix);
900 if (rmdir(p) < 0) {
901 if (!IN_SET(errno, ENOENT, ENOTEMPTY))
902 return log_error_errno(errno, "Failed to remove \"%s\": %m", p);
903 } else
904 log_info("Removed \"%s\".", p);
905
906 return 0;
907 }
908
909 static int remove_binaries(const char *esp_path) {
910 char *p;
911 int r, q;
912 unsigned i;
913
914 p = strjoina(esp_path, "/EFI/systemd");
915 r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
916
917 q = remove_boot_efi(esp_path);
918 if (q < 0 && r == 0)
919 r = q;
920
921 for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
922 q = rmdir_one(esp_path, efi_subdirs[i-1]);
923 if (q < 0 && r == 0)
924 r = q;
925 }
926
927 return r;
928 }
929
930 static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
931 uint16_t slot;
932 int r;
933
934 if (!is_efi_boot())
935 return 0;
936
937 r = find_slot(uuid, path, &slot);
938 if (r != 1)
939 return 0;
940
941 r = efi_remove_boot_option(slot);
942 if (r < 0)
943 return r;
944
945 if (in_order)
946 return remove_from_order(slot);
947
948 return 0;
949 }
950
951 static int install_loader_config(const char *esp_path) {
952
953 _cleanup_fclose_ FILE *f = NULL;
954 char machine_string[SD_ID128_STRING_MAX];
955 sd_id128_t machine_id;
956 const char *p;
957 int r;
958
959 r = sd_id128_get_machine(&machine_id);
960 if (r < 0)
961 return log_error_errno(r, "Failed to get machine did: %m");
962
963 p = strjoina(esp_path, "/loader/loader.conf");
964 f = fopen(p, "wxe");
965 if (!f)
966 return log_error_errno(errno, "Failed to open loader.conf for writing: %m");
967
968 fprintf(f, "#timeout 3\n");
969 fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
970
971 r = fflush_and_check(f);
972 if (r < 0)
973 return log_error_errno(r, "Failed to write \"%s\": %m", p);
974
975 return 0;
976 }
977
978 static int help(int argc, char *argv[], void *userdata) {
979
980 printf("%s [COMMAND] [OPTIONS...]\n"
981 "\n"
982 "Install, update or remove the systemd-boot EFI boot manager.\n\n"
983 " -h --help Show this help\n"
984 " --version Print version\n"
985 " --path=PATH Path to the EFI System Partition (ESP)\n"
986 " --no-variables Don't touch EFI variables\n"
987 "\n"
988 "Commands:\n"
989 " status Show status of installed systemd-boot and EFI variables\n"
990 " install Install systemd-boot to the ESP and EFI variables\n"
991 " update Update systemd-boot in the ESP and EFI variables\n"
992 " remove Remove systemd-boot from the ESP and EFI variables\n",
993 program_invocation_short_name);
994
995 return 0;
996 }
997
998 static int parse_argv(int argc, char *argv[]) {
999 enum {
1000 ARG_PATH = 0x100,
1001 ARG_VERSION,
1002 ARG_NO_VARIABLES,
1003 };
1004
1005 static const struct option options[] = {
1006 { "help", no_argument, NULL, 'h' },
1007 { "version", no_argument, NULL, ARG_VERSION },
1008 { "path", required_argument, NULL, ARG_PATH },
1009 { "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
1010 { NULL, 0, NULL, 0 }
1011 };
1012
1013 int c, r;
1014
1015 assert(argc >= 0);
1016 assert(argv);
1017
1018 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
1019 switch (c) {
1020
1021 case 'h':
1022 help(0, NULL, NULL);
1023 return 0;
1024
1025 case ARG_VERSION:
1026 return version();
1027
1028 case ARG_PATH:
1029 r = free_and_strdup(&arg_path, optarg);
1030 if (r < 0)
1031 return log_oom();
1032 break;
1033
1034 case ARG_NO_VARIABLES:
1035 arg_touch_variables = false;
1036 break;
1037
1038 case '?':
1039 return -EINVAL;
1040
1041 default:
1042 assert_not_reached("Unknown option");
1043 }
1044
1045 return 1;
1046 }
1047
1048 static void read_loader_efi_var(const char *name, char **var) {
1049 int r;
1050
1051 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var);
1052 if (r < 0 && r != -ENOENT)
1053 log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
1054 }
1055
1056 static int must_be_root(void) {
1057
1058 if (geteuid() == 0)
1059 return 0;
1060
1061 log_error("Need to be root.");
1062 return -EPERM;
1063 }
1064
1065 static int verb_status(int argc, char *argv[], void *userdata) {
1066
1067 sd_id128_t uuid = SD_ID128_NULL;
1068 int r;
1069
1070 r = must_be_root();
1071 if (r < 0)
1072 return r;
1073
1074 r = find_esp(NULL, NULL, NULL, &uuid);
1075 if (r < 0)
1076 return r;
1077
1078 if (is_efi_boot()) {
1079 _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
1080 sd_id128_t loader_part_uuid = SD_ID128_NULL;
1081
1082 read_loader_efi_var("LoaderFirmwareType", &fw_type);
1083 read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
1084 read_loader_efi_var("LoaderInfo", &loader);
1085 read_loader_efi_var("LoaderImageIdentifier", &loader_path);
1086
1087 if (loader_path)
1088 efi_tilt_backslashes(loader_path);
1089
1090 r = efi_loader_get_device_part_uuid(&loader_part_uuid);
1091 if (r < 0 && r != -ENOENT)
1092 log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
1093
1094 printf("System:\n");
1095 printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
1096
1097 r = is_efi_secure_boot();
1098 if (r < 0)
1099 log_warning_errno(r, "Failed to query secure boot status: %m");
1100 else
1101 printf(" Secure Boot: %sd\n", enable_disable(r));
1102
1103 r = is_efi_secure_boot_setup_mode();
1104 if (r < 0)
1105 log_warning_errno(r, "Failed to query secure boot mode: %m");
1106 else
1107 printf(" Setup Mode: %s\n", r ? "setup" : "user");
1108 printf("\n");
1109
1110 printf("Loader:\n");
1111 printf(" Product: %s\n", strna(loader));
1112 if (!sd_id128_is_null(loader_part_uuid))
1113 printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
1114 SD_ID128_FORMAT_VAL(loader_part_uuid));
1115 else
1116 printf(" Partition: n/a\n");
1117 printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
1118 printf("\n");
1119 } else
1120 printf("System:\n Not booted with EFI\n");
1121
1122 r = status_binaries(arg_path, uuid);
1123 if (r < 0)
1124 return r;
1125
1126 if (arg_touch_variables)
1127 r = status_variables();
1128
1129 return r;
1130 }
1131
1132 static int verb_install(int argc, char *argv[], void *userdata) {
1133
1134 sd_id128_t uuid = SD_ID128_NULL;
1135 uint64_t pstart = 0, psize = 0;
1136 uint32_t part = 0;
1137 bool install;
1138 int r;
1139
1140 r = must_be_root();
1141 if (r < 0)
1142 return r;
1143
1144 r = find_esp(&part, &pstart, &psize, &uuid);
1145 if (r < 0)
1146 return r;
1147
1148 install = streq(argv[0], "install");
1149
1150 RUN_WITH_UMASK(0002) {
1151 r = install_binaries(arg_path, install);
1152 if (r < 0)
1153 return r;
1154
1155 if (install) {
1156 r = install_loader_config(arg_path);
1157 if (r < 0)
1158 return r;
1159 }
1160 }
1161
1162 if (arg_touch_variables)
1163 r = install_variables(arg_path,
1164 part, pstart, psize, uuid,
1165 "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
1166 install);
1167
1168 return r;
1169 }
1170
1171 static int verb_remove(int argc, char *argv[], void *userdata) {
1172 sd_id128_t uuid = SD_ID128_NULL;
1173 int r;
1174
1175 r = must_be_root();
1176 if (r < 0)
1177 return r;
1178
1179 r = find_esp(NULL, NULL, NULL, &uuid);
1180 if (r < 0)
1181 return r;
1182
1183 r = remove_binaries(arg_path);
1184
1185 if (arg_touch_variables) {
1186 int q;
1187
1188 q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
1189 if (q < 0 && r == 0)
1190 r = q;
1191 }
1192
1193 return r;
1194 }
1195
1196 static int bootctl_main(int argc, char *argv[]) {
1197
1198 static const Verb verbs[] = {
1199 { "help", VERB_ANY, VERB_ANY, 0, help },
1200 { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
1201 { "install", VERB_ANY, 1, 0, verb_install },
1202 { "update", VERB_ANY, 1, 0, verb_install },
1203 { "remove", VERB_ANY, 1, 0, verb_remove },
1204 {}
1205 };
1206
1207 return dispatch_verb(argc, argv, verbs, NULL);
1208 }
1209
1210 int main(int argc, char *argv[]) {
1211 int r;
1212
1213 log_parse_environment();
1214 log_open();
1215
1216 /* If we run in a container, automatically turn of EFI file system access */
1217 if (detect_container() > 0)
1218 arg_touch_variables = false;
1219
1220 r = parse_argv(argc, argv);
1221 if (r <= 0)
1222 goto finish;
1223
1224 r = bootctl_main(argc, argv);
1225
1226 finish:
1227 free(arg_path);
1228 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1229 }