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