OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcSerializeLib.c
Go to the documentation of this file.
1
20#include <Library/BaseLib.h>
21#include <Library/DebugLib.h>
22
23STATIC
24CONST CHAR8 *
26 [OC_SCHEMA_VALUE_BOOLEAN] = "boolean",
27 [OC_SCHEMA_VALUE_INTEGER] = "integer",
28 [OC_SCHEMA_VALUE_DATA] = "data",
29 [OC_SCHEMA_VALUE_STRING] = "string",
30 [OC_SCHEMA_VALUE_MDATA] = "mdata"
31};
32
33STATIC
34CONST CHAR8 *
36 IN UINT32 Type
37 )
38{
39 if (Type < ARRAY_SIZE (mSchemaTypeNames)) {
40 return mSchemaTypeNames[Type];
41 }
42
43 return "custom";
44}
45
48 IN OC_SCHEMA *SortedList,
49 IN UINT32 Size,
50 IN CONST CHAR8 *Name
51 )
52{
53 UINT32 Start;
54 UINT32 End;
55 UINT32 Curr;
56 INTN Cmp;
57
58 if (Size == 0) {
59 return NULL;
60 }
61
62 //
63 // Classic binary search in a sorted string list.
64 //
65 Start = 0;
66 End = Size - 1;
67
68 while (Start <= End) {
69 Curr = (Start + End) / 2;
70 Cmp = AsciiStrCmp (SortedList[Curr].Name, Name);
71
72 if (Cmp == 0) {
73 return &SortedList[Curr];
74 } else if (Cmp < 0) {
75 Start = Curr + 1;
76 } else if (Curr > 0) {
77 End = Curr - 1;
78 } else {
79 //
80 // Even the first element does not match, required due to unsigned End.
81 //
82 return NULL;
83 }
84 }
85
86 return NULL;
87}
88
89VOID
91 OUT VOID *Serialized,
92 IN XML_NODE *Node,
93 IN OC_SCHEMA_INFO *Info,
94 IN CONST CHAR8 *Context OPTIONAL,
95 IN OUT UINT32 *ErrorCount OPTIONAL
96 )
97{
98 UINT32 DictSize;
99 UINT32 Index;
100 UINT32 Index2;
101 CONST CHAR8 *CurrentKey;
102 XML_NODE *CurrentValue;
103 XML_NODE *OldValue;
104 OC_SCHEMA *NewSchema;
105
106 DictSize = PlistDictChildren (Node);
107
108 for (Index = 0; Index < DictSize; Index++) {
109 CurrentKey = PlistKeyValue (PlistDictChild (Node, Index, &CurrentValue));
110
111 if (CurrentKey == NULL) {
112 DEBUG ((DEBUG_WARN, "OCS: No serialized key at %u index, context <%a>!\n", Index, Context));
113 if (ErrorCount != NULL) {
114 ++*ErrorCount;
115 }
116
117 continue;
118 }
119
120 //
121 // Skip comments.
122 //
123 if (CurrentKey[0] == '#') {
124 continue;
125 }
126
127 DEBUG ((DEBUG_VERBOSE, "OCS: Parsing serialized at %a at %u index!\n", CurrentKey, Index));
128
129 //
130 // We do not protect from duplicating serialized entries.
131 //
132 NewSchema = LookupConfigSchema (Info->Dict.Schema, Info->Dict.SchemaSize, CurrentKey);
133
134 if (NewSchema == NULL) {
135 DEBUG ((DEBUG_WARN, "OCS: No schema for %a at %u index, context <%a>!\n", CurrentKey, Index, Context));
136 if (ErrorCount != NULL) {
137 ++*ErrorCount;
138 }
139
140 continue;
141 }
142
143 OldValue = CurrentValue;
144 CurrentValue = PlistNodeCast (CurrentValue, NewSchema->Type);
145 if (CurrentValue == NULL) {
146 DEBUG ((
147 DEBUG_WARN,
148 "OCS: No type match for %a at %u index, expected type %a got %a, context <%a>!\n",
149 CurrentKey,
150 Index,
151 GetSchemaTypeName (NewSchema->Type),
152 XmlNodeName (OldValue),
153 Context
154 ));
155 if (ErrorCount != NULL) {
156 ++*ErrorCount;
157 }
158
159 continue;
160 }
161
162 NewSchema->Apply (Serialized, CurrentValue, &NewSchema->Info, CurrentKey, ErrorCount);
163 }
164
165 DEBUG_CODE_BEGIN ();
166
167 for (Index = 0; Index < Info->Dict.SchemaSize; ++Index) {
168 if (Info->Dict.Schema[Index].Optional) {
169 continue;
170 }
171
172 for (Index2 = 0; Index2 < DictSize; ++Index2) {
173 CurrentKey = PlistKeyValue (PlistDictChild (Node, Index2, NULL));
174
175 if (CurrentKey == NULL) {
176 continue;
177 }
178
179 if (AsciiStrCmp (CurrentKey, Info->Dict.Schema[Index].Name) == 0) {
180 break;
181 }
182 }
183
184 if (Index2 == DictSize) {
185 DEBUG ((
186 DEBUG_WARN,
187 "OCS: Missing key %a, context <%a>!\n",
188 Info->Dict.Schema[Index].Name,
189 Context
190 ));
191 if (ErrorCount != NULL) {
192 ++*ErrorCount;
193 }
194 }
195 }
196
197 DEBUG_CODE_END ();
198}
199
200VOID
202 OUT VOID *Serialized,
203 IN XML_NODE *Node,
204 IN OC_SCHEMA_INFO *Info,
205 IN CONST CHAR8 *Context OPTIONAL,
206 IN OUT UINT32 *ErrorCount OPTIONAL
207 )
208{
209 BOOLEAN Result;
210 VOID *Field;
211 UINT32 Size;
212
213 Result = FALSE;
214 Field = OC_SCHEMA_FIELD (Serialized, VOID, Info->Value.Field);
215 Size = Info->Value.FieldSize;
216
217 switch (Info->Value.Type) {
219 Result = PlistBooleanValue (Node, (BOOLEAN *)Field);
220 break;
222 Result = PlistIntegerValue (Node, Field, Size, FALSE);
223 break;
225 Result = PlistDataValue (Node, Field, &Size);
226 break;
228 Result = PlistStringValue (Node, Field, &Size);
229 break;
231 Result = PlistMultiDataValue (Node, Field, &Size);
232 break;
233 }
234
235 if (Result == FALSE) {
236 DEBUG ((
237 DEBUG_WARN,
238 "OCS: Failed to parse %a field as value with type %a and <%a> contents, context <%a>!\n",
239 XmlNodeName (Node),
240 GetSchemaTypeName (Info->Value.Type),
241 XmlNodeContent (Node) != NULL ? XmlNodeContent (Node) : "empty",
242 Context
243 ));
244 if (ErrorCount != NULL) {
245 ++*ErrorCount;
246 }
247 }
248}
249
250VOID
252 OUT VOID *Serialized,
253 IN XML_NODE *Node,
254 IN OC_SCHEMA_INFO *Info,
255 IN CONST CHAR8 *Context OPTIONAL,
256 IN OUT UINT32 *ErrorCount OPTIONAL
257 )
258{
259 BOOLEAN Result;
260 VOID *Field;
261 UINT32 Size;
262 VOID *BlobMemory;
263 UINT32 *BlobSize;
264
265 Result = FALSE;
266
267 switch (Info->Blob.Type) {
269 Result = PlistDataSize (Node, &Size);
270 break;
272 Result = PlistStringSize (Node, &Size);
273 break;
275 Result = PlistMultiDataSize (Node, &Size);
276 break;
277 }
278
279 if (Result == FALSE) {
280 DEBUG ((
281 DEBUG_WARN,
282 "OCS: Failed to calculate size of %a field containing <%a> as type %a, context <%a>!\n",
283 XmlNodeName (Node),
284 XmlNodeContent (Node) != NULL ? XmlNodeContent (Node) : "empty",
285 GetSchemaTypeName (Info->Blob.Type),
286 Context
287 ));
288 if (ErrorCount != NULL) {
289 ++*ErrorCount;
290 }
291
292 return;
293 }
294
295 Field = OC_SCHEMA_FIELD (Serialized, VOID, Info->Blob.Field);
296 BlobMemory = OcBlobAllocate (Field, Size, &BlobSize);
297
298 if (BlobMemory == NULL) {
299 DEBUG ((
300 DEBUG_INFO,
301 "OCS: Failed to allocate %u bytes %a field of type %a, context <%a>!\n",
302 Size,
303 XmlNodeName (Node),
304 GetSchemaTypeName (Info->Value.Type),
305 Context
306 ));
307 if (ErrorCount != NULL) {
308 ++*ErrorCount;
309 }
310
311 return;
312 }
313
314 Result = FALSE;
315
316 switch (Info->Blob.Type) {
318 Result = PlistDataValue (Node, (UINT8 *)BlobMemory, BlobSize);
319 break;
321 Result = PlistStringValue (Node, (CHAR8 *)BlobMemory, BlobSize);
322 break;
324 Result = PlistMultiDataValue (Node, (UINT8 *)BlobMemory, BlobSize);
325 break;
326 }
327
328 if (Result == FALSE) {
329 DEBUG ((
330 DEBUG_WARN,
331 "OCS: Failed to parse %a field as blob with type %a and <%a> contents, context <%a>!\n",
332 XmlNodeName (Node),
333 GetSchemaTypeName (Info->Value.Type),
334 XmlNodeContent (Node) != NULL ? XmlNodeContent (Node) : "empty",
335 Context
336 ));
337 if (ErrorCount != NULL) {
338 ++*ErrorCount;
339 }
340 }
341}
342
343VOID
345 OUT VOID *Serialized,
346 IN XML_NODE *Node,
347 IN OC_SCHEMA_INFO *Info,
348 IN CONST CHAR8 *Context OPTIONAL,
349 IN OUT UINT32 *ErrorCount OPTIONAL
350 )
351{
352 UINT32 DictSize;
353 UINT32 Index;
354 CONST CHAR8 *CurrentKey;
355 UINT32 CurrentKeyLen;
356 XML_NODE *ChildNode;
357 VOID *NewValue;
358 VOID *NewKey;
359 VOID *NewKeyValue;
360 BOOLEAN Success;
361
362 DictSize = PlistDictChildren (Node);
363
364 for (Index = 0; Index < DictSize; Index++) {
365 CurrentKey = PlistKeyValue (PlistDictChild (Node, Index, &ChildNode));
366 CurrentKeyLen = CurrentKey != NULL ? (UINT32)(AsciiStrLen (CurrentKey) + 1) : 0;
367
368 if (CurrentKeyLen == 0) {
369 DEBUG ((DEBUG_INFO, "OCS: No get serialized key at %u index!\n", Index));
370 if (ErrorCount != NULL) {
371 ++*ErrorCount;
372 }
373
374 continue;
375 }
376
377 //
378 // Skip comments.
379 //
380 if (CurrentKey[0] == '#') {
381 continue;
382 }
383
384 if (PlistNodeCast (ChildNode, Info->List.Schema->Type) == NULL) {
385 DEBUG ((DEBUG_INFO, "OCS: No valid serialized value at %u index!\n", Index));
386 if (ErrorCount != NULL) {
387 ++*ErrorCount;
388 }
389
390 continue;
391 }
392
393 Success = OcListEntryAllocate (
394 OC_SCHEMA_FIELD (Serialized, VOID, Info->List.Field),
395 &NewValue,
396 &NewKey
397 );
398 if (Success == FALSE) {
399 DEBUG ((DEBUG_INFO, "OCS: Couldn't insert dict serialized at %u index!\n", Index));
400 if (ErrorCount != NULL) {
401 ++*ErrorCount;
402 }
403
404 continue;
405 }
406
407 NewKeyValue = OcBlobAllocate (NewKey, CurrentKeyLen, NULL);
408 if (NewKeyValue != NULL) {
409 AsciiStrnCpyS ((CHAR8 *)NewKeyValue, CurrentKeyLen, CurrentKey, CurrentKeyLen - 1);
410 } else {
411 DEBUG ((DEBUG_INFO, "OCS: Couldn't allocate key name at %u index!\n", Index));
412 if (ErrorCount != NULL) {
413 ++*ErrorCount;
414 }
415 }
416
417 Info->List.Schema->Apply (NewValue, ChildNode, &Info->List.Schema->Info, CurrentKey, ErrorCount);
418 }
419}
420
421VOID
423 OUT VOID *Serialized,
424 IN XML_NODE *Node,
425 IN OC_SCHEMA_INFO *Info,
426 IN CONST CHAR8 *Context OPTIONAL,
427 IN OUT UINT32 *ErrorCount OPTIONAL
428 )
429{
430 UINT32 ArraySize;
431 UINT32 Index;
432 XML_NODE *ChildNode;
433 VOID *NewValue;
434 BOOLEAN Success;
435
436 ArraySize = XmlNodeChildren (Node);
437
438 for (Index = 0; Index < ArraySize; Index++) {
439 ChildNode = PlistNodeCast (XmlNodeChild (Node, Index), Info->List.Schema->Type);
440
441 DEBUG ((DEBUG_VERBOSE, "OCS: Processing array %u/%u element\n", Index + 1, ArraySize));
442
443 if (ChildNode == NULL) {
444 DEBUG ((DEBUG_INFO, "OCS: Couldn't get array serialized at %u index!\n", Index));
445 if (ErrorCount != NULL) {
446 ++*ErrorCount;
447 }
448
449 continue;
450 }
451
452 Success = OcListEntryAllocate (
453 OC_SCHEMA_FIELD (Serialized, VOID, Info->List.Field),
454 &NewValue,
455 NULL
456 );
457 if (Success == FALSE) {
458 DEBUG ((DEBUG_INFO, "OCS: Couldn't insert array serialized at %u index!\n", Index));
459 if (ErrorCount != NULL) {
460 ++*ErrorCount;
461 }
462
463 continue;
464 }
465
466 Info->List.Schema->Apply (NewValue, ChildNode, &Info->List.Schema->Info, Context, ErrorCount);
467 }
468}
469
470BOOLEAN
472 OUT VOID *Serialized,
473 IN OC_SCHEMA_INFO *RootSchema,
474 IN VOID *PlistBuffer,
475 IN UINT32 PlistSize,
476 IN OUT UINT32 *ErrorCount OPTIONAL
477 )
478{
479 XML_DOCUMENT *Document;
480 XML_NODE *RootDict;
481
482 Document = XmlDocumentParse (PlistBuffer, PlistSize, FALSE);
483
484 if (Document == NULL) {
485 DEBUG ((DEBUG_INFO, "OCS: Couldn't parse serialized file!\n"));
486 if (ErrorCount != NULL) {
487 ++*ErrorCount;
488 }
489
490 return FALSE;
491 }
492
494
495 if (RootDict == NULL) {
496 DEBUG ((DEBUG_INFO, "OCS: Couldn't get serialized root!\n"));
497 XmlDocumentFree (Document);
498 if (ErrorCount != NULL) {
499 ++*ErrorCount;
500 }
501
502 return FALSE;
503 }
504
506 Serialized,
507 RootDict,
508 RootSchema,
509 "root",
510 ErrorCount
511 );
512
513 XmlDocumentFree (Document);
514 return TRUE;
515}
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
UINT64 Start
EFI_DEVICE_PATH_PROTOCOL End
DMG_SIZE_DEVICE_PATH Size
STATIC CONST CHAR8 * mSchemaTypeNames[]
VOID ParseSerializedArray(OUT VOID *Serialized, IN XML_NODE *Node, IN OC_SCHEMA_INFO *Info, IN CONST CHAR8 *Context OPTIONAL, IN OUT UINT32 *ErrorCount OPTIONAL)
OC_SCHEMA * LookupConfigSchema(IN OC_SCHEMA *SortedList, IN UINT32 Size, IN CONST CHAR8 *Name)
BOOLEAN ParseSerialized(OUT VOID *Serialized, IN OC_SCHEMA_INFO *RootSchema, IN VOID *PlistBuffer, IN UINT32 PlistSize, IN OUT UINT32 *ErrorCount OPTIONAL)
VOID ParseSerializedValue(OUT VOID *Serialized, IN XML_NODE *Node, IN OC_SCHEMA_INFO *Info, IN CONST CHAR8 *Context OPTIONAL, IN OUT UINT32 *ErrorCount OPTIONAL)
VOID ParseSerializedBlob(OUT VOID *Serialized, IN XML_NODE *Node, IN OC_SCHEMA_INFO *Info, IN CONST CHAR8 *Context OPTIONAL, IN OUT UINT32 *ErrorCount OPTIONAL)
VOID ParseSerializedDict(OUT VOID *Serialized, IN XML_NODE *Node, IN OC_SCHEMA_INFO *Info, IN CONST CHAR8 *Context OPTIONAL, IN OUT UINT32 *ErrorCount OPTIONAL)
STATIC CONST CHAR8 * GetSchemaTypeName(IN UINT32 Type)
VOID ParseSerializedMap(OUT VOID *Serialized, IN XML_NODE *Node, IN OC_SCHEMA_INFO *Info, IN CONST CHAR8 *Context OPTIONAL, IN OUT UINT32 *ErrorCount OPTIONAL)
#define OC_SCHEMA_FIELD(Base, Type, Offset)
@ OC_SCHEMA_VALUE_BOOLEAN
@ OC_SCHEMA_VALUE_DATA
@ OC_SCHEMA_VALUE_INTEGER
@ OC_SCHEMA_VALUE_MDATA
@ OC_SCHEMA_VALUE_STRING
@ OC_SCHEMA_BLOB_DATA
@ OC_SCHEMA_BLOB_STRING
@ OC_SCHEMA_BLOB_MDATA
BOOLEAN OcListEntryAllocate(VOID *Pointer, VOID **Value, VOID **Key)
VOID * OcBlobAllocate(VOID *Pointer, UINT32 Size, UINT32 **OutSize OPTIONAL)
@ PLIST_NODE_TYPE_DICT
Definition OcXmlLib.h:91
BOOLEAN PlistDataSize(IN XML_NODE *Node OPTIONAL, OUT UINT32 *Size)
Definition OcXmlLib.c:2102
XML_DOCUMENT * XmlDocumentParse(IN OUT CHAR8 *Buffer, IN UINT32 Length, IN BOOLEAN WithRefs)
Definition OcXmlLib.c:1308
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
Definition OcXmlLib.c:1841
BOOLEAN PlistMultiDataSize(IN XML_NODE *Node OPTIONAL, OUT UINT32 *Size)
Definition OcXmlLib.c:2126
UINT32 XmlNodeChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1493
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1467
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1813
BOOLEAN PlistStringSize(IN XML_NODE *Node OPTIONAL, OUT UINT32 *Size)
Definition OcXmlLib.c:2078
BOOLEAN PlistStringValue(IN XML_NODE *Node OPTIONAL, OUT CHAR8 *Value, IN OUT UINT32 *Size)
Definition OcXmlLib.c:1853
BOOLEAN PlistIntegerValue(IN XML_NODE *Node OPTIONAL, OUT VOID *Value, IN UINT32 Size, IN BOOLEAN Hex)
Definition OcXmlLib.c:1943
XML_NODE * PlistNodeCast(IN XML_NODE *Node OPTIONAL, IN PLIST_NODE_TYPE Type)
Definition OcXmlLib.c:1760
CONST CHAR8 * XmlNodeName(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1457
XML_NODE * PlistDocumentRoot(IN CONST XML_DOCUMENT *Document)
Definition OcXmlLib.c:1736
BOOLEAN PlistDataValue(IN XML_NODE *Node OPTIONAL, OUT UINT8 *Buffer, IN OUT UINT32 *Size)
Definition OcXmlLib.c:1886
XML_NODE * XmlNodeChild(IN CONST XML_NODE *Node, IN UINT32 Child)
Definition OcXmlLib.c:1503
BOOLEAN PlistBooleanValue(IN XML_NODE *Node OPTIONAL, OUT BOOLEAN *Value)
Definition OcXmlLib.c:1922
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
Definition OcXmlLib.c:1435
BOOLEAN PlistMultiDataValue(IN XML_NODE *Node OPTIONAL, OUT VOID *Buffer, IN OUT UINT32 *Size)
Definition OcXmlLib.c:2008
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
Definition OcXmlLib.c:1823
OC_SCHEMA_INFO Info
OC_APPLY Apply
PLIST_NODE_TYPE Type