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/>.
33 #define LOAD_OPTION_ACTIVE 0x00000001
34 #define MEDIA_DEVICE_PATH 0x04
35 #define MEDIA_HARDDRIVE_DP 0x01
36 #define MEDIA_FILEPATH_DP 0x04
37 #define SIGNATURE_TYPE_GUID 0x02
38 #define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
39 #define END_DEVICE_PATH_TYPE 0x7f
40 #define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
41 #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
55 uint8_t signature_type
;
64 struct drive_path drive
;
68 bool is_efi_boot(void) {
69 return access("/sys/firmware/efi", F_OK
) >= 0;
72 static int read_flag(const char *varname
) {
74 _cleanup_free_
void *v
= NULL
;
78 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, varname
, NULL
, &v
, &s
);
90 bool is_efi_secure_boot(void) {
91 return read_flag("SecureBoot") > 0;
94 bool is_efi_secure_boot_setup_mode(void) {
95 return read_flag("SetupMode") > 0;
98 int efi_reboot_to_firmware_supported(void) {
102 _cleanup_free_
void *v
= NULL
;
104 if (!is_efi_boot() || detect_container(NULL
) > 0)
107 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndicationsSupported", NULL
, &v
, &s
);
110 else if (s
!= sizeof(uint64_t))
114 b
&= EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
115 return b
> 0 ? 0 : -EOPNOTSUPP
;
118 static int get_os_indications(uint64_t *os_indication
) {
121 _cleanup_free_
void *v
= NULL
;
123 r
= efi_reboot_to_firmware_supported();
127 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "OsIndications", NULL
, &v
, &s
);
129 /* Some firmware implementations that do support
130 * OsIndications and report that with
131 * OsIndicationsSupported will remove the
132 * OsIndications variable when it is unset. Let's
133 * pretend it's 0 then, to hide this implementation
134 * detail. Note that this call will return -ENOENT
135 * then only if the support for OsIndications is
136 * missing entirely, as determined by
137 * efi_reboot_to_firmware_supported() above. */
142 else if (s
!= sizeof(uint64_t))
145 *os_indication
= *(uint64_t *)v
;
149 int efi_get_reboot_to_firmware(void) {
153 r
= get_os_indications(&b
);
157 return !!(b
& EFI_OS_INDICATIONS_BOOT_TO_FW_UI
);
160 int efi_set_reboot_to_firmware(bool value
) {
164 r
= get_os_indications(&b
);
169 b_new
= b
| EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
171 b_new
= b
& ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI
;
173 /* Avoid writing to efi vars store if we can due to firmware bugs. */
175 return efi_set_variable(EFI_VENDOR_GLOBAL
, "OsIndications", &b_new
, sizeof(uint64_t));
180 int efi_get_variable(
187 _cleanup_close_
int fd
= -1;
188 _cleanup_free_
char *p
= NULL
;
192 _cleanup_free_
void *buf
= NULL
;
199 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
200 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
203 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
207 if (fstat(fd
, &st
) < 0)
211 if (st
.st_size
> 4*1024*1024 + 4)
214 n
= read(fd
, &a
, sizeof(a
));
220 buf
= malloc(st
.st_size
- 4 + 2);
224 n
= read(fd
, buf
, (size_t) st
.st_size
- 4);
227 if (n
!= (ssize_t
) st
.st_size
- 4)
230 /* Always NUL terminate (2 bytes, to protect UTF-16) */
231 ((char*) buf
)[st
.st_size
- 4] = 0;
232 ((char*) buf
)[st
.st_size
- 4 + 1] = 0;
236 *size
= (size_t) st
.st_size
- 4;
244 int efi_set_variable(
253 } _packed_
* _cleanup_free_ buf
= NULL
;
254 _cleanup_free_
char *p
= NULL
;
255 _cleanup_close_
int fd
= -1;
260 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
261 name
, SD_ID128_FORMAT_VAL(vendor
)) < 0)
270 fd
= open(p
, O_WRONLY
|O_CREAT
|O_NOCTTY
|O_CLOEXEC
, 0644);
274 buf
= malloc(sizeof(uint32_t) + size
);
278 buf
->attr
= EFI_VARIABLE_NON_VOLATILE
|EFI_VARIABLE_BOOTSERVICE_ACCESS
|EFI_VARIABLE_RUNTIME_ACCESS
;
279 memcpy(buf
->buf
, value
, size
);
281 return loop_write(fd
, buf
, sizeof(uint32_t) + size
, false);
284 int efi_get_variable_string(sd_id128_t vendor
, const char *name
, char **p
) {
285 _cleanup_free_
void *s
= NULL
;
290 r
= efi_get_variable(vendor
, name
, NULL
, &s
, &ss
);
294 x
= utf16_to_utf8(s
, ss
);
302 static size_t utf16_size(const uint16_t *s
) {
308 return (l
+1) * sizeof(uint16_t);
311 static void efi_guid_to_id128(const void *guid
, sd_id128_t
*id128
) {
318 const struct uuid
*uuid
= guid
;
320 id128
->bytes
[0] = (uuid
->u1
>> 24) & 0xff;
321 id128
->bytes
[1] = (uuid
->u1
>> 16) & 0xff;
322 id128
->bytes
[2] = (uuid
->u1
>> 8) & 0xff;
323 id128
->bytes
[3] = (uuid
->u1
) & 0xff;
324 id128
->bytes
[4] = (uuid
->u2
>> 8) & 0xff;
325 id128
->bytes
[5] = (uuid
->u2
) & 0xff;
326 id128
->bytes
[6] = (uuid
->u3
>> 8) & 0xff;
327 id128
->bytes
[7] = (uuid
->u3
) & 0xff;
328 memcpy(&id128
->bytes
[8], uuid
->u4
, sizeof(uuid
->u4
));
331 int efi_get_boot_option(
334 sd_id128_t
*part_uuid
,
339 _cleanup_free_
uint8_t *buf
= NULL
;
341 struct boot_option
*header
;
343 _cleanup_free_
char *s
= NULL
, *p
= NULL
;
344 sd_id128_t p_uuid
= SD_ID128_NULL
;
347 xsprintf(boot_id
, "Boot%04X", id
);
348 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, (void **)&buf
, &l
);
351 if (l
< sizeof(struct boot_option
))
354 header
= (struct boot_option
*)buf
;
355 title_size
= utf16_size(header
->title
);
356 if (title_size
> l
- offsetof(struct boot_option
, title
))
360 s
= utf16_to_utf8(header
->title
, title_size
);
365 if (header
->path_len
> 0) {
369 dbuf
= buf
+ offsetof(struct boot_option
, title
) + title_size
;
371 while (dnext
< header
->path_len
) {
372 struct device_path
*dpath
;
374 dpath
= (struct device_path
*)(dbuf
+ dnext
);
375 if (dpath
->length
< 4)
378 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
379 if (dpath
->type
== END_DEVICE_PATH_TYPE
&& dpath
->sub_type
== END_ENTIRE_DEVICE_PATH_SUBTYPE
)
382 dnext
+= dpath
->length
;
384 /* Type 0x04 – Media Device Path */
385 if (dpath
->type
!= MEDIA_DEVICE_PATH
)
388 /* Sub-Type 1 – Hard Drive */
389 if (dpath
->sub_type
== MEDIA_HARDDRIVE_DP
) {
390 /* 0x02 – GUID Partition Table */
391 if (dpath
->drive
.mbr_type
!= MBR_TYPE_EFI_PARTITION_TABLE_HEADER
)
394 /* 0x02 – GUID signature */
395 if (dpath
->drive
.signature_type
!= SIGNATURE_TYPE_GUID
)
399 efi_guid_to_id128(dpath
->drive
.signature
, &p_uuid
);
403 /* Sub-Type 4 – File Path */
404 if (dpath
->sub_type
== MEDIA_FILEPATH_DP
&& !p
&& path
) {
405 p
= utf16_to_utf8(dpath
->path
, dpath
->length
-4);
406 efi_tilt_backslashes(p
);
423 *active
= !!(header
->attr
& LOAD_OPTION_ACTIVE
);
428 static void to_utf16(uint16_t *dest
, const char *src
) {
431 for (i
= 0; src
[i
] != '\0'; i
++)
443 static void id128_to_efi_guid(sd_id128_t id
, void *guid
) {
444 struct guid
*uuid
= guid
;
446 uuid
->u1
= id
.bytes
[0] << 24 | id
.bytes
[1] << 16 | id
.bytes
[2] << 8 | id
.bytes
[3];
447 uuid
->u2
= id
.bytes
[4] << 8 | id
.bytes
[5];
448 uuid
->u3
= id
.bytes
[6] << 8 | id
.bytes
[7];
449 memcpy(uuid
->u4
, id
.bytes
+8, sizeof(uuid
->u4
));
452 static uint16_t *tilt_slashes(uint16_t *s
) {
462 int efi_add_boot_option(uint16_t id
, const char *title
,
463 uint32_t part
, uint64_t pstart
, uint64_t psize
,
464 sd_id128_t part_uuid
, const char *path
) {
469 struct boot_option
*option
;
470 struct device_path
*devicep
;
471 _cleanup_free_
char *buf
= NULL
;
473 title_len
= (strlen(title
)+1) * 2;
474 path_len
= (strlen(path
)+1) * 2;
476 buf
= calloc(sizeof(struct boot_option
) + title_len
+
477 sizeof(struct drive_path
) +
478 sizeof(struct device_path
) + path_len
, 1);
483 option
= (struct boot_option
*)buf
;
484 option
->attr
= LOAD_OPTION_ACTIVE
;
485 option
->path_len
= offsetof(struct device_path
, drive
) + sizeof(struct drive_path
) +
486 offsetof(struct device_path
, path
) + path_len
+
487 offsetof(struct device_path
, path
);
488 to_utf16(option
->title
, title
);
489 size
= offsetof(struct boot_option
, title
) + title_len
;
492 devicep
= (struct device_path
*)(buf
+ size
);
493 devicep
->type
= MEDIA_DEVICE_PATH
;
494 devicep
->sub_type
= MEDIA_HARDDRIVE_DP
;
495 devicep
->length
= offsetof(struct device_path
, drive
) + sizeof(struct drive_path
);
496 devicep
->drive
.part_nr
= part
;
497 devicep
->drive
.part_start
= pstart
;
498 devicep
->drive
.part_size
= psize
;
499 devicep
->drive
.signature_type
= SIGNATURE_TYPE_GUID
;
500 devicep
->drive
.mbr_type
= MBR_TYPE_EFI_PARTITION_TABLE_HEADER
;
501 id128_to_efi_guid(part_uuid
, devicep
->drive
.signature
);
502 size
+= devicep
->length
;
505 devicep
= (struct device_path
*)(buf
+ size
);
506 devicep
->type
= MEDIA_DEVICE_PATH
;
507 devicep
->sub_type
= MEDIA_FILEPATH_DP
;
508 devicep
->length
= offsetof(struct device_path
, path
) + path_len
;
509 to_utf16(devicep
->path
, path
);
510 tilt_slashes(devicep
->path
);
511 size
+= devicep
->length
;
514 devicep
= (struct device_path
*)(buf
+ size
);
515 devicep
->type
= END_DEVICE_PATH_TYPE
;
516 devicep
->sub_type
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
517 devicep
->length
= offsetof(struct device_path
, path
);
518 size
+= devicep
->length
;
520 xsprintf(boot_id
, "Boot%04X", id
);
521 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, buf
, size
);
524 int efi_remove_boot_option(uint16_t id
) {
527 xsprintf(boot_id
, "Boot%04X", id
);
528 return efi_set_variable(EFI_VENDOR_GLOBAL
, boot_id
, NULL
, 0);
531 int efi_get_boot_order(uint16_t **order
) {
532 _cleanup_free_
void *buf
= NULL
;
536 r
= efi_get_variable(EFI_VENDOR_GLOBAL
, "BootOrder", NULL
, &buf
, &l
);
543 if (l
% sizeof(uint16_t) > 0 ||
544 l
/ sizeof(uint16_t) > INT_MAX
)
549 return (int) (l
/ sizeof(uint16_t));
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));
556 static int boot_id_hex(const char s
[4]) {
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;
571 static int cmp_uint16(const void *_a
, const void *_b
) {
572 const uint16_t *a
= _a
, *b
= _b
;
574 return (int)*a
- (int)*b
;
577 int efi_get_boot_options(uint16_t **options
) {
578 _cleanup_closedir_
DIR *dir
= NULL
;
580 _cleanup_free_
uint16_t *list
= NULL
;
586 dir
= opendir("/sys/firmware/efi/efivars/");
590 FOREACH_DIRENT(de
, dir
, return -errno
) {
593 if (strncmp(de
->d_name
, "Boot", 4) != 0)
596 if (strlen(de
->d_name
) != 45)
599 if (strcmp(de
->d_name
+ 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
602 id
= boot_id_hex(de
->d_name
+ 4);
606 if (!GREEDY_REALLOC(list
, alloc
, count
+ 1))
612 qsort_safe(list
, count
, sizeof(uint16_t), cmp_uint16
);
619 static int read_usec(sd_id128_t vendor
, const char *name
, usec_t
*u
) {
620 _cleanup_free_
char *j
= NULL
;
627 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, name
, &j
);
631 r
= safe_atou64(j
, &x
);
639 int efi_loader_get_boot_usec(usec_t
*firmware
, usec_t
*loader
) {
646 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeInitUSec", &x
);
650 r
= read_usec(EFI_VENDOR_LOADER
, "LoaderTimeExecUSec", &y
);
657 if (y
> USEC_PER_HOUR
)
666 int efi_loader_get_device_part_uuid(sd_id128_t
*u
) {
667 _cleanup_free_
char *p
= NULL
;
670 r
= efi_get_variable_string(EFI_VENDOR_LOADER
, "LoaderDevicePartUUID", &p
);
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)
684 for (i
= 0; i
< ELEMENTSOF(parsed
); i
++)
685 u
->bytes
[i
] = parsed
[i
];
693 char *efi_tilt_backslashes(char *s
) {