• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 - 2015, 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
ProfileGetLine(IN UINT8 * Buffer,IN UINTN BufferSize,IN OUT UINT8 * LineBuffer,IN OUT UINTN * LineSize)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
ProfileTrim(IN OUT UINT8 * Buffer,IN OUT UINTN * BufferSize)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
ProfileGetComments(IN UINT8 * Buffer,IN UINTN BufferSize,IN OUT COMMENT_LINE ** CommentHead)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
ProfileGetSection(IN UINT8 * Buffer,IN UINTN BufferSize,IN OUT SECTION_ITEM ** SectionHead)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
ProfileGetEntry(IN UINT8 * Buffer,IN UINTN BufferSize,IN OUT SECTION_ITEM ** SectionHead)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
FreeAllList(IN SECTION_ITEM * Section,IN COMMENT_LINE * Comment)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
UpdateGetProfileString(IN SECTION_ITEM * Section,IN UINT8 * SectionName,IN UINT8 * EntryName,OUT UINT8 ** EntryValue)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
UpdateAtoi(IN UINT8 * Str)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
UpdateValueToString(IN OUT UINT8 * Buffer,IN INT64 Value)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
UpdateStrCatNumber(IN OUT UINT8 * Str,IN UINTN Number)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
UpdateStringToGuid(IN UINT8 * Str,IN OUT EFI_GUID * Guid)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          = AllocateCopyPool (StrLen + 1, Str);
678   if (Buffer == NULL) {
679     return EFI_OUT_OF_RESOURCES;
680   }
681 
682   //
683   // Data1
684   //
685   PtrBuffer       = Buffer;
686   PtrPosition     = PtrBuffer;
687   while (*PtrBuffer != '\0') {
688     if (*PtrBuffer == '-') {
689       break;
690     }
691     PtrBuffer++;
692   }
693   if (*PtrBuffer == '\0') {
694     FreePool (Buffer);
695     return EFI_NOT_FOUND;
696   }
697 
698   *PtrBuffer      = '\0';
699   Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
700   Guid->Data1     = (UINT32)Data;
701 
702   //
703   // Data2
704   //
705   PtrBuffer++;
706   PtrPosition     = PtrBuffer;
707   while (*PtrBuffer != '\0') {
708     if (*PtrBuffer == '-') {
709       break;
710     }
711     PtrBuffer++;
712   }
713   if (*PtrBuffer == '\0') {
714     FreePool (Buffer);
715     return EFI_NOT_FOUND;
716   }
717   *PtrBuffer      = '\0';
718   Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
719   Guid->Data2     = (UINT16)Data;
720 
721   //
722   // Data3
723   //
724   PtrBuffer++;
725   PtrPosition     = PtrBuffer;
726   while (*PtrBuffer != '\0') {
727     if (*PtrBuffer == '-') {
728       break;
729     }
730     PtrBuffer++;
731   }
732   if (*PtrBuffer == '\0') {
733     FreePool (Buffer);
734     return EFI_NOT_FOUND;
735   }
736   *PtrBuffer      = '\0';
737   Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
738   Guid->Data3     = (UINT16)Data;
739 
740   //
741   // Data4[0..1]
742   //
743   for ( Index = 0 ; Index < 2 ; Index++) {
744     PtrBuffer++;
745     if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
746       FreePool (Buffer);
747       return EFI_NOT_FOUND;
748     }
749     Digits[0]     = *PtrBuffer;
750     PtrBuffer++;
751     Digits[1]     = *PtrBuffer;
752     Digits[2]     = '\0';
753     Data          = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
754     Guid->Data4[Index] = (UINT8)Data;
755   }
756 
757   //
758   // skip the '-'
759   //
760   PtrBuffer++;
761   if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) {
762     return EFI_NOT_FOUND;
763   }
764 
765   //
766   // Data4[2..7]
767   //
768   for ( ; Index < 8; Index++) {
769     PtrBuffer++;
770     if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
771       FreePool (Buffer);
772       return EFI_NOT_FOUND;
773     }
774     Digits[0]     = *PtrBuffer;
775     PtrBuffer++;
776     Digits[1]     = *PtrBuffer;
777     Digits[2]     = '\0';
778     Data          = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
779     Guid->Data4[Index] = (UINT8)Data;
780   }
781 
782   FreePool (Buffer);
783 
784   return EFI_SUCCESS;
785 }
786 
787 /**
788   Pre process config data buffer into Section entry list and Comment entry list.
789 
790   @param DataBuffer      Config raw file buffer.
791   @param BufferSize      Size of raw buffer.
792   @param SectionHead     Pointer to the section entry list.
793   @param CommentHead     Pointer to the comment entry list.
794 
795   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
796   @retval EFI_SUCCESS           Config data buffer is preprocessed.
797 
798 **/
799 EFI_STATUS
PreProcessDataFile(IN UINT8 * DataBuffer,IN UINTN BufferSize,IN OUT SECTION_ITEM ** SectionHead,IN OUT COMMENT_LINE ** CommentHead)800 PreProcessDataFile (
801   IN      UINT8                         *DataBuffer,
802   IN      UINTN                         BufferSize,
803   IN OUT  SECTION_ITEM                  **SectionHead,
804   IN OUT  COMMENT_LINE                  **CommentHead
805   )
806 {
807   EFI_STATUS                            Status;
808   CHAR8                                 *Source;
809   CHAR8                                 *CurrentPtr;
810   CHAR8                                 *BufferEnd;
811   CHAR8                                 *PtrLine;
812   UINTN                                 LineLength;
813   UINTN                                 SourceLength;
814   UINTN                                 MaxLineLength;
815 
816   *SectionHead          = NULL;
817   *CommentHead          = NULL;
818   BufferEnd             = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
819   CurrentPtr            = (CHAR8 *) DataBuffer;
820   MaxLineLength         = MAX_LINE_LENGTH;
821   Status                = EFI_SUCCESS;
822 
823   PtrLine = AllocatePool (MaxLineLength);
824   if (PtrLine == NULL) {
825     return EFI_OUT_OF_RESOURCES;
826   }
827 
828   while (CurrentPtr < BufferEnd) {
829     Source              = CurrentPtr;
830     SourceLength        = (UINTN)BufferEnd - (UINTN)CurrentPtr;
831     LineLength          = MaxLineLength;
832     //
833     // With the assumption that line length is less than 512
834     // characters. Otherwise BUFFER_TOO_SMALL will be returned.
835     //
836     Status              = ProfileGetLine (
837                             (UINT8 *) Source,
838                             SourceLength,
839                             (UINT8 *) PtrLine,
840                             &LineLength
841                             );
842     if (EFI_ERROR (Status)) {
843       if (Status == EFI_BUFFER_TOO_SMALL) {
844         //
845         // If buffer too small, re-allocate the buffer according
846         // to the returned LineLength and try again.
847         //
848         FreePool (PtrLine);
849         PtrLine         = NULL;
850         PtrLine = AllocatePool (LineLength);
851         if (PtrLine == NULL) {
852           Status        = EFI_OUT_OF_RESOURCES;
853           break;
854         }
855         SourceLength    = LineLength;
856         Status          = ProfileGetLine (
857                             (UINT8 *) Source,
858                             SourceLength,
859                             (UINT8 *) PtrLine,
860                             &LineLength
861                             );
862         if (EFI_ERROR (Status)) {
863           break;
864         }
865         MaxLineLength   = LineLength;
866       } else {
867         break;
868       }
869     }
870     CurrentPtr          = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
871 
872     //
873     // Line got. Trim the line before processing it.
874     //
875     ProfileTrim (
876       (UINT8 *) PtrLine,
877       &LineLength
878    );
879 
880     //
881     // Blank line
882     //
883     if (LineLength == 0) {
884       continue;
885     }
886 
887     if (PtrLine[0] == '#') {
888       Status            = ProfileGetComments (
889                             (UINT8 *) PtrLine,
890                             LineLength,
891                             CommentHead
892                             );
893     } else if (PtrLine[0] == '[') {
894       Status            = ProfileGetSection (
895                             (UINT8 *) PtrLine,
896                             LineLength,
897                             SectionHead
898                             );
899     } else {
900       Status            = ProfileGetEntry (
901                             (UINT8 *) PtrLine,
902                             LineLength,
903                             SectionHead
904                             );
905     }
906 
907     if (EFI_ERROR (Status)) {
908       break;
909     }
910   }
911 
912   //
913   // Free buffer
914   //
915   FreePool (PtrLine);
916 
917   return Status;
918 }
919 
920 /**
921   Parse Config data file to get the updated data array.
922 
923   @param DataBuffer      Config raw file buffer.
924   @param BufferSize      Size of raw buffer.
925   @param NumOfUpdates    Pointer to the number of update data.
926   @param UpdateArray     Pointer to the config of update data.
927 
928   @retval EFI_NOT_FOUND         No config data is found.
929   @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
930   @retval EFI_SUCCESS           Parse the config file successfully.
931 
932 **/
933 EFI_STATUS
ParseUpdateDataFile(IN UINT8 * DataBuffer,IN UINTN BufferSize,IN OUT UINTN * NumOfUpdates,IN OUT UPDATE_CONFIG_DATA ** UpdateArray)934 ParseUpdateDataFile (
935   IN      UINT8                         *DataBuffer,
936   IN      UINTN                         BufferSize,
937   IN OUT  UINTN                         *NumOfUpdates,
938   IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
939   )
940 {
941   EFI_STATUS                            Status;
942   CHAR8                                 *Value;
943   CHAR8                                 *SectionName;
944   CHAR8                                 Entry[MAX_LINE_LENGTH];
945   SECTION_ITEM                          *SectionHead;
946   COMMENT_LINE                          *CommentHead;
947   UINTN                                 Num;
948   UINTN                                 Index;
949   EFI_GUID                              FileGuid;
950 
951   SectionHead           = NULL;
952   CommentHead           = NULL;
953 
954   //
955   // First process the data buffer and get all sections and entries
956   //
957   Status                = PreProcessDataFile (
958                             DataBuffer,
959                             BufferSize,
960                             &SectionHead,
961                             &CommentHead
962                             );
963   if (EFI_ERROR (Status)) {
964     FreeAllList (SectionHead, CommentHead);
965     return Status;
966   }
967 
968   //
969   // Now get NumOfUpdate
970   //
971   Value                 = NULL;
972   Status                = UpdateGetProfileString (
973                             SectionHead,
974                             (UINT8 *) "Head",
975                             (UINT8 *) "NumOfUpdate",
976                             (UINT8 **) &Value
977                             );
978   if (Value == NULL) {
979     FreeAllList (SectionHead, CommentHead);
980     return EFI_NOT_FOUND;
981   }
982   Num                   = UpdateAtoi((UINT8 *) Value);
983   if (Num <= 0) {
984     FreeAllList (SectionHead, CommentHead);
985     return EFI_NOT_FOUND;
986   }
987 
988   *NumOfUpdates         = Num;
989   *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num));
990   if (*UpdateArray == NULL) {
991     FreeAllList (SectionHead, CommentHead);
992     return EFI_OUT_OF_RESOURCES;
993   }
994 
995   for ( Index = 0 ; Index < *NumOfUpdates ; Index++) {
996     //
997     // Get the section name of each update
998     //
999     AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");
1000     UpdateStrCatNumber ((UINT8 *) Entry, Index);
1001     Value               = NULL;
1002     Status              = UpdateGetProfileString (
1003                             SectionHead,
1004                             (UINT8 *) "Head",
1005                             (UINT8 *) Entry,
1006                             (UINT8 **) &Value
1007                             );
1008     if (Value == NULL) {
1009       FreeAllList (SectionHead, CommentHead);
1010       return EFI_NOT_FOUND;
1011     }
1012 
1013     //
1014     // The section name of this update has been found.
1015     // Now looks for all the config data of this update
1016     //
1017     SectionName         = Value;
1018 
1019     //
1020     // UpdateType
1021     //
1022     Value               = NULL;
1023     Status              = UpdateGetProfileString (
1024                             SectionHead,
1025                             (UINT8 *) SectionName,
1026                             (UINT8 *) "UpdateType",
1027                             (UINT8 **) &Value
1028                             );
1029     if (Value == NULL) {
1030       FreeAllList (SectionHead, CommentHead);
1031       return EFI_NOT_FOUND;
1032     }
1033 
1034     Num                 = UpdateAtoi((UINT8 *) Value);
1035     if (( Num >= (UINTN) UpdateOperationMaximum)) {
1036       FreeAllList (SectionHead, CommentHead);
1037       return Status;
1038     }
1039     (*UpdateArray)[Index].Index       = Index;
1040     (*UpdateArray)[Index].UpdateType  = (UPDATE_OPERATION_TYPE) Num;
1041 
1042     //
1043     // FvBaseAddress
1044     //
1045     Value               = NULL;
1046     Status              = UpdateGetProfileString (
1047                             SectionHead,
1048                             (UINT8 *) SectionName,
1049                             (UINT8 *) "FvBaseAddress",
1050                             (UINT8 **) &Value
1051                             );
1052     if (Value == NULL) {
1053       FreeAllList (SectionHead, CommentHead);
1054       return EFI_NOT_FOUND;
1055     }
1056 
1057     Num                 = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
1058     (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num;
1059 
1060     //
1061     // FileBuid
1062     //
1063     Value               = NULL;
1064     Status              = UpdateGetProfileString (
1065                             SectionHead,
1066                             (UINT8 *) SectionName,
1067                             (UINT8 *) "FileGuid",
1068                             (UINT8 **) &Value
1069                             );
1070     if (Value == NULL) {
1071       FreeAllList (SectionHead, CommentHead);
1072       return EFI_NOT_FOUND;
1073     }
1074 
1075     Status              = UpdateStringToGuid ((UINT8 *) Value, &FileGuid);
1076     if (EFI_ERROR (Status)) {
1077       FreeAllList (SectionHead, CommentHead);
1078       return Status;
1079     }
1080     CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
1081 
1082     //
1083     // FaultTolerant
1084     // Default value is FALSE
1085     //
1086     Value               = NULL;
1087     (*UpdateArray)[Index].FaultTolerant = FALSE;
1088     Status              = UpdateGetProfileString (
1089                             SectionHead,
1090                             (UINT8 *) SectionName,
1091                             (UINT8 *) "FaultTolerant",
1092                             (UINT8 **) &Value
1093                            );
1094     if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1095       FreeAllList (SectionHead, CommentHead);
1096       return Status;
1097     } else if (Value != NULL) {
1098       if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) {
1099         (*UpdateArray)[Index].FaultTolerant = TRUE;
1100       } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) {
1101         (*UpdateArray)[Index].FaultTolerant = FALSE;
1102       }
1103     }
1104 
1105     if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) {
1106       //
1107       // Length
1108       //
1109       Value             = NULL;
1110       Status            = UpdateGetProfileString (
1111                             SectionHead,
1112                             (UINT8 *) SectionName,
1113                             (UINT8 *) "Length",
1114                             (UINT8 **) &Value
1115                             );
1116       if (Value == NULL) {
1117         FreeAllList (SectionHead, CommentHead);
1118         return EFI_NOT_FOUND;
1119       }
1120 
1121       Num               = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
1122       (*UpdateArray)[Index].Length = (UINTN) Num;
1123     }
1124   }
1125 
1126   //
1127   // Now all configuration data got. Free those temporary buffers
1128   //
1129   FreeAllList (SectionHead, CommentHead);
1130 
1131   return EFI_SUCCESS;
1132 }
1133 
1134