Home | History | Annotate | Download | only in UpdateDriverDxe
      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
     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          = 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
    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
    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