1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "alloc-util.h"
5 #include "efi-loader.h"
9 #include "parse-util.h"
10 #include "path-util.h"
11 #include "stat-util.h"
12 #include "string-util.h"
14 #include "time-util.h"
19 static int read_usec(const char *variable
, usec_t
*ret
) {
20 _cleanup_free_
char *j
= NULL
;
27 r
= efi_get_variable_string(variable
, &j
);
31 r
= safe_atou64(j
, &x
);
39 static int get_device_part_uuid(const char *variable
, sd_id128_t
*ret
) {
43 return efi_get_variable_id128(variable
, ret
);
47 int efi_loader_get_boot_usec(usec_t
*ret_firmware
, usec_t
*ret_loader
) {
58 r
= read_usec(EFI_LOADER_VARIABLE_STR("LoaderTimeInitUSec"), &x
);
60 return log_debug_errno(r
, "Failed to read LoaderTimeInitUSec: %m");
62 r
= read_usec(EFI_LOADER_VARIABLE_STR("LoaderTimeExecUSec"), &y
);
64 return log_debug_errno(r
, "Failed to read LoaderTimeExecUSec: %m");
66 if (y
== 0 || y
< x
|| y
- x
> USEC_PER_HOUR
)
67 return log_debug_errno(SYNTHETIC_ERRNO(EIO
),
68 "Bad LoaderTimeInitUSec=%"PRIu64
", LoaderTimeExecUSec=%" PRIu64
"; refusing.",
79 int efi_loader_get_device_part_uuid(sd_id128_t
*ret
) {
81 return get_device_part_uuid(EFI_LOADER_VARIABLE_STR("LoaderDevicePartUUID"), ret
);
87 int efi_stub_get_device_part_uuid(sd_id128_t
*ret
) {
89 return get_device_part_uuid(EFI_LOADER_VARIABLE_STR("StubDevicePartUUID"), ret
);
95 int efi_loader_get_entries(char ***ret
) {
97 _cleanup_free_ char16_t
*entries
= NULL
;
98 _cleanup_strv_free_
char **l
= NULL
;
107 r
= efi_get_variable(EFI_LOADER_VARIABLE_STR("LoaderEntries"), NULL
, (void**) &entries
, &size
);
111 /* The variable contains a series of individually NUL terminated UTF-16 strings. We gracefully
112 * consider the final NUL byte optional (i.e. the last string may or may not end in a NUL byte). */
114 for (size_t i
= 0, start
= 0;; i
++) {
115 _cleanup_free_
char *decoded
= NULL
;
118 /* Is this the end of the variable's data? */
119 end
= i
* sizeof(char16_t
) >= size
;
121 /* Are we in the middle of a string? (i.e. not at the end of the variable, nor at a NUL terminator?) If
122 * so, let's go to the next entry. */
123 if (!end
&& entries
[i
] != 0)
126 /* Empty string at the end of variable? That's the trailer, we are done (i.e. we have a final
127 * NUL terminator). */
128 if (end
&& start
== i
)
131 /* We reached the end of a string, let's decode it into UTF-8 */
132 decoded
= utf16_to_utf8(entries
+ start
, (i
- start
) * sizeof(char16_t
));
136 if (efi_loader_entry_name_valid(decoded
)) {
137 r
= strv_consume(&l
, TAKE_PTR(decoded
));
141 log_debug("Ignoring invalid loader entry '%s'.", decoded
);
143 /* Exit the loop if we reached the end of the variable (i.e. we do not have a final NUL
148 /* Continue after the NUL byte */
159 int efi_loader_get_features(uint64_t *ret
) {
161 _cleanup_free_
void *v
= NULL
;
167 if (!is_efi_boot()) {
172 r
= efi_get_variable(EFI_LOADER_VARIABLE_STR("LoaderFeatures"), NULL
, &v
, &s
);
174 _cleanup_free_
char *info
= NULL
;
176 /* The new (v240+) LoaderFeatures variable is not supported, let's see if it's systemd-boot at all */
177 r
= efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderInfo"), &info
);
182 /* Variable not set, definitely means not systemd-boot */
184 } else if (first_word(info
, "systemd-boot")) {
186 /* An older systemd-boot version. Let's hardcode the feature set, since it was pretty
187 * static in all its versions. */
189 *ret
= EFI_LOADER_FEATURE_CONFIG_TIMEOUT
|
190 EFI_LOADER_FEATURE_ENTRY_DEFAULT
|
191 EFI_LOADER_FEATURE_ENTRY_ONESHOT
;
196 /* No features supported */
203 if (s
!= sizeof(uint64_t))
204 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
205 "LoaderFeatures EFI variable doesn't have the right size.");
207 memcpy(ret
, v
, sizeof(uint64_t));
214 int efi_stub_get_features(uint64_t *ret
) {
216 _cleanup_free_
void *v
= NULL
;
222 if (!is_efi_boot()) {
227 r
= efi_get_variable(EFI_LOADER_VARIABLE_STR("StubFeatures"), NULL
, &v
, &s
);
229 _cleanup_free_
char *info
= NULL
;
231 /* The new (v252+) StubFeatures variable is not supported, let's see if it's systemd-stub at all */
232 r
= efi_get_variable_string(EFI_LOADER_VARIABLE_STR("StubInfo"), &info
);
237 /* Variable not set, definitely means not systemd-stub */
239 } else if (first_word(info
, "systemd-stub")) {
241 /* An older systemd-stub version. Let's hardcode the feature set, since it was pretty
242 * static in all its versions. */
244 *ret
= EFI_STUB_FEATURE_REPORT_BOOT_PARTITION
;
248 /* No features supported */
255 if (s
!= sizeof(uint64_t))
256 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
),
257 "StubFeatures EFI variable doesn't have the right size.");
259 memcpy(ret
, v
, sizeof(uint64_t));
266 int efi_measured_uki(int log_level
) {
268 _cleanup_free_
char *pcr_string
= NULL
;
269 static int cached
= -1;
276 /* Checks if we are booted on a kernel with sd-stub which measured the kernel into PCR 11 on a TPM2
277 * chip. Or in other words, if we are running on a TPM enabled UKI. (TPM 1.2 situations are ignored.)
279 * Returns == 0 and > 0 depending on the result of the test. Returns -EREMOTE if we detected a stub
280 * being used, but it measured things into a different PCR than we are configured for in
281 * userspace. (i.e. we expect PCR 11 being used for this by both sd-stub and us) */
283 r
= secure_getenv_bool("SYSTEMD_FORCE_MEASURE"); /* Give user a chance to override the variable test,
284 * for debugging purposes */
288 log_debug_errno(r
, "Failed to parse $SYSTEMD_FORCE_MEASURE, ignoring: %m");
293 r
= efi_get_variable_string(EFI_LOADER_VARIABLE_STR("StubPcrKernelImage"), &pcr_string
);
297 return log_full_errno(log_level
, r
,
298 "Failed to get StubPcrKernelImage EFI variable: %m");
300 r
= safe_atou(pcr_string
, &pcr_nr
);
302 return log_full_errno(log_level
, r
,
303 "Failed to parse StubPcrKernelImage EFI variable: %s", pcr_string
);
304 if (pcr_nr
!= TPM2_PCR_KERNEL_BOOT
)
305 return log_full_errno(log_level
, SYNTHETIC_ERRNO(EREMOTE
),
306 "Kernel stub measured kernel image into PCR %u, which is different than expected %i.",
307 pcr_nr
, TPM2_PCR_KERNEL_BOOT
);
311 return log_full_errno(log_level
, SYNTHETIC_ERRNO(EOPNOTSUPP
), "Compiled without support for EFI");
315 int efi_loader_get_config_timeout_one_shot(usec_t
*ret
) {
317 _cleanup_free_
char *v
= NULL
;
318 static struct stat cache_stat
= {};
319 struct stat new_stat
;
326 /* stat() the EFI variable, to see if the mtime changed. If it did, we need to cache again. */
327 if (stat(EFIVAR_PATH(EFI_LOADER_VARIABLE_STR("LoaderConfigTimeoutOneShot")), &new_stat
) < 0)
330 if (stat_inode_unmodified(&new_stat
, &cache_stat
)) {
335 r
= efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderConfigTimeoutOneShot"), &v
);
339 r
= safe_atou64(v
, &sec
);
342 if (sec
> USEC_INFINITY
/ USEC_PER_SEC
)
345 cache_stat
= new_stat
;
346 *ret
= cache
= sec
* USEC_PER_SEC
; /* return in μs */
353 int efi_loader_update_entry_one_shot_cache(char **cache
, struct stat
*cache_stat
) {
355 _cleanup_free_
char *v
= NULL
;
356 struct stat new_stat
;
362 /* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
363 if (stat(EFIVAR_PATH(EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot")), &new_stat
) < 0)
366 if (stat_inode_unmodified(&new_stat
, cache_stat
))
369 r
= efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderEntryOneShot"), &v
);
373 if (!efi_loader_entry_name_valid(v
))
376 *cache_stat
= new_stat
;
377 free_and_replace(*cache
, v
);
385 int efi_get_variable_id128(const char *variable
, sd_id128_t
*ret
) {
391 /* This is placed here (rather than in basic/efivars.c) because code in basic/ is not allowed to link
392 * against libsystemd.so */
394 _cleanup_free_
char *p
= NULL
;
395 r
= efi_get_variable_string(variable
, &p
);
399 return sd_id128_from_string(p
, ret
);
405 bool efi_loader_entry_name_valid(const char *s
) {
406 if (!filename_is_valid(s
)) /* Make sure entry names fit in filenames */
409 return in_charset(s
, ALPHANUMERICAL
"+-_.@");