]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/ParseUpdateProfile.c
IntelFrameworkModulePkg: Add UpdateDriverDxe driver
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / UpdateDriverDxe / ParseUpdateProfile.c
1 /** @file
2 Source file for the component update driver. It parse the update
3 configuration file and pass the information to the update driver
4 so that the driver can perform updates accordingly.
5
6 Copyright (c) 2002 - 2010, Intel Corporation. All rights reserved.<BR>
7
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions
10 of the BSD License which accompanies this distribution. The
11 full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include "UpdateDriver.h"
20
21 /**
22 Copy one line data from buffer data to the line buffer.
23
24 @param Buffer Buffer data.
25 @param BufferSize Buffer Size.
26 @param LineBuffer Line buffer to store the found line data.
27 @param LineSize On input, size of the input line buffer.
28 On output, size of the actual line buffer.
29
30 @retval EFI_BUFFER_TOO_SMALL The size of input line buffer is not enough.
31 @retval EFI_SUCCESS Copy line data into the line buffer.
32
33 **/
34 EFI_STATUS
35 ProfileGetLine (
36 IN UINT8 *Buffer,
37 IN UINTN BufferSize,
38 IN OUT UINT8 *LineBuffer,
39 IN OUT UINTN *LineSize
40 )
41 {
42 UINTN Length;
43 UINT8 *PtrBuf;
44 UINTN PtrEnd;
45
46 PtrBuf = Buffer;
47 PtrEnd = (UINTN)Buffer + BufferSize;
48
49 //
50 // 0x0D indicates a line break. Otherwise there is no line break
51 //
52 while ((UINTN)PtrBuf < PtrEnd) {
53 if (*PtrBuf == 0x0D) {
54 break;
55 }
56 PtrBuf++;
57 }
58
59 if ((UINTN)PtrBuf >= (PtrEnd - 1)) {
60 //
61 // The buffer ends without any line break
62 // or it is the last character of the buffer
63 //
64 Length = BufferSize;
65 } else if (*(PtrBuf + 1) == 0x0A) {
66 //
67 // Further check if a 0x0A follows. If yes, count 0xA
68 //
69 Length = (UINTN) PtrBuf - (UINTN) Buffer + 2;
70 } else {
71 Length = (UINTN) PtrBuf - (UINTN) Buffer + 1;
72 }
73
74 if (Length > (*LineSize)) {
75 *LineSize = Length;
76 return EFI_BUFFER_TOO_SMALL;
77 }
78
79 SetMem (LineBuffer, *LineSize, 0x0);
80 *LineSize = Length;
81 CopyMem (LineBuffer, Buffer, Length);
82
83 return EFI_SUCCESS;
84 }
85
86 /**
87 Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.
88
89 @param Buffer On input, buffer data to be trimed.
90 On output, the trimmed buffer.
91 @param BufferSize On input, size of original buffer data.
92 On output, size of the trimmed buffer.
93
94 **/
95 VOID
96 ProfileTrim (
97 IN OUT UINT8 *Buffer,
98 IN OUT UINTN *BufferSize
99 )
100 {
101 UINTN Length;
102 UINT8 *PtrBuf;
103 UINT8 *PtrEnd;
104
105 if (*BufferSize == 0) {
106 return;
107 }
108
109 //
110 // Trim the tail first, include CR, LF, TAB, and SPACE.
111 //
112 Length = *BufferSize;
113 PtrBuf = (UINT8 *) ((UINTN) Buffer + Length - 1);
114 while (PtrBuf >= Buffer) {
115 if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
116 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
117 break;
118 }
119 PtrBuf --;
120 }
121
122 //
123 // all spaces, a blank line, return directly;
124 //
125 if (PtrBuf < Buffer) {
126 *BufferSize = 0;
127 return;
128 }
129
130 Length = (UINTN)PtrBuf - (UINTN)Buffer + 1;
131 PtrEnd = PtrBuf;
132 PtrBuf = Buffer;
133
134 //
135 // Now skip the heading CR, LF, TAB and SPACE
136 //
137 while (PtrBuf <= PtrEnd) {
138 if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
139 && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
140 break;
141 }
142 PtrBuf++;
143 }
144
145 //
146 // If no heading CR, LF, TAB or SPACE, directly return
147 //
148 if (PtrBuf == Buffer) {
149 *BufferSize = Length;
150 return;
151 }
152
153 *BufferSize = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;
154
155 //
156 // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.
157 // Now move out all these characters.
158 //
159 while (PtrBuf <= PtrEnd) {
160 *Buffer = *PtrBuf;
161 Buffer++;
162 PtrBuf++;
163 }
164
165 return;
166 }
167
168 /**
169 Insert new comment item into comment head.
170
171 @param Buffer Comment buffer to be added.
172 @param BufferSize Size of comment buffer.
173 @param CommentHead Comment Item head entry.
174
175 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
176 @retval EFI_SUCCESS New comment item is inserted.
177
178 **/
179 EFI_STATUS
180 ProfileGetComments (
181 IN UINT8 *Buffer,
182 IN UINTN BufferSize,
183 IN OUT COMMENT_LINE **CommentHead
184 )
185 {
186 COMMENT_LINE *CommentItem;
187
188 CommentItem = NULL;
189 CommentItem = AllocatePool (sizeof (COMMENT_LINE));
190 if (CommentItem == NULL) {
191 return EFI_OUT_OF_RESOURCES;
192 }
193
194 CommentItem->ptrNext = *CommentHead;
195 *CommentHead = CommentItem;
196
197 //
198 // Add a trailing '\0'
199 //
200 CommentItem->ptrComment = AllocatePool (BufferSize + 1);
201 if (CommentItem->ptrComment == NULL) {
202 FreePool (CommentItem);
203 return EFI_OUT_OF_RESOURCES;
204 }
205 CopyMem (CommentItem->ptrComment, Buffer, BufferSize);
206 *(CommentItem->ptrComment + BufferSize) = '\0';
207
208 return EFI_SUCCESS;
209 }
210
211 /**
212 Add new section item into Section head.
213
214 @param Buffer Section item data buffer.
215 @param BufferSize Size of section item.
216 @param SectionHead Section item head entry.
217
218 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
219 @retval EFI_SUCCESS Section item is NULL or Section item is added.
220
221 **/
222 EFI_STATUS
223 ProfileGetSection (
224 IN UINT8 *Buffer,
225 IN UINTN BufferSize,
226 IN OUT SECTION_ITEM **SectionHead
227 )
228 {
229 EFI_STATUS Status;
230 SECTION_ITEM *SectionItem;
231 UINTN Length;
232 UINT8 *PtrBuf;
233
234 Status = EFI_SUCCESS;
235 //
236 // The first character of Buffer is '[', now we want for ']'
237 //
238 PtrBuf = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
239 while (PtrBuf > Buffer) {
240 if (*PtrBuf == ']') {
241 break;
242 }
243 PtrBuf --;
244 }
245 if (PtrBuf <= Buffer) {
246 //
247 // Not found. Omit this line
248 //
249 return Status;
250 }
251
252 //
253 // excluding the heading '[' and tailing ']'
254 //
255 Length = PtrBuf - Buffer - 1;
256 ProfileTrim (
257 Buffer + 1,
258 &Length
259 );
260
261 //
262 // omit this line if the section name is null
263 //
264 if (Length == 0) {
265 return Status;
266 }
267
268 SectionItem = AllocatePool (sizeof (SECTION_ITEM));
269 if (SectionItem == NULL) {
270 return EFI_OUT_OF_RESOURCES;
271 }
272
273 SectionItem->ptrSection = NULL;
274 SectionItem->SecNameLen = Length;
275 SectionItem->ptrEntry = NULL;
276 SectionItem->ptrValue = NULL;
277 SectionItem->ptrNext = *SectionHead;
278 *SectionHead = SectionItem;
279
280 //
281 // Add a trailing '\0'
282 //
283 SectionItem->ptrSection = AllocatePool (Length + 1);
284 if (SectionItem->ptrSection == NULL) {
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 //
289 // excluding the heading '['
290 //
291 CopyMem (SectionItem->ptrSection, Buffer + 1, Length);
292 *(SectionItem->ptrSection + Length) = '\0';
293
294 return EFI_SUCCESS;
295 }
296
297 /**
298 Add new section entry and entry value into Section head.
299
300 @param Buffer Section entry data buffer.
301 @param BufferSize Size of section entry.
302 @param SectionHead Section item head entry.
303
304 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
305 @retval EFI_SUCCESS Section entry is NULL or Section entry is added.
306
307 **/
308 EFI_STATUS
309 ProfileGetEntry (
310 IN UINT8 *Buffer,
311 IN UINTN BufferSize,
312 IN OUT SECTION_ITEM **SectionHead
313 )
314 {
315 EFI_STATUS Status;
316 SECTION_ITEM *SectionItem;
317 SECTION_ITEM *PtrSection;
318 UINTN Length;
319 UINT8 *PtrBuf;
320 UINT8 *PtrEnd;
321
322 Status = EFI_SUCCESS;
323 PtrBuf = Buffer;
324 PtrEnd = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);
325
326 //
327 // First search for '='
328 //
329 while (PtrBuf <= PtrEnd) {
330 if (*PtrBuf == '=') {
331 break;
332 }
333 PtrBuf++;
334 }
335 if (PtrBuf > PtrEnd) {
336 //
337 // Not found. Omit this line
338 //
339 return Status;
340 }
341
342 //
343 // excluding the tailing '='
344 //
345 Length = PtrBuf - Buffer;
346 ProfileTrim (
347 Buffer,
348 &Length
349 );
350
351 //
352 // Omit this line if the entry name is null
353 //
354 if (Length == 0) {
355 return Status;
356 }
357
358 //
359 // Omit this line if no section header has been found before
360 //
361 if (*SectionHead == NULL) {
362 return Status;
363 }
364 PtrSection = *SectionHead;
365
366 SectionItem = AllocatePool (sizeof (SECTION_ITEM));
367 if (SectionItem == NULL) {
368 return EFI_OUT_OF_RESOURCES;
369 }
370
371 SectionItem->ptrSection = NULL;
372 SectionItem->ptrEntry = NULL;
373 SectionItem->ptrValue = NULL;
374 SectionItem->SecNameLen = PtrSection->SecNameLen;
375 SectionItem->ptrNext = *SectionHead;
376 *SectionHead = SectionItem;
377
378 //
379 // SectionName, add a trailing '\0'
380 //
381 SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);
382 if (SectionItem->ptrSection == NULL) {
383 return EFI_OUT_OF_RESOURCES;
384 }
385 CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);
386
387 //
388 // EntryName, add a trailing '\0'
389 //
390 SectionItem->ptrEntry = AllocatePool (Length + 1);
391 if (SectionItem->ptrEntry == NULL) {
392 return EFI_OUT_OF_RESOURCES;
393 }
394 CopyMem (SectionItem->ptrEntry, Buffer, Length);
395 *(SectionItem->ptrEntry + Length) = '\0';
396
397 //
398 // Next search for '#'
399 //
400 PtrBuf = PtrBuf + 1;
401 Buffer = PtrBuf;
402 while (PtrBuf <= PtrEnd) {
403 if (*PtrBuf == '#') {
404 break;
405 }
406 PtrBuf++;
407 }
408 Length = PtrBuf - Buffer;
409 ProfileTrim (
410 Buffer,
411 &Length
412 );
413
414 if (Length > 0) {
415 //
416 // EntryValue, add a trailing '\0'
417 //
418 SectionItem->ptrValue = AllocatePool (Length + 1);
419 if (SectionItem->ptrValue == NULL) {
420 return EFI_OUT_OF_RESOURCES;
421 }
422 CopyMem (SectionItem->ptrValue, Buffer, Length);
423 *(SectionItem->ptrValue + Length) = '\0';
424 }
425
426 return EFI_SUCCESS;
427 }
428
429 /**
430 Free all comment entry and section entry.
431
432 @param Section Section entry list.
433 @param Comment Comment entry list.
434
435 **/
436 VOID
437 FreeAllList (
438 IN SECTION_ITEM *Section,
439 IN COMMENT_LINE *Comment
440 )
441 {
442 SECTION_ITEM *PtrSection;
443 COMMENT_LINE *PtrComment;
444
445 while (Section != NULL) {
446 PtrSection = Section;
447 Section = Section->ptrNext;
448 if (PtrSection->ptrEntry != NULL) {
449 FreePool (PtrSection->ptrEntry);
450 }
451 if (PtrSection->ptrSection != NULL) {
452 FreePool (PtrSection->ptrSection);
453 }
454 if (PtrSection->ptrValue != NULL) {
455 FreePool (PtrSection->ptrValue);
456 }
457 FreePool (PtrSection);
458 }
459
460 while (Comment != NULL) {
461 PtrComment = Comment;
462 Comment = Comment->ptrNext;
463 if (PtrComment->ptrComment != NULL) {
464 FreePool (PtrComment->ptrComment);
465 }
466 FreePool (PtrComment);
467 }
468
469 return;
470 }
471
472 /**
473 Get section entry value.
474
475 @param Section Section entry list.
476 @param SectionName Section name.
477 @param EntryName Section entry name.
478 @param EntryValue Point to the got entry value.
479
480 @retval EFI_NOT_FOUND Section is not found.
481 @retval EFI_SUCCESS Section entry value is got.
482
483 **/
484 EFI_STATUS
485 UpdateGetProfileString (
486 IN SECTION_ITEM *Section,
487 IN UINT8 *SectionName,
488 IN UINT8 *EntryName,
489 OUT UINT8 **EntryValue
490 )
491 {
492 *EntryValue = NULL;
493
494 while (Section != NULL) {
495 if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {
496 if (Section->ptrEntry != NULL) {
497 if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {
498 break;
499 }
500 }
501 }
502 Section = Section->ptrNext;
503 }
504
505 if (Section == NULL) {
506 return EFI_NOT_FOUND;
507 }
508
509 *EntryValue = (UINT8 *) Section->ptrValue;
510
511 return EFI_SUCCESS;
512 }
513
514 /**
515 Convert the dec or hex ascii string to value.
516
517 @param Str ascii string to be converted.
518
519 @return the converted value.
520
521 **/
522 UINTN
523 UpdateAtoi (
524 IN UINT8 *Str
525 )
526 {
527 UINTN Number;
528
529 Number = 0;
530
531 //
532 // Skip preceeding while spaces
533 //
534 while (*Str != '\0') {
535 if (*Str != 0x20) {
536 break;
537 }
538 Str++;
539 }
540
541 if (*Str == '\0') {
542 return Number;
543 }
544
545 //
546 // Find whether the string is prefixed by 0x.
547 // That is, it should be xtoi or atoi.
548 //
549 if (*Str == '0') {
550 if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) {
551 return AsciiStrHexToUintn ((CONST CHAR8 *) Str);
552 }
553 }
554
555 while (*Str != '\0') {
556 if ((*Str >= '0') && (*Str <= '9')) {
557 Number = Number * 10 + *Str - '0';
558 } else {
559 break;
560 }
561 Str++;
562 }
563
564 return Number;
565 }
566
567 /**
568 Converts a decimal value to a Null-terminated ascii string.
569
570 @param Buffer Pointer to the output buffer for the produced Null-terminated
571 ASCII string.
572 @param Value The 64-bit sgned value to convert to a string.
573
574 @return The number of ASCII characters in Buffer not including the Null-terminator.
575
576 **/
577 UINTN
578 UpdateValueToString (
579 IN OUT UINT8 *Buffer,
580 IN INT64 Value
581 )
582 {
583 UINT8 TempBuffer[30];
584 UINT8 *TempStr;
585 UINT8 *BufferPtr;
586 UINTN Count;
587 UINT32 Remainder;
588
589 TempStr = TempBuffer;
590 BufferPtr = Buffer;
591 Count = 0;
592
593 if (Value < 0) {
594 *BufferPtr = '-';
595 BufferPtr++;
596 Value = -Value;
597 Count++;
598 }
599
600 do {
601 Value = (INT64) DivU64x32Remainder ((UINT64)Value, 10, &Remainder);
602 //
603 // The first item of TempStr is not occupied. It's kind of flag
604 //
605 TempStr++;
606 Count++;
607 *TempStr = (UINT8) ((UINT8)Remainder + '0');
608 } while (Value != 0);
609
610 //
611 // Reverse temp string into Buffer.
612 //
613 while (TempStr != TempBuffer) {
614 *BufferPtr = *TempStr;
615 BufferPtr++;
616 TempStr --;
617 }
618
619 *BufferPtr = 0;
620
621 return Count;
622 }
623
624 /**
625 Convert the input value to a ascii string,
626 and concatenates this string to the input string.
627
628 @param Str Pointer to a Null-terminated ASCII string.
629 @param Number The unsgned value to convert to a string.
630
631 **/
632 VOID
633 UpdateStrCatNumber (
634 IN OUT UINT8 *Str,
635 IN UINTN Number
636 )
637 {
638 UINTN Count;
639
640 while (*Str != '\0') {
641 Str++;
642 }
643
644 Count = UpdateValueToString (Str, (INT64)Number);
645
646 *(Str + Count) = '\0';
647
648 return;
649 }
650
651 /**
652 Convert the input ascii string into GUID value.
653
654 @param Str Ascii GUID string to be converted.
655 @param Guid Pointer to the converted GUID value.
656
657 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
658 @retval EFI_NOT_FOUND The input ascii string is not a valid GUID format string.
659 @retval EFI_SUCCESS GUID value is got.
660
661 **/
662 EFI_STATUS
663 UpdateStringToGuid (
664 IN UINT8 *Str,
665 IN OUT EFI_GUID *Guid
666 )
667 {
668 UINT8 *PtrBuffer;
669 UINT8 *PtrPosition;
670 UINT8 *Buffer;
671 UINTN Data;
672 UINTN StrLen;
673 UINTN Index;
674 UINT8 Digits[3];
675
676 StrLen = AsciiStrLen ((CONST CHAR8 *) Str);
677 Buffer = AllocatePool (StrLen + 1);
678 if (Buffer == NULL) {
679 return EFI_OUT_OF_RESOURCES;
680 }
681 AsciiStrCpy ((CHAR8 *)Buffer, (CHAR8 *)Str);
682
683 //
684 // Data1
685 //
686 PtrBuffer = Buffer;
687 PtrPosition = PtrBuffer;
688 while (*PtrBuffer != '\0') {
689 if (*PtrBuffer == '-') {
690 break;
691 }
692 PtrBuffer++;
693 }
694 if (*PtrBuffer == '\0') {
695 FreePool (Buffer);
696 return EFI_NOT_FOUND;
697 }
698
699 *PtrBuffer = '\0';
700 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
701 Guid->Data1 = (UINT32)Data;
702
703 //
704 // Data2
705 //
706 PtrBuffer++;
707 PtrPosition = PtrBuffer;
708 while (*PtrBuffer != '\0') {
709 if (*PtrBuffer == '-') {
710 break;
711 }
712 PtrBuffer++;
713 }
714 if (*PtrBuffer == '\0') {
715 FreePool (Buffer);
716 return EFI_NOT_FOUND;
717 }
718 *PtrBuffer = '\0';
719 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
720 Guid->Data2 = (UINT16)Data;
721
722 //
723 // Data3
724 //
725 PtrBuffer++;
726 PtrPosition = PtrBuffer;
727 while (*PtrBuffer != '\0') {
728 if (*PtrBuffer == '-') {
729 break;
730 }
731 PtrBuffer++;
732 }
733 if (*PtrBuffer == '\0') {
734 FreePool (Buffer);
735 return EFI_NOT_FOUND;
736 }
737 *PtrBuffer = '\0';
738 Data = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
739 Guid->Data3 = (UINT16)Data;
740
741 //
742 // Data4[0..1]
743 //
744 for ( Index = 0 ; Index < 2 ; Index++) {
745 PtrBuffer++;
746 if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
747 FreePool (Buffer);
748 return EFI_NOT_FOUND;
749 }
750 Digits[0] = *PtrBuffer;
751 PtrBuffer++;
752 Digits[1] = *PtrBuffer;
753 Digits[2] = '\0';
754 Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
755 Guid->Data4[Index] = (UINT8)Data;
756 }
757
758 //
759 // skip the '-'
760 //
761 PtrBuffer++;
762 if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) {
763 return EFI_NOT_FOUND;
764 }
765
766 //
767 // Data4[2..7]
768 //
769 for ( ; Index < 8; Index++) {
770 PtrBuffer++;
771 if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
772 FreePool (Buffer);
773 return EFI_NOT_FOUND;
774 }
775 Digits[0] = *PtrBuffer;
776 PtrBuffer++;
777 Digits[1] = *PtrBuffer;
778 Digits[2] = '\0';
779 Data = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
780 Guid->Data4[Index] = (UINT8)Data;
781 }
782
783 FreePool (Buffer);
784
785 return EFI_SUCCESS;
786 }
787
788 /**
789 Pre process config data buffer into Section entry list and Comment entry list.
790
791 @param DataBuffer Config raw file buffer.
792 @param BufferSize Size of raw buffer.
793 @param SectionHead Pointer to the section entry list.
794 @param CommentHead Pointer to the comment entry list.
795
796 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
797 @retval EFI_SUCCESS Config data buffer is preprocessed.
798
799 **/
800 EFI_STATUS
801 PreProcessDataFile (
802 IN UINT8 *DataBuffer,
803 IN UINTN BufferSize,
804 IN OUT SECTION_ITEM **SectionHead,
805 IN OUT COMMENT_LINE **CommentHead
806 )
807 {
808 EFI_STATUS Status;
809 CHAR8 *Source;
810 CHAR8 *CurrentPtr;
811 CHAR8 *BufferEnd;
812 CHAR8 *PtrLine;
813 UINTN LineLength;
814 UINTN SourceLength;
815 UINTN MaxLineLength;
816
817 *SectionHead = NULL;
818 *CommentHead = NULL;
819 BufferEnd = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
820 CurrentPtr = (CHAR8 *) DataBuffer;
821 MaxLineLength = MAX_LINE_LENGTH;
822 Status = EFI_SUCCESS;
823
824 PtrLine = AllocatePool (MaxLineLength);
825 if (PtrLine == NULL) {
826 return EFI_OUT_OF_RESOURCES;
827 }
828
829 while (CurrentPtr < BufferEnd) {
830 Source = CurrentPtr;
831 SourceLength = (UINTN)BufferEnd - (UINTN)CurrentPtr;
832 LineLength = MaxLineLength;
833 //
834 // With the assumption that line length is less than 512
835 // characters. Otherwise BUFFER_TOO_SMALL will be returned.
836 //
837 Status = ProfileGetLine (
838 (UINT8 *) Source,
839 SourceLength,
840 (UINT8 *) PtrLine,
841 &LineLength
842 );
843 if (EFI_ERROR (Status)) {
844 if (Status == EFI_BUFFER_TOO_SMALL) {
845 //
846 // If buffer too small, re-allocate the buffer according
847 // to the returned LineLength and try again.
848 //
849 FreePool (PtrLine);
850 PtrLine = NULL;
851 PtrLine = AllocatePool (LineLength);
852 if (PtrLine == NULL) {
853 Status = EFI_OUT_OF_RESOURCES;
854 break;
855 }
856 SourceLength = LineLength;
857 Status = ProfileGetLine (
858 (UINT8 *) Source,
859 SourceLength,
860 (UINT8 *) PtrLine,
861 &LineLength
862 );
863 if (EFI_ERROR (Status)) {
864 break;
865 }
866 MaxLineLength = LineLength;
867 } else {
868 break;
869 }
870 }
871 CurrentPtr = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
872
873 //
874 // Line got. Trim the line before processing it.
875 //
876 ProfileTrim (
877 (UINT8 *) PtrLine,
878 &LineLength
879 );
880
881 //
882 // Blank line
883 //
884 if (LineLength == 0) {
885 continue;
886 }
887
888 if (PtrLine[0] == '#') {
889 Status = ProfileGetComments (
890 (UINT8 *) PtrLine,
891 LineLength,
892 CommentHead
893 );
894 } else if (PtrLine[0] == '[') {
895 Status = ProfileGetSection (
896 (UINT8 *) PtrLine,
897 LineLength,
898 SectionHead
899 );
900 } else {
901 Status = ProfileGetEntry (
902 (UINT8 *) PtrLine,
903 LineLength,
904 SectionHead
905 );
906 }
907
908 if (EFI_ERROR (Status)) {
909 break;
910 }
911 }
912
913 //
914 // Free buffer
915 //
916 FreePool (PtrLine);
917
918 return Status;
919 }
920
921 /**
922 Parse Config data file to get the updated data array.
923
924 @param DataBuffer Config raw file buffer.
925 @param BufferSize Size of raw buffer.
926 @param NumOfUpdates Pointer to the number of update data.
927 @param UpdateArray Pointer to the config of update data.
928
929 @retval EFI_NOT_FOUND No config data is found.
930 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
931 @retval EFI_SUCCESS Parse the config file successfully.
932
933 **/
934 EFI_STATUS
935 ParseUpdateDataFile (
936 IN UINT8 *DataBuffer,
937 IN UINTN BufferSize,
938 IN OUT UINTN *NumOfUpdates,
939 IN OUT UPDATE_CONFIG_DATA **UpdateArray
940 )
941 {
942 EFI_STATUS Status;
943 CHAR8 *Value;
944 CHAR8 *SectionName;
945 CHAR8 Entry[MAX_LINE_LENGTH];
946 SECTION_ITEM *SectionHead;
947 COMMENT_LINE *CommentHead;
948 UINTN Num;
949 UINTN Index;
950 EFI_GUID FileGuid;
951
952 SectionHead = NULL;
953 CommentHead = NULL;
954
955 //
956 // First process the data buffer and get all sections and entries
957 //
958 Status = PreProcessDataFile (
959 DataBuffer,
960 BufferSize,
961 &SectionHead,
962 &CommentHead
963 );
964 if (EFI_ERROR (Status)) {
965 FreeAllList (SectionHead, CommentHead);
966 return Status;
967 }
968
969 //
970 // Now get NumOfUpdate
971 //
972 Value = NULL;
973 Status = UpdateGetProfileString (
974 SectionHead,
975 (UINT8 *) "Head",
976 (UINT8 *) "NumOfUpdate",
977 (UINT8 **) &Value
978 );
979 if (Value == NULL) {
980 FreeAllList (SectionHead, CommentHead);
981 return EFI_NOT_FOUND;
982 }
983 Num = UpdateAtoi((UINT8 *) Value);
984 if (Num <= 0) {
985 FreeAllList (SectionHead, CommentHead);
986 return EFI_NOT_FOUND;
987 }
988
989 *NumOfUpdates = Num;
990 *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num));
991 if (*UpdateArray == NULL) {
992 FreeAllList (SectionHead, CommentHead);
993 return EFI_OUT_OF_RESOURCES;
994 }
995
996 for ( Index = 0 ; Index < *NumOfUpdates ; Index++) {
997 //
998 // Get the section name of each update
999 //
1000 AsciiStrCpy (Entry, "Update");
1001 UpdateStrCatNumber ((UINT8 *) Entry, Index);
1002 Value = NULL;
1003 Status = UpdateGetProfileString (
1004 SectionHead,
1005 (UINT8 *) "Head",
1006 (UINT8 *) Entry,
1007 (UINT8 **) &Value
1008 );
1009 if (Value == NULL) {
1010 FreeAllList (SectionHead, CommentHead);
1011 return EFI_NOT_FOUND;
1012 }
1013
1014 //
1015 // The section name of this update has been found.
1016 // Now looks for all the config data of this update
1017 //
1018 SectionName = Value;
1019
1020 //
1021 // UpdateType
1022 //
1023 Value = NULL;
1024 Status = UpdateGetProfileString (
1025 SectionHead,
1026 (UINT8 *) SectionName,
1027 (UINT8 *) "UpdateType",
1028 (UINT8 **) &Value
1029 );
1030 if (Value == NULL) {
1031 FreeAllList (SectionHead, CommentHead);
1032 return EFI_NOT_FOUND;
1033 }
1034
1035 Num = UpdateAtoi((UINT8 *) Value);
1036 if (( Num >= (UINTN) UpdateOperationMaximum)) {
1037 FreeAllList (SectionHead, CommentHead);
1038 return Status;
1039 }
1040 (*UpdateArray)[Index].Index = Index;
1041 (*UpdateArray)[Index].UpdateType = (UPDATE_OPERATION_TYPE) Num;
1042
1043 //
1044 // FvBaseAddress
1045 //
1046 Value = NULL;
1047 Status = UpdateGetProfileString (
1048 SectionHead,
1049 (UINT8 *) SectionName,
1050 (UINT8 *) "FvBaseAddress",
1051 (UINT8 **) &Value
1052 );
1053 if (Value == NULL) {
1054 FreeAllList (SectionHead, CommentHead);
1055 return EFI_NOT_FOUND;
1056 }
1057
1058 Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
1059 (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num;
1060
1061 //
1062 // FileBuid
1063 //
1064 Value = NULL;
1065 Status = UpdateGetProfileString (
1066 SectionHead,
1067 (UINT8 *) SectionName,
1068 (UINT8 *) "FileGuid",
1069 (UINT8 **) &Value
1070 );
1071 if (Value == NULL) {
1072 FreeAllList (SectionHead, CommentHead);
1073 return EFI_NOT_FOUND;
1074 }
1075
1076 Status = UpdateStringToGuid ((UINT8 *) Value, &FileGuid);
1077 if (EFI_ERROR (Status)) {
1078 FreeAllList (SectionHead, CommentHead);
1079 return Status;
1080 }
1081 CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
1082
1083 //
1084 // FaultTolerant
1085 // Default value is FALSE
1086 //
1087 Value = NULL;
1088 (*UpdateArray)[Index].FaultTolerant = FALSE;
1089 Status = UpdateGetProfileString (
1090 SectionHead,
1091 (UINT8 *) SectionName,
1092 (UINT8 *) "FaultTolerant",
1093 (UINT8 **) &Value
1094 );
1095 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1096 FreeAllList (SectionHead, CommentHead);
1097 return Status;
1098 } else if (Value != NULL) {
1099 if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) {
1100 (*UpdateArray)[Index].FaultTolerant = TRUE;
1101 } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) {
1102 (*UpdateArray)[Index].FaultTolerant = FALSE;
1103 }
1104 }
1105
1106 if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) {
1107 //
1108 // Length
1109 //
1110 Value = NULL;
1111 Status = UpdateGetProfileString (
1112 SectionHead,
1113 (UINT8 *) SectionName,
1114 (UINT8 *) "Length",
1115 (UINT8 **) &Value
1116 );
1117 if (Value == NULL) {
1118 FreeAllList (SectionHead, CommentHead);
1119 return EFI_NOT_FOUND;
1120 }
1121
1122 Num = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
1123 (*UpdateArray)[Index].Length = (UINTN) Num;
1124 }
1125 }
1126
1127 //
1128 // Now all configuration data got. Free those temporary buffers
1129 //
1130 FreeAllList (SectionHead, CommentHead);
1131
1132 return EFI_SUCCESS;
1133 }
1134