]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/efivars.c
Merge pull request #8417 from brauner/2018-03-09/add_bind_mount_fallback_to_private_d...
[thirdparty/systemd.git] / src / shared / efivars.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6 ***/
7
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
16 #include <unistd.h>
17
18 #include "sd-id128.h"
19
20 #include "alloc-util.h"
21 #include "dirent-util.h"
22 #include "efivars.h"
23 #include "fd-util.h"
24 #include "io-util.h"
25 #include "macro.h"
26 #include "parse-util.h"
27 #include "stdio-util.h"
28 #include "time-util.h"
29 #include "utf8.h"
30 #include "util.h"
31 #include "virt.h"
32
33 #if ENABLE_EFI
34
35 #define LOAD_OPTION_ACTIVE 0x00000001
36 #define MEDIA_DEVICE_PATH 0x04
37 #define MEDIA_HARDDRIVE_DP 0x01
38 #define MEDIA_FILEPATH_DP 0x04
39 #define SIGNATURE_TYPE_GUID 0x02
40 #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
41 #define END_DEVICE_PATH_TYPE 0x7f
42 #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
43 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
44
45 struct boot_option {
46 uint32_t attr;
47 uint16_t path_len;
48 uint16_t title[];
49 } _packed_;
50
51 struct drive_path {
52 uint32_t part_nr;
53 uint64_t part_start;
54 uint64_t part_size;
55 char signature[16];
56 uint8_t mbr_type;
57 uint8_t signature_type;
58 } _packed_;
59
60 struct device_path {
61 uint8_t type;
62 uint8_t sub_type;
63 uint16_t length;
64 union {
65 uint16_t path[0];
66 struct drive_path drive;
67 };
68 } _packed_;
69
70 bool is_efi_boot(void) {
71 return access("/sys/firmware/efi", F_OK) >= 0;
72 }
73
74 static int read_flag(const char *varname) {
75 _cleanup_free_ void *v = NULL;
76 uint8_t b;
77 size_t s;
78 int r;
79
80 r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s);
81 if (r < 0)
82 return r;
83
84 if (s != 1)
85 return -EINVAL;
86
87 b = *(uint8_t *)v;
88 return b > 0;
89 }
90
91 bool is_efi_secure_boot(void) {
92 return read_flag("SecureBoot") > 0;
93 }
94
95 bool is_efi_secure_boot_setup_mode(void) {
96 return read_flag("SetupMode") > 0;
97 }
98
99 int efi_reboot_to_firmware_supported(void) {
100 _cleanup_free_ void *v = NULL;
101 uint64_t b;
102 size_t s;
103 int r;
104
105 if (!is_efi_boot() || detect_container() > 0)
106 return -EOPNOTSUPP;
107
108 r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
109 if (r == -ENOENT) /* variable doesn't exist? it's not supported then */
110 return -EOPNOTSUPP;
111 if (r < 0)
112 return r;
113 if (s != sizeof(uint64_t))
114 return -EINVAL;
115
116 b = *(uint64_t*) v;
117 if (!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
118 return -EOPNOTSUPP; /* bit unset? it's not supported then */
119
120 return 0;
121 }
122
123 static int get_os_indications(uint64_t *os_indication) {
124 _cleanup_free_ void *v = NULL;
125 size_t s;
126 int r;
127
128 r = efi_reboot_to_firmware_supported();
129 if (r < 0)
130 return r;
131
132 r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
133 if (r == -ENOENT) {
134 /* Some firmware implementations that do support
135 * OsIndications and report that with
136 * OsIndicationsSupported will remove the
137 * OsIndications variable when it is unset. Let's
138 * pretend it's 0 then, to hide this implementation
139 * detail. Note that this call will return -ENOENT
140 * then only if the support for OsIndications is
141 * missing entirely, as determined by
142 * efi_reboot_to_firmware_supported() above. */
143 *os_indication = 0;
144 return 0;
145 } else if (r < 0)
146 return r;
147 else if (s != sizeof(uint64_t))
148 return -EINVAL;
149
150 *os_indication = *(uint64_t *)v;
151 return 0;
152 }
153
154 int efi_get_reboot_to_firmware(void) {
155 int r;
156 uint64_t b;
157
158 r = get_os_indications(&b);
159 if (r < 0)
160 return r;
161
162 return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
163 }
164
165 int efi_set_reboot_to_firmware(bool value) {
166 int r;
167 uint64_t b, b_new;
168
169 r = get_os_indications(&b);
170 if (r < 0)
171 return r;
172
173 if (value)
174 b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
175 else
176 b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
177
178 /* Avoid writing to efi vars store if we can due to firmware bugs. */
179 if (b != b_new)
180 return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t));
181
182 return 0;
183 }
184
185 int efi_get_variable(
186 sd_id128_t vendor,
187 const char *name,
188 uint32_t *attribute,
189 void **value,
190 size_t *size) {
191
192 _cleanup_close_ int fd = -1;
193 _cleanup_free_ char *p = NULL;
194 uint32_t a;
195 ssize_t n;
196 struct stat st;
197 _cleanup_free_ void *buf = NULL;
198
199 assert(name);
200 assert(value);
201 assert(size);
202
203 if (asprintf(&p,
204 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
205 name, SD_ID128_FORMAT_VAL(vendor)) < 0)
206 return -ENOMEM;
207
208 fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
209 if (fd < 0)
210 return -errno;
211
212 if (fstat(fd, &st) < 0)
213 return -errno;
214 if (st.st_size < 4)
215 return -EIO;
216 if (st.st_size > 4*1024*1024 + 4)
217 return -E2BIG;
218
219 n = read(fd, &a, sizeof(a));
220 if (n < 0)
221 return -errno;
222 if (n != sizeof(a))
223 return -EIO;
224
225 buf = malloc(st.st_size - 4 + 2);
226 if (!buf)
227 return -ENOMEM;
228
229 n = read(fd, buf, (size_t) st.st_size - 4);
230 if (n < 0)
231 return -errno;
232 if (n != (ssize_t) st.st_size - 4)
233 return -EIO;
234
235 /* Always NUL terminate (2 bytes, to protect UTF-16) */
236 ((char*) buf)[st.st_size - 4] = 0;
237 ((char*) buf)[st.st_size - 4 + 1] = 0;
238
239 *value = TAKE_PTR(buf);
240 *size = (size_t) st.st_size - 4;
241
242 if (attribute)
243 *attribute = a;
244
245 return 0;
246 }
247
248 int efi_set_variable(
249 sd_id128_t vendor,
250 const char *name,
251 const void *value,
252 size_t size) {
253
254 struct var {
255 uint32_t attr;
256 char buf[];
257 } _packed_ * _cleanup_free_ buf = NULL;
258 _cleanup_free_ char *p = NULL;
259 _cleanup_close_ int fd = -1;
260
261 assert(name);
262 assert(value || size == 0);
263
264 if (asprintf(&p,
265 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
266 name, SD_ID128_FORMAT_VAL(vendor)) < 0)
267 return -ENOMEM;
268
269 if (size == 0) {
270 if (unlink(p) < 0)
271 return -errno;
272 return 0;
273 }
274
275 fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644);
276 if (fd < 0)
277 return -errno;
278
279 buf = malloc(sizeof(uint32_t) + size);
280 if (!buf)
281 return -ENOMEM;
282
283 buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
284 memcpy(buf->buf, value, size);
285
286 return loop_write(fd, buf, sizeof(uint32_t) + size, false);
287 }
288
289 int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
290 _cleanup_free_ void *s = NULL;
291 size_t ss = 0;
292 int r;
293 char *x;
294
295 r = efi_get_variable(vendor, name, NULL, &s, &ss);
296 if (r < 0)
297 return r;
298
299 x = utf16_to_utf8(s, ss);
300 if (!x)
301 return -ENOMEM;
302
303 *p = x;
304 return 0;
305 }
306
307 static size_t utf16_size(const uint16_t *s) {
308 size_t l = 0;
309
310 while (s[l] > 0)
311 l++;
312
313 return (l+1) * sizeof(uint16_t);
314 }
315
316 static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
317 struct uuid {
318 uint32_t u1;
319 uint16_t u2;
320 uint16_t u3;
321 uint8_t u4[8];
322 } _packed_;
323 const struct uuid *uuid = guid;
324
325 id128->bytes[0] = (uuid->u1 >> 24) & 0xff;
326 id128->bytes[1] = (uuid->u1 >> 16) & 0xff;
327 id128->bytes[2] = (uuid->u1 >> 8) & 0xff;
328 id128->bytes[3] = (uuid->u1) & 0xff;
329 id128->bytes[4] = (uuid->u2 >> 8) & 0xff;
330 id128->bytes[5] = (uuid->u2) & 0xff;
331 id128->bytes[6] = (uuid->u3 >> 8) & 0xff;
332 id128->bytes[7] = (uuid->u3) & 0xff;
333 memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
334 }
335
336 int efi_get_boot_option(
337 uint16_t id,
338 char **title,
339 sd_id128_t *part_uuid,
340 char **path,
341 bool *active) {
342
343 char boot_id[9];
344 _cleanup_free_ uint8_t *buf = NULL;
345 size_t l;
346 struct boot_option *header;
347 size_t title_size;
348 _cleanup_free_ char *s = NULL, *p = NULL;
349 sd_id128_t p_uuid = SD_ID128_NULL;
350 int r;
351
352 xsprintf(boot_id, "Boot%04X", id);
353 r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
354 if (r < 0)
355 return r;
356 if (l < sizeof(struct boot_option))
357 return -ENOENT;
358
359 header = (struct boot_option *)buf;
360 title_size = utf16_size(header->title);
361 if (title_size > l - offsetof(struct boot_option, title))
362 return -EINVAL;
363
364 if (title) {
365 s = utf16_to_utf8(header->title, title_size);
366 if (!s)
367 return -ENOMEM;
368 }
369
370 if (header->path_len > 0) {
371 uint8_t *dbuf;
372 size_t dnext;
373
374 dbuf = buf + offsetof(struct boot_option, title) + title_size;
375 dnext = 0;
376 while (dnext < header->path_len) {
377 struct device_path *dpath;
378
379 dpath = (struct device_path *)(dbuf + dnext);
380 if (dpath->length < 4)
381 break;
382
383 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
384 if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
385 break;
386
387 dnext += dpath->length;
388
389 /* Type 0x04 – Media Device Path */
390 if (dpath->type != MEDIA_DEVICE_PATH)
391 continue;
392
393 /* Sub-Type 1 – Hard Drive */
394 if (dpath->sub_type == MEDIA_HARDDRIVE_DP) {
395 /* 0x02 – GUID Partition Table */
396 if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
397 continue;
398
399 /* 0x02 – GUID signature */
400 if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID)
401 continue;
402
403 if (part_uuid)
404 efi_guid_to_id128(dpath->drive.signature, &p_uuid);
405 continue;
406 }
407
408 /* Sub-Type 4 – File Path */
409 if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && path) {
410 p = utf16_to_utf8(dpath->path, dpath->length-4);
411 efi_tilt_backslashes(p);
412 continue;
413 }
414 }
415 }
416
417 if (title)
418 *title = TAKE_PTR(s);
419 if (part_uuid)
420 *part_uuid = p_uuid;
421 if (path)
422 *path = TAKE_PTR(p);
423 if (active)
424 *active = !!(header->attr & LOAD_OPTION_ACTIVE);
425
426 return 0;
427 }
428
429 static void to_utf16(uint16_t *dest, const char *src) {
430 int i;
431
432 for (i = 0; src[i] != '\0'; i++)
433 dest[i] = src[i];
434 dest[i] = '\0';
435 }
436
437 struct guid {
438 uint32_t u1;
439 uint16_t u2;
440 uint16_t u3;
441 uint8_t u4[8];
442 } _packed_;
443
444 static void id128_to_efi_guid(sd_id128_t id, void *guid) {
445 struct guid *uuid = guid;
446
447 uuid->u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3];
448 uuid->u2 = id.bytes[4] << 8 | id.bytes[5];
449 uuid->u3 = id.bytes[6] << 8 | id.bytes[7];
450 memcpy(uuid->u4, id.bytes+8, sizeof(uuid->u4));
451 }
452
453 static uint16_t *tilt_slashes(uint16_t *s) {
454 uint16_t *p;
455
456 for (p = s; *p; p++)
457 if (*p == '/')
458 *p = '\\';
459
460 return s;
461 }
462
463 int efi_add_boot_option(uint16_t id, const char *title,
464 uint32_t part, uint64_t pstart, uint64_t psize,
465 sd_id128_t part_uuid, const char *path) {
466 char boot_id[9];
467 size_t size;
468 size_t title_len;
469 size_t path_len;
470 struct boot_option *option;
471 struct device_path *devicep;
472 _cleanup_free_ char *buf = NULL;
473
474 title_len = (strlen(title)+1) * 2;
475 path_len = (strlen(path)+1) * 2;
476
477 buf = calloc(sizeof(struct boot_option) + title_len +
478 sizeof(struct drive_path) +
479 sizeof(struct device_path) + path_len, 1);
480 if (!buf)
481 return -ENOMEM;
482
483 /* header */
484 option = (struct boot_option *)buf;
485 option->attr = LOAD_OPTION_ACTIVE;
486 option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) +
487 offsetof(struct device_path, path) + path_len +
488 offsetof(struct device_path, path);
489 to_utf16(option->title, title);
490 size = offsetof(struct boot_option, title) + title_len;
491
492 /* partition info */
493 devicep = (struct device_path *)(buf + size);
494 devicep->type = MEDIA_DEVICE_PATH;
495 devicep->sub_type = MEDIA_HARDDRIVE_DP;
496 devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path);
497 devicep->drive.part_nr = part;
498 devicep->drive.part_start = pstart;
499 devicep->drive.part_size = psize;
500 devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
501 devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
502 id128_to_efi_guid(part_uuid, devicep->drive.signature);
503 size += devicep->length;
504
505 /* path to loader */
506 devicep = (struct device_path *)(buf + size);
507 devicep->type = MEDIA_DEVICE_PATH;
508 devicep->sub_type = MEDIA_FILEPATH_DP;
509 devicep->length = offsetof(struct device_path, path) + path_len;
510 to_utf16(devicep->path, path);
511 tilt_slashes(devicep->path);
512 size += devicep->length;
513
514 /* end of path */
515 devicep = (struct device_path *)(buf + size);
516 devicep->type = END_DEVICE_PATH_TYPE;
517 devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE;
518 devicep->length = offsetof(struct device_path, path);
519 size += devicep->length;
520
521 xsprintf(boot_id, "Boot%04X", id);
522 return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, buf, size);
523 }
524
525 int efi_remove_boot_option(uint16_t id) {
526 char boot_id[9];
527
528 xsprintf(boot_id, "Boot%04X", id);
529 return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0);
530 }
531
532 int efi_get_boot_order(uint16_t **order) {
533 _cleanup_free_ void *buf = NULL;
534 size_t l;
535 int r;
536
537 r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
538 if (r < 0)
539 return r;
540
541 if (l <= 0)
542 return -ENOENT;
543
544 if (l % sizeof(uint16_t) > 0 ||
545 l / sizeof(uint16_t) > INT_MAX)
546 return -EINVAL;
547
548 *order = TAKE_PTR(buf);
549 return (int) (l / sizeof(uint16_t));
550 }
551
552 int efi_set_boot_order(uint16_t *order, size_t n) {
553 return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t));
554 }
555
556 static int boot_id_hex(const char s[4]) {
557 int i;
558 int id = 0;
559
560 for (i = 0; i < 4; i++)
561 if (s[i] >= '0' && s[i] <= '9')
562 id |= (s[i] - '0') << (3 - i) * 4;
563 else if (s[i] >= 'A' && s[i] <= 'F')
564 id |= (s[i] - 'A' + 10) << (3 - i) * 4;
565 else
566 return -EINVAL;
567
568 return id;
569 }
570
571 static int cmp_uint16(const void *_a, const void *_b) {
572 const uint16_t *a = _a, *b = _b;
573
574 return (int)*a - (int)*b;
575 }
576
577 int efi_get_boot_options(uint16_t **options) {
578 _cleanup_closedir_ DIR *dir = NULL;
579 struct dirent *de;
580 _cleanup_free_ uint16_t *list = NULL;
581 size_t alloc = 0;
582 int count = 0;
583
584 assert(options);
585
586 dir = opendir("/sys/firmware/efi/efivars/");
587 if (!dir)
588 return -errno;
589
590 FOREACH_DIRENT(de, dir, return -errno) {
591 int id;
592
593 if (strncmp(de->d_name, "Boot", 4) != 0)
594 continue;
595
596 if (strlen(de->d_name) != 45)
597 continue;
598
599 if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
600 continue;
601
602 id = boot_id_hex(de->d_name + 4);
603 if (id < 0)
604 continue;
605
606 if (!GREEDY_REALLOC(list, alloc, count + 1))
607 return -ENOMEM;
608
609 list[count++] = id;
610 }
611
612 qsort_safe(list, count, sizeof(uint16_t), cmp_uint16);
613
614 *options = TAKE_PTR(list);
615
616 return count;
617 }
618
619 static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
620 _cleanup_free_ char *j = NULL;
621 int r;
622 uint64_t x = 0;
623
624 assert(name);
625 assert(u);
626
627 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j);
628 if (r < 0)
629 return r;
630
631 r = safe_atou64(j, &x);
632 if (r < 0)
633 return r;
634
635 *u = x;
636 return 0;
637 }
638
639 int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
640 uint64_t x, y;
641 int r;
642
643 assert(firmware);
644 assert(loader);
645
646 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
647 if (r < 0)
648 return r;
649
650 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
651 if (r < 0)
652 return r;
653
654 if (y == 0 || y < x)
655 return -EIO;
656
657 if (y > USEC_PER_HOUR)
658 return -EIO;
659
660 *firmware = x;
661 *loader = y;
662
663 return 0;
664 }
665
666 int efi_loader_get_device_part_uuid(sd_id128_t *u) {
667 _cleanup_free_ char *p = NULL;
668 int r, parsed[16];
669
670 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p);
671 if (r < 0)
672 return r;
673
674 if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
675 &parsed[0], &parsed[1], &parsed[2], &parsed[3],
676 &parsed[4], &parsed[5], &parsed[6], &parsed[7],
677 &parsed[8], &parsed[9], &parsed[10], &parsed[11],
678 &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
679 return -EIO;
680
681 if (u) {
682 unsigned i;
683
684 for (i = 0; i < ELEMENTSOF(parsed); i++)
685 u->bytes[i] = parsed[i];
686 }
687
688 return 0;
689 }
690
691 #endif
692
693 char *efi_tilt_backslashes(char *s) {
694 char *p;
695
696 for (p = s; *p; p++)
697 if (*p == '\\')
698 *p = '/';
699
700 return s;
701 }