OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcTemplateLib.h
Go to the documentation of this file.
1
19#ifndef OC_TEMPLATE_LIB_H
20#define OC_TEMPLATE_LIB_H
21
22#include <Library/BaseMemoryLib.h>
23
24//
25// Common structor prototype.
26//
27typedef
28VOID
29(*OC_STRUCTOR) (
30 VOID *Ptr,
31 UINT32 Size
32 );
33
34//
35// Private primitives for type generations
36//
37
38#define PRIV_OC_STRUCTOR_IGNORE(...)
39#define PRIV_OC_STRUCTOR_EXPAND(...) __VA_ARGS__
40
41#define PRIV_OC_SELECT_NEXT_INNER(Dummy, Next, ...) Next
42//
43// Without this layer of indirection, MSVC evaluates __VA_ARGS__ early and
44// PRIV_OC_SELECT_NEXT_INNER receives only two arguments, the second always
45// being Unused as per PRIV_OC_SELECT_NEXT.
46//
47#define PRIV_OC_SELECT_NEXT_INNER_INDIR(...) PRIV_OC_SELECT_NEXT_INNER __VA_ARGS__
48#define PRIV_OC_SELECT_NEXT(...) PRIV_OC_SELECT_NEXT_INNER_INDIR((__VA_ARGS__, Unused))
49#define PRIV_OC_REMOVE_NEXT(...) , do { } while (0),
50
51#define PRIV_OC_DECLARE_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
52 Type Name Suffix;
53
54#define PRIV_OC_CONSTRUCT_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
55 .Name = Constructor,
56
57#define PRIV_OC_DESTRUCT_STRUCT_MEMBER(Type, Name, Suffix, Constructor, Destructor) \
58 PRIV_OC_SELECT_NEXT(PRIV_OC_REMOVE_NEXT Destructor, Destructor(&Obj->Name, sizeof (Type Suffix)));
59
60#define PRIV_OC_INVOKE_DESTRUCTOR(Destructor, Obj, Size) \
61 PRIV_OC_SELECT_NEXT(PRIV_OC_REMOVE_NEXT Destructor, Destructor(Obj, Size))
62
63#define PRIV_NO_KEY_TYPE UINT8
64
65//
66// Declare structure type NAME. Construction and destruction interfaces will also be
67// available with corresponding prototypes:
68// VOID NAME_CONSTRUCT(Void *Ptr, UINTN Size);
69// VOID NAME_DESTRUCT(Void *Ptr, UINTN Size);
70//
71// Field information will be retrieved from NAME_FIELDS X-Macro, written as follows:
72#if 0
73#define NAME_FIELDS(_, __) \
74 _(Type, Name, Type Suffix, __(Constant Initializer), Destructor Function) \
75 _(Type, Name, Type Suffix, OC_CONSTR(Type, _, __), OC_DESTR(Type))
76#endif
77//
78
79#define OC_DECLARE(Name) \
80 typedef struct Name ## _ { \
81 Name ## _FIELDS (PRIV_OC_DECLARE_STRUCT_MEMBER, PRIV_OC_STRUCTOR_IGNORE) \
82 } Name; \
83 VOID Name ## _CONSTRUCT(VOID *Ptr, UINT32 Size); \
84 VOID Name ## _DESTRUCT(VOID *Ptr, UINT32 Size);
85
86//
87// Generate constructors and destructors for structure type NAME.
88// Second argument permits to do extra actions prior to field destruction.
89// Pass () to the second argument to ignore this option.
90//
91#define OC_STRUCTORS(Name, Destructor) \
92 VOID Name ## _CONSTRUCT(VOID *Ptr, UINT32 Size) { \
93 STATIC Name Obj = { \
94 Name ## _FIELDS(PRIV_OC_CONSTRUCT_STRUCT_MEMBER, PRIV_OC_STRUCTOR_EXPAND) \
95 }; \
96 CopyMem (Ptr, &Obj, sizeof (Name)); \
97 } \
98 VOID Name ## _DESTRUCT(VOID *Ptr, UINT32 Size) { \
99 Name *Obj = (Name *) Ptr; (VOID) Obj; \
100 PRIV_OC_INVOKE_DESTRUCTOR(Destructor, Obj, sizeof (Name)); \
101 Name ## _FIELDS(PRIV_OC_DESTRUCT_STRUCT_MEMBER, PRIV_OC_STRUCTOR_EXPAND) \
102 }
103
104//
105// Use previously defined structure constructor or destructor
106// FIXME: We need to use these recursively, and normally one would implement
107// it with deferred execution, like this:
108// #define OC_CONSTR_REAL(A, _, __) ({A ## _FIELDS(_, __)})
109// #define OC_CONSTR_REAL_ID() OC_CONSTR_REAL
110// #define OC_CONSTR DEFER(OC_CONSTR_REAL_ID)()
111// However, this will not work in this exact case, as _, which itself is a macro,
112// changes the expansion order. The right fix here is to entirely remove the mess
113// and use external tool for template generation.
114//
115#define OC_CONSTR(A, _, __) {A ## _FIELDS(_, __)}
116#define OC_CONSTR1(A, _, __) {A ## _FIELDS(_, __)}
117#define OC_CONSTR2(A, _, __) {A ## _FIELDS(_, __)}
118#define OC_CONSTR3(A, _, __) {A ## _FIELDS(_, __)}
119#define OC_CONSTR5(A, _, __) {A ## _FIELDS(_, __)}
120#define OC_DESTR(A) A ## _DESTRUCT
121
122//
123// Generate array-like blob (string, data, metadata) of type Type,
124// Count static size, MaxSize is real size, and default value Default.
125//
126#define OC_BLOB(Type, Count, Default, _, __) \
127 _(UINT32 , Size , , 0 , OcZeroField ) \
128 _(UINT32 , MaxSize , , sizeof (Type Count) , OcZeroField ) \
129 _(Type * , DynValue , , NULL , OcFreePointer ) \
130 _(Type , Value , Count , __(Default) , () )
131
132#define OC_BLOB_STRUCTORS(Name) \
133 OC_STRUCTORS(Name, ())
134
135#define OC_BLOB_CONSTR(Type, Constructor, SizeConstructor, _, __) \
136 __({.Size = SizeConstructor, .MaxSize = sizeof (((Type *)0)->Value), .DynValue = NULL, .Value = Constructor})
137
138//
139// Generate map-like container with key elements of type KeyType, OC_BLOB derivative,
140// value types of Type constructed by Constructor and destructed by Destructor:
141#if 0
142#define CONT_FIELDS(_, __) \
143 OC_MAP (KEY, ELEM, _, __)
144OC_DECLARE (CONT)
145#endif
146//
147
148#define OC_MAP(KeyType, Type, _, __) \
149 _(UINT32 , Count , , 0 , () ) \
150 _(UINT32 , AllocCount , , 0 , () ) \
151 _(OC_STRUCTOR , Construct , , Type ## _CONSTRUCT , () ) \
152 _(OC_STRUCTOR , Destruct , , Type ## _DESTRUCT , () ) \
153 _(Type ** , Values , , NULL , () ) \
154 _(UINT32 , ValueSize , , sizeof (Type) , () ) \
155 _(UINT32 , KeySize , , sizeof (KeyType) , () ) \
156 _(OC_STRUCTOR , KeyConstruct , , KeyType ## _CONSTRUCT , () ) \
157 _(OC_STRUCTOR , KeyDestruct , , KeyType ## _DESTRUCT , () ) \
158 _(KeyType ** , Keys , , NULL , () )
159
160#define OC_MAP_STRUCTORS(Name) \
161 OC_STRUCTORS(Name, OcFreeMap)
162
163//
164// Generate array-like container with elements of type Type, constructed
165// by Constructor and destructed by Destructor.
166#if 0
167#define CONT_FIELDS(_, __) \
168 OC_ARRAY (ELEM, _, __)
169OC_DECLARE (CONT)
170#endif
171//
172
173#define OC_ARRAY(Type, _, __) \
174 _(UINT32 , Count , , 0 , () ) \
175 _(UINT32 , AllocCount , , 0 , () ) \
176 _(OC_STRUCTOR , Construct , , Type ## _CONSTRUCT , () ) \
177 _(OC_STRUCTOR , Destruct , , Type ## _DESTRUCT , () ) \
178 _(Type ** , Values , , NULL , () ) \
179 _(UINT32 , ValueSize , , sizeof (Type) , () )
180
181#define OC_ARRAY_STRUCTORS(Name) \
182 OC_STRUCTORS(Name, OcFreeArray)
183
184//
185// Free dynamically allocated memory if non NULL.
186// Note, that the first argument is actually VOID **.
187//
188VOID
190 VOID *Pointer,
191 UINT32 Size
192 );
193
194//
195// Zero field memory.
196//
197VOID
199 VOID *Pointer,
200 UINT32 Size
201 );
202
203//
204// Do not invoke any actions at destruction.
205//
206VOID
208 VOID *Pointer,
209 UINT32 Size
210 );
211
212//
213// OC_MAP-like destructor.
214//
215VOID
216OcFreeMap (
217 VOID *Pointer,
218 UINT32 Size
219 );
220
221//
222// OC_ARRAY-like destructor.
223//
224VOID
226 VOID *Pointer,
227 UINT32 Size
228 );
229
230//
231// Prepare memory for blob at Pointer to contain Size bytes.
232// Assignable size may be returned via OutSize.
233// This method guarantees not to overwrite "Default" value,
234// but may destroy the previous value.
235// NULL is returned on allocation failure.
236//
237VOID *
239 VOID *Pointer,
240 UINT32 Size,
241 UINT32 **OutSize OPTIONAL
242 );
243
244//
245// Obtain blob value
246//
247#define OC_BLOB_GET(Blob) (((Blob)->DynValue) != NULL ? ((Blob)->DynValue) : ((Blob)->Value))
248
249//
250// Insert new empty element into the OC_MAP or OC_ARRAY, depending
251// on Key value.
252//
253BOOLEAN
255 VOID *Pointer,
256 VOID **Value,
257 VOID **Key
258 );
259
260//
261// Some useful generic types
262// OC_STRING - implements support for resizable ASCII strings.
263// OC_DATA - implements support for resizable data blobs.
264// OC_ASSOC - implements support for maps with ASCII keys and data values.
265//
266#define OC_STRING_FIELDS(_, __) \
267 OC_BLOB (CHAR8, [64], {0}, _, __)
268OC_DECLARE (OC_STRING)
269
270#define OC_STRING_CONSTR(Constructor, _, __) \
271 OC_BLOB_CONSTR (OC_STRING, __(Constructor), sizeof (Constructor), _, __)
272
273#define OC_ESTRING_CONSTR(_, __) \
274 OC_BLOB_CONSTR (OC_STRING, __(""), 0, _, __)
275
276#define OC_DATA_FIELDS(_, __) \
277 OC_BLOB (UINT8, [64], {0}, _, __)
278OC_DECLARE (OC_DATA)
279
280#define OC_EDATA_CONSTR(_, __) \
281 OC_BLOB_CONSTR (OC_DATA, __({0}), 0, _, __)
282
283#define OC_DATA_CONSTR(Constructor, _, __) \
284 OC_BLOB_CONSTR (OC_DATA, __(Constructor), sizeof ((UINT8[]) Constructor), _, __)
285
286#define OC_ASSOC_FIELDS(_, __) \
287 OC_MAP (OC_STRING, OC_DATA, _, __)
288OC_DECLARE (OC_ASSOC)
289
290#endif // OC_TEMPLATE_LIB_H
DMG_SIZE_DEVICE_PATH Size
VOID OcDestructEmpty(VOID *Pointer, UINT32 Size)
VOID OcZeroField(VOID *Pointer, UINT32 Size)
VOID OcFreeMap(VOID *Pointer, UINT32 Size)
VOID OcFreeArray(VOID *Pointer, UINT32 Size)
BOOLEAN OcListEntryAllocate(VOID *Pointer, VOID **Value, VOID **Key)
#define OC_DECLARE(Name)
VOID OcFreePointer(VOID *Pointer, UINT32 Size)
VOID * OcBlobAllocate(VOID *Pointer, UINT32 Size, UINT32 **OutSize OPTIONAL)
VOID(* OC_STRUCTOR)(VOID *Ptr, UINT32 Size)