]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/boot/efi/util.h
Merge pull request #21981 from medhefgo/boot-cleanup
[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(type, member) __builtin_offsetof(type, member)
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 #define assert_alloc_ret(p) \
28 ({ \
29 void *_p = (p); \
30 assert(_p); \
31 _p; \
32 })
33
34 #define xnew_alloc(type, n, alloc) \
35 ({ \
36 UINTN _alloc_size; \
37 if (__builtin_mul_overflow(sizeof(type), (n), &_alloc_size)) \
38 assert_not_reached(); \
39 (type *) alloc(_alloc_size); \
40 })
41
42 #define xallocate_pool(size) assert_alloc_ret(AllocatePool(size))
43 #define xallocate_zero_pool(size) assert_alloc_ret(AllocateZeroPool(size))
44 #define xreallocate_pool(p, old_size, new_size) assert_alloc_ret(ReallocatePool((p), (old_size), (new_size)))
45 #define xpool_print(fmt, ...) ((CHAR16 *) assert_alloc_ret(PoolPrint((fmt), ##__VA_ARGS__)))
46 #define xstrdup(str) ((CHAR16 *) assert_alloc_ret(StrDuplicate(str)))
47 #define xnew(type, n) xnew_alloc(type, (n), xallocate_pool)
48 #define xnew0(type, n) xnew_alloc(type, (n), xallocate_zero_pool)
49
50 EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
51
52 UINT64 ticks_read(void);
53 UINT64 ticks_freq(void);
54 UINT64 time_usec(void);
55
56 EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags);
57 EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const void *buf, UINTN size, UINT32 flags);
58 EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags);
59 EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *NAME, UINT32 value, UINT32 flags);
60 EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags);
61 void efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec);
62
63 EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value);
64 EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size);
65 EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i);
66 EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret);
67 EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret);
68 EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret);
69
70 CHAR8 *strchra(const CHAR8 *s, CHAR8 c);
71 CHAR16 *xstra_to_path(const CHAR8 *stra);
72 CHAR16 *xstra_to_str(const CHAR8 *stra);
73
74 EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
75
76 static inline void free_poolp(void *p) {
77 void *q = *(void**) p;
78
79 if (!q)
80 return;
81
82 FreePool(q);
83 }
84
85 #define _cleanup_freepool_ _cleanup_(free_poolp)
86
87 static inline void file_handle_closep(EFI_FILE_HANDLE *handle) {
88 if (!*handle)
89 return;
90
91 (*handle)->Close(*handle);
92 }
93
94 /*
95 * Allocated random UUID, intended to be shared across tools that implement
96 * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
97 * associated EFI variables.
98 */
99 #define LOADER_GUID \
100 &(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
101 #define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
102
103 void log_error_stall(const CHAR16 *fmt, ...);
104 EFI_STATUS log_oom(void);
105
106 /* This works just like log_error_errno() from userspace, but requires you
107 * to provide err a second time if you want to use %r in the message! */
108 #define log_error_status_stall(err, fmt, ...) \
109 ({ \
110 log_error_stall(fmt, ##__VA_ARGS__); \
111 err; \
112 })
113
114 void print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str);
115 void clear_screen(UINTN attr);
116
117 typedef INTN (*compare_pointer_func_t)(const void *a, const void *b);
118 void sort_pointer_array(void **array, UINTN n_members, compare_pointer_func_t compare);
119
120 EFI_STATUS get_file_info_harder(EFI_FILE_HANDLE handle, EFI_FILE_INFO **ret, UINTN *ret_size);
121
122 EFI_STATUS readdir_harder(EFI_FILE_HANDLE handle, EFI_FILE_INFO **buffer, UINTN *buffer_size);
123
124 UINTN strnlena(const CHAR8 *p, UINTN maxlen);
125 CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz);
126 INTN strncasecmpa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen);
127 static inline BOOLEAN strncaseeqa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen) {
128 return strncasecmpa(a, b, maxlen) == 0;
129 }
130
131 BOOLEAN is_ascii(const CHAR16 *f);
132
133 CHAR16 **strv_free(CHAR16 **l);
134
135 static inline void strv_freep(CHAR16 ***p) {
136 strv_free(*p);
137 }
138
139 EFI_STATUS open_directory(EFI_FILE_HANDLE root_dir, const CHAR16 *path, EFI_FILE_HANDLE *ret);
140
141 /* Conversion between EFI_PHYSICAL_ADDRESS and pointers is not obvious. The former is always 64bit, even on
142 * 32bit archs. And gcc complains if we cast a pointer to an integer of a different size. Hence let's do the
143 * conversion indirectly: first into UINTN (which is defined by UEFI to have the same size as a pointer), and
144 * then extended to EFI_PHYSICAL_ADDRESS. */
145 static inline EFI_PHYSICAL_ADDRESS POINTER_TO_PHYSICAL_ADDRESS(const void *p) {
146 return (EFI_PHYSICAL_ADDRESS) (UINTN) p;
147 }
148
149 static inline void *PHYSICAL_ADDRESS_TO_POINTER(EFI_PHYSICAL_ADDRESS addr) {
150 #if __SIZEOF_POINTER__ == 4
151 /* On 32bit systems the address might not be convertible (as pointers are 32bit but
152 * EFI_PHYSICAL_ADDRESS 64bit) */
153 assert(addr <= UINT32_MAX);
154 #elif __SIZEOF_POINTER__ != 8
155 #error "Unexpected pointer size"
156 #endif
157
158 return (void*) (UINTN) addr;
159 }
160
161 UINT64 get_os_indications_supported(void);
162
163 #ifdef EFI_DEBUG
164 void debug_break(void);
165 extern UINT8 _text, _data;
166 /* Report the relocated position of text and data sections so that a debugger
167 * can attach to us. See debug-sd-boot.sh for how this can be done. */
168 # define debug_hook(identity) Print(identity L"@0x%x,0x%x\n", &_text, &_data)
169 #else
170 # define debug_hook(identity)
171 #endif