OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcTemplateLib.c
Go to the documentation of this file.
1
20#include <Library/BaseLib.h>
21#include <Library/BaseMemoryLib.h>
22#include <Library/BaseOverflowLib.h>
23#include <Library/DebugLib.h>
24#include <Library/MemoryAllocationLib.h>
25
26#define PRIV_OC_BLOB_FIELDS(_, __) \
27 OC_BLOB (CHAR8, [], {0}, _, __)
28OC_DECLARE (PRIV_OC_BLOB)
29
30#define PRIV_OC_MAP_FIELDS(_, __) \
31 OC_MAP (PRIV_OC_BLOB, PRIV_OC_BLOB, _, __)
32OC_DECLARE (PRIV_OC_MAP)
33
34#define PRIV_OC_ARRAY_FIELDS(_, __) \
35 OC_ARRAY (PRIV_OC_BLOB, _, __)
36OC_DECLARE (PRIV_OC_ARRAY)
37
38typedef union PRIV_OC_LIST_ {
39 PRIV_OC_MAP Map;
40 PRIV_OC_ARRAY Array;
42
43//
44// We have to be a bit careful about this hack, so assert that type layouts match at the very least.
45//
46#if defined (__GNUC__) || defined (__clang__)
47STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, Count) == OFFSET_OF (PRIV_OC_MAP, Count), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
48STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, AllocCount) == OFFSET_OF (PRIV_OC_MAP, AllocCount), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
49STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, Construct) == OFFSET_OF (PRIV_OC_MAP, Construct), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
50STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, Destruct) == OFFSET_OF (PRIV_OC_MAP, Destruct), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
51STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, Values) == OFFSET_OF (PRIV_OC_MAP, Values), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
52STATIC_ASSERT (OFFSET_OF (PRIV_OC_ARRAY, ValueSize) == OFFSET_OF (PRIV_OC_MAP, ValueSize), "PRIV_OC_ARRAY vs PRIV_OC_MAP");
53#endif
54
55VOID
57 VOID *Pointer,
58 UINT32 Size
59 )
60{
61 VOID **Field = (VOID **)Pointer;
62
63 if (*Field) {
64 FreePool (*Field);
65 *Field = NULL;
66 }
67}
68
69VOID
71 VOID *Pointer,
72 UINT32 Size
73 )
74{
75 ZeroMem (Pointer, Size);
76}
77
78VOID
80 VOID *Pointer,
81 UINT32 Size
82 )
83{
84 (VOID)Pointer;
85 (VOID)Size;
86}
87
88STATIC
89VOID
91 VOID *Pointer,
92 BOOLEAN HasKeys
93 )
94{
95 UINT32 Index;
96 PRIV_OC_LIST *List;
97
98 List = (PRIV_OC_LIST *)Pointer;
99
100 for (Index = 0; Index < List->Array.Count; Index++) {
101 List->Array.Destruct (List->Array.Values[Index], List->Array.ValueSize);
102 FreePool (List->Array.Values[Index]);
103
104 if (HasKeys) {
105 List->Map.KeyDestruct (List->Map.Keys[Index], List->Map.KeySize);
106 FreePool (List->Map.Keys[Index]);
107 }
108 }
109
110 OcFreePointer (&List->Array.Values, List->Array.AllocCount * List->Array.ValueSize);
111 if (HasKeys) {
112 OcFreePointer (&List->Map.Keys, List->Array.AllocCount * List->Map.KeySize);
113 }
114
115 List->Array.Count = 0;
116 List->Array.AllocCount = 0;
117}
118
119VOID
121 VOID *Pointer,
122 UINT32 Size
123 )
124{
125 OcFreeList (Pointer, TRUE);
126}
127
128VOID
130 VOID *Pointer,
131 UINT32 Size
132 )
133{
134 OcFreeList (Pointer, FALSE);
135}
136
137VOID *
139 VOID *Pointer,
140 UINT32 Size,
141 UINT32 **OutSize OPTIONAL
142 )
143{
144 PRIV_OC_BLOB *Blob;
145 VOID *DynValue;
146
147 Blob = (PRIV_OC_BLOB *)Pointer;
148
149 DEBUG ((
150 DEBUG_VERBOSE,
151 "OCTPL: Allocating %u bytes in blob %p with size %u/%u curr %p\n",
152 Size,
153 Blob,
154 Blob->Size,
155 Blob->MaxSize,
156 Blob->DynValue
157 ));
158
159 //
160 // We fit into static space
161 //
162 if (Size <= Blob->MaxSize) {
163 OcFreePointer (&Blob->DynValue, Blob->Size);
164 Blob->Size = Size;
165 if (OutSize != NULL) {
166 *OutSize = &Blob->Size;
167 }
168
169 return Blob->Value;
170 }
171
172 //
173 // We do not fit into dynamic space
174 //
175 if (Size > Blob->Size) {
176 OcFreePointer (&Blob->DynValue, Blob->Size);
177 DynValue = AllocatePool (Size);
178 if (DynValue == NULL) {
179 DEBUG ((DEBUG_VERBOSE, "OCTPL: Failed to fit %u bytes in OC_BLOB\n", Size));
180 return NULL;
181 }
182
183 //
184 // Propagate default value.
185 //
186 CopyMem (DynValue, Blob->Value, Blob->MaxSize);
187 Blob->DynValue = DynValue;
188 }
189
190 Blob->Size = Size;
191 if (OutSize != NULL) {
192 *OutSize = &Blob->Size;
193 }
194
195 return Blob->DynValue;
196}
197
198BOOLEAN
200 VOID *Pointer,
201 VOID **Value,
202 VOID **Key
203 )
204{
205 PRIV_OC_LIST *List;
206 UINT32 Count;
207 UINT32 AllocCount;
208 VOID **NewValues;
209 VOID **NewKeys;
210
211 List = (PRIV_OC_LIST *)Pointer;
212
213 //
214 // Prepare new pair.
215 //
216 *Value = AllocatePool (List->Array.ValueSize);
217 if (*Value == NULL) {
218 return FALSE;
219 }
220
221 if (Key != NULL) {
222 *Key = AllocatePool (List->Map.KeySize);
223 if (*Key == NULL) {
224 FreePool (*Value);
225 return FALSE;
226 }
227 }
228
229 //
230 // Initialize new pair.
231 //
232 List->Array.Construct (*Value, List->Array.ValueSize);
233 if (Key != NULL) {
234 List->Map.KeyConstruct (*Key, List->Map.KeySize);
235 }
236
237 Count = 0;
238 AllocCount = 1;
239
240 //
241 // Push new entry if there is enough room.
242 //
243 if (List->Array.Values != NULL) {
244 Count = List->Array.Count;
245 AllocCount = List->Array.AllocCount;
246
247 if (AllocCount > Count) {
248 List->Array.Count++;
249 List->Array.Values[Count] = *Value;
250 if (Key != NULL) {
251 List->Map.Keys[Count] = *Key;
252 }
253
254 return TRUE;
255 }
256 }
257
258 //
259 // Allocate twice more room and destruct on failure.
260 //
261 AllocCount *= 2;
262
263 NewValues = (VOID **)AllocatePool (
264 sizeof (VOID *) * AllocCount
265 );
266
267 if (NewValues == NULL) {
268 List->Array.Destruct (*Value, List->Array.ValueSize);
269 FreePool (*Value);
270 if (Key != NULL) {
271 List->Map.KeyDestruct (*Key, List->Map.KeySize);
272 FreePool (*Key);
273 }
274
275 return FALSE;
276 }
277
278 if (Key != NULL) {
279 NewKeys = (VOID **)AllocatePool (
280 sizeof (VOID *) * AllocCount
281 );
282
283 if (NewKeys == NULL) {
284 List->Array.Destruct (*Value, List->Array.ValueSize);
285 List->Map.KeyDestruct (*Key, List->Map.KeySize);
286 FreePool (NewValues);
287 FreePool (*Value);
288 FreePool (*Key);
289 return FALSE;
290 }
291 } else {
292 NewKeys = NULL;
293 }
294
295 //
296 // Insert and return.
297 //
298 if (List->Array.Values != NULL) {
299 CopyMem (
300 &NewValues[0],
301 &List->Array.Values[0],
302 sizeof (VOID *) * Count
303 );
304
305 FreePool (List->Array.Values);
306 }
307
308 if ((Key != NULL) && (List->Map.Keys != NULL)) {
309 CopyMem (
310 &NewKeys[0],
311 &List->Map.Keys[0],
312 sizeof (VOID *) * Count
313 );
314
315 FreePool (List->Map.Keys);
316 }
317
318 List->Array.Count++;
319 List->Array.AllocCount = AllocCount;
320
321 NewValues[Count] = *Value;
322 List->Array.Values = (PRIV_OC_BLOB **)NewValues;
323
324 if (Key != NULL) {
325 NewKeys[Count] = *Key;
326 List->Map.Keys = (PRIV_OC_BLOB **)NewKeys;
327 }
328
329 return TRUE;
330}
331
332OC_BLOB_STRUCTORS (OC_STRING)
333OC_BLOB_STRUCTORS (OC_DATA)
334OC_MAP_STRUCTORS (OC_ASSOC)
DMG_SIZE_DEVICE_PATH Size
STATIC_ASSERT(BYTES_PER_PIXEL==sizeof(UINT32), "Non 4-byte pixels are unsupported!")
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)
STATIC VOID OcFreeList(VOID *Pointer, BOOLEAN HasKeys)
VOID OcFreePointer(VOID *Pointer, UINT32 Size)
union PRIV_OC_LIST_ PRIV_OC_LIST
VOID * OcBlobAllocate(VOID *Pointer, UINT32 Size, UINT32 **OutSize OPTIONAL)
#define OC_MAP_STRUCTORS(Name)
#define OC_BLOB_STRUCTORS(Name)
#define OC_DECLARE(Name)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
PRIV_OC_MAP Map
PRIV_OC_ARRAY Array