]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/boot/efi/util.h
network: drop support for old kernels which cannot set prefix route with non-main...
[thirdparty/systemd.git] / src / boot / efi / util.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
7a3c343c 2#pragma once
0fa2cac4
KS
3
4#include <efi.h>
5#include <efilib.h>
6
e5bc5f1f
YW
7#include "string-util-fundamental.h"
8
7700e9ba 9#define offsetof(type, member) __builtin_offsetof(type, member)
0fa2cac4 10
88657f75
LP
11#define UINTN_MAX (~(UINTN)0)
12#define INTN_MAX ((INTN)(UINTN_MAX>>1))
13#ifndef UINT32_MAX
14#define UINT32_MAX ((UINT32) -1)
15#endif
16#ifndef UINT64_MAX
17#define UINT64_MAX ((UINT64) -1)
18#endif
19
ec4106af
JJ
20/* gnu-efi format specifiers for integers are fixed to either 64bit with 'l' and 32bit without a size prefix.
21 * We rely on %u/%d/%x to format regular ints, so ensure the size is what we expect. At the same time, we also
22 * need specifiers for (U)INTN which are native (pointer) sized. */
23assert_cc(sizeof(int) == sizeof(UINT32));
24#if __SIZEOF_POINTER__ == 4
25# define PRIuN L"u"
26# define PRIiN L"d"
27#elif __SIZEOF_POINTER__ == 8
28# define PRIuN L"lu"
29# define PRIiN L"ld"
30#else
31# error "Unexpected pointer size"
32#endif
33
484ddd29
JJ
34#define xnew_alloc(type, n, alloc) \
35 ({ \
36 UINTN _alloc_size; \
1462d245 37 assert_se(!__builtin_mul_overflow(sizeof(type), (n), &_alloc_size)); \
484ddd29
JJ
38 (type *) alloc(_alloc_size); \
39 })
40
1462d245
LP
41#define xallocate_pool(size) ASSERT_SE_PTR(AllocatePool(size))
42#define xallocate_zero_pool(size) ASSERT_SE_PTR(AllocateZeroPool(size))
43#define xreallocate_pool(p, old_size, new_size) ASSERT_SE_PTR(ReallocatePool((p), (old_size), (new_size)))
44#define xpool_print(fmt, ...) ((CHAR16 *) ASSERT_SE_PTR(PoolPrint((fmt), ##__VA_ARGS__)))
45#define xstrdup(str) ((CHAR16 *) ASSERT_SE_PTR(StrDuplicate(str)))
484ddd29
JJ
46#define xnew(type, n) xnew_alloc(type, (n), xallocate_pool)
47#define xnew0(type, n) xnew_alloc(type, (n), xallocate_zero_pool)
48
427ee7ec 49EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b);
4db7e6d7 50
bcea9332 51EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, UINT32 flags);
70cd15e9 52EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const void *buf, UINTN size, UINT32 flags);
edad24c6
YW
53EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags);
54EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const CHAR16 *NAME, UINT32 value, UINT32 flags);
55EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 value, UINT32 flags);
70cd15e9 56void efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 usec);
0fa2cac4 57
5e1f0e6f 58EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value);
427ee7ec 59EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size);
a7308a26 60EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i);
987d0a12
DDM
61EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret);
62EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret);
2a7c1675 63EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret);
0fa2cac4 64
ef53d52b 65CHAR8 *strchra(const CHAR8 *s, CHAR8 c);
4f943415
JJ
66CHAR16 *xstra_to_path(const CHAR8 *stra);
67CHAR16 *xstra_to_str(const CHAR8 *stra);
0fa2cac4 68
85eb489e 69EFI_STATUS file_read(EFI_FILE *dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
a42d7cf1 70
0b2281a2 71static inline void free_poolp(void *p) {
2880e665
LP
72 void *q = *(void**) p;
73
74 if (!q)
75 return;
76
2d1ac308 77 (void) BS->FreePool(q);
a42d7cf1
ZJS
78}
79
0b2281a2 80#define _cleanup_freepool_ _cleanup_(free_poolp)
3aaa95e0 81
85eb489e 82static inline void file_closep(EFI_FILE **handle) {
3aaa95e0
LP
83 if (!*handle)
84 return;
85
12f32748 86 (*handle)->Close(*handle);
3aaa95e0 87}
0e2bc732 88
7d2ebb6f
DDM
89/*
90 * Allocated random UUID, intended to be shared across tools that implement
91 * the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
92 * associated EFI variables.
93 */
94#define LOADER_GUID \
95 &(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
96#define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
b49dd00f 97
70cd15e9 98void log_error_stall(const CHAR16 *fmt, ...);
b19fa812 99EFI_STATUS log_oom(void);
8aba0eec
JJ
100
101/* This works just like log_error_errno() from userspace, but requires you
102 * to provide err a second time if you want to use %r in the message! */
103#define log_error_status_stall(err, fmt, ...) \
104 ({ \
105 log_error_stall(fmt, ##__VA_ARGS__); \
106 err; \
107 })
43ee1fe0 108
70cd15e9
JJ
109void print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str);
110void clear_screen(UINTN attr);
c6dfe360 111
70cd15e9
JJ
112typedef INTN (*compare_pointer_func_t)(const void *a, const void *b);
113void sort_pointer_array(void **array, UINTN n_members, compare_pointer_func_t compare);
80b2f4d9 114
85eb489e 115EFI_STATUS get_file_info_harder(EFI_FILE *handle, EFI_FILE_INFO **ret, UINTN *ret_size);
c6dfe360 116
85eb489e 117EFI_STATUS readdir_harder(EFI_FILE *handle, EFI_FILE_INFO **buffer, UINTN *buffer_size);
c6dfe360
LP
118
119UINTN strnlena(const CHAR8 *p, UINTN maxlen);
0a15a824 120CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz);
245e9d55
JJ
121INTN strncasecmpa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen);
122static inline BOOLEAN strncaseeqa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen) {
123 return strncasecmpa(a, b, maxlen) == 0;
124}
c6dfe360
LP
125
126BOOLEAN is_ascii(const CHAR16 *f);
127
128CHAR16 **strv_free(CHAR16 **l);
129
130static inline void strv_freep(CHAR16 ***p) {
131 strv_free(*p);
132}
133
85eb489e 134EFI_STATUS open_directory(EFI_FILE *root_dir, const CHAR16 *path, EFI_FILE **ret);
a0a644be
LP
135
136/* Conversion between EFI_PHYSICAL_ADDRESS and pointers is not obvious. The former is always 64bit, even on
137 * 32bit archs. And gcc complains if we cast a pointer to an integer of a different size. Hence let's do the
138 * conversion indirectly: first into UINTN (which is defined by UEFI to have the same size as a pointer), and
139 * then extended to EFI_PHYSICAL_ADDRESS. */
140static inline EFI_PHYSICAL_ADDRESS POINTER_TO_PHYSICAL_ADDRESS(const void *p) {
141 return (EFI_PHYSICAL_ADDRESS) (UINTN) p;
142}
143
144static inline void *PHYSICAL_ADDRESS_TO_POINTER(EFI_PHYSICAL_ADDRESS addr) {
145#if __SIZEOF_POINTER__ == 4
146 /* On 32bit systems the address might not be convertible (as pointers are 32bit but
147 * EFI_PHYSICAL_ADDRESS 64bit) */
148 assert(addr <= UINT32_MAX);
149#elif __SIZEOF_POINTER__ != 8
150 #error "Unexpected pointer size"
151#endif
152
153 return (void*) (UINTN) addr;
154}
3a624912 155
70cd15e9 156UINT64 get_os_indications_supported(void);
948d085e
JJ
157
158#ifdef EFI_DEBUG
159void debug_break(void);
160extern UINT8 _text, _data;
161/* Report the relocated position of text and data sections so that a debugger
162 * can attach to us. See debug-sd-boot.sh for how this can be done. */
ec4106af 163# define debug_hook(identity) Print(identity L"@0x%lx,0x%lx\n", POINTER_TO_PHYSICAL_ADDRESS(&_text), POINTER_TO_PHYSICAL_ADDRESS(&_data))
948d085e
JJ
164#else
165# define debug_hook(identity)
166#endif
85d2f13b
JJ
167
168#if defined(__i386__) || defined(__x86_64__)
cc25bedb 169void beep(UINTN beep_count);
85d2f13b 170#else
cc25bedb 171static inline void beep(UINTN beep_count) {}
85d2f13b 172#endif