1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "dirent-util.h"
30 #include "parse-util.h"
31 #include "stdio-util.h"
38 #define LOAD_OPTION_ACTIVE 0x00000001
39 #define MEDIA_DEVICE_PATH 0x04
40 #define MEDIA_HARDDRIVE_DP 0x01
41 #define MEDIA_FILEPATH_DP 0x04
42 #define SIGNATURE_TYPE_GUID 0x02
43 #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
44 #define END_DEVICE_PATH_TYPE 0x7f
45 #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
46 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
60 uint8_t signature_type
;
69 struct drive_path drive
;
73 bool is_efi_boot(void) {
74 return access("/sys/firmware/efi", F_OK
) >= 0;
77 static int read_flag(const char *varname
) {
79 _cleanup_free_
void *v
= NULL
;
83 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, varname
, NULL
, &v
, &s
);
95 bool is_efi_secure_boot(void) {
96 return read_flag("SecureBoot") > 0;
99 bool is_efi_secure_boot_setup_mode(void) {
100 return read_flag("SetupMode") > 0;
103 int efi_reboot_to_firmware_supported(void) {
107 _cleanup_free_
void *v
= NULL
;
109 if (!is_efi_boot() || detect_container() > 0)
112 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndicationsSupported", NULL
, &v
, &s
);
115 else if (s
!= sizeof(uint64_t))
119 b
&= EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
120 return b
> 0 ? 0 : -EOPNOTSUPP
;
123 static int get_os_indications(uint64_t *os_indication
) {
126 _cleanup_free_
void *v
= NULL
;
128 r
= efi_reboot_to_firmware_supported();
132 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndications", NULL
, &v
, &s
);
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. */
147 else if (s
!= sizeof(uint64_t))
150 *os_indication
= *(uint64_t *)v
;
154 int efi_get_reboot_to_firmware(void) {
158 r
= get_os_indications(&b
);
162 return !!(b
& EFI_OS_INDICATIONS_BOOT_TO_FW_UI
);
165 int efi_set_reboot_to_firmware(bool value
) {
169 r
= get_os_indications(&b
);
174 b_new
= b
| EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
176 b_new
= b
& ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
178 /* Avoid writing to efi vars store if we can due to firmware bugs. */
180 return efi_set_variable(EFI_VENDOR_GLOBAL
, "OsIndications", &b_new
, sizeof(uint64_t));
185 int efi_get_variable(
192 _cleanup_close_
int fd
= -1;
193 _cleanup_free_
char *p
= NULL
;
197 _cleanup_free_
void *buf
= NULL
;
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)
208 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
212 if (fstat(fd
, &st
) < 0)
216 if (st
.st_size
> 4*1024*1024 + 4)
219 n
= read(fd
, &a
, sizeof(a
));
225 buf
= malloc(st
.st_size
- 4 + 2);
229 n
= read(fd
, buf
, (size_t) st
.st_size
- 4);
232 if (n
!= (ssize_t
) st
.st_size
- 4)
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;
241 *size
= (size_t) st
.st_size
- 4;
249 int efi_set_variable(
258 } _packed_
* _cleanup_free_ buf
= NULL
;
259 _cleanup_free_
char *p
= NULL
;
260 _cleanup_close_
int fd
= -1;
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)
275 fd
= open(p
, O_WRONLY
|O_CREAT
|O_NOCTTY
|O_CLOEXEC
, 0644);
279 buf
= malloc(sizeof(uint32_t) + size
);
283 buf
->attr
= EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
;
284 memcpy(buf
->buf
, value
, size
);
286 return loop_write(fd
, buf
, sizeof(uint32_t) + size
, false);
289 int efi_get_variable_string(sd_id128_t vendor
, const char *name
, char **p
) {
290 _cleanup_free_
void *s
= NULL
;
295 r
= efi_get_variable(vendor
, name
, NULL
, &s
, &ss
);
299 x
= utf16_to_utf8(s
, ss
);
307 static size_t utf16_size(const uint16_t *s
) {
313 return (l
+1) * sizeof(uint16_t);
316 static void efi_guid_to_id128(const void *guid
, sd_id128_t
*id128
) {
323 const struct uuid
*uuid
= guid
;
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
));
336 int efi_get_boot_option(
339 sd_id128_t
*part_uuid
,
344 _cleanup_free_
uint8_t *buf
= NULL
;
346 struct boot_option
*header
;
348 _cleanup_free_
char *s
= NULL
, *p
= NULL
;
349 sd_id128_t p_uuid
= SD_ID128_NULL
;
352 xsprintf(boot_id
, "Boot%04X", id
);
353 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, (void **)&buf
, &l
);
356 if (l
< sizeof(struct boot_option
))
359 header
= (struct boot_option
*)buf
;
360 title_size
= utf16_size(header
->title
);
361 if (title_size
> l
- offsetof(struct boot_option
, title
))
365 s
= utf16_to_utf8(header
->title
, title_size
);
370 if (header
->path_len
> 0) {
374 dbuf
= buf
+ offsetof(struct boot_option
, title
) + title_size
;
376 while (dnext
< header
->path_len
) {
377 struct device_path
*dpath
;
379 dpath
= (struct device_path
*)(dbuf
+ dnext
);
380 if (dpath
->length
< 4)
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
)
387 dnext
+= dpath
->length
;
389 /* Type 0x04 – Media Device Path */
390 if (dpath
->type
!= MEDIA_DEVICE_PATH
)
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
)
399 /* 0x02 – GUID signature */
400 if (dpath
->drive
.signature_type
!= SIGNATURE_TYPE_GUID
)
404 efi_guid_to_id128(dpath
->drive
.signature
, &p_uuid
);
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
);
428 *active
= !!(header
->attr
& LOAD_OPTION_ACTIVE
);
433 static void to_utf16(uint16_t *dest
, const char *src
) {
436 for (i
= 0; src
[i
] != '\0'; i
++)
448 static void id128_to_efi_guid(sd_id128_t id
, void *guid
) {
449 struct guid
*uuid
= guid
;
451 uuid
->u1
= id
.bytes
[0] << 24 | id
.bytes
[1] << 16 | id
.bytes
[2] << 8 | id
.bytes
[3];
452 uuid
->u2
= id
.bytes
[4] << 8 | id
.bytes
[5];
453 uuid
->u3
= id
.bytes
[6] << 8 | id
.bytes
[7];
454 memcpy(uuid
->u4
, id
.bytes
+8, sizeof(uuid
->u4
));
457 static uint16_t *tilt_slashes(uint16_t *s
) {
467 int efi_add_boot_option(uint16_t id
, const char *title
,
468 uint32_t part
, uint64_t pstart
, uint64_t psize
,
469 sd_id128_t part_uuid
, const char *path
) {
474 struct boot_option
*option
;
475 struct device_path
*devicep
;
476 _cleanup_free_
char *buf
= NULL
;
478 title_len
= (strlen(title
)+1) * 2;
479 path_len
= (strlen(path
)+1) * 2;
481 buf
= calloc(sizeof(struct boot_option
) + title_len
+
482 sizeof(struct drive_path
) +
483 sizeof(struct device_path
) + path_len
, 1);
488 option
= (struct boot_option
*)buf
;
489 option
->attr
= LOAD_OPTION_ACTIVE
;
490 option
->path_len
= offsetof(struct device_path
, drive
) + sizeof(struct drive_path
) +
491 offsetof(struct device_path
, path
) + path_len
+
492 offsetof(struct device_path
, path
);
493 to_utf16(option
->title
, title
);
494 size
= offsetof(struct boot_option
, title
) + title_len
;
497 devicep
= (struct device_path
*)(buf
+ size
);
498 devicep
->type
= MEDIA_DEVICE_PATH
;
499 devicep
->sub_type
= MEDIA_HARDDRIVE_DP
;
500 devicep
->length
= offsetof(struct device_path
, drive
) + sizeof(struct drive_path
);
501 devicep
->drive
.part_nr
= part
;
502 devicep
->drive
.part_start
= pstart
;
503 devicep
->drive
.part_size
= psize
;
504 devicep
->drive
.signature_type
= SIGNATURE_TYPE_GUID
;
505 devicep
->drive
.mbr_type
= MBR_TYPE_EFI_PARTITION_TABLE_HEADER
;
506 id128_to_efi_guid(part_uuid
, devicep
->drive
.signature
);
507 size
+= devicep
->length
;
510 devicep
= (struct device_path
*)(buf
+ size
);
511 devicep
->type
= MEDIA_DEVICE_PATH
;
512 devicep
->sub_type
= MEDIA_FILEPATH_DP
;
513 devicep
->length
= offsetof(struct device_path
, path
) + path_len
;
514 to_utf16(devicep
->path
, path
);
515 tilt_slashes(devicep
->path
);
516 size
+= devicep
->length
;
519 devicep
= (struct device_path
*)(buf
+ size
);
520 devicep
->type
= END_DEVICE_PATH_TYPE
;
521 devicep
->sub_type
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
522 devicep
->length
= offsetof(struct device_path
, path
);
523 size
+= devicep
->length
;
525 xsprintf(boot_id
, "Boot%04X", id
);
526 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, buf
, size
);
529 int efi_remove_boot_option(uint16_t id
) {
532 xsprintf(boot_id
, "Boot%04X", id
);
533 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, 0);
536 int efi_get_boot_order(uint16_t **order
) {
537 _cleanup_free_
void *buf
= NULL
;
541 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "BootOrder", NULL
, &buf
, &l
);
548 if (l
% sizeof(uint16_t) > 0 ||
549 l
/ sizeof(uint16_t) > INT_MAX
)
554 return (int) (l
/ sizeof(uint16_t));
557 int efi_set_boot_order(uint16_t *order
, size_t n
) {
558 return efi_set_variable(EFI_VENDOR_GLOBAL
, "BootOrder", order
, n
* sizeof(uint16_t));
561 static int boot_id_hex(const char s
[4]) {
565 for (i
= 0; i
< 4; i
++)
566 if (s
[i
] >= '0' && s
[i
] <= '9')
567 id
|= (s
[i
] - '0') << (3 - i
) * 4;
568 else if (s
[i
] >= 'A' && s
[i
] <= 'F')
569 id
|= (s
[i
] - 'A' + 10) << (3 - i
) * 4;
576 static int cmp_uint16(const void *_a
, const void *_b
) {
577 const uint16_t *a
= _a
, *b
= _b
;
579 return (int)*a
- (int)*b
;
582 int efi_get_boot_options(uint16_t **options
) {
583 _cleanup_closedir_
DIR *dir
= NULL
;
585 _cleanup_free_
uint16_t *list
= NULL
;
591 dir
= opendir("/sys/firmware/efi/efivars/");
595 FOREACH_DIRENT(de
, dir
, return -errno
) {
598 if (strncmp(de
->d_name
, "Boot", 4) != 0)
601 if (strlen(de
->d_name
) != 45)
604 if (strcmp(de
->d_name
+ 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
607 id
= boot_id_hex(de
->d_name
+ 4);
611 if (!GREEDY_REALLOC(list
, alloc
, count
+ 1))
617 qsort_safe(list
, count
, sizeof(uint16_t), cmp_uint16
);
624 static int read_usec(sd_id128_t vendor
, const char *name
, usec_t
*u
) {
625 _cleanup_free_
char *j
= NULL
;
632 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, name
, &j
);
636 r
= safe_atou64(j
, &x
);
644 int efi_loader_get_boot_usec(usec_t
*firmware
, usec_t
*loader
) {
651 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeInitUSec", &x
);
655 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeExecUSec", &y
);
662 if (y
> USEC_PER_HOUR
)
671 int efi_loader_get_device_part_uuid(sd_id128_t
*u
) {
672 _cleanup_free_
char *p
= NULL
;
675 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, "LoaderDevicePartUUID", &p
);
679 if (sscanf(p
, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
680 &parsed
[0], &parsed
[1], &parsed
[2], &parsed
[3],
681 &parsed
[4], &parsed
[5], &parsed
[6], &parsed
[7],
682 &parsed
[8], &parsed
[9], &parsed
[10], &parsed
[11],
683 &parsed
[12], &parsed
[13], &parsed
[14], &parsed
[15]) != 16)
689 for (i
= 0; i
< ELEMENTSOF(parsed
); i
++)
690 u
->bytes
[i
] = parsed
[i
];
698 char *efi_tilt_backslashes(char *s
) {