OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcXmlLib.c
Go to the documentation of this file.
1
19//
20// Copyright (c) 2012 ooxi/xml.c
21// https://github.com/ooxi/xml.c
22//
23// This software is provided 'as-is', without any express or implied warranty.
24// In no event will the authors be held liable for any damages arising from the
25// use of this software.
26//
27// Permission is granted to anyone to use this software for any purpose,
28// including commercial applications, and to alter it and redistribute it
29// freely, subject to the following restrictions:
30//
31// 1. The origin of this software must not be misrepresented; you must not
32// claim that you wrote the original software. If you use this software in a
33// product, an acknowledgment in the product documentation would be
34// appreciated but is not required.
35//
36// 2. Altered source versions must be plainly marked as such, and must not be
37// misrepresented as being the original software.
38//
39// 3. This notice may not be removed or altered from any source distribution.
40//
41
42#include <Library/OcXmlLib.h>
43#include <Library/BaseLib.h>
44#include <Library/BaseMemoryLib.h>
45#include <Library/DebugLib.h>
46#include <Library/MemoryAllocationLib.h>
47#include <Library/OcMiscLib.h>
48#include <Library/OcStringLib.h>
49
53#define XML_EXPORT_MIN_ALLOCATION_SIZE 4096
54
55#define XML_PLIST_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
56
57struct XML_NODE_LIST_;
58struct XML_PARSER_;
59
61typedef struct XML_PARSER_ XML_PARSER;
62
67struct XML_NODE_ {
68 CONST CHAR8 *Name;
69 CONST CHAR8 *Attributes;
70 CONST CHAR8 *Content;
73};
74
80
81typedef struct {
82 UINT32 RefCount;
86
91 struct {
92 CHAR8 *Buffer;
93 UINT32 Length;
95
98};
99
104 CHAR8 *Buffer;
105 UINT32 Position;
106 UINT32 Length;
107 UINT32 Level;
108};
109
118
122CONST CHAR8 *
124 NULL,
125 "array",
126 "dict",
127 "key",
128 "string",
129 "data",
130 "date",
131 "true",
132 "false",
133 "real",
134 "integer"
135};
136
147STATIC
148BOOLEAN
150 IN CONST CHAR8 *Attributes,
151 IN CONST CHAR8 *Argument,
152 IN UINT32 ArgumentLength,
153 OUT UINT32 *ArgumentValue
154 )
155{
156 CONST CHAR8 *ArgumentStart;
157 CONST CHAR8 *ArgumentEnd;
158 UINTN Number;
159 CHAR8 NumberStr[16];
160
161 ASSERT (Attributes != NULL);
162 ASSERT (Argument != NULL);
163 ASSERT (ArgumentValue != NULL);
164
165 //
166 // FIXME: This may give false positives.
167 //
168
169 ArgumentStart = AsciiStrStr (Attributes, Argument);
170 if (ArgumentStart == NULL) {
171 return FALSE;
172 }
173
174 ArgumentStart += ArgumentLength;
175 ArgumentEnd = AsciiStrStr (ArgumentStart, "\"");
176 Number = ArgumentEnd - ArgumentStart;
177
178 if ((ArgumentEnd == NULL) || (Number > sizeof (NumberStr) - 1)) {
179 return FALSE;
180 }
181
182 CopyMem (&NumberStr, ArgumentStart, Number);
183 NumberStr[Number] = '\0';
184 *ArgumentValue = (UINT32)AsciiStrDecimalToUint64 (NumberStr);
185
186 return TRUE;
187}
188
200STATIC
201XML_NODE *
203 IN CONST CHAR8 *Name,
204 IN CONST CHAR8 *Attributes OPTIONAL,
205 IN CONST CHAR8 *Content OPTIONAL,
206 IN XML_NODE *Real OPTIONAL,
207 IN XML_NODE_LIST *Children OPTIONAL
208 )
209{
210 XML_NODE *Node;
211
212 ASSERT (Name != NULL);
213
214 Node = AllocatePool (sizeof (XML_NODE));
215
216 if (Node != NULL) {
217 Node->Name = Name;
218 Node->Attributes = Attributes;
219 Node->Content = Content;
220 Node->Real = Real;
221 Node->Children = Children;
222 }
223
224 return Node;
225}
226
235STATIC
236BOOLEAN
238 IN OUT XML_NODE *Node,
239 IN XML_NODE *Child
240 )
241{
242 UINT32 NodeCount;
243 UINT32 AllocCount;
244 XML_NODE_LIST *NewList;
245
246 ASSERT (Node != NULL);
247 ASSERT (Child != NULL);
248
249 NodeCount = 0;
250 AllocCount = 1;
251
252 //
253 // Push new node if there is enough room.
254 //
255 if (Node->Children != NULL) {
256 NodeCount = Node->Children->NodeCount;
257 AllocCount = Node->Children->AllocCount;
258
259 if ((NodeCount < XML_PARSER_NODE_COUNT) && (AllocCount > NodeCount)) {
260 Node->Children->NodeList[NodeCount] = Child;
261 ++Node->Children->NodeCount;
262 return TRUE;
263 }
264 }
265
266 //
267 // Insertion will exceed the limit.
268 //
269 if (NodeCount >= XML_PARSER_NODE_COUNT - 1) {
270 return FALSE;
271 }
272
273 //
274 // Allocate three times more room.
275 // This balances performance and memory usage on large files like prelinked plist.
276 //
277 AllocCount *= 3;
278
279 NewList = (XML_NODE_LIST *)AllocatePool (
280 sizeof (XML_NODE_LIST) + sizeof (NewList->NodeList[0]) * AllocCount
281 );
282
283 if (NewList == NULL) {
284 return FALSE;
285 }
286
287 NewList->NodeCount = NodeCount + 1;
288 NewList->AllocCount = AllocCount;
289
290 if (Node->Children != NULL) {
291 CopyMem (
292 &NewList->NodeList[0],
293 &Node->Children->NodeList[0],
294 sizeof (NewList->NodeList[0]) * NodeCount
295 );
296
297 FreePool (Node->Children);
298 }
299
300 NewList->NodeList[NodeCount] = Child;
301 Node->Children = NewList;
302
303 return TRUE;
304}
305
315STATIC
316BOOLEAN
318 IN OUT XML_REFLIST *References,
319 IN XML_NODE *Node,
320 IN UINT32 ReferenceNumber
321 )
322{
323 XML_NODE **NewReferences;
324 UINT32 NewRefAllocCount;
325
326 ASSERT (References != NULL);
327 ASSERT (Node != NULL);
328
329 if (ReferenceNumber >= XML_PARSER_MAX_REFERENCE_COUNT) {
330 return FALSE;
331 }
332
333 if (ReferenceNumber >= References->RefAllocCount) {
334 if (BaseOverflowAddMulU32 (ReferenceNumber, 1, 2, &NewRefAllocCount)) {
335 return FALSE;
336 }
337
338 NewReferences = AllocateZeroPool (NewRefAllocCount * sizeof (References->RefList[0]));
339 if (NewReferences == NULL) {
340 return FALSE;
341 }
342
343 if (References->RefList != NULL) {
344 CopyMem (
345 &NewReferences[0],
346 &References->RefList[0],
347 References->RefCount * sizeof (References->RefList[0])
348 );
349 FreePool (References->RefList);
350 }
351
352 References->RefList = NewReferences;
353 References->RefAllocCount = NewRefAllocCount;
354 }
355
356 References->RefList[ReferenceNumber] = Node;
357 if (ReferenceNumber >= References->RefCount) {
358 References->RefCount = ReferenceNumber + 1;
359 }
360
361 return TRUE;
362}
363
372STATIC
373XML_NODE *
375 IN CONST XML_REFLIST *References OPTIONAL,
376 IN CONST CHAR8 *Attributes OPTIONAL
377 )
378{
379 BOOLEAN HasArgument;
380 UINT32 Number;
381
382 if ((References == NULL) || (Attributes == NULL)) {
383 return NULL;
384 }
385
386 HasArgument = XmlParseAttributeNumber (
387 Attributes,
388 "IDREF=\"",
389 L_STR_LEN ("IDREF=\""),
390 &Number
391 );
392
393 if (!HasArgument || (Number >= References->RefCount)) {
394 return NULL;
395 }
396
397 return References->RefList[Number];
398}
399
405STATIC
406VOID
408 IN OUT XML_NODE *Node
409 )
410{
411 UINT32 Index;
412
413 ASSERT (Node != NULL);
414
415 if (Node->Children != NULL) {
416 for (Index = 0; Index < Node->Children->NodeCount; ++Index) {
417 XmlNodeFree (Node->Children->NodeList[Index]);
418 }
419
420 FreePool (Node->Children);
421 }
422
423 FreePool (Node);
424}
425
431STATIC
432VOID
434 IN OUT XML_REFLIST *References
435 )
436{
437 ASSERT (References != NULL);
438
439 if (References->RefList != NULL) {
440 FreePool (References->RefList);
441 References->RefList = NULL;
442 }
443}
444
448#ifdef XML_PARSER_VERBOSE
449#define XML_PARSER_INFO(Parser, Message) \
450 DEBUG ((DEBUG_VERBOSE, "OCXML: XML_PARSER_INFO %a\n", Message));
451#define XML_PARSER_TAG(Parser, Tag) \
452 DEBUG ((DEBUG_VERBOSE, "OCXML: XML_PARSER_TAG %a\n", Tag));
453#else
454#define XML_PARSER_INFO(Parser, Message) do {} while (0)
455#define XML_PARSER_TAG(Parser, Tag) do {} while (0)
456#endif
457
465VOID
467 IN CONST XML_PARSER *Parser,
468 IN XML_PARSER_OFFSET Offset,
469 IN CONST CHAR8 *Message
470 )
471{
472 UINT32 Character;
473 UINT32 Position;
474 UINT32 Row;
475 UINT32 Column;
476
477 ASSERT (Parser != NULL);
478 ASSERT (Message != NULL);
479
480 Character = 0;
481 Row = 0;
482 Column = 0;
483
484 if ((Parser->Length > 0) && ((Parser->Position > 0) || (NO_CHARACTER != Offset))) {
485 Character = Parser->Position + Offset;
486 if (Character > Parser->Length-1) {
487 Character = Parser->Length-1;
488 }
489
490 for (Position = 0; Position <= Character; ++Position) {
491 ++Column;
492
493 if ('\n' == Parser->Buffer[Position]) {
494 ++Row;
495 Column = 0;
496 }
497 }
498 }
499
500 if (NO_CHARACTER != Offset) {
501 DEBUG ((
502 DEBUG_INFO,
503 "OCXML: XmlParserError at %u:%u (is %c): %a\n",
504 Row + 1,
505 Column,
506 Parser->Buffer[Character],
507 Message
508 ));
509 } else {
510 DEBUG ((
511 DEBUG_INFO,
512 "OCXML: XmlParserError at %u:%u: %a\n",
513 Row + 1,
514 Column,
515 Message
516 ));
517 }
518}
519
523#ifdef XML_PRINT_ERRORS
524#define XML_PARSER_ERROR(Parser, Offset, Message) \
525 XmlParserError (Parser, Offset, Message)
526#define XML_USAGE_ERROR(Message) \
527 DEBUG ((DEBUG_VERBOSE, "OCXML: %a\n", Message));
528#else
529#define XML_PARSER_ERROR(Parser, Offset, Message) do {} while (0)
530#define XML_USAGE_ERROR(X) do {} while (0)
531#endif
532
541STATIC
542CHAR8
544 IN CONST XML_PARSER *Parser,
545 IN UINT32 N
546 )
547{
548 UINT32 Position;
549
550 ASSERT (Parser != NULL);
551
552 if ( !BaseOverflowAddU32 (Parser->Position, N, &Position)
553 && (Position < Parser->Length))
554 {
555 return Parser->Buffer[Position];
556 }
557
558 return 0;
559}
560
568STATIC
569VOID
571 IN OUT XML_PARSER *Parser,
572 IN UINT32 N
573 )
574{
575 ASSERT (Parser != NULL);
576
577 #ifdef XML_PARSER_VERBOSE
578 CHAR8 *Consumed;
579 CHAR8 *MessageBuffer;
580 UINT32 Left;
581
582 //
583 // Debug information.
584 //
585
586 Consumed = AllocatePool ((N + 1) * sizeof (CHAR8));
587 MessageBuffer = AllocatePool (512 * sizeof (CHAR8));
588 if ((Consumed != NULL) && (MessageBuffer != NULL)) {
589 Left = N;
590 if (Left > Parser->Length - Parser->Position) {
591 Left = Parser->Length - Parser->Position;
592 }
593
594 CopyMem (Consumed, &Parser->Buffer[Parser->Position], Left);
595 Consumed[Left] = 0;
596
597 AsciiSPrint (MessageBuffer, 512, "Consuming %u bytes \"%a\"", N, Consumed);
598 XML_PARSER_INFO (Parser, MessageBuffer);
599 }
600
601 if (Consumed != NULL) {
602 FreePool (Consumed);
603 }
604
605 if (MessageBuffer != NULL) {
606 FreePool (MessageBuffer);
607 }
608
609 #endif
610
611 //
612 // Move the position forward.
613 //
614 if ( BaseOverflowAddU32 (Parser->Position, N, &Parser->Position)
615 || (Parser->Position > Parser->Length))
616 {
617 Parser->Position = Parser->Length;
618 }
619}
620
626STATIC
627VOID
629 IN OUT XML_PARSER *Parser
630 )
631{
632 ASSERT (Parser != NULL);
633
634 XML_PARSER_INFO (Parser, "whitespace");
635
636 while ( Parser->Position < Parser->Length
637 && IsAsciiSpace (Parser->Buffer[Parser->Position]))
638 {
639 ++Parser->Position;
640 }
641}
642
656STATIC
657CONST CHAR8 *
659 IN OUT XML_PARSER *Parser,
660 OUT BOOLEAN *SelfClosing OPTIONAL,
661 OUT CONST CHAR8 **Attributes OPTIONAL
662 )
663{
664 CHAR8 Current;
665 UINT32 Start;
666 UINT32 AttributeStart;
667 UINT32 Length = 0;
668 UINT32 NameLength = 0;
669
670 ASSERT (Parser != NULL);
671
672 XML_PARSER_INFO (Parser, "tag_end");
673
674 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
675 Start = Parser->Position;
676
677 //
678 // Parse until `>' or a whitespace is reached.
679 //
681 if (('/' == Current) || ('>' == Current)) {
682 break;
683 }
684
685 if ((NameLength == 0) && IsAsciiSpace (Current)) {
686 NameLength = Length;
687
688 if (NameLength == 0) {
689 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagEnd::expected tag name");
690 return NULL;
691 }
692 }
693
694 XmlParserConsume (Parser, 1);
695 ++Length;
696
697 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
698 }
699
700 //
701 // Handle attributes.
702 //
703 if (NameLength != 0) {
704 if ((Attributes != NULL) && ((Current == '/') || (Current == '>'))) {
705 *Attributes = &Parser->Buffer[Start + NameLength];
706 AttributeStart = NameLength;
707 while (AttributeStart < Length && IsAsciiSpace (**Attributes)) {
708 ++(*Attributes);
709 ++AttributeStart;
710 }
711
712 Parser->Buffer[Start + Length] = '\0';
713 }
714 } else {
715 //
716 // No attributes besides name.
717 //
718 NameLength = Length;
719 }
720
721 if ('/' == Current) {
722 if (SelfClosing == NULL) {
723 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagEnd::unexpected self closing tag");
724 return NULL;
725 }
726
727 *SelfClosing = TRUE;
728 XmlParserConsume (Parser, 1);
729 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
730 }
731
732 //
733 // Consume `>'.
734 //
735 if ('>' != Current) {
736 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagEnd::expected tag end");
737 return NULL;
738 }
739
740 XmlParserConsume (Parser, 1);
741
742 //
743 // Return parsed tag name.
744 //
745 Parser->Buffer[Start + NameLength] = 0;
746 XML_PARSER_TAG (Parser, &Parser->Buffer[Start]);
747 return &Parser->Buffer[Start];
748}
749
763STATIC
764CONST CHAR8 *
766 IN OUT XML_PARSER *Parser,
767 OUT BOOLEAN *SelfClosing OPTIONAL,
768 OUT CONST CHAR8 **Attributes
769 )
770{
771 CHAR8 Current;
772 CHAR8 Next;
773 BOOLEAN IsComment;
774
775 ASSERT (Parser != NULL);
776 ASSERT (Attributes != NULL);
777
778 XML_PARSER_INFO (Parser, "tag_open");
779
780 do {
781 XmlSkipWhitespace (Parser);
782
783 //
784 // Consume `<'.
785 //
786 if ('<' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
787 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagOpen::expected opening tag");
788 return NULL;
789 }
790
791 XmlParserConsume (Parser, 1);
792
793 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
794
795 //
796 // This is closing tag, e.g. `</tag>', return.
797 //
798 if (Current == '/') {
799 return NULL;
800 }
801
802 //
803 // This is not a control sequence, e.g. `<!DOCTYPE...>', continue parsing tag.
804 //
805 if ((Current != '?') && (Current != '!')) {
806 break;
807 }
808
809 //
810 // A crazy XML comment may look like this:
811 // <!-- som>>><<<<ething -->
812 //
813 // '<' has already been consumed a bit earlier, now continue to check '!',
814 // and then the two '-'.
815 //
816 IsComment = FALSE;
817 if (Current == '!') {
818 //
819 // Consume one more byte to check the two `-'.
820 // Now `<!--' is guaranteed.
821 //
822 XmlParserConsume (Parser, 1);
823 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
824 Next = XmlParserPeek (Parser, NEXT_CHARACTER);
825 if ((Current == '-') && (Next == '-')) {
826 //
827 // Now consume Current and Next which take up 2 bytes.
828 //
829 XmlParserConsume (Parser, 2);
830 IsComment = TRUE;
831 }
832 }
833
834 //
835 // Skip the control sequence.
836 // NOTE: This inner loop is created mainly for code simplification.
837 //
838 while (Parser->Position < Parser->Length) {
839 if (IsComment) {
840 //
841 // Scan `-->' for comments and break if matched.
842 //
843 if ( (XmlParserPeek (Parser, CURRENT_CHARACTER) == '-')
844 && (XmlParserPeek (Parser, NEXT_CHARACTER) == '-')
845 && (XmlParserPeek (Parser, 2) == '>'))
846 {
847 //
848 // `-->' should all be consumed, which takes 3 bytes.
849 //
850 XmlParserConsume (Parser, 3);
851 break;
852 }
853 } else {
854 //
855 // For non-comments, simply match '>'.
856 //
857 if (XmlParserPeek (Parser, CURRENT_CHARACTER) == '>') {
858 XmlParserConsume (Parser, 1);
859 break;
860 }
861 }
862
863 //
864 // Consume each byte normally.
865 //
866 XmlParserConsume (Parser, 1);
867 }
868 } while (Parser->Position < Parser->Length);
869
870 //
871 // Consume tag name.
872 //
873 return XmlParseTagEnd (Parser, SelfClosing, Attributes);
874}
875
888STATIC
889CONST CHAR8 *
891 IN OUT XML_PARSER *Parser,
892 IN BOOLEAN Unprefixed
893 )
894{
895 ASSERT (Parser != NULL);
896
897 XML_PARSER_INFO (Parser, "tag_close");
898 XmlSkipWhitespace (Parser);
899
900 if (Unprefixed) {
901 //
902 // Consume `/'.
903 //
904 if ('/' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
905 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagClose::expected closing tag `/'");
906 return NULL;
907 }
908
909 XmlParserConsume (Parser, 1);
910 } else {
911 //
912 // Consume `</'.
913 //
914 if ('<' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
915 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseTagClose::expected closing tag `<'");
916 return NULL;
917 }
918
919 if ('/' != XmlParserPeek (Parser, NEXT_CHARACTER)) {
920 XML_PARSER_ERROR (Parser, NEXT_CHARACTER, "XmlParseTagClose::expected closing tag `/'");
921 return NULL;
922 }
923
924 XmlParserConsume (Parser, 2);
925 }
926
927 //
928 // Consume tag name.
929 //
930 return XmlParseTagEnd (Parser, NULL, NULL);
931}
932
948STATIC
949CONST CHAR8 *
951 IN OUT XML_PARSER *Parser
952 )
953{
954 UINTN Start;
955 UINTN Length;
956 CHAR8 Current;
957
958 ASSERT (Parser != NULL);
959
960 XML_PARSER_INFO (Parser, "content");
961
962 //
963 // Whitespace will be ignored.
964 //
965 XmlSkipWhitespace (Parser);
966
967 Start = Parser->Position;
968 Length = 0;
969
970 //
971 // Consume until `<' is reached.
972 //
974 Current = XmlParserPeek (Parser, CURRENT_CHARACTER);
975
976 if ('<' == Current) {
977 break;
978 } else {
979 XmlParserConsume (Parser, 1);
980 ++Length;
981 }
982 }
983
984 //
985 // Next character must be an `<' or we have reached end of file.
986 //
987 if ('<' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
988 XML_PARSER_ERROR (Parser, CURRENT_CHARACTER, "XmlParseContent::expected <");
989 return NULL;
990 }
991
992 //
993 // Ignore tailing whitespace.
994 //
995 while ((Length > 0) && IsAsciiSpace (Parser->Buffer[Start + Length - 1])) {
996 --Length;
997 }
998
999 //
1000 // Return text.
1001 //
1002 Parser->Buffer[Start + Length] = 0;
1003 XmlParserConsume (Parser, 1);
1004 return &Parser->Buffer[Start];
1005}
1006
1016STATIC
1017VOID
1019 IN OUT CHAR8 **Buffer,
1020 IN OUT UINT32 *AllocSize,
1021 IN OUT UINT32 *CurrentSize,
1022 IN CONST CHAR8 *Data,
1023 IN UINT32 DataLength
1024 )
1025{
1026 CHAR8 *NewBuffer;
1027 UINT32 NewSize;
1028
1029 ASSERT (Buffer != NULL);
1030 ASSERT (AllocSize != NULL);
1031 ASSERT (CurrentSize != NULL);
1032 ASSERT (Data != NULL);
1033
1034 NewSize = *AllocSize;
1035
1036 if (NewSize - *CurrentSize <= DataLength) {
1037 if (DataLength + 1 <= XML_EXPORT_MIN_ALLOCATION_SIZE) {
1039 } else {
1040 NewSize += DataLength + 1;
1041 }
1042
1043 NewBuffer = AllocatePool (NewSize);
1044 if (NewBuffer == NULL) {
1045 XML_USAGE_ERROR ("XmlBufferAppend::failed to allocate");
1046 return;
1047 }
1048
1049 CopyMem (NewBuffer, *Buffer, *CurrentSize);
1050 FreePool (*Buffer);
1051 *Buffer = NewBuffer;
1052 *AllocSize = NewSize;
1053 }
1054
1055 CopyMem (&(*Buffer)[*CurrentSize], Data, DataLength);
1056 *CurrentSize += DataLength;
1057}
1058
1068STATIC
1069VOID
1071 IN CONST XML_NODE *Node,
1072 IN OUT CHAR8 **Buffer,
1073 IN OUT UINT32 *AllocSize,
1074 IN OUT UINT32 *CurrentSize,
1075 IN UINT32 Skip
1076 )
1077{
1078 UINT32 Index;
1079 UINT32 NameLength;
1080
1081 ASSERT (Node != NULL);
1082 ASSERT (Buffer != NULL);
1083 ASSERT (AllocSize != NULL);
1084 ASSERT (CurrentSize != NULL);
1085
1086 if (Skip != 0) {
1087 if (Node->Children != NULL) {
1088 for (Index = 0; Index < Node->Children->NodeCount; ++Index) {
1089 XmlNodeExportRecursive (Node->Children->NodeList[Index], Buffer, AllocSize, CurrentSize, Skip - 1);
1090 }
1091 }
1092
1093 return;
1094 }
1095
1096 NameLength = (UINT32)AsciiStrLen (Node->Name);
1097
1098 XmlBufferAppend (Buffer, AllocSize, CurrentSize, "<", L_STR_LEN ("<"));
1099 XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Name, NameLength);
1100
1101 if (Node->Attributes != NULL) {
1102 XmlBufferAppend (Buffer, AllocSize, CurrentSize, " ", L_STR_LEN (" "));
1103 XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Attributes, (UINT32)AsciiStrLen (Node->Attributes));
1104 }
1105
1106 if ((Node->Children != NULL) || (Node->Content != NULL)) {
1107 XmlBufferAppend (Buffer, AllocSize, CurrentSize, ">", L_STR_LEN (">"));
1108
1109 if (Node->Children != NULL) {
1110 for (Index = 0; Index < Node->Children->NodeCount; ++Index) {
1111 XmlNodeExportRecursive (Node->Children->NodeList[Index], Buffer, AllocSize, CurrentSize, 0);
1112 }
1113 } else {
1114 XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Content, (UINT32)AsciiStrLen (Node->Content));
1115 }
1116
1117 XmlBufferAppend (Buffer, AllocSize, CurrentSize, "</", L_STR_LEN ("</"));
1118 XmlBufferAppend (Buffer, AllocSize, CurrentSize, Node->Name, NameLength);
1119 XmlBufferAppend (Buffer, AllocSize, CurrentSize, ">", L_STR_LEN (">"));
1120 } else {
1121 XmlBufferAppend (Buffer, AllocSize, CurrentSize, "/>", L_STR_LEN ("/>"));
1122 }
1123}
1124
1145STATIC
1146XML_NODE *
1148 IN OUT XML_PARSER *Parser,
1149 IN OUT XML_REFLIST *References OPTIONAL
1150 )
1151{
1152 CONST CHAR8 *TagOpen;
1153 CONST CHAR8 *TagClose;
1154 CONST CHAR8 *Attributes;
1155 XML_NODE *Node;
1156 XML_NODE *Child;
1157 UINT32 ReferenceNumber;
1158 BOOLEAN IsReference;
1159 BOOLEAN SelfClosing;
1160 BOOLEAN Unprefixed;
1161 BOOLEAN HasChildren;
1162
1163 ASSERT (Parser != NULL);
1164
1165 XML_PARSER_INFO (Parser, "node");
1166
1167 Attributes = NULL;
1168 SelfClosing = FALSE;
1169 Unprefixed = FALSE;
1170 IsReference = FALSE;
1171 ReferenceNumber = 0;
1172
1173 //
1174 // Parse open tag.
1175 //
1176 TagOpen = XmlParseTagOpen (Parser, &SelfClosing, &Attributes);
1177 if (TagOpen == NULL) {
1178 if ('/' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
1179 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::tag_open");
1180 }
1181
1182 return NULL;
1183 }
1184
1185 XmlSkipWhitespace (Parser);
1186
1187 Node = XmlNodeCreate (TagOpen, Attributes, NULL, XmlNodeReal (References, Attributes), NULL);
1188 if (Node == NULL) {
1189 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::node alloc fail");
1190 return NULL;
1191 }
1192
1193 //
1194 // If tag ends with `/' it's self closing, skip content lookup.
1195 //
1196 if (SelfClosing) {
1197 return Node;
1198 }
1199
1200 //
1201 // If the content does not start with '<', a text content is assumed.
1202 //
1203 if ('<' != XmlParserPeek (Parser, CURRENT_CHARACTER)) {
1204 Node->Content = XmlParseContent (Parser);
1205
1206 if (Node->Content == NULL) {
1207 XML_PARSER_ERROR (Parser, 0, "XmlParseNode::content");
1208 XmlNodeFree (Node);
1209 return NULL;
1210 }
1211
1212 //
1213 // All references must be defined sequentially.
1214 //
1215 if ((References != NULL) && (Node->Attributes != NULL)) {
1216 IsReference = XmlParseAttributeNumber (
1217 Node->Attributes,
1218 "ID=\"",
1219 L_STR_LEN ("ID=\""),
1220 &ReferenceNumber
1221 );
1222 }
1223
1224 Unprefixed = TRUE;
1225
1226 //
1227 // Otherwise children are to be expected.
1228 //
1229 } else {
1230 ++Parser->Level;
1231
1232 if (Parser->Level > XML_PARSER_NEST_LEVEL) {
1233 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::level overflow");
1234 XmlNodeFree (Node);
1235 return NULL;
1236 }
1237
1238 HasChildren = FALSE;
1239
1240 while ('/' != XmlParserPeek (Parser, NEXT_CHARACTER)) {
1241 //
1242 // Parse child node.
1243 //
1244 Child = XmlParseNode (Parser, References);
1245 if (Child == NULL) {
1246 if ('/' == XmlParserPeek (Parser, CURRENT_CHARACTER)) {
1247 XML_PARSER_INFO (Parser, "child_end");
1248 Unprefixed = TRUE;
1249 break;
1250 }
1251
1252 XML_PARSER_ERROR (Parser, NEXT_CHARACTER, "XmlParseNode::child");
1253 XmlNodeFree (Node);
1254 return NULL;
1255 }
1256
1257 if (!XmlNodeChildPush (Node, Child)) {
1258 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::node push fail");
1259 XmlNodeFree (Node);
1260 XmlNodeFree (Child);
1261 return NULL;
1262 }
1263
1264 HasChildren = TRUE;
1265 }
1266
1267 --Parser->Level;
1268
1269 if (!HasChildren && (References != NULL) && (Attributes != NULL)) {
1270 IsReference = XmlParseAttributeNumber (
1271 Node->Attributes,
1272 "ID=\"",
1273 L_STR_LEN ("ID=\""),
1274 &ReferenceNumber
1275 );
1276 }
1277 }
1278
1279 //
1280 // Parse close tag.
1281 //
1282 TagClose = XmlParseTagClose (Parser, Unprefixed);
1283 if (TagClose == NULL) {
1284 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::tag close");
1285 XmlNodeFree (Node);
1286 return NULL;
1287 }
1288
1289 //
1290 // Close tag has to match open tag.
1291 //
1292 if (AsciiStrCmp (TagOpen, TagClose) != 0) {
1293 XML_PARSER_ERROR (Parser, NO_CHARACTER, "XmlParseNode::tag missmatch");
1294 XmlNodeFree (Node);
1295 return NULL;
1296 }
1297
1298 if (IsReference && !XmlPushReference (References, Node, ReferenceNumber)) {
1299 XML_PARSER_ERROR (Parser, 0, "XmlParseNode::reference");
1300 XmlNodeFree (Node);
1301 return NULL;
1302 }
1303
1304 return Node;
1305}
1306
1309 IN OUT CHAR8 *Buffer,
1310 IN UINT32 Length,
1311 IN BOOLEAN WithRefs
1312 )
1313{
1314 XML_NODE *Root;
1315 XML_DOCUMENT *Document;
1316 XML_REFLIST References;
1317 XML_PARSER Parser;
1318
1319 ASSERT (Buffer != NULL);
1320
1321 //
1322 // Initialize parser.
1323 //
1324 ZeroMem (&Parser, sizeof (Parser));
1325 Parser.Buffer = Buffer;
1326 Parser.Length = Length;
1327 ZeroMem (&References, sizeof (References));
1328
1329 //
1330 // An empty buffer can never contain a valid document.
1331 //
1332 if ((Length == 0) || (Length > XML_PARSER_MAX_SIZE)) {
1333 XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::length is too small or too large");
1334 return NULL;
1335 }
1336
1337 //
1338 // Parse the root node.
1339 //
1340 Root = XmlParseNode (&Parser, WithRefs ? &References : NULL);
1341 if (Root == NULL) {
1342 XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::parsing document failed");
1343 return NULL;
1344 }
1345
1346 //
1347 // Return parsed document.
1348 //
1349 Document = AllocatePool (sizeof (XML_DOCUMENT));
1350
1351 if (Document == NULL) {
1352 XML_PARSER_ERROR (&Parser, NO_CHARACTER, "XmlDocumentParse::document allocation failed");
1353 XmlNodeFree (Root);
1354 XmlFreeRefs (&References);
1355 return NULL;
1356 }
1357
1358 Document->Buffer.Buffer = Buffer;
1359 Document->Buffer.Length = Length;
1360 Document->Root = Root;
1361 CopyMem (&Document->References, &References, sizeof (References));
1362
1363 return Document;
1364}
1365
1366CHAR8 *
1368 IN CONST XML_DOCUMENT *Document,
1369 OUT UINT32 *Length OPTIONAL,
1370 IN UINT32 Skip,
1371 IN BOOLEAN PrependPlistInfo
1372 )
1373{
1374 CHAR8 *Buffer;
1375 CHAR8 *NewBuffer;
1376 UINT32 AllocSize;
1377 UINT32 CurrentSize;
1378 UINT32 NewSize;
1379
1380 ASSERT (Document != NULL);
1381
1382 AllocSize = Document->Buffer.Length + 1;
1383 Buffer = AllocatePool (AllocSize);
1384 if (Buffer == NULL) {
1385 XML_USAGE_ERROR ("XmlDocumentExport::failed to allocate");
1386 return NULL;
1387 }
1388
1389 CurrentSize = 0;
1390 XmlNodeExportRecursive (Document->Root, &Buffer, &AllocSize, &CurrentSize, Skip);
1391
1392 if (PrependPlistInfo) {
1393 //
1394 // XmlNodeExportRecursive returns a size that does not include the null terminator,
1395 // but the allocated buffer does. During this reallocation, we count the null terminator
1396 // of the plist header instead to ensure allocated buffer is the proper size.
1397 //
1398 if (BaseOverflowAddU32 (CurrentSize, L_STR_SIZE (XML_PLIST_HEADER), &NewSize)) {
1399 FreePool (Buffer);
1400 return NULL;
1401 }
1402
1403 NewBuffer = AllocatePool (NewSize);
1404 if (NewBuffer == NULL) {
1405 FreePool (Buffer);
1406 XML_USAGE_ERROR ("XmlDocumentExport::failed to allocate");
1407 return NULL;
1408 }
1409
1411 CopyMem (&NewBuffer[L_STR_LEN (XML_PLIST_HEADER)], Buffer, CurrentSize);
1412 FreePool (Buffer);
1413
1414 //
1415 // Null terminator is not included in size returned by XmlBufferAppend.
1416 //
1417 CurrentSize = NewSize - 1;
1418 Buffer = NewBuffer;
1419 }
1420
1421 if (Length != NULL) {
1422 *Length = CurrentSize;
1423 }
1424
1425 //
1426 // Null terminator is not included in size returned by XmlBufferAppend,
1427 // but the buffer is allocated to include it.
1428 //
1429 Buffer[CurrentSize] = '\0';
1430
1431 return Buffer;
1432}
1433
1434VOID
1436 IN OUT XML_DOCUMENT *Document
1437 )
1438{
1439 ASSERT (Document != NULL);
1440
1441 XmlNodeFree (Document->Root);
1442 XmlFreeRefs (&Document->References);
1443 FreePool (Document);
1444}
1445
1446XML_NODE *
1448 IN CONST XML_DOCUMENT *Document
1449 )
1450{
1451 ASSERT (Document != NULL);
1452
1453 return Document->Root;
1454}
1455
1456CONST CHAR8 *
1458 IN CONST XML_NODE *Node
1459 )
1460{
1461 ASSERT (Node != NULL);
1462
1463 return Node->Name;
1464}
1465
1466CONST CHAR8 *
1468 IN CONST XML_NODE *Node
1469 )
1470{
1471 ASSERT (Node != NULL);
1472
1473 return Node->Real != NULL ? Node->Real->Content : Node->Content;
1474}
1475
1476VOID
1478 IN OUT XML_NODE *Node,
1479 IN CONST CHAR8 *Content
1480 )
1481{
1482 ASSERT (Node != NULL);
1483 ASSERT (Content != NULL);
1484
1485 if (Node->Real != NULL) {
1486 Node->Real->Content = Content;
1487 }
1488
1489 Node->Content = Content;
1490}
1491
1492UINT32
1494 IN CONST XML_NODE *Node
1495 )
1496{
1497 ASSERT (Node != NULL);
1498
1499 return Node->Children ? Node->Children->NodeCount : 0;
1500}
1501
1502XML_NODE *
1504 IN CONST XML_NODE *Node,
1505 IN UINT32 Child
1506 )
1507{
1508 ASSERT (Node != NULL);
1509
1510 return Node->Children->NodeList[Child];
1511}
1512
1513XML_NODE *
1514EFIAPI
1516 IN OUT XML_NODE *Node,
1517 IN CONST CHAR8 *ChildName,
1518 ...
1519 )
1520{
1521 VA_LIST Arguments;
1522 XML_NODE *Next;
1523 XML_NODE *Child;
1524 UINT32 Index;
1525
1526 ASSERT (Node != NULL);
1527 ASSERT (ChildName != NULL);
1528
1529 VA_START (Arguments, ChildName);
1530
1531 //
1532 // Descent to current child.
1533 //
1534 while (ChildName != NULL) {
1535 //
1536 // Interate through all children.
1537 //
1538 Next = NULL;
1539
1540 for (Index = 0; Index < XmlNodeChildren (Node); ++Index) {
1541 Child = XmlNodeChild (Node, Index);
1542
1543 if (AsciiStrCmp (XmlNodeName (Child), ChildName) != 0) {
1544 if (Next == NULL) {
1545 Next = Child;
1546 } else {
1547 //
1548 // Two children with the same name.
1549 //
1550 VA_END (Arguments);
1551 return NULL;
1552 }
1553 }
1554 }
1555
1556 //
1557 // No child with that name found.
1558 //
1559 if (Next == NULL) {
1560 VA_END (Arguments);
1561 return NULL;
1562 }
1563
1564 Node = Next;
1565
1566 //
1567 // Find name of next child.
1568 //
1569 ChildName = VA_ARG (Arguments, CONST CHAR8 *);
1570 }
1571
1572 VA_END (Arguments);
1573
1574 //
1575 // Return current element.
1576 //
1577 return Node;
1578}
1579
1580XML_NODE *
1582 IN OUT XML_NODE *Node,
1583 IN CONST CHAR8 *Name,
1584 IN CONST CHAR8 *Attributes OPTIONAL,
1585 IN CONST CHAR8 *Content OPTIONAL
1586 )
1587{
1588 XML_NODE *NewNode;
1589
1590 ASSERT (Node != NULL);
1591 ASSERT (Name != NULL);
1592
1593 NewNode = XmlNodeCreate (Name, Attributes, Content, NULL, NULL);
1594 if (NewNode == NULL) {
1595 return NULL;
1596 }
1597
1598 if (!XmlNodeChildPush (Node, NewNode)) {
1599 XmlNodeFree (NewNode);
1600 return NULL;
1601 }
1602
1603 return NewNode;
1604}
1605
1606XML_NODE *
1608 IN OUT XML_NODE *Node,
1609 IN CONST CHAR8 *Name,
1610 IN CONST CHAR8 *Attributes,
1611 IN CONST CHAR8 *Content
1612 )
1613{
1614 XML_NODE *NewNode;
1615
1616 ASSERT (Node != NULL);
1617 ASSERT (Name != NULL);
1618 ASSERT (Attributes != NULL);
1619 ASSERT (Content != NULL);
1620
1621 NewNode = XmlNodeAppend (Node, Name, Attributes, Content);
1622 if (NewNode == NULL) {
1623 return NULL;
1624 }
1625
1626 CopyMem (&Node->Children->NodeList[1], &Node->Children->NodeList[0], (Node->Children->NodeCount - 1) * sizeof (Node->Children->NodeList[0]));
1627 Node->Children->NodeList[0] = NewNode;
1628
1629 return NewNode;
1630}
1631
1632VOID
1634 IN OUT XML_NODE *Node,
1635 IN UINT32 Index
1636 )
1637{
1638 ASSERT (Node != NULL);
1639 ASSERT (Node->Children != NULL);
1640 ASSERT (Index < Node->Children->NodeCount);
1641
1642 //
1643 // Free the Index-th XML node.
1644 //
1645 XmlNodeFree (Node->Children->NodeList[Index]);
1646
1647 //
1648 // Overwrite the Index-th node with remaining nodes.
1649 //
1650 CopyMem (
1651 &Node->Children->NodeList[Index],
1652 &Node->Children->NodeList[Index+1],
1653 (Node->Children->NodeCount - 1 - Index) * sizeof (*Node->Children->NodeList)
1654 );
1655
1656 //
1657 // Drop the last entry as the node above has been removed.
1658 //
1659 ZeroMem (&Node->Children->NodeList[Node->Children->NodeCount-1], sizeof (*Node->Children->NodeList));
1660 --Node->Children->NodeCount;
1661}
1662
1663VOID
1665 IN OUT XML_NODE *Node,
1666 IN XML_NODE *ChildNode
1667 )
1668{
1669 UINT32 Index;
1670
1671 ASSERT (Node != NULL);
1672 ASSERT (Node->Children != NULL);
1673 ASSERT (ChildNode != NULL);
1674
1675 for (Index = 0; CompareMem (Node->Children->NodeList[Index], ChildNode, sizeof (XML_NODE)) != 0; ++Index) {
1676 //
1677 // Locate ChildNode inside Node.
1678 //
1679 }
1680
1681 ASSERT (Index < Node->Children->NodeCount);
1682
1683 XmlNodeRemoveByIndex (Node, Index);
1684}
1685
1686CONST CHAR8 *
1688 IN CONST CHAR8 *String
1689 )
1690{
1691 UINTN StringSize;
1692 CHAR8 *Buffer;
1693 CHAR8 *Pointer;
1694
1695 ASSERT (String != NULL);
1696
1697 StringSize = AsciiStrSize (String);
1698 Pointer = (CHAR8 *)AllocatePool (StringSize);
1699 if (Pointer == NULL) {
1700 return NULL;
1701 }
1702
1703 Buffer = Pointer;
1704
1705 while (*String != '\0') {
1706 if (*String == '&') {
1707 if (AsciiStrnCmp (String + 1, "apos;", L_STR_LEN ("apos;")) == 0) {
1708 *Pointer++ = '\'';
1709 String += L_STR_LEN ("&apos;");
1710 } else if (AsciiStrnCmp (String + 1, "quot;", L_STR_LEN ("quot;")) == 0) {
1711 *Pointer++ = '\"';
1712 String += L_STR_LEN ("&quot;");
1713 } else if (AsciiStrnCmp (String + 1, "amp;", L_STR_LEN ("amp;")) == 0) {
1714 *Pointer++ = '&';
1715 String += L_STR_LEN ("&amp;");
1716 } else if (AsciiStrnCmp (String + 1, "lt;", L_STR_LEN ("lt;")) == 0) {
1717 *Pointer++ = '<';
1718 String += L_STR_LEN ("&lt;");
1719 } else if (AsciiStrnCmp (String + 1, "gt;", L_STR_LEN ("gt;")) == 0) {
1720 *Pointer++ = '>';
1721 String += L_STR_LEN ("&gt;");
1722 } else {
1723 *Pointer++ = *String++;
1724 }
1725 } else {
1726 *Pointer++ = *String++;
1727 }
1728 }
1729
1730 *Pointer = '\0';
1731
1732 return (CONST CHAR8 *)Buffer;
1733}
1734
1735XML_NODE *
1737 IN CONST XML_DOCUMENT *Document
1738 )
1739{
1740 XML_NODE *Node;
1741
1742 ASSERT (Document != NULL);
1743
1744 Node = Document->Root;
1745
1746 if (AsciiStrCmp (XmlNodeName (Node), "plist") != 0) {
1747 XML_USAGE_ERROR ("PlistDocumentRoot::not plist root");
1748 return NULL;
1749 }
1750
1751 if (XmlNodeChildren (Node) != 1) {
1752 XML_USAGE_ERROR ("PlistDocumentRoot::no single first node");
1753 return NULL;
1754 }
1755
1756 return XmlNodeChild (Node, 0);
1757}
1758
1759XML_NODE *
1761 IN XML_NODE *Node OPTIONAL,
1762 IN PLIST_NODE_TYPE Type
1763 )
1764{
1765 UINT32 ChildrenNum;
1766
1767 if ((Node == NULL) || (Type == PLIST_NODE_TYPE_ANY)) {
1768 return Node;
1769 }
1770
1771 if (AsciiStrCmp (XmlNodeName (Node), PlistNodeTypes[Type]) != 0) {
1772 // XML_USAGE_ERROR ("PlistNodeType::wrong type");
1773 return NULL;
1774 }
1775
1776 ChildrenNum = XmlNodeChildren (Node);
1777
1778 switch (Type) {
1780 if (ChildrenNum % 2 != 0) {
1781 XML_USAGE_ERROR ("PlistNodeType::dict has odd children");
1782 return NULL;
1783 }
1784
1785 break;
1787 break;
1791 if (XmlNodeContent (Node) == NULL) {
1792 XML_USAGE_ERROR ("PlistNodeType::key or int have no content");
1793 return NULL;
1794 }
1795
1796 // Fallthrough
1797 default:
1798 //
1799 // Only dictionaries and arrays are allowed to have child nodes.
1800 //
1801 if (ChildrenNum > 0) {
1802 XML_USAGE_ERROR ("PlistNodeType::non dict array has children");
1803 return NULL;
1804 }
1805
1806 break;
1807 }
1808
1809 return (XML_NODE *)Node;
1810}
1811
1812UINT32
1814 IN CONST XML_NODE *Node
1815 )
1816{
1817 ASSERT (Node != NULL);
1818
1819 return XmlNodeChildren (Node) / 2;
1820}
1821
1822XML_NODE *
1824 IN CONST XML_NODE *Node,
1825 IN UINT32 Child,
1826 OUT XML_NODE **Value OPTIONAL
1827 )
1828{
1829 ASSERT (Node != NULL);
1830
1831 Child *= 2;
1832
1833 if (Value != NULL) {
1834 *Value = XmlNodeChild (Node, Child + 1);
1835 }
1836
1837 return XmlNodeChild (Node, Child);
1838}
1839
1840CONST CHAR8 *
1842 IN XML_NODE *Node OPTIONAL
1843 )
1844{
1845 if (PlistNodeCast (Node, PLIST_NODE_TYPE_KEY) == NULL) {
1846 return NULL;
1847 }
1848
1849 return XmlNodeContent (Node);
1850}
1851
1852BOOLEAN
1854 IN XML_NODE *Node OPTIONAL,
1855 OUT CHAR8 *Value,
1856 IN OUT UINT32 *Size
1857 )
1858{
1859 CONST CHAR8 *Content;
1860 UINTN Length;
1861
1862 ASSERT (Value != NULL);
1863 ASSERT (Size != NULL);
1864
1865 if (PlistNodeCast (Node, PLIST_NODE_TYPE_STRING) == NULL) {
1866 return FALSE;
1867 }
1868
1869 Content = XmlNodeContent (Node);
1870 if (Content == NULL) {
1871 Value[0] = '\0';
1872 *Size = 1;
1873 return TRUE;
1874 }
1875
1876 Length = AsciiStrLen (Content);
1877 if (Length < *Size) {
1878 *Size = (UINT32)(Length + 1);
1879 }
1880
1881 AsciiStrnCpyS (Value, *Size, Content, Length);
1882 return TRUE;
1883}
1884
1885BOOLEAN
1887 IN XML_NODE *Node OPTIONAL,
1888 OUT UINT8 *Buffer,
1889 IN OUT UINT32 *Size
1890 )
1891{
1892 CONST CHAR8 *Content;
1893 UINTN Length;
1894 EFI_STATUS Status;
1895
1896 ASSERT (Buffer != NULL);
1897 ASSERT (Size != NULL);
1898
1899 if (PlistNodeCast (Node, PLIST_NODE_TYPE_DATA) == NULL) {
1900 return FALSE;
1901 }
1902
1903 Content = XmlNodeContent (Node);
1904 if (Content == NULL) {
1905 *Size = 0;
1906 return TRUE;
1907 }
1908
1909 Length = *Size;
1910 Status = Base64Decode (Content, AsciiStrLen (Content), Buffer, &Length);
1911
1912 if (!EFI_ERROR (Status) && ((UINT32)Length == Length)) {
1913 *Size = (UINT32)Length;
1914 return TRUE;
1915 }
1916
1917 *Size = 0;
1918 return FALSE;
1919}
1920
1921BOOLEAN
1923 IN XML_NODE *Node OPTIONAL,
1924 OUT BOOLEAN *Value
1925 )
1926{
1927 ASSERT (Value != NULL);
1928
1929 if (PlistNodeCast (Node, PLIST_NODE_TYPE_TRUE) != NULL) {
1930 *Value = TRUE;
1931 return TRUE;
1932 }
1933
1934 if (PlistNodeCast (Node, PLIST_NODE_TYPE_FALSE) != NULL) {
1935 *Value = FALSE;
1936 return TRUE;
1937 }
1938
1939 return FALSE;
1940}
1941
1942BOOLEAN
1944 IN XML_NODE *Node OPTIONAL,
1945 OUT VOID *Value,
1946 IN UINT32 Size,
1947 IN BOOLEAN Hex
1948 )
1949{
1950 UINT64 Temp;
1951 CONST CHAR8 *TempStr;
1952 BOOLEAN Negate;
1953
1954 ASSERT (Value != NULL);
1955
1956 if (PlistNodeCast (Node, PLIST_NODE_TYPE_INTEGER) == NULL) {
1957 return FALSE;
1958 }
1959
1960 TempStr = XmlNodeContent (Node);
1961
1962 while (*TempStr == ' ' || *TempStr == '\t') {
1963 ++TempStr;
1964 }
1965
1966 Negate = *TempStr == '-';
1967
1968 if (Negate) {
1969 ++TempStr;
1970 }
1971
1972 if (Hex && (TempStr[0] != '0') && (TempStr[1] != 'x')) {
1973 Hex = FALSE;
1974 }
1975
1976 if (Hex) {
1977 Temp = AsciiStrHexToUint64 (TempStr);
1978 } else {
1979 Temp = AsciiStrDecimalToUint64 (TempStr);
1980 }
1981
1982 //
1983 // May produce unexpected results when the value is too large, but just do not care.
1984 //
1985 if (Negate) {
1986 Temp = 0ULL - Temp;
1987 }
1988
1989 switch (Size) {
1990 case sizeof (UINT64):
1991 *(UINT64 *)Value = Temp;
1992 return TRUE;
1993 case sizeof (UINT32):
1994 *(UINT32 *)Value = (UINT32)Temp;
1995 return TRUE;
1996 case sizeof (UINT16):
1997 *(UINT16 *)Value = (UINT16)Temp;
1998 return TRUE;
1999 case sizeof (UINT8):
2000 *(UINT8 *)Value = (UINT8)Temp;
2001 return TRUE;
2002 default:
2003 return FALSE;
2004 }
2005}
2006
2007BOOLEAN
2009 IN XML_NODE *Node OPTIONAL,
2010 OUT VOID *Buffer,
2011 IN OUT UINT32 *Size
2012 )
2013{
2014 CONST CHAR8 *Content;
2015 UINTN Length;
2016 EFI_STATUS Status;
2017
2018 ASSERT (Buffer != NULL);
2019 ASSERT (Size != NULL);
2020
2021 if (PlistNodeCast (Node, PLIST_NODE_TYPE_DATA) != NULL) {
2022 Content = XmlNodeContent (Node);
2023 if (Content != NULL) {
2024 Length = *Size;
2025 Status = Base64Decode (Content, AsciiStrLen (Content), Buffer, &Length);
2026
2027 if (!EFI_ERROR (Status) && ((UINT32)Length == Length)) {
2028 *Size = (UINT32)Length;
2029 } else {
2030 return FALSE;
2031 }
2032 } else {
2033 *Size = 0;
2034 }
2035
2036 return TRUE;
2037 }
2038
2039 if (PlistNodeCast (Node, PLIST_NODE_TYPE_STRING) != NULL) {
2040 Content = XmlNodeContent (Node);
2041 if (Content != NULL) {
2042 Length = AsciiStrLen (Content);
2043 if (Length < *Size) {
2044 *Size = (UINT32)(Length + 1);
2045 }
2046
2047 AsciiStrnCpyS (Buffer, *Size, Content, Length);
2048 } else {
2049 *(CHAR8 *)Buffer = '\0';
2050 *Size = 1;
2051 }
2052
2053 return TRUE;
2054 }
2055
2056 if (PlistNodeCast (Node, PLIST_NODE_TYPE_INTEGER) != NULL) {
2057 *(UINT32 *)Buffer = (UINT32)AsciiStrDecimalToUint64 (XmlNodeContent (Node));
2058 *Size = sizeof (UINT32);
2059 return TRUE;
2060 }
2061
2062 if (PlistNodeCast (Node, PLIST_NODE_TYPE_TRUE) != NULL) {
2063 *(UINT8 *)Buffer = 1;
2064 *Size = sizeof (UINT8);
2065 return TRUE;
2066 }
2067
2068 if (PlistNodeCast (Node, PLIST_NODE_TYPE_FALSE) != NULL) {
2069 *(UINT8 *)Buffer = 0;
2070 *Size = sizeof (UINT8);
2071 return TRUE;
2072 }
2073
2074 return FALSE;
2075}
2076
2077BOOLEAN
2079 IN XML_NODE *Node OPTIONAL,
2080 OUT UINT32 *Size
2081 )
2082{
2083 CONST CHAR8 *Content;
2084
2085 ASSERT (Size != NULL);
2086
2087 if (PlistNodeCast (Node, PLIST_NODE_TYPE_STRING) == NULL) {
2088 return FALSE;
2089 }
2090
2091 Content = XmlNodeContent (Node);
2092 if (Content != NULL) {
2093 *Size = (UINT32)AsciiStrSize (Content);
2094 return TRUE;
2095 }
2096
2097 *Size = 0;
2098 return TRUE;
2099}
2100
2101BOOLEAN
2103 IN XML_NODE *Node OPTIONAL,
2104 OUT UINT32 *Size
2105 )
2106{
2107 CONST CHAR8 *Content;
2108
2109 ASSERT (Size != NULL);
2110
2111 if (PlistNodeCast (Node, PLIST_NODE_TYPE_DATA) == NULL) {
2112 return FALSE;
2113 }
2114
2115 Content = XmlNodeContent (Node);
2116 if (Content != NULL) {
2117 *Size = (UINT32)AsciiStrLen (Content);
2118 } else {
2119 *Size = 0;
2120 }
2121
2122 return TRUE;
2123}
2124
2125BOOLEAN
2127 IN XML_NODE *Node OPTIONAL,
2128 OUT UINT32 *Size
2129 )
2130{
2131 CONST CHAR8 *Content;
2132
2133 ASSERT (Size != NULL);
2134
2135 if (PlistNodeCast (Node, PLIST_NODE_TYPE_DATA) != NULL) {
2136 Content = XmlNodeContent (Node);
2137 if (Content != NULL) {
2138 *Size = (UINT32)AsciiStrLen (Content);
2139 } else {
2140 *Size = 0;
2141 }
2142
2143 return TRUE;
2144 }
2145
2146 if (PlistNodeCast (Node, PLIST_NODE_TYPE_STRING) != NULL) {
2147 Content = XmlNodeContent (Node);
2148 if (Content != NULL) {
2149 *Size = (UINT32)(AsciiStrLen (Content) + 1);
2150 } else {
2151 *Size = 0;
2152 }
2153
2154 return TRUE;
2155 }
2156
2157 if (PlistNodeCast (Node, PLIST_NODE_TYPE_INTEGER) != NULL) {
2158 *Size = sizeof (UINT32);
2159 return TRUE;
2160 }
2161
2162 if ( (PlistNodeCast (Node, PLIST_NODE_TYPE_TRUE) != NULL)
2163 || (PlistNodeCast (Node, PLIST_NODE_TYPE_FALSE) != NULL))
2164 {
2165 *Size = sizeof (UINT8);
2166 return TRUE;
2167 }
2168
2169 return FALSE;
2170}
UINT64 Start
UINT64 Length
DMG_SIZE_DEVICE_PATH Size
#define L_STR_LEN(String)
Definition OcStringLib.h:26
INTN IsAsciiSpace(IN CHAR8 Char)
Definition OcAsciiLib.c:65
#define L_STR_SIZE(String)
Definition OcStringLib.h:35
#define L_STR_SIZE_NT(String)
Definition OcStringLib.h:44
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
XML_NODE * XmlDocumentRoot(IN CONST XML_DOCUMENT *Document)
Definition OcXmlLib.c:1447
VOID XmlParserError(IN CONST XML_PARSER *Parser, IN XML_PARSER_OFFSET Offset, IN CONST CHAR8 *Message)
Definition OcXmlLib.c:466
STATIC XML_NODE * XmlNodeCreate(IN CONST CHAR8 *Name, IN CONST CHAR8 *Attributes OPTIONAL, IN CONST CHAR8 *Content OPTIONAL, IN XML_NODE *Real OPTIONAL, IN XML_NODE_LIST *Children OPTIONAL)
Definition OcXmlLib.c:202
STATIC BOOLEAN XmlParseAttributeNumber(IN CONST CHAR8 *Attributes, IN CONST CHAR8 *Argument, IN UINT32 ArgumentLength, OUT UINT32 *ArgumentValue)
Definition OcXmlLib.c:149
STATIC BOOLEAN XmlPushReference(IN OUT XML_REFLIST *References, IN XML_NODE *Node, IN UINT32 ReferenceNumber)
Definition OcXmlLib.c:317
STATIC CONST CHAR8 * XmlParseTagEnd(IN OUT XML_PARSER *Parser, OUT BOOLEAN *SelfClosing OPTIONAL, OUT CONST CHAR8 **Attributes OPTIONAL)
Definition OcXmlLib.c:658
BOOLEAN PlistDataSize(IN XML_NODE *Node OPTIONAL, OUT UINT32 *Size)
Definition OcXmlLib.c:2102
STATIC XML_NODE * XmlParseNode(IN OUT XML_PARSER *Parser, IN OUT XML_REFLIST *References OPTIONAL)
Definition OcXmlLib.c:1147
#define XML_PARSER_ERROR(Parser, Offset, Message)
Definition OcXmlLib.c:529
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
enum XML_PARSER_OFFSET_ XML_PARSER_OFFSET
#define XML_PARSER_INFO(Parser, Message)
Definition OcXmlLib.c:454
STATIC VOID XmlParserConsume(IN OUT XML_PARSER *Parser, IN UINT32 N)
Definition OcXmlLib.c:570
CONST CHAR8 * PlistNodeTypes[PLIST_NODE_TYPE_MAX]
Definition OcXmlLib.c:123
UINT32 XmlNodeChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1493
VOID XmlNodeRemoveByIndex(IN OUT XML_NODE *Node, IN UINT32 Index)
Definition OcXmlLib.c:1633
#define XML_EXPORT_MIN_ALLOCATION_SIZE
Definition OcXmlLib.c:53
XML_NODE *EFIAPI XmlEasyChild(IN OUT XML_NODE *Node, IN CONST CHAR8 *ChildName,...)
Definition OcXmlLib.c:1515
#define XML_USAGE_ERROR(X)
Definition OcXmlLib.c:530
#define XML_PLIST_HEADER
Definition OcXmlLib.c:55
CHAR8 * XmlDocumentExport(IN CONST XML_DOCUMENT *Document, OUT UINT32 *Length OPTIONAL, IN UINT32 Skip, IN BOOLEAN PrependPlistInfo)
Definition OcXmlLib.c:1367
STATIC CONST CHAR8 * XmlParseTagOpen(IN OUT XML_PARSER *Parser, OUT BOOLEAN *SelfClosing OPTIONAL, OUT CONST CHAR8 **Attributes)
Definition OcXmlLib.c:765
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1467
STATIC XML_NODE * XmlNodeReal(IN CONST XML_REFLIST *References OPTIONAL, IN CONST CHAR8 *Attributes OPTIONAL)
Definition OcXmlLib.c:374
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
XML_NODE * XmlNodeAppend(IN OUT XML_NODE *Node, IN CONST CHAR8 *Name, IN CONST CHAR8 *Attributes OPTIONAL, IN CONST CHAR8 *Content OPTIONAL)
Definition OcXmlLib.c:1581
CONST CHAR8 * XmlNodeName(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1457
STATIC VOID XmlSkipWhitespace(IN OUT XML_PARSER *Parser)
Definition OcXmlLib.c:628
STATIC VOID XmlBufferAppend(IN OUT CHAR8 **Buffer, IN OUT UINT32 *AllocSize, IN OUT UINT32 *CurrentSize, IN CONST CHAR8 *Data, IN UINT32 DataLength)
Definition OcXmlLib.c:1018
VOID XmlNodeRemove(IN OUT XML_NODE *Node, IN XML_NODE *ChildNode)
Definition OcXmlLib.c:1664
XML_NODE * XmlNodePrepend(IN OUT XML_NODE *Node, IN CONST CHAR8 *Name, IN CONST CHAR8 *Attributes, IN CONST CHAR8 *Content)
Definition OcXmlLib.c:1607
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
CONST CHAR8 * XmlUnescapeString(IN CONST CHAR8 *String)
Definition OcXmlLib.c:1687
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
STATIC CONST CHAR8 * XmlParseContent(IN OUT XML_PARSER *Parser)
Definition OcXmlLib.c:950
STATIC VOID XmlNodeFree(IN OUT XML_NODE *Node)
Definition OcXmlLib.c:407
XML_PARSER_OFFSET_
Definition OcXmlLib.c:113
@ NO_CHARACTER
Definition OcXmlLib.c:114
@ CURRENT_CHARACTER
Definition OcXmlLib.c:115
@ NEXT_CHARACTER
Definition OcXmlLib.c:116
STATIC VOID XmlNodeExportRecursive(IN CONST XML_NODE *Node, IN OUT CHAR8 **Buffer, IN OUT UINT32 *AllocSize, IN OUT UINT32 *CurrentSize, IN UINT32 Skip)
Definition OcXmlLib.c:1070
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
Definition OcXmlLib.c:1435
VOID XmlNodeChangeContent(IN OUT XML_NODE *Node, IN CONST CHAR8 *Content)
Definition OcXmlLib.c:1477
STATIC CHAR8 XmlParserPeek(IN CONST XML_PARSER *Parser, IN UINT32 N)
Definition OcXmlLib.c:543
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
STATIC BOOLEAN XmlNodeChildPush(IN OUT XML_NODE *Node, IN XML_NODE *Child)
Definition OcXmlLib.c:237
STATIC CONST CHAR8 * XmlParseTagClose(IN OUT XML_PARSER *Parser, IN BOOLEAN Unprefixed)
Definition OcXmlLib.c:890
STATIC VOID XmlFreeRefs(IN OUT XML_REFLIST *References)
Definition OcXmlLib.c:433
#define XML_PARSER_TAG(Parser, Tag)
Definition OcXmlLib.c:455
@ PLIST_NODE_TYPE_MAX
Definition OcXmlLib.h:100
@ PLIST_NODE_TYPE_DICT
Definition OcXmlLib.h:91
@ PLIST_NODE_TYPE_REAL
Definition OcXmlLib.h:98
@ PLIST_NODE_TYPE_DATA
Definition OcXmlLib.h:94
@ PLIST_NODE_TYPE_STRING
Definition OcXmlLib.h:93
@ PLIST_NODE_TYPE_KEY
Definition OcXmlLib.h:92
@ PLIST_NODE_TYPE_FALSE
Definition OcXmlLib.h:97
@ PLIST_NODE_TYPE_ARRAY
Definition OcXmlLib.h:90
@ PLIST_NODE_TYPE_INTEGER
Definition OcXmlLib.h:99
@ PLIST_NODE_TYPE_TRUE
Definition OcXmlLib.h:96
@ PLIST_NODE_TYPE_ANY
Definition OcXmlLib.h:89
#define XML_PARSER_MAX_SIZE
Definition OcXmlLib.h:76
#define XML_PARSER_NODE_COUNT
Definition OcXmlLib.h:60
#define XML_PARSER_MAX_REFERENCE_COUNT
Definition OcXmlLib.h:68
#define XML_PARSER_NEST_LEVEL
Definition OcXmlLib.h:52
enum PLIST_NODE_TYPE_ PLIST_NODE_TYPE
BOOLEAN HasChildren(IN EFI_HANDLE ControllerHandle)
Definition Partition.c:1367
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
#define N
Definition lzss.c:65
UINT32 Length
Definition OcXmlLib.c:93
XML_REFLIST References
Definition OcXmlLib.c:97
XML_NODE * Root
Definition OcXmlLib.c:96
CHAR8 * Buffer
Definition OcXmlLib.c:92
CONST CHAR8 * Content
Definition OcXmlLib.c:70
CONST CHAR8 * Name
Definition OcXmlLib.c:68
CONST CHAR8 * Attributes
Definition OcXmlLib.c:69
XML_NODE * Real
Definition OcXmlLib.c:71
XML_NODE_LIST * Children
Definition OcXmlLib.c:72
UINT32 AllocCount
Definition OcXmlLib.c:77
UINT32 NodeCount
Definition OcXmlLib.c:76
XML_NODE * NodeList[]
Definition OcXmlLib.c:78
CHAR8 * Buffer
Definition OcXmlLib.c:104
UINT32 Length
Definition OcXmlLib.c:106
UINT32 Position
Definition OcXmlLib.c:105
UINT32 Level
Definition OcXmlLib.c:107
UINT32 RefAllocCount
Definition OcXmlLib.c:83
UINT32 RefCount
Definition OcXmlLib.c:82
XML_NODE ** RefList
Definition OcXmlLib.c:84