]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/efi/util.h
Merge pull request #20219 from khfeng/use-intel-hid-rfkill
[thirdparty/systemd.git] / src / boot / efi / util.h
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include <efi.h>
5 #include <efilib.h>
6
7 #include "string-util-fundamental.h"
8
9 /* This TPM PCR is where most Linux infrastructure extends the kernel command line into, and so do we. We also extend
10 * any passed credentials here. */
11 #define TPM_PCR_INDEX_KERNEL_PARAMETERS 8
12
13 /* This TPM PCR is where most Linux infrastructure extends the initrd binary images into, and so do we. */
14 #define TPM_PCR_INDEX_INITRD 4
15
16 #define OFFSETOF(x,y) __builtin_offsetof(x,y)
17
18 #define UINTN_MAX (~(UINTN)0)
19 #define INTN_MAX ((INTN)(UINTN_MAX>>1))
20 #ifndef UINT32_MAX
21 #define UINT32_MAX ((UINT32) -1)
22 #endif
23 #ifndef UINT64_MAX
24 #define UINT64_MAX ((UINT64) -1)
25 #endif
26
27 static inline UINTN ALIGN_TO(UINTN l, UINTN ali) {
28 if (l > UINTN_MAX - (ali - 1)) /* Overflow? */
29 return UINTN_MAX;
30
31 return ((l + (ali - 1)) & ~(ali - 1));
32 }
33
34 EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
35
36 UINT64 ticks_read(void);
37 UINT64 ticks_freq(void);
38 UINT64 time_usec(void);
39
40 EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags);
41 EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, UINT32 flags);
42 EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags);
43 EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *NAME, UINT32 value, UINT32 flags);
44 EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags);
45 VOID efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec);
46
47 EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value);
48 EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size);
49 EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i);
50 EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret);
51 EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret);
52 EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret);
53
54 CHAR8 *strchra(const CHAR8 *s, CHAR8 c);
55 CHAR16 *stra_to_path(const CHAR8 *stra);
56 CHAR16 *stra_to_str(const CHAR8 *stra);
57
58 EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
59
60 static inline void FreePoolp(void *p) {
61 void *q = *(void**) p;
62
63 if (!q)
64 return;
65
66 FreePool(q);
67 }
68
69 #define _cleanup_freepool_ _cleanup_(FreePoolp)
70
71 static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
72 if (!*handle)
73 return;
74
75 uefi_call_wrapper((*handle)->Close, 1, *handle);
76 }
77
78 /*
79 * Allocated random UUID, intended to be shared across tools that implement
80 * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
81 * associated EFI variables.
82 */
83 #define LOADER_GUID \
84 &(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
85 #define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
86
87 VOID log_error_stall(const CHAR16 *fmt, ...);
88 EFI_STATUS log_oom(void);
89
90 /* This works just like log_error_errno() from userspace, but requires you
91 * to provide err a second time if you want to use %r in the message! */
92 #define log_error_status_stall(err, fmt, ...) \
93 ({ \
94 log_error_stall(fmt, ##__VA_ARGS__); \
95 err; \
96 })
97
98 VOID *memmem_safe(const VOID *haystack, UINTN haystack_len, const VOID *needle, UINTN needle_len);
99
100 static inline VOID *mempmem_safe(const VOID *haystack, UINTN haystack_len, const VOID *needle, UINTN needle_len) {
101 CHAR8 *p = memmem_safe(haystack, haystack_len, needle, needle_len);
102 return p ? p + needle_len : NULL;
103 }
104
105 VOID print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str);
106 VOID clear_screen(UINTN attr);
107
108 typedef INTN (*compare_pointer_func_t)(const VOID *a, const VOID *b);
109 void sort_pointer_array(VOID **array, UINTN n_members, compare_pointer_func_t compare);
110
111 EFI_STATUS get_file_info_harder(EFI_FILE_HANDLE handle, EFI_FILE_INFO **ret, UINTN *ret_size);
112
113 EFI_STATUS readdir_harder(EFI_FILE_HANDLE handle, EFI_FILE_INFO **buffer, UINTN *buffer_size);
114
115 UINTN strnlena(const CHAR8 *p, UINTN maxlen);
116 CHAR8 *strndup8(const CHAR8 *p, UINTN sz);
117
118 BOOLEAN is_ascii(const CHAR16 *f);
119
120 CHAR16 **strv_free(CHAR16 **l);
121
122 static inline void strv_freep(CHAR16 ***p) {
123 strv_free(*p);
124 }
125
126 EFI_STATUS open_directory(EFI_FILE_HANDLE root_dir, const CHAR16 *path, EFI_FILE_HANDLE *ret);
127
128 /* Conversion between EFI_PHYSICAL_ADDRESS and pointers is not obvious. The former is always 64bit, even on
129 * 32bit archs. And gcc complains if we cast a pointer to an integer of a different size. Hence let's do the
130 * conversion indirectly: first into UINTN (which is defined by UEFI to have the same size as a pointer), and
131 * then extended to EFI_PHYSICAL_ADDRESS. */
132 static inline EFI_PHYSICAL_ADDRESS POINTER_TO_PHYSICAL_ADDRESS(const void *p) {
133 return (EFI_PHYSICAL_ADDRESS) (UINTN) p;
134 }
135
136 static inline void *PHYSICAL_ADDRESS_TO_POINTER(EFI_PHYSICAL_ADDRESS addr) {
137 #if __SIZEOF_POINTER__ == 4
138 /* On 32bit systems the address might not be convertible (as pointers are 32bit but
139 * EFI_PHYSICAL_ADDRESS 64bit) */
140 assert(addr <= UINT32_MAX);
141 #elif __SIZEOF_POINTER__ != 8
142 #error "Unexpected pointer size"
143 #endif
144
145 return (void*) (UINTN) addr;
146 }
147
148 UINT64 get_os_indications_supported(VOID);