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 bool is_efi_boot(void) {
34 return access("/sys/firmware/efi", F_OK) >= 0;
37 static int read_flag(const char *varname) {
43 r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s);
59 int is_efi_secure_boot(void) {
60 return read_flag("SecureBoot");
63 int is_efi_secure_boot_setup_mode(void) {
64 return read_flag("SetupMode");
74 _cleanup_close_ int fd = -1;
75 _cleanup_free_ char *p = NULL;
86 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
87 name, SD_ID128_FORMAT_VAL(vendor)) < 0)
90 fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
94 if (fstat(fd, &st) < 0)
98 if (st.st_size > 4*1024*1024 + 4)
101 n = read(fd, &a, sizeof(a));
107 r = malloc(st.st_size - 4 + 2);
111 n = read(fd, r, (size_t) st.st_size - 4);
116 if (n != (ssize_t) st.st_size - 4) {
121 /* Always NUL terminate (2 bytes, to protect UTF-16) */
122 ((char*) r)[st.st_size - 4] = 0;
123 ((char*) r)[st.st_size - 4 + 1] = 0;
126 *size = (size_t) st.st_size - 4;
134 int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
135 _cleanup_free_ void *s = NULL;
140 r = efi_get_variable(vendor, name, NULL, &s, &ss);
144 x = utf16_to_utf8(s, ss);
152 static size_t utf16_size(const uint16_t *s) {
158 return (l+1) * sizeof(uint16_t);
161 static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
168 const struct uuid *uuid = guid;
170 id128->bytes[0] = (uuid->u1 >> 24) & 0xff;
171 id128->bytes[1] = (uuid->u1 >> 16) & 0xff;
172 id128->bytes[2] = (uuid->u1 >> 8) & 0xff;
173 id128->bytes[3] = (uuid->u1) & 0xff;
174 id128->bytes[4] = (uuid->u2 >> 8) & 0xff;
175 id128->bytes[5] = (uuid->u2) & 0xff;
176 id128->bytes[6] = (uuid->u3 >> 8) & 0xff;
177 id128->bytes[7] = (uuid->u3) & 0xff;
178 memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
181 int efi_get_boot_option(
184 sd_id128_t *part_uuid,
199 uint8_t signature_type;
208 struct drive_path drive;
213 _cleanup_free_ uint8_t *buf = NULL;
215 struct boot_option *header;
219 sd_id128_t p_uuid = SD_ID128_NULL;
222 snprintf(boot_id, sizeof(boot_id), "Boot%04X", id);
223 err = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
226 if (l < sizeof(struct boot_option))
229 header = (struct boot_option *)buf;
230 title_size = utf16_size(header->title);
231 if (title_size > l - offsetof(struct boot_option, title))
234 s = utf16_to_utf8(header->title, title_size);
240 if (header->path_len > 0) {
244 dbuf = buf + offsetof(struct boot_option, title) + title_size;
246 while (dnext < header->path_len) {
247 struct device_path *dpath;
249 dpath = (struct device_path *)(dbuf + dnext);
250 if (dpath->length < 4)
253 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
254 if (dpath->type == 0x7f && dpath->sub_type == 0xff)
257 dnext += dpath->length;
259 /* Type 0x04 – Media Device Path */
260 if (dpath->type != 0x04)
263 /* Sub-Type 1 – Hard Drive */
264 if (dpath->sub_type == 0x01) {
265 /* 0x02 – GUID Partition Table */
266 if (dpath->drive.mbr_type != 0x02)
269 /* 0x02 – GUID signature */
270 if (dpath->drive.signature_type != 0x02)
273 efi_guid_to_id128(dpath->drive.signature, &p_uuid);
277 /* Sub-Type 4 – File Path */
278 if (dpath->sub_type == 0x04) {
279 p = utf16_to_utf8(dpath->path, dpath->length-4);
299 int efi_get_boot_order(uint16_t **order) {
304 r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
313 if ((l % sizeof(uint16_t) > 0) ||
314 (l / sizeof(uint16_t) > INT_MAX)) {
320 return (int) (l / sizeof(uint16_t));
323 static int boot_id_hex(const char s[4]) {
327 for (i = 0; i < 4; i++)
328 if (s[i] >= '0' && s[i] <= '9')
329 id |= (s[i] - '0') << (3 - i) * 4;
330 else if (s[i] >= 'A' && s[i] <= 'F')
331 id |= (s[i] - 'A' + 10) << (3 - i) * 4;
338 static int cmp_uint16(const void *_a, const void *_b) {
339 const uint16_t *a = _a, *b = _b;
341 return (int)*a - (int)*b;
344 int efi_get_boot_options(uint16_t **options) {
345 _cleanup_closedir_ DIR *dir = NULL;
347 uint16_t *list = NULL;
352 dir = opendir("/sys/firmware/efi/efivars/");
356 FOREACH_DIRENT(de, dir, r = -errno; goto fail) {
360 if (strncmp(de->d_name, "Boot", 4) != 0)
363 if (strlen(de->d_name) != 45)
366 if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
369 id = boot_id_hex(de->d_name + 4);
373 t = realloc(list, (count + 1) * sizeof(uint16_t));
383 qsort(list, count, sizeof(uint16_t), cmp_uint16);
393 static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
394 _cleanup_free_ char *j = NULL;
401 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j);
405 r = safe_atou64(j, &x);
413 static int get_boot_usec(usec_t *firmware, usec_t *loader) {
420 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
424 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
431 if (y > USEC_PER_HOUR)
440 int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
449 dual_timestamp_get(&_n);
453 r = get_boot_usec(&x, &y);
457 /* Let's convert this to timestamps where the firmware
458 * began/loader began working. To make this more confusing:
459 * since usec_t is unsigned and the kernel's monotonic clock
460 * begins at kernel initialization we'll actually initialize
461 * the monotonic timestamps here as negative of the actual
464 firmware->monotonic = y;
465 loader->monotonic = y - x;
467 a = n->monotonic + firmware->monotonic;
468 firmware->realtime = n->realtime > a ? n->realtime - a : 0;
470 a = n->monotonic + loader->monotonic;
471 loader->realtime = n->realtime > a ? n->realtime - a : 0;
476 int efi_get_loader_device_part_uuid(sd_id128_t *u) {
477 _cleanup_free_ char *p = NULL;
483 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p);
487 if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
488 &parsed[0], &parsed[1], &parsed[2], &parsed[3],
489 &parsed[4], &parsed[5], &parsed[6], &parsed[7],
490 &parsed[8], &parsed[9], &parsed[10], &parsed[11],
491 &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
494 for (i = 0; i < ELEMENTSOF(parsed); i++)
495 u->bytes[i] = parsed[i];