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