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/>.
34 #define LOAD_OPTION_ACTIVE 0x00000001
35 #define MEDIA_DEVICE_PATH 0x04
36 #define MEDIA_HARDDRIVE_DP 0x01
37 #define MEDIA_FILEPATH_DP 0x04
38 #define SIGNATURE_TYPE_GUID 0x02
39 #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
40 #define END_DEVICE_PATH_TYPE 0x7f
41 #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
42 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
56 uint8_t signature_type
;
65 struct drive_path drive
;
69 bool is_efi_boot(void) {
70 return access("/sys/firmware/efi", F_OK
) >= 0;
73 static int read_flag(const char *varname
) {
75 _cleanup_free_
void *v
= NULL
;
79 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, varname
, NULL
, &v
, &s
);
91 bool is_efi_secure_boot(void) {
92 return read_flag("SecureBoot") > 0;
95 bool is_efi_secure_boot_setup_mode(void) {
96 return read_flag("SetupMode") > 0;
99 int efi_reboot_to_firmware_supported(void) {
103 _cleanup_free_
void *v
= NULL
;
105 if (!is_efi_boot() || detect_container() > 0)
108 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndicationsSupported", NULL
, &v
, &s
);
111 else if (s
!= sizeof(uint64_t))
115 b
&= EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
116 return b
> 0 ? 0 : -EOPNOTSUPP
;
119 static int get_os_indications(uint64_t *os_indication
) {
122 _cleanup_free_
void *v
= NULL
;
124 r
= efi_reboot_to_firmware_supported();
128 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndications", NULL
, &v
, &s
);
130 /* Some firmware implementations that do support
131 * OsIndications and report that with
132 * OsIndicationsSupported will remove the
133 * OsIndications variable when it is unset. Let's
134 * pretend it's 0 then, to hide this implementation
135 * detail. Note that this call will return -ENOENT
136 * then only if the support for OsIndications is
137 * missing entirely, as determined by
138 * efi_reboot_to_firmware_supported() above. */
143 else if (s
!= sizeof(uint64_t))
146 *os_indication
= *(uint64_t *)v
;
150 int efi_get_reboot_to_firmware(void) {
154 r
= get_os_indications(&b
);
158 return !!(b
& EFI_OS_INDICATIONS_BOOT_TO_FW_UI
);
161 int efi_set_reboot_to_firmware(bool value
) {
165 r
= get_os_indications(&b
);
170 b_new
= b
| EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
172 b_new
= b
& ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
174 /* Avoid writing to efi vars store if we can due to firmware bugs. */
176 return efi_set_variable(EFI_VENDOR_GLOBAL
, "OsIndications", &b_new
, sizeof(uint64_t));
181 int efi_get_variable(
188 _cleanup_close_
int fd
= -1;
189 _cleanup_free_
char *p
= NULL
;
193 _cleanup_free_
void *buf
= NULL
;
200 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
201 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
204 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
208 if (fstat(fd
, &st
) < 0)
212 if (st
.st_size
> 4*1024*1024 + 4)
215 n
= read(fd
, &a
, sizeof(a
));
221 buf
= malloc(st
.st_size
- 4 + 2);
225 n
= read(fd
, buf
, (size_t) st
.st_size
- 4);
228 if (n
!= (ssize_t
) st
.st_size
- 4)
231 /* Always NUL terminate (2 bytes, to protect UTF-16) */
232 ((char*) buf
)[st
.st_size
- 4] = 0;
233 ((char*) buf
)[st
.st_size
- 4 + 1] = 0;
237 *size
= (size_t) st
.st_size
- 4;
245 int efi_set_variable(
254 } _packed_
* _cleanup_free_ buf
= NULL
;
255 _cleanup_free_
char *p
= NULL
;
256 _cleanup_close_
int fd
= -1;
261 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
262 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
271 fd
= open(p
, O_WRONLY
|O_CREAT
|O_NOCTTY
|O_CLOEXEC
, 0644);
275 buf
= malloc(sizeof(uint32_t) + size
);
279 buf
->attr
= EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
;
280 memcpy(buf
->buf
, value
, size
);
282 return loop_write(fd
, buf
, sizeof(uint32_t) + size
, false);
285 int efi_get_variable_string(sd_id128_t vendor
, const char *name
, char **p
) {
286 _cleanup_free_
void *s
= NULL
;
291 r
= efi_get_variable(vendor
, name
, NULL
, &s
, &ss
);
295 x
= utf16_to_utf8(s
, ss
);
303 static size_t utf16_size(const uint16_t *s
) {
309 return (l
+1) * sizeof(uint16_t);
312 static void efi_guid_to_id128(const void *guid
, sd_id128_t
*id128
) {
319 const struct uuid
*uuid
= guid
;
321 id128
->bytes
[0] = (uuid
->u1
>> 24) & 0xff;
322 id128
->bytes
[1] = (uuid
->u1
>> 16) & 0xff;
323 id128
->bytes
[2] = (uuid
->u1
>> 8) & 0xff;
324 id128
->bytes
[3] = (uuid
->u1
) & 0xff;
325 id128
->bytes
[4] = (uuid
->u2
>> 8) & 0xff;
326 id128
->bytes
[5] = (uuid
->u2
) & 0xff;
327 id128
->bytes
[6] = (uuid
->u3
>> 8) & 0xff;
328 id128
->bytes
[7] = (uuid
->u3
) & 0xff;
329 memcpy(&id128
->bytes
[8], uuid
->u4
, sizeof(uuid
->u4
));
332 int efi_get_boot_option(
335 sd_id128_t
*part_uuid
,
340 _cleanup_free_
uint8_t *buf
= NULL
;
342 struct boot_option
*header
;
344 _cleanup_free_
char *s
= NULL
, *p
= NULL
;
345 sd_id128_t p_uuid
= SD_ID128_NULL
;
348 xsprintf(boot_id
, "Boot%04X", id
);
349 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, (void **)&buf
, &l
);
352 if (l
< sizeof(struct boot_option
))
355 header
= (struct boot_option
*)buf
;
356 title_size
= utf16_size(header
->title
);
357 if (title_size
> l
- offsetof(struct boot_option
, title
))
361 s
= utf16_to_utf8(header
->title
, title_size
);
366 if (header
->path_len
> 0) {
370 dbuf
= buf
+ offsetof(struct boot_option
, title
) + title_size
;
372 while (dnext
< header
->path_len
) {
373 struct device_path
*dpath
;
375 dpath
= (struct device_path
*)(dbuf
+ dnext
);
376 if (dpath
->length
< 4)
379 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
380 if (dpath
->type
== END_DEVICE_PATH_TYPE
&& dpath
->sub_type
== END_ENTIRE_DEVICE_PATH_SUBTYPE
)
383 dnext
+= dpath
->length
;
385 /* Type 0x04 – Media Device Path */
386 if (dpath
->type
!= MEDIA_DEVICE_PATH
)
389 /* Sub-Type 1 – Hard Drive */
390 if (dpath
->sub_type
== MEDIA_HARDDRIVE_DP
) {
391 /* 0x02 – GUID Partition Table */
392 if (dpath
->drive
.mbr_type
!= MBR_TYPE_EFI_PARTITION_TABLE_HEADER
)
395 /* 0x02 – GUID signature */
396 if (dpath
->drive
.signature_type
!= SIGNATURE_TYPE_GUID
)
400 efi_guid_to_id128(dpath
->drive
.signature
, &p_uuid
);
404 /* Sub-Type 4 – File Path */
405 if (dpath
->sub_type
== MEDIA_FILEPATH_DP
&& !p
&& path
) {
406 p
= utf16_to_utf8(dpath
->path
, dpath
->length
-4);
407 efi_tilt_backslashes(p
);
424 *active
= !!(header
->attr
& LOAD_OPTION_ACTIVE
);
429 static void to_utf16(uint16_t *dest
, const char *src
) {
432 for (i
= 0; src
[i
] != '\0'; i
++)
444 static void id128_to_efi_guid(sd_id128_t id
, void *guid
) {
445 struct guid
*uuid
= guid
;
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
));
453 static uint16_t *tilt_slashes(uint16_t *s
) {
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
) {
470 struct boot_option
*option
;
471 struct device_path
*devicep
;
472 _cleanup_free_
char *buf
= NULL
;
474 title_len
= (strlen(title
)+1) * 2;
475 path_len
= (strlen(path
)+1) * 2;
477 buf
= calloc(sizeof(struct boot_option
) + title_len
+
478 sizeof(struct drive_path
) +
479 sizeof(struct device_path
) + path_len
, 1);
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
;
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
;
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
;
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
;
521 xsprintf(boot_id
, "Boot%04X", id
);
522 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, buf
, size
);
525 int efi_remove_boot_option(uint16_t id
) {
528 xsprintf(boot_id
, "Boot%04X", id
);
529 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, 0);
532 int efi_get_boot_order(uint16_t **order
) {
533 _cleanup_free_
void *buf
= NULL
;
537 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "BootOrder", NULL
, &buf
, &l
);
544 if (l
% sizeof(uint16_t) > 0 ||
545 l
/ sizeof(uint16_t) > INT_MAX
)
550 return (int) (l
/ sizeof(uint16_t));
553 int efi_set_boot_order(uint16_t *order
, size_t n
) {
554 return efi_set_variable(EFI_VENDOR_GLOBAL
, "BootOrder", order
, n
* sizeof(uint16_t));
557 static int boot_id_hex(const char s
[4]) {
561 for (i
= 0; i
< 4; i
++)
562 if (s
[i
] >= '0' && s
[i
] <= '9')
563 id
|= (s
[i
] - '0') << (3 - i
) * 4;
564 else if (s
[i
] >= 'A' && s
[i
] <= 'F')
565 id
|= (s
[i
] - 'A' + 10) << (3 - i
) * 4;
572 static int cmp_uint16(const void *_a
, const void *_b
) {
573 const uint16_t *a
= _a
, *b
= _b
;
575 return (int)*a
- (int)*b
;
578 int efi_get_boot_options(uint16_t **options
) {
579 _cleanup_closedir_
DIR *dir
= NULL
;
581 _cleanup_free_
uint16_t *list
= NULL
;
587 dir
= opendir("/sys/firmware/efi/efivars/");
591 FOREACH_DIRENT(de
, dir
, return -errno
) {
594 if (strncmp(de
->d_name
, "Boot", 4) != 0)
597 if (strlen(de
->d_name
) != 45)
600 if (strcmp(de
->d_name
+ 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
603 id
= boot_id_hex(de
->d_name
+ 4);
607 if (!GREEDY_REALLOC(list
, alloc
, count
+ 1))
613 qsort_safe(list
, count
, sizeof(uint16_t), cmp_uint16
);
620 static int read_usec(sd_id128_t vendor
, const char *name
, usec_t
*u
) {
621 _cleanup_free_
char *j
= NULL
;
628 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, name
, &j
);
632 r
= safe_atou64(j
, &x
);
640 int efi_loader_get_boot_usec(usec_t
*firmware
, usec_t
*loader
) {
647 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeInitUSec", &x
);
651 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeExecUSec", &y
);
658 if (y
> USEC_PER_HOUR
)
667 int efi_loader_get_device_part_uuid(sd_id128_t
*u
) {
668 _cleanup_free_
char *p
= NULL
;
671 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, "LoaderDevicePartUUID", &p
);
675 if (sscanf(p
, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
676 &parsed
[0], &parsed
[1], &parsed
[2], &parsed
[3],
677 &parsed
[4], &parsed
[5], &parsed
[6], &parsed
[7],
678 &parsed
[8], &parsed
[9], &parsed
[10], &parsed
[11],
679 &parsed
[12], &parsed
[13], &parsed
[14], &parsed
[15]) != 16)
685 for (i
= 0; i
< ELEMENTSOF(parsed
); i
++)
686 u
->bytes
[i
] = parsed
[i
];
694 char *efi_tilt_backslashes(char *s
) {