Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17739 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1134 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1134 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Source file for the component update driver. It parse the update
 | 
						|
  configuration file and pass the information to the update driver
 | 
						|
  so that the driver can perform updates accordingly.
 | 
						|
 | 
						|
  Copyright (c) 2002 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions
 | 
						|
  of the BSD License which accompanies this distribution.  The
 | 
						|
  full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "UpdateDriver.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Copy one line data from buffer data to the line buffer.
 | 
						|
 | 
						|
  @param Buffer          Buffer data.
 | 
						|
  @param BufferSize      Buffer Size.
 | 
						|
  @param LineBuffer      Line buffer to store the found line data.
 | 
						|
  @param LineSize        On input, size of the input line buffer.
 | 
						|
                         On output, size of the actual line buffer.
 | 
						|
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  The size of input line buffer is not enough.
 | 
						|
  @retval EFI_SUCCESS           Copy line data into the line buffer.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProfileGetLine (
 | 
						|
  IN      UINT8                         *Buffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  UINT8                         *LineBuffer,
 | 
						|
  IN OUT  UINTN                         *LineSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                 Length;
 | 
						|
  UINT8                                 *PtrBuf;
 | 
						|
  UINTN                                 PtrEnd;
 | 
						|
 | 
						|
  PtrBuf      = Buffer;
 | 
						|
  PtrEnd      = (UINTN)Buffer + BufferSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // 0x0D indicates a line break. Otherwise there is no line break
 | 
						|
  //
 | 
						|
  while ((UINTN)PtrBuf < PtrEnd) {
 | 
						|
    if (*PtrBuf == 0x0D) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((UINTN)PtrBuf >= (PtrEnd - 1)) {
 | 
						|
    //
 | 
						|
    // The buffer ends without any line break
 | 
						|
    // or it is the last character of the buffer
 | 
						|
    //
 | 
						|
    Length    = BufferSize;
 | 
						|
  } else if (*(PtrBuf + 1) == 0x0A) {
 | 
						|
    //
 | 
						|
    // Further check if a 0x0A follows. If yes, count 0xA
 | 
						|
    //
 | 
						|
    Length    = (UINTN) PtrBuf - (UINTN) Buffer + 2;
 | 
						|
  } else {
 | 
						|
    Length    = (UINTN) PtrBuf - (UINTN) Buffer + 1;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Length > (*LineSize)) {
 | 
						|
    *LineSize = Length;
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  SetMem (LineBuffer, *LineSize, 0x0);
 | 
						|
  *LineSize   = Length;
 | 
						|
  CopyMem (LineBuffer, Buffer, Length);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Trim Buffer by removing all CR, LF, TAB, and SPACE chars in its head and tail.
 | 
						|
 | 
						|
  @param Buffer          On input,  buffer data to be trimed.
 | 
						|
                         On output, the trimmed buffer.
 | 
						|
  @param BufferSize      On input,  size of original buffer data.
 | 
						|
                         On output, size of the trimmed buffer.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ProfileTrim (
 | 
						|
  IN OUT  UINT8                         *Buffer,
 | 
						|
  IN OUT  UINTN                         *BufferSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                 Length;
 | 
						|
  UINT8                                 *PtrBuf;
 | 
						|
  UINT8                                 *PtrEnd;
 | 
						|
 | 
						|
  if (*BufferSize == 0) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Trim the tail first, include CR, LF, TAB, and SPACE.
 | 
						|
  //
 | 
						|
  Length          = *BufferSize;
 | 
						|
  PtrBuf          = (UINT8 *) ((UINTN) Buffer + Length - 1);
 | 
						|
  while (PtrBuf >= Buffer) {
 | 
						|
    if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
 | 
						|
      && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf --;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // all spaces, a blank line, return directly;
 | 
						|
  //
 | 
						|
  if (PtrBuf < Buffer) {
 | 
						|
    *BufferSize   = 0;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Length          = (UINTN)PtrBuf - (UINTN)Buffer + 1;
 | 
						|
  PtrEnd          = PtrBuf;
 | 
						|
  PtrBuf          = Buffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Now skip the heading CR, LF, TAB and SPACE
 | 
						|
  //
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    if ((*PtrBuf != 0x0D) && (*PtrBuf != 0x0A )
 | 
						|
      && (*PtrBuf != 0x20) && (*PtrBuf != 0x09)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If no heading CR, LF, TAB or SPACE, directly return
 | 
						|
  //
 | 
						|
  if (PtrBuf == Buffer) {
 | 
						|
    *BufferSize   = Length;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  *BufferSize     = (UINTN)PtrEnd - (UINTN)PtrBuf + 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // The first Buffer..PtrBuf characters are CR, LF, TAB or SPACE.
 | 
						|
  // Now move out all these characters.
 | 
						|
  //
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    *Buffer       = *PtrBuf;
 | 
						|
    Buffer++;
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert new comment item into comment head.
 | 
						|
 | 
						|
  @param Buffer          Comment buffer to be added.
 | 
						|
  @param BufferSize      Size of comment buffer.
 | 
						|
  @param CommentHead     Comment Item head entry.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS            New comment item is inserted.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProfileGetComments (
 | 
						|
  IN      UINT8                         *Buffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  COMMENT_LINE                  **CommentHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  COMMENT_LINE                          *CommentItem;
 | 
						|
 | 
						|
  CommentItem = NULL;
 | 
						|
  CommentItem = AllocatePool (sizeof (COMMENT_LINE));
 | 
						|
  if (CommentItem == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CommentItem->ptrNext  = *CommentHead;
 | 
						|
  *CommentHead          = CommentItem;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add a trailing '\0'
 | 
						|
  //
 | 
						|
  CommentItem->ptrComment = AllocatePool (BufferSize + 1);
 | 
						|
  if (CommentItem->ptrComment == NULL) {
 | 
						|
    FreePool (CommentItem);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  CopyMem (CommentItem->ptrComment, Buffer, BufferSize);
 | 
						|
  *(CommentItem->ptrComment + BufferSize) = '\0';
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add new section item into Section head.
 | 
						|
 | 
						|
  @param Buffer          Section item data buffer.
 | 
						|
  @param BufferSize      Size of section item.
 | 
						|
  @param SectionHead     Section item head entry.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS            Section item is NULL or Section item is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProfileGetSection (
 | 
						|
  IN      UINT8                         *Buffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  SECTION_ITEM                  **SectionHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  SECTION_ITEM                          *SectionItem;
 | 
						|
  UINTN                                 Length;
 | 
						|
  UINT8                                 *PtrBuf;
 | 
						|
 | 
						|
  Status      = EFI_SUCCESS;
 | 
						|
  //
 | 
						|
  // The first character of Buffer is '[', now we want for ']'
 | 
						|
  //
 | 
						|
  PtrBuf      = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
 | 
						|
  while (PtrBuf > Buffer) {
 | 
						|
    if (*PtrBuf == ']') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf --;
 | 
						|
  }
 | 
						|
  if (PtrBuf <= Buffer) {
 | 
						|
    //
 | 
						|
    // Not found. Omit this line
 | 
						|
    //
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // excluding the heading '[' and tailing ']'
 | 
						|
  //
 | 
						|
  Length      = PtrBuf - Buffer - 1;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer + 1,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  //
 | 
						|
  // omit this line if the section name is null
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  SectionItem = AllocatePool (sizeof (SECTION_ITEM));
 | 
						|
  if (SectionItem == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  SectionItem->ptrSection = NULL;
 | 
						|
  SectionItem->SecNameLen = Length;
 | 
						|
  SectionItem->ptrEntry   = NULL;
 | 
						|
  SectionItem->ptrValue   = NULL;
 | 
						|
  SectionItem->ptrNext    = *SectionHead;
 | 
						|
  *SectionHead            = SectionItem;
 | 
						|
 | 
						|
  //
 | 
						|
  // Add a trailing '\0'
 | 
						|
  //
 | 
						|
  SectionItem->ptrSection = AllocatePool (Length + 1);
 | 
						|
  if (SectionItem->ptrSection == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // excluding the heading '['
 | 
						|
  //
 | 
						|
  CopyMem (SectionItem->ptrSection, Buffer + 1, Length);
 | 
						|
  *(SectionItem->ptrSection + Length) = '\0';
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add new section entry and entry value into Section head.
 | 
						|
 | 
						|
  @param Buffer          Section entry data buffer.
 | 
						|
  @param BufferSize      Size of section entry.
 | 
						|
  @param SectionHead     Section item head entry.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS            Section entry is NULL or Section entry is added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ProfileGetEntry (
 | 
						|
  IN      UINT8                         *Buffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  SECTION_ITEM                  **SectionHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  SECTION_ITEM                          *SectionItem;
 | 
						|
  SECTION_ITEM                          *PtrSection;
 | 
						|
  UINTN                                 Length;
 | 
						|
  UINT8                                 *PtrBuf;
 | 
						|
  UINT8                                 *PtrEnd;
 | 
						|
 | 
						|
  Status      = EFI_SUCCESS;
 | 
						|
  PtrBuf      = Buffer;
 | 
						|
  PtrEnd      = (UINT8 *) ((UINTN)Buffer + BufferSize - 1);
 | 
						|
 | 
						|
  //
 | 
						|
  // First search for '='
 | 
						|
  //
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    if (*PtrBuf == '=') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
  if (PtrBuf > PtrEnd) {
 | 
						|
    //
 | 
						|
    // Not found. Omit this line
 | 
						|
    //
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // excluding the tailing '='
 | 
						|
  //
 | 
						|
  Length      = PtrBuf - Buffer;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Omit this line if the entry name is null
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Omit this line if no section header has been found before
 | 
						|
  //
 | 
						|
  if (*SectionHead == NULL) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  PtrSection  = *SectionHead;
 | 
						|
 | 
						|
  SectionItem = AllocatePool (sizeof (SECTION_ITEM));
 | 
						|
  if (SectionItem == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  SectionItem->ptrSection = NULL;
 | 
						|
  SectionItem->ptrEntry   = NULL;
 | 
						|
  SectionItem->ptrValue   = NULL;
 | 
						|
  SectionItem->SecNameLen = PtrSection->SecNameLen;
 | 
						|
  SectionItem->ptrNext    = *SectionHead;
 | 
						|
  *SectionHead            = SectionItem;
 | 
						|
 | 
						|
  //
 | 
						|
  // SectionName, add a trailing '\0'
 | 
						|
  //
 | 
						|
  SectionItem->ptrSection = AllocatePool (PtrSection->SecNameLen + 1);
 | 
						|
  if (SectionItem->ptrSection == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  CopyMem (SectionItem->ptrSection, PtrSection->ptrSection, PtrSection->SecNameLen + 1);
 | 
						|
 | 
						|
  //
 | 
						|
  // EntryName, add a trailing '\0'
 | 
						|
  //
 | 
						|
  SectionItem->ptrEntry = AllocatePool (Length + 1);
 | 
						|
  if (SectionItem->ptrEntry == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  CopyMem (SectionItem->ptrEntry, Buffer, Length);
 | 
						|
  *(SectionItem->ptrEntry + Length) = '\0';
 | 
						|
 | 
						|
  //
 | 
						|
  // Next search for '#'
 | 
						|
  //
 | 
						|
  PtrBuf      = PtrBuf + 1;
 | 
						|
  Buffer      = PtrBuf;
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    if (*PtrBuf == '#') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
  Length      = PtrBuf - Buffer;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  if (Length > 0) {
 | 
						|
    //
 | 
						|
    // EntryValue, add a trailing '\0'
 | 
						|
    //
 | 
						|
    SectionItem->ptrValue = AllocatePool (Length + 1);
 | 
						|
    if (SectionItem->ptrValue == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    CopyMem (SectionItem->ptrValue, Buffer, Length);
 | 
						|
    *(SectionItem->ptrValue + Length) = '\0';
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Free all comment entry and section entry.
 | 
						|
 | 
						|
  @param Section         Section entry list.
 | 
						|
  @param Comment         Comment entry list.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
FreeAllList (
 | 
						|
  IN      SECTION_ITEM                  *Section,
 | 
						|
  IN      COMMENT_LINE                  *Comment
 | 
						|
  )
 | 
						|
{
 | 
						|
  SECTION_ITEM                          *PtrSection;
 | 
						|
  COMMENT_LINE                          *PtrComment;
 | 
						|
 | 
						|
  while (Section != NULL) {
 | 
						|
    PtrSection    = Section;
 | 
						|
    Section       = Section->ptrNext;
 | 
						|
    if (PtrSection->ptrEntry != NULL) {
 | 
						|
      FreePool (PtrSection->ptrEntry);
 | 
						|
    }
 | 
						|
    if (PtrSection->ptrSection != NULL) {
 | 
						|
      FreePool (PtrSection->ptrSection);
 | 
						|
    }
 | 
						|
    if (PtrSection->ptrValue != NULL) {
 | 
						|
      FreePool (PtrSection->ptrValue);
 | 
						|
    }
 | 
						|
    FreePool (PtrSection);
 | 
						|
  }
 | 
						|
 | 
						|
  while (Comment != NULL) {
 | 
						|
    PtrComment    = Comment;
 | 
						|
    Comment       = Comment->ptrNext;
 | 
						|
    if (PtrComment->ptrComment != NULL) {
 | 
						|
      FreePool (PtrComment->ptrComment);
 | 
						|
    }
 | 
						|
    FreePool (PtrComment);
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry value.
 | 
						|
 | 
						|
  @param Section         Section entry list.
 | 
						|
  @param SectionName     Section name.
 | 
						|
  @param EntryName       Section entry name.
 | 
						|
  @param EntryValue      Point to the got entry value.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
  @retval EFI_SUCCESS    Section entry value is got.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateGetProfileString (
 | 
						|
  IN      SECTION_ITEM                  *Section,
 | 
						|
  IN      UINT8                         *SectionName,
 | 
						|
  IN      UINT8                         *EntryName,
 | 
						|
  OUT     UINT8                         **EntryValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  *EntryValue   = NULL;
 | 
						|
 | 
						|
  while (Section != NULL) {
 | 
						|
    if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrSection, (CONST CHAR8 *) SectionName) == 0) {
 | 
						|
      if (Section->ptrEntry != NULL) {
 | 
						|
        if (AsciiStrCmp ((CONST CHAR8 *) Section->ptrEntry, (CONST CHAR8 *) EntryName) == 0) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    Section     = Section->ptrNext;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Section == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *EntryValue   = (UINT8 *) Section->ptrValue;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the dec or hex ascii string to value.
 | 
						|
 | 
						|
  @param Str             ascii string to be converted.
 | 
						|
 | 
						|
  @return the converted value.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
UpdateAtoi (
 | 
						|
  IN      UINT8                         *Str
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Number;
 | 
						|
 | 
						|
  Number = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip preceeding while spaces
 | 
						|
  //
 | 
						|
  while (*Str != '\0') {
 | 
						|
    if (*Str != 0x20) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    Str++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*Str == '\0') {
 | 
						|
    return Number;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find whether the string is prefixed by 0x.
 | 
						|
  // That is, it should be xtoi or atoi.
 | 
						|
  //
 | 
						|
  if (*Str == '0') {
 | 
						|
    if ((*(Str+1) == 'x' ) || ( *(Str+1) == 'X')) {
 | 
						|
      return AsciiStrHexToUintn ((CONST CHAR8 *) Str);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  while (*Str != '\0') {
 | 
						|
    if ((*Str >= '0') && (*Str <= '9')) {
 | 
						|
      Number  = Number * 10 + *Str - '0';
 | 
						|
    } else {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    Str++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Number;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Converts a decimal value to a Null-terminated ascii string.
 | 
						|
 | 
						|
  @param  Buffer  Pointer to the output buffer for the produced Null-terminated
 | 
						|
                  ASCII string.
 | 
						|
  @param  Value   The 64-bit sgned value to convert to a string.
 | 
						|
 | 
						|
  @return The number of ASCII characters in Buffer not including the Null-terminator.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
UpdateValueToString (
 | 
						|
  IN  OUT UINT8                         *Buffer,
 | 
						|
  IN      INT64                         Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                                 TempBuffer[30];
 | 
						|
  UINT8                                 *TempStr;
 | 
						|
  UINT8                                 *BufferPtr;
 | 
						|
  UINTN                                 Count;
 | 
						|
  UINT32                                Remainder;
 | 
						|
 | 
						|
  TempStr           = TempBuffer;
 | 
						|
  BufferPtr         = Buffer;
 | 
						|
  Count             = 0;
 | 
						|
 | 
						|
  if (Value < 0) {
 | 
						|
    *BufferPtr      = '-';
 | 
						|
    BufferPtr++;
 | 
						|
    Value           = -Value;
 | 
						|
    Count++;
 | 
						|
  }
 | 
						|
 | 
						|
  do {
 | 
						|
    Value = (INT64) DivU64x32Remainder  ((UINT64)Value, 10, &Remainder);
 | 
						|
    //
 | 
						|
    // The first item of TempStr is not occupied. It's kind of flag
 | 
						|
    //
 | 
						|
    TempStr++;
 | 
						|
    Count++;
 | 
						|
    *TempStr        = (UINT8) ((UINT8)Remainder + '0');
 | 
						|
  } while (Value != 0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Reverse temp string into Buffer.
 | 
						|
  //
 | 
						|
  while (TempStr != TempBuffer) {
 | 
						|
    *BufferPtr      = *TempStr;
 | 
						|
    BufferPtr++;
 | 
						|
    TempStr --;
 | 
						|
  }
 | 
						|
 | 
						|
  *BufferPtr = 0;
 | 
						|
 | 
						|
  return Count;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the input value to a ascii string, 
 | 
						|
  and concatenates this string to the input string.
 | 
						|
 | 
						|
  @param Str             Pointer to a Null-terminated ASCII string.
 | 
						|
  @param Number          The unsgned value to convert to a string.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UpdateStrCatNumber (
 | 
						|
  IN OUT  UINT8                         *Str,
 | 
						|
  IN      UINTN                         Number
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                 Count;
 | 
						|
 | 
						|
  while (*Str != '\0') {
 | 
						|
    Str++;
 | 
						|
  }
 | 
						|
 | 
						|
  Count = UpdateValueToString (Str, (INT64)Number);
 | 
						|
 | 
						|
  *(Str + Count) = '\0';
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the input ascii string into GUID value.
 | 
						|
 | 
						|
  @param Str             Ascii GUID string to be converted.
 | 
						|
  @param Guid            Pointer to the converted GUID value.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
 | 
						|
  @retval EFI_NOT_FOUND         The input ascii string is not a valid GUID format string.
 | 
						|
  @retval EFI_SUCCESS           GUID value is got.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateStringToGuid (
 | 
						|
  IN      UINT8                         *Str,
 | 
						|
  IN OUT  EFI_GUID                      *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                                 *PtrBuffer;
 | 
						|
  UINT8                                 *PtrPosition;
 | 
						|
  UINT8                                 *Buffer;
 | 
						|
  UINTN                                 Data;
 | 
						|
  UINTN                                 StrLen;
 | 
						|
  UINTN                                 Index;
 | 
						|
  UINT8                                 Digits[3];
 | 
						|
 | 
						|
  StrLen          = AsciiStrLen  ((CONST CHAR8 *) Str);
 | 
						|
  Buffer          = AllocateCopyPool (StrLen + 1, Str);
 | 
						|
  if (Buffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Data1
 | 
						|
  //
 | 
						|
  PtrBuffer       = Buffer;
 | 
						|
  PtrPosition     = PtrBuffer;
 | 
						|
  while (*PtrBuffer != '\0') {
 | 
						|
    if (*PtrBuffer == '-') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuffer++;
 | 
						|
  }
 | 
						|
  if (*PtrBuffer == '\0') {
 | 
						|
    FreePool (Buffer);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *PtrBuffer      = '\0';
 | 
						|
  Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
 | 
						|
  Guid->Data1     = (UINT32)Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Data2
 | 
						|
  //
 | 
						|
  PtrBuffer++;
 | 
						|
  PtrPosition     = PtrBuffer;
 | 
						|
  while (*PtrBuffer != '\0') {
 | 
						|
    if (*PtrBuffer == '-') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuffer++;
 | 
						|
  }
 | 
						|
  if (*PtrBuffer == '\0') {
 | 
						|
    FreePool (Buffer);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  *PtrBuffer      = '\0';
 | 
						|
  Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
 | 
						|
  Guid->Data2     = (UINT16)Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Data3
 | 
						|
  //
 | 
						|
  PtrBuffer++;
 | 
						|
  PtrPosition     = PtrBuffer;
 | 
						|
  while (*PtrBuffer != '\0') {
 | 
						|
    if (*PtrBuffer == '-') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuffer++;
 | 
						|
  }
 | 
						|
  if (*PtrBuffer == '\0') {
 | 
						|
    FreePool (Buffer);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  *PtrBuffer      = '\0';
 | 
						|
  Data            = AsciiStrHexToUintn ((CONST CHAR8 *) PtrPosition);
 | 
						|
  Guid->Data3     = (UINT16)Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Data4[0..1]
 | 
						|
  //
 | 
						|
  for ( Index = 0 ; Index < 2 ; Index++) {
 | 
						|
    PtrBuffer++;
 | 
						|
    if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
 | 
						|
      FreePool (Buffer);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
    Digits[0]     = *PtrBuffer;
 | 
						|
    PtrBuffer++;
 | 
						|
    Digits[1]     = *PtrBuffer;
 | 
						|
    Digits[2]     = '\0';
 | 
						|
    Data          = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
 | 
						|
    Guid->Data4[Index] = (UINT8)Data;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // skip the '-'
 | 
						|
  //
 | 
						|
  PtrBuffer++;
 | 
						|
  if ((*PtrBuffer != '-' ) || ( *PtrBuffer == '\0')) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Data4[2..7]
 | 
						|
  //
 | 
						|
  for ( ; Index < 8; Index++) {
 | 
						|
    PtrBuffer++;
 | 
						|
    if ((*PtrBuffer == '\0') || ( *(PtrBuffer + 1) == '\0')) {
 | 
						|
      FreePool (Buffer);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
    Digits[0]     = *PtrBuffer;
 | 
						|
    PtrBuffer++;
 | 
						|
    Digits[1]     = *PtrBuffer;
 | 
						|
    Digits[2]     = '\0';
 | 
						|
    Data          = AsciiStrHexToUintn ((CONST CHAR8 *) Digits);
 | 
						|
    Guid->Data4[Index] = (UINT8)Data;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Buffer);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Pre process config data buffer into Section entry list and Comment entry list.
 | 
						|
 
 | 
						|
  @param DataBuffer      Config raw file buffer.
 | 
						|
  @param BufferSize      Size of raw buffer.
 | 
						|
  @param SectionHead     Pointer to the section entry list.
 | 
						|
  @param CommentHead     Pointer to the comment entry list.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS           Config data buffer is preprocessed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PreProcessDataFile (
 | 
						|
  IN      UINT8                         *DataBuffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  SECTION_ITEM                  **SectionHead,
 | 
						|
  IN OUT  COMMENT_LINE                  **CommentHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  CHAR8                                 *Source;
 | 
						|
  CHAR8                                 *CurrentPtr;
 | 
						|
  CHAR8                                 *BufferEnd;
 | 
						|
  CHAR8                                 *PtrLine;
 | 
						|
  UINTN                                 LineLength;
 | 
						|
  UINTN                                 SourceLength;
 | 
						|
  UINTN                                 MaxLineLength;
 | 
						|
 | 
						|
  *SectionHead          = NULL;
 | 
						|
  *CommentHead          = NULL;
 | 
						|
  BufferEnd             = (CHAR8 *) ( (UINTN) DataBuffer + BufferSize);
 | 
						|
  CurrentPtr            = (CHAR8 *) DataBuffer;
 | 
						|
  MaxLineLength         = MAX_LINE_LENGTH;
 | 
						|
  Status                = EFI_SUCCESS;
 | 
						|
 | 
						|
  PtrLine = AllocatePool (MaxLineLength);
 | 
						|
  if (PtrLine == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  while (CurrentPtr < BufferEnd) {
 | 
						|
    Source              = CurrentPtr;
 | 
						|
    SourceLength        = (UINTN)BufferEnd - (UINTN)CurrentPtr;
 | 
						|
    LineLength          = MaxLineLength;
 | 
						|
    //
 | 
						|
    // With the assumption that line length is less than 512
 | 
						|
    // characters. Otherwise BUFFER_TOO_SMALL will be returned.
 | 
						|
    //
 | 
						|
    Status              = ProfileGetLine (
 | 
						|
                            (UINT8 *) Source,
 | 
						|
                            SourceLength,
 | 
						|
                            (UINT8 *) PtrLine,
 | 
						|
                            &LineLength
 | 
						|
                            );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
        //
 | 
						|
        // If buffer too small, re-allocate the buffer according
 | 
						|
        // to the returned LineLength and try again.
 | 
						|
        //
 | 
						|
        FreePool (PtrLine);
 | 
						|
        PtrLine         = NULL;
 | 
						|
        PtrLine = AllocatePool (LineLength);
 | 
						|
        if (PtrLine == NULL) {
 | 
						|
          Status        = EFI_OUT_OF_RESOURCES;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        SourceLength    = LineLength;
 | 
						|
        Status          = ProfileGetLine (
 | 
						|
                            (UINT8 *) Source,
 | 
						|
                            SourceLength,
 | 
						|
                            (UINT8 *) PtrLine,
 | 
						|
                            &LineLength
 | 
						|
                            );
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        MaxLineLength   = LineLength;
 | 
						|
      } else {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    CurrentPtr          = (CHAR8 *) ( (UINTN) CurrentPtr + LineLength);
 | 
						|
 | 
						|
    //
 | 
						|
    // Line got. Trim the line before processing it.
 | 
						|
    //
 | 
						|
    ProfileTrim (
 | 
						|
      (UINT8 *) PtrLine,
 | 
						|
      &LineLength
 | 
						|
   );
 | 
						|
 | 
						|
    //
 | 
						|
    // Blank line
 | 
						|
    //
 | 
						|
    if (LineLength == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PtrLine[0] == '#') {
 | 
						|
      Status            = ProfileGetComments (
 | 
						|
                            (UINT8 *) PtrLine,
 | 
						|
                            LineLength,
 | 
						|
                            CommentHead
 | 
						|
                            );
 | 
						|
    } else if (PtrLine[0] == '[') {
 | 
						|
      Status            = ProfileGetSection (
 | 
						|
                            (UINT8 *) PtrLine,
 | 
						|
                            LineLength,
 | 
						|
                            SectionHead
 | 
						|
                            );
 | 
						|
    } else {
 | 
						|
      Status            = ProfileGetEntry (
 | 
						|
                            (UINT8 *) PtrLine,
 | 
						|
                            LineLength,
 | 
						|
                            SectionHead
 | 
						|
                            );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free buffer
 | 
						|
  //
 | 
						|
  FreePool (PtrLine);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Parse Config data file to get the updated data array.
 | 
						|
 | 
						|
  @param DataBuffer      Config raw file buffer.
 | 
						|
  @param BufferSize      Size of raw buffer.
 | 
						|
  @param NumOfUpdates    Pointer to the number of update data.
 | 
						|
  @param UpdateArray     Pointer to the config of update data.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND         No config data is found.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS           Parse the config file successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ParseUpdateDataFile (
 | 
						|
  IN      UINT8                         *DataBuffer,
 | 
						|
  IN      UINTN                         BufferSize,
 | 
						|
  IN OUT  UINTN                         *NumOfUpdates,
 | 
						|
  IN OUT  UPDATE_CONFIG_DATA            **UpdateArray
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  CHAR8                                 *Value;
 | 
						|
  CHAR8                                 *SectionName;
 | 
						|
  CHAR8                                 Entry[MAX_LINE_LENGTH];
 | 
						|
  SECTION_ITEM                          *SectionHead;
 | 
						|
  COMMENT_LINE                          *CommentHead;
 | 
						|
  UINTN                                 Num;
 | 
						|
  UINTN                                 Index;
 | 
						|
  EFI_GUID                              FileGuid;
 | 
						|
 | 
						|
  SectionHead           = NULL;
 | 
						|
  CommentHead           = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // First process the data buffer and get all sections and entries
 | 
						|
  //
 | 
						|
  Status                = PreProcessDataFile (
 | 
						|
                            DataBuffer,
 | 
						|
                            BufferSize,
 | 
						|
                            &SectionHead,
 | 
						|
                            &CommentHead
 | 
						|
                            );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreeAllList (SectionHead, CommentHead);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Now get NumOfUpdate
 | 
						|
  //
 | 
						|
  Value                 = NULL;
 | 
						|
  Status                = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) "Head",
 | 
						|
                            (UINT8 *) "NumOfUpdate",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
  if (Value == NULL) {
 | 
						|
    FreeAllList (SectionHead, CommentHead);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  Num                   = UpdateAtoi((UINT8 *) Value);
 | 
						|
  if (Num <= 0) {
 | 
						|
    FreeAllList (SectionHead, CommentHead);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *NumOfUpdates         = Num;
 | 
						|
  *UpdateArray = AllocatePool ((sizeof (UPDATE_CONFIG_DATA) * Num));
 | 
						|
  if (*UpdateArray == NULL) {
 | 
						|
    FreeAllList (SectionHead, CommentHead);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  for ( Index = 0 ; Index < *NumOfUpdates ; Index++) {
 | 
						|
    //
 | 
						|
    // Get the section name of each update
 | 
						|
    //
 | 
						|
    AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");
 | 
						|
    UpdateStrCatNumber ((UINT8 *) Entry, Index);
 | 
						|
    Value               = NULL;
 | 
						|
    Status              = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) "Head",
 | 
						|
                            (UINT8 *) Entry,
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
    if (Value == NULL) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // The section name of this update has been found.
 | 
						|
    // Now looks for all the config data of this update
 | 
						|
    //
 | 
						|
    SectionName         = Value;
 | 
						|
 | 
						|
    //
 | 
						|
    // UpdateType
 | 
						|
    //
 | 
						|
    Value               = NULL;
 | 
						|
    Status              = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) SectionName,
 | 
						|
                            (UINT8 *) "UpdateType",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
    if (Value == NULL) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    Num                 = UpdateAtoi((UINT8 *) Value);
 | 
						|
    if (( Num >= (UINTN) UpdateOperationMaximum)) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    (*UpdateArray)[Index].Index       = Index;
 | 
						|
    (*UpdateArray)[Index].UpdateType  = (UPDATE_OPERATION_TYPE) Num;
 | 
						|
 | 
						|
    //
 | 
						|
    // FvBaseAddress
 | 
						|
    //
 | 
						|
    Value               = NULL;
 | 
						|
    Status              = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) SectionName,
 | 
						|
                            (UINT8 *) "FvBaseAddress",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
    if (Value == NULL) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    Num                 = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
 | 
						|
    (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS) Num;
 | 
						|
 | 
						|
    //
 | 
						|
    // FileBuid
 | 
						|
    //
 | 
						|
    Value               = NULL;
 | 
						|
    Status              = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) SectionName,
 | 
						|
                            (UINT8 *) "FileGuid",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
    if (Value == NULL) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    Status              = UpdateStringToGuid ((UINT8 *) Value, &FileGuid);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    CopyMem (&((*UpdateArray)[Index].FileGuid), &FileGuid, sizeof(EFI_GUID));
 | 
						|
 | 
						|
    //
 | 
						|
    // FaultTolerant
 | 
						|
    // Default value is FALSE
 | 
						|
    //
 | 
						|
    Value               = NULL;
 | 
						|
    (*UpdateArray)[Index].FaultTolerant = FALSE;
 | 
						|
    Status              = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) SectionName,
 | 
						|
                            (UINT8 *) "FaultTolerant",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                           );
 | 
						|
    if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
 | 
						|
      FreeAllList (SectionHead, CommentHead);
 | 
						|
      return Status;
 | 
						|
    } else if (Value != NULL) {
 | 
						|
      if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "TRUE") == 0) {
 | 
						|
        (*UpdateArray)[Index].FaultTolerant = TRUE;
 | 
						|
      } else if (AsciiStriCmp ((CONST CHAR8 *) Value, (CONST CHAR8 *) "FALSE") == 0) {
 | 
						|
        (*UpdateArray)[Index].FaultTolerant = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if ((*UpdateArray)[Index].UpdateType == UpdateFvRange) {
 | 
						|
      //
 | 
						|
      // Length
 | 
						|
      //
 | 
						|
      Value             = NULL;
 | 
						|
      Status            = UpdateGetProfileString (
 | 
						|
                            SectionHead,
 | 
						|
                            (UINT8 *) SectionName,
 | 
						|
                            (UINT8 *) "Length",
 | 
						|
                            (UINT8 **) &Value
 | 
						|
                            );
 | 
						|
      if (Value == NULL) {
 | 
						|
        FreeAllList (SectionHead, CommentHead);
 | 
						|
        return EFI_NOT_FOUND;
 | 
						|
      }
 | 
						|
 | 
						|
      Num               = AsciiStrHexToUintn ((CONST CHAR8 *) Value);
 | 
						|
      (*UpdateArray)[Index].Length = (UINTN) Num;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Now all configuration data got. Free those temporary buffers
 | 
						|
  //
 | 
						|
  FreeAllList (SectionHead, CommentHead);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 |