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))
235 s = utf16_to_utf8(header->title, title_size);
242 if (header->path_len > 0) {
246 dbuf = buf + offsetof(struct boot_option, title) + title_size;
248 while (dnext < header->path_len) {
249 struct device_path *dpath;
251 dpath = (struct device_path *)(dbuf + dnext);
252 if (dpath->length < 4)
255 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
256 if (dpath->type == 0x7f && dpath->sub_type == 0xff)
259 dnext += dpath->length;
261 /* Type 0x04 – Media Device Path */
262 if (dpath->type != 0x04)
265 /* Sub-Type 1 – Hard Drive */
266 if (dpath->sub_type == 0x01) {
267 /* 0x02 – GUID Partition Table */
268 if (dpath->drive.mbr_type != 0x02)
271 /* 0x02 – GUID signature */
272 if (dpath->drive.signature_type != 0x02)
276 efi_guid_to_id128(dpath->drive.signature, &p_uuid);
280 /* Sub-Type 4 – File Path */
281 if (dpath->sub_type == 0x04 && !p && path) {
282 p = utf16_to_utf8(dpath->path, dpath->length-4);
302 int efi_get_boot_order(uint16_t **order) {
307 r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
316 if ((l % sizeof(uint16_t) > 0) ||
317 (l / sizeof(uint16_t) > INT_MAX)) {
323 return (int) (l / sizeof(uint16_t));
326 static int boot_id_hex(const char s[4]) {
330 for (i = 0; i < 4; i++)
331 if (s[i] >= '0' && s[i] <= '9')
332 id |= (s[i] - '0') << (3 - i) * 4;
333 else if (s[i] >= 'A' && s[i] <= 'F')
334 id |= (s[i] - 'A' + 10) << (3 - i) * 4;
341 static int cmp_uint16(const void *_a, const void *_b) {
342 const uint16_t *a = _a, *b = _b;
344 return (int)*a - (int)*b;
347 int efi_get_boot_options(uint16_t **options) {
348 _cleanup_closedir_ DIR *dir = NULL;
350 uint16_t *list = NULL;
355 dir = opendir("/sys/firmware/efi/efivars/");
359 FOREACH_DIRENT(de, dir, r = -errno; goto fail) {
363 if (strncmp(de->d_name, "Boot", 4) != 0)
366 if (strlen(de->d_name) != 45)
369 if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0)
372 id = boot_id_hex(de->d_name + 4);
376 t = realloc(list, (count + 1) * sizeof(uint16_t));
386 qsort(list, count, sizeof(uint16_t), cmp_uint16);
396 static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
397 _cleanup_free_ char *j = NULL;
404 r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j);
408 r = safe_atou64(j, &x);
416 static int get_boot_usec(usec_t *firmware, usec_t *loader) {
423 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
427 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
434 if (y > USEC_PER_HOUR)
443 int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
452 dual_timestamp_get(&_n);
456 r = get_boot_usec(&x, &y);
460 /* Let's convert this to timestamps where the firmware
461 * began/loader began working. To make this more confusing:
462 * since usec_t is unsigned and the kernel's monotonic clock
463 * begins at kernel initialization we'll actually initialize
464 * the monotonic timestamps here as negative of the actual
467 firmware->monotonic = y;
468 loader->monotonic = y - x;
470 a = n->monotonic + firmware->monotonic;
471 firmware->realtime = n->realtime > a ? n->realtime - a : 0;
473 a = n->monotonic + loader->monotonic;
474 loader->realtime = n->realtime > a ? n->realtime - a : 0;
479 int efi_get_loader_device_part_uuid(sd_id128_t *u) {
480 _cleanup_free_ char *p = NULL;
486 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p);
490 if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
491 &parsed[0], &parsed[1], &parsed[2], &parsed[3],
492 &parsed[4], &parsed[5], &parsed[6], &parsed[7],
493 &parsed[8], &parsed[9], &parsed[10], &parsed[11],
494 &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
497 for (i = 0; i < ELEMENTSOF(parsed); i++)
498 u->bytes[i] = parsed[i];