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