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/>.
30 bool is_efiboot(void) {
31 return access("/sys/firmware/efi", F_OK) >= 0;
34 int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) {
35 _cleanup_close_ int fd = -1;
36 _cleanup_free_ char *p = NULL;
47 "/sys/firmware/efi/efivars/%s-%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
48 name, SD_ID128_FORMAT_VAL(vendor)) < 0)
51 fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
55 if (fstat(fd, &st) < 0)
59 if (st.st_size > 4*1024*1024 + 4)
62 n = read(fd, &a, sizeof(a));
68 r = malloc(st.st_size - 4 + 2);
72 n = read(fd, r, (size_t) st.st_size - 4);
77 if (n != (ssize_t) st.st_size - 4) {
82 /* Always NUL terminate (2 bytes, to protect UTF-16) */
83 ((char*) r)[st.st_size - 4] = 0;
84 ((char*) r)[st.st_size - 4 + 1] = 0;
87 *size = (size_t) st.st_size - 4;
95 char *efi_get_variable_string(sd_id128_t vendor, const char *name) {
96 _cleanup_free_ void *s = NULL;
100 err = efi_get_variable(vendor, name, NULL, &s, &ss);
103 return utf16_to_utf8(s, ss);
106 static size_t utf16_size(const uint16_t *s) {
111 return (l+1) * sizeof(uint16_t);
114 static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
121 const struct uuid *uuid = guid;
123 id128->bytes[0] = (uuid->u1 >> 24) & 0xff;
124 id128->bytes[1] = (uuid->u1 >> 16) & 0xff;
125 id128->bytes[2] = (uuid->u1 >> 8) & 0xff;
126 id128->bytes[3] = (uuid->u1) & 0xff;
127 id128->bytes[4] = (uuid->u2 >> 8) & 0xff;
128 id128->bytes[5] = (uuid->u2) & 0xff;
129 id128->bytes[6] = (uuid->u3 >> 8) & 0xff;
130 id128->bytes[7] = (uuid->u3) & 0xff;
131 memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
134 int efi_get_boot_option(uint32_t id, uint32_t *attributes, char **title, sd_id128_t *part_uuid, char **path, char **data, size_t *data_size) {
147 uint8_t signature_type;
156 struct drive_path drive;
161 _cleanup_free_ char *buf = NULL;
163 struct boot_option *header;
167 sd_id128_t p_uuid = SD_ID128_NULL;
172 snprintf(boot_id, sizeof(boot_id), "Boot%04X", id);
173 err = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
177 if (l < sizeof(struct boot_option))
180 header = (struct boot_option *)buf;
181 title_size = utf16_size(header->title);
182 if (title_size > l - offsetof(struct boot_option, title))
185 s = utf16_to_utf8(header->title, title_size);
191 if (header->path_len > 0) {
195 dbuf = buf + offsetof(struct boot_option, title) + title_size;
197 while (dnext < header->path_len) {
198 struct device_path *dpath;
200 dpath = (struct device_path *)(dbuf + dnext);
201 if (dpath->length < 4)
204 /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
205 if (dpath->type == 0x7f && dpath->sub_type == 0xff)
208 dnext += dpath->length;
210 /* Type 0x04 – Media Device Path */
211 if (dpath->type != 0x04)
214 /* Sub-Type 1 – Hard Drive */
215 if (dpath->sub_type == 0x01) {
216 /* 0x02 – GUID Partition Table */
217 if (dpath->drive.mbr_type != 0x02)
220 /* 0x02 – GUID signature */
221 if (dpath->drive.signature_type != 0x02)
224 efi_guid_to_id128(dpath->drive.signature, &p_uuid);
228 /* Sub-Type 4 – File Path */
229 if (dpath->sub_type == 0x04) {
230 p = utf16_to_utf8(dpath->path, dpath->length-4);
253 int efi_get_boot_order(uint16_t **order, size_t *count) {
258 err = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
267 if ((l % sizeof(uint16_t) > 0)) {
273 *count = l / sizeof(uint16_t);
277 static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) {
278 _cleanup_free_ void *i = NULL;
279 _cleanup_free_ char *j = NULL;
287 r = efi_get_variable(EFI_VENDOR_LOADER, name, NULL, &i, &is);
291 j = utf16_to_utf8(i, is);
295 r = safe_atou64(j, &x);
303 static int get_boot_usec(usec_t *firmware, usec_t *loader) {
310 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
314 r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
321 if (y > USEC_PER_HOUR)
330 int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) {
339 dual_timestamp_get(&_n);
343 r = get_boot_usec(&x, &y);
347 /* Let's convert this to timestamps where the firmware
348 * began/loader began working. To make this more confusing:
349 * since usec_t is unsigned and the kernel's monotonic clock
350 * begins at kernel initialization we'll actually initialize
351 * the monotonic timestamps here as negative of the actual
354 firmware->monotonic = y;
355 loader->monotonic = y - x;
357 a = n->monotonic + firmware->monotonic;
358 firmware->realtime = n->realtime > a ? n->realtime - a : 0;
360 a = n->monotonic + loader->monotonic;
361 loader->realtime = n->realtime > a ? n->realtime - a : 0;
366 int efi_get_loader_device_part_uuid(sd_id128_t *u) {
367 _cleanup_free_ void *s = NULL;
368 _cleanup_free_ char *p = NULL;
375 r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", NULL, &s, &ss);
379 p = utf16_to_utf8(s, ss);
383 if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
384 &parsed[0], &parsed[1], &parsed[2], &parsed[3],
385 &parsed[4], &parsed[5], &parsed[6], &parsed[7],
386 &parsed[8], &parsed[9], &parsed[10], &parsed[11],
387 &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
390 for (i = 0; i < ELEMENTSOF(parsed); i++)
391 u->bytes[i] = parsed[i];