Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
		
			
				
	
	
		
			1285 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1285 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  This library parses the INI configuration file.
 | 
						|
 | 
						|
  The INI file format is:
 | 
						|
    ================
 | 
						|
    [SectionName]
 | 
						|
    EntryName=EntryValue
 | 
						|
    ================
 | 
						|
 | 
						|
    Where:
 | 
						|
      1) SectionName is an ASCII string. The valid format is [A-Za-z0-9_]+
 | 
						|
      2) EntryName is an ASCII string. The valid format is [A-Za-z0-9_]+
 | 
						|
      3) EntryValue can be:
 | 
						|
         3.1) an ASCII String. The valid format is [A-Za-z0-9_]+
 | 
						|
         3.2) a GUID. The valid format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is [A-Fa-f0-9]
 | 
						|
         3.3) a decimal value. The valid format is [0-9]+
 | 
						|
         3.4) a heximal value. The valid format is 0x[A-Fa-f0-9]+
 | 
						|
      4) '#' or ';' can be used as comment at anywhere.
 | 
						|
      5) TAB(0x20) or SPACE(0x9) can be used as separator.
 | 
						|
      6) LF(\n, 0xA) or CR(\r, 0xD) can be used as line break.
 | 
						|
 | 
						|
  Caution: This module requires additional review when modified.
 | 
						|
  This driver will have external input - INI data file.
 | 
						|
 | 
						|
  OpenIniFile(), PreProcessDataFile(), ProfileGetSection(), ProfileGetEntry()
 | 
						|
  will receive untrusted input and do basic validation.
 | 
						|
 | 
						|
  Copyright (c) 2016 - 2017, 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 <Uefi.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
 | 
						|
#define IS_HYPHEN(a)               ((a) == '-')
 | 
						|
#define IS_NULL(a)                 ((a) == '\0')
 | 
						|
 | 
						|
// This is default allocation. Reallocation will happen if it is not enough.
 | 
						|
#define MAX_LINE_LENGTH           512
 | 
						|
 | 
						|
typedef struct _INI_SECTION_ITEM SECTION_ITEM;
 | 
						|
struct _INI_SECTION_ITEM {
 | 
						|
  CHAR8                           *PtrSection;
 | 
						|
  UINTN                           SecNameLen;
 | 
						|
  CHAR8                           *PtrEntry;
 | 
						|
  CHAR8                           *PtrValue;
 | 
						|
  SECTION_ITEM                    *PtrNext;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct _INI_COMMENT_LINE COMMENT_LINE;
 | 
						|
struct _INI_COMMENT_LINE {
 | 
						|
  CHAR8                           *PtrComment;
 | 
						|
  COMMENT_LINE                    *PtrNext;
 | 
						|
};
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  SECTION_ITEM                  *SectionHead;
 | 
						|
  COMMENT_LINE                  *CommentHead;
 | 
						|
} INI_PARSING_LIB_CONTEXT;
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the digital char is valid.
 | 
						|
 | 
						|
  @param[in] DigitalChar    The digital char to be checked.
 | 
						|
  @param[in] IncludeHex     If it include HEX char.
 | 
						|
 | 
						|
  @retval TRUE   The digital char is valid.
 | 
						|
  @retval FALSE  The digital char is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidDigitalChar (
 | 
						|
  IN CHAR8    DigitalChar,
 | 
						|
  IN BOOLEAN  IncludeHex
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (DigitalChar >= '0' && DigitalChar <= '9') {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  if (IncludeHex) {
 | 
						|
    if (DigitalChar >= 'a' && DigitalChar <= 'f') {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
    if (DigitalChar >= 'A' && DigitalChar <= 'F') {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the name char is valid.
 | 
						|
 | 
						|
  @param[in] NameChar    The name char to be checked.
 | 
						|
 | 
						|
  @retval TRUE   The name char is valid.
 | 
						|
  @retval FALSE  The name char is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidNameChar (
 | 
						|
  IN CHAR8  NameChar
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (NameChar >= 'a' && NameChar <= 'z') {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  if (NameChar >= 'A' && NameChar <= 'Z') {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  if (NameChar >= '0' && NameChar <= '9') {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  if (NameChar == '_') {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the digital string is valid.
 | 
						|
 | 
						|
  @param[in] Digital        The digital to be checked.
 | 
						|
  @param[in] Length         The length of digital string in bytes.
 | 
						|
  @param[in] IncludeHex     If it include HEX char.
 | 
						|
 | 
						|
  @retval TRUE   The digital string is valid.
 | 
						|
  @retval FALSE  The digital string is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidDigital (
 | 
						|
  IN CHAR8    *Digital,
 | 
						|
  IN UINTN    Length,
 | 
						|
  IN BOOLEAN  IncludeHex
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Index;
 | 
						|
  for (Index = 0; Index < Length; Index++) {
 | 
						|
    if (!IsValidDigitalChar(Digital[Index], IncludeHex)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the decimal string is valid.
 | 
						|
 | 
						|
  @param[in] Decimal The decimal string to be checked.
 | 
						|
  @param[in] Length  The length of decimal string in bytes.
 | 
						|
 | 
						|
  @retval TRUE   The decimal string is valid.
 | 
						|
  @retval FALSE  The decimal string is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidDecimalString (
 | 
						|
  IN CHAR8  *Decimal,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  return IsValidDigital(Decimal, Length, FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the heximal string is valid.
 | 
						|
 | 
						|
  @param[in] Hex     The heximal string to be checked.
 | 
						|
  @param[in] Length  The length of heximal string in bytes.
 | 
						|
 | 
						|
  @retval TRUE   The heximal string is valid.
 | 
						|
  @retval FALSE  The heximal string is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidHexString (
 | 
						|
  IN CHAR8  *Hex,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Length <= 2) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (Hex[0] != '0') {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (Hex[1] != 'x' && Hex[1] != 'X') {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  return IsValidDigital(&Hex[2], Length - 2, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the name string is valid.
 | 
						|
 | 
						|
  @param[in] Name    The name to be checked.
 | 
						|
  @param[in] Length  The length of name string in bytes.
 | 
						|
 | 
						|
  @retval TRUE   The name string is valid.
 | 
						|
  @retval FALSE  The name string is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidName (
 | 
						|
  IN CHAR8  *Name,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  Index;
 | 
						|
  for (Index = 0; Index < Length; Index++) {
 | 
						|
    if (!IsValidNameChar(Name[Index])) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the value string is valid GUID.
 | 
						|
 | 
						|
  @param[in] Value   The value to be checked.
 | 
						|
  @param[in] Length  The length of value string in bytes.
 | 
						|
 | 
						|
  @retval TRUE   The value string is valid GUID.
 | 
						|
  @retval FALSE  The value string is invalid GUID.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidGuid (
 | 
						|
  IN CHAR8  *Value,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Length != sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") - 1) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IS_HYPHEN(Value[8])) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IS_HYPHEN(Value[13])) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IS_HYPHEN(Value[18])) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IS_HYPHEN(Value[23])) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IsValidDigital(&Value[0], 8, TRUE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IsValidDigital(&Value[9], 4, TRUE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IsValidDigital(&Value[14], 4, TRUE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IsValidDigital(&Value[19], 4, TRUE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (!IsValidDigital(&Value[24], 12, TRUE)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return if the value string is valid.
 | 
						|
 | 
						|
  @param[in] Value    The value to be checked.
 | 
						|
  @param[in] Length  The length of value string in bytes.
 | 
						|
 | 
						|
  @retval TRUE   The name string is valid.
 | 
						|
  @retval FALSE  The name string is invalid.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsValidValue (
 | 
						|
  IN CHAR8  *Value,
 | 
						|
  IN UINTN  Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IsValidName(Value, Length) || IsValidGuid(Value, Length)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump an INI config file context.
 | 
						|
 | 
						|
  @param[in] Context         INI Config file context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DumpIniSection (
 | 
						|
  IN VOID  *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  INI_PARSING_LIB_CONTEXT               *IniContext;
 | 
						|
  SECTION_ITEM                          *PtrSection;
 | 
						|
  SECTION_ITEM                          *Section;
 | 
						|
 | 
						|
  if (Context == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  IniContext = Context;
 | 
						|
  Section = IniContext->SectionHead;
 | 
						|
 | 
						|
  while (Section != NULL) {
 | 
						|
    PtrSection = Section;
 | 
						|
    Section = Section->PtrNext;
 | 
						|
    if (PtrSection->PtrSection != NULL) {
 | 
						|
      DEBUG((DEBUG_VERBOSE, "Section - %a\n", PtrSection->PtrSection));
 | 
						|
    }
 | 
						|
    if (PtrSection->PtrEntry != NULL) {
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "  Entry - %a\n", PtrSection->PtrEntry));
 | 
						|
    }
 | 
						|
    if (PtrSection->PtrValue != NULL) {
 | 
						|
      DEBUG((DEBUG_VERBOSE, "  Value - %a\n", PtrSection->PtrValue));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy one line data from buffer data to the line buffer.
 | 
						|
 | 
						|
  @param[in]      Buffer          Buffer data.
 | 
						|
  @param[in]      BufferSize      Buffer Size.
 | 
						|
  @param[in, out] LineBuffer      Line buffer to store the found line data.
 | 
						|
  @param[in, out] 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 || *PtrBuf == 0x0A) {
 | 
						|
      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[in, out] Buffer          On input,  buffer data to be trimed.
 | 
						|
                                  On output, the trimmed buffer.
 | 
						|
  @param[in, out] 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[in]      Buffer          Comment buffer to be added.
 | 
						|
  @param[in]      BufferSize      Size of comment buffer.
 | 
						|
  @param[in, out] 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[in]      Buffer          Section item data buffer.
 | 
						|
  @param[in]      BufferSize      Size of section item.
 | 
						|
  @param[in, out] 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
 | 
						|
  )
 | 
						|
{
 | 
						|
  SECTION_ITEM                          *SectionItem;
 | 
						|
  UINTN                                 Length;
 | 
						|
  UINT8                                 *PtrBuf;
 | 
						|
  UINT8                                 *PtrEnd;
 | 
						|
 | 
						|
  ASSERT(BufferSize >= 1);
 | 
						|
  //
 | 
						|
  // The first character of Buffer is '[', now we want for ']'
 | 
						|
  //
 | 
						|
  PtrEnd      = (UINT8 *)((UINTN)Buffer + BufferSize - 1);
 | 
						|
  PtrBuf      = (UINT8 *)((UINTN)Buffer + 1);
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    if (*PtrBuf == ']') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf ++;
 | 
						|
  }
 | 
						|
  if (PtrBuf > PtrEnd) {
 | 
						|
    //
 | 
						|
    // Not found. Invalid line
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  if (PtrBuf <= Buffer + 1) {
 | 
						|
    // Empty name
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // excluding the heading '[' and tailing ']'
 | 
						|
  //
 | 
						|
  Length      = PtrBuf - Buffer - 1;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer + 1,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Invalid line if the section name is null
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsValidName((CHAR8 *)Buffer + 1, Length)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  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[in]      Buffer          Section entry data buffer.
 | 
						|
  @param[in]      BufferSize      Size of section entry.
 | 
						|
  @param[in, out] SectionHead     Section item head entry.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough memory is allocated.
 | 
						|
  @retval EFI_SUCCESS            Section entry is added.
 | 
						|
  @retval EFI_NOT_FOUND          Section entry is not found.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Section entry is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
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. Invalid line
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  if (PtrBuf <= Buffer) {
 | 
						|
    // Empty name
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // excluding the tailing '='
 | 
						|
  //
 | 
						|
  Length      = PtrBuf - Buffer;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Invalid line if the entry name is null
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsValidName((CHAR8 *)Buffer, Length)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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) {
 | 
						|
    FreePool(SectionItem->PtrSection);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  CopyMem (SectionItem->PtrEntry, Buffer, Length);
 | 
						|
  *(SectionItem->PtrEntry + Length) = '\0';
 | 
						|
 | 
						|
  //
 | 
						|
  // Next search for '#' or ';'
 | 
						|
  //
 | 
						|
  PtrBuf      = PtrBuf + 1;
 | 
						|
  Buffer      = PtrBuf;
 | 
						|
  while (PtrBuf <= PtrEnd) {
 | 
						|
    if (*PtrBuf == '#' || *PtrBuf == ';') {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PtrBuf++;
 | 
						|
  }
 | 
						|
  if (PtrBuf <= Buffer) {
 | 
						|
    // Empty name
 | 
						|
    FreePool(SectionItem->PtrEntry);
 | 
						|
    FreePool(SectionItem->PtrSection);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  Length      = PtrBuf - Buffer;
 | 
						|
  ProfileTrim (
 | 
						|
    Buffer,
 | 
						|
    &Length
 | 
						|
  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Invalid line if the entry value is null
 | 
						|
  //
 | 
						|
  if (Length == 0) {
 | 
						|
    FreePool(SectionItem->PtrEntry);
 | 
						|
    FreePool(SectionItem->PtrSection);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsValidValue((CHAR8 *)Buffer, Length)) {
 | 
						|
    FreePool(SectionItem->PtrEntry);
 | 
						|
    FreePool(SectionItem->PtrSection);
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // EntryValue, add a trailing '\0'
 | 
						|
  //
 | 
						|
  SectionItem->PtrValue = AllocatePool (Length + 1);
 | 
						|
  if (SectionItem->PtrValue == NULL) {
 | 
						|
    FreePool(SectionItem->PtrEntry);
 | 
						|
    FreePool(SectionItem->PtrSection);
 | 
						|
    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[in] Section         Section entry list.
 | 
						|
  @param[in] 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[in]  Section         Section entry list.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] 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      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     CHAR8                         **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   = Section->PtrValue;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Pre process config data buffer into Section entry list and Comment entry list.
 | 
						|
 | 
						|
  @param[in]      DataBuffer      Config raw file buffer.
 | 
						|
  @param[in]      BufferSize      Size of raw buffer.
 | 
						|
  @param[in, out] SectionHead     Pointer to the section entry list.
 | 
						|
  @param[in, out] 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.
 | 
						|
  @retval EFI_NOT_FOUND         Config data buffer is invalid, because Section or Entry is not found.
 | 
						|
  @retval EFI_INVALID_PARAMETER Config data buffer is invalid, because Section or Entry is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
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] == '#' || 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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Open an INI config file and return a context.
 | 
						|
 | 
						|
  @param[in] DataBuffer      Config raw file buffer.
 | 
						|
  @param[in] BufferSize      Size of raw buffer.
 | 
						|
 | 
						|
  @return       Config data buffer is opened and context is returned.
 | 
						|
  @retval NULL  No enough memory is allocated.
 | 
						|
  @retval NULL  Config data buffer is invalid.
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EFIAPI
 | 
						|
OpenIniFile (
 | 
						|
  IN      UINT8                         *DataBuffer,
 | 
						|
  IN      UINTN                         BufferSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  INI_PARSING_LIB_CONTEXT               *IniContext;
 | 
						|
 | 
						|
  if (DataBuffer == NULL || BufferSize == 0) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  IniContext = AllocateZeroPool(sizeof(INI_PARSING_LIB_CONTEXT));
 | 
						|
  if (IniContext == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // First process the data buffer and get all sections and entries
 | 
						|
  //
 | 
						|
  Status = PreProcessDataFile (
 | 
						|
             DataBuffer,
 | 
						|
             BufferSize,
 | 
						|
             &IniContext->SectionHead,
 | 
						|
             &IniContext->CommentHead
 | 
						|
             );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    FreePool(IniContext);
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  DEBUG_CODE_BEGIN ();
 | 
						|
    DumpIniSection(IniContext);
 | 
						|
  DEBUG_CODE_END ();
 | 
						|
  return IniContext;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry string value.
 | 
						|
 | 
						|
  @param[in]  Context         INI Config file context.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] EntryValue      Point to the got entry string value.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    Section entry string value is got.
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetStringFromDataFile(
 | 
						|
  IN      VOID                          *Context,
 | 
						|
  IN      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     CHAR8                         **EntryValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  INI_PARSING_LIB_CONTEXT               *IniContext;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
 | 
						|
  if (Context == NULL || SectionName == NULL || EntryName == NULL || EntryValue == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  IniContext = Context;
 | 
						|
 | 
						|
  *EntryValue  = NULL;
 | 
						|
  Status = UpdateGetProfileString (
 | 
						|
             IniContext->SectionHead,
 | 
						|
             SectionName,
 | 
						|
             EntryName,
 | 
						|
             EntryValue
 | 
						|
             );
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry GUID value.
 | 
						|
 | 
						|
  @param[in]  Context         INI Config file context.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] Guid            Point to the got GUID value.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    Section entry GUID value is got.
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetGuidFromDataFile (
 | 
						|
  IN      VOID                          *Context,
 | 
						|
  IN      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     EFI_GUID                      *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                                 *Value;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  RETURN_STATUS                         RStatus;
 | 
						|
 | 
						|
  if (Context == NULL || SectionName == NULL || EntryName == NULL || Guid == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetStringFromDataFile(
 | 
						|
             Context,
 | 
						|
             SectionName,
 | 
						|
             EntryName,
 | 
						|
             &Value
 | 
						|
             );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  ASSERT (Value != NULL);
 | 
						|
  RStatus = AsciiStrToGuid (Value, Guid);
 | 
						|
  if (RETURN_ERROR (RStatus) || (Value[GUID_STRING_LENGTH] != '\0')) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry decimal UINTN value.
 | 
						|
 | 
						|
  @param[in]  Context         INI Config file context.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] Data            Point to the got decimal UINTN value.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    Section entry decimal UINTN value is got.
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetDecimalUintnFromDataFile (
 | 
						|
  IN      VOID                          *Context,
 | 
						|
  IN      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     UINTN                         *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                                 *Value;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
 | 
						|
  if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetStringFromDataFile(
 | 
						|
             Context,
 | 
						|
             SectionName,
 | 
						|
             EntryName,
 | 
						|
             &Value
 | 
						|
             );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  ASSERT (Value != NULL);
 | 
						|
  if (!IsValidDecimalString(Value, AsciiStrLen(Value))) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  *Data = AsciiStrDecimalToUintn(Value);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry heximal UINTN value.
 | 
						|
 | 
						|
  @param[in]  Context         INI Config file context.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] Data            Point to the got heximal UINTN value.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    Section entry heximal UINTN value is got.
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetHexUintnFromDataFile (
 | 
						|
  IN      VOID                          *Context,
 | 
						|
  IN      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     UINTN                         *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                                 *Value;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
 | 
						|
  if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetStringFromDataFile(
 | 
						|
             Context,
 | 
						|
             SectionName,
 | 
						|
             EntryName,
 | 
						|
             &Value
 | 
						|
             );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  ASSERT (Value != NULL);
 | 
						|
  if (!IsValidHexString(Value, AsciiStrLen(Value))) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  *Data = AsciiStrHexToUintn(Value);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get section entry heximal UINT64 value.
 | 
						|
 | 
						|
  @param[in]  Context         INI Config file context.
 | 
						|
  @param[in]  SectionName     Section name.
 | 
						|
  @param[in]  EntryName       Section entry name.
 | 
						|
  @param[out] Data            Point to the got heximal UINT64 value.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    Section entry heximal UINT64 value is got.
 | 
						|
  @retval EFI_NOT_FOUND  Section is not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetHexUint64FromDataFile (
 | 
						|
  IN      VOID                          *Context,
 | 
						|
  IN      CHAR8                         *SectionName,
 | 
						|
  IN      CHAR8                         *EntryName,
 | 
						|
  OUT     UINT64                        *Data
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                                 *Value;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
 | 
						|
  if (Context == NULL || SectionName == NULL || EntryName == NULL || Data == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = GetStringFromDataFile(
 | 
						|
             Context,
 | 
						|
             SectionName,
 | 
						|
             EntryName,
 | 
						|
             &Value
 | 
						|
             );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  ASSERT (Value != NULL);
 | 
						|
  if (!IsValidHexString(Value, AsciiStrLen(Value))) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  *Data = AsciiStrHexToUint64(Value);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Close an INI config file and free the context.
 | 
						|
 | 
						|
  @param[in] Context         INI Config file context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
CloseIniFile (
 | 
						|
  IN      VOID                          *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  INI_PARSING_LIB_CONTEXT               *IniContext;
 | 
						|
 | 
						|
  if (Context == NULL) {
 | 
						|
    return ;
 | 
						|
  }
 | 
						|
 | 
						|
  IniContext = Context;
 | 
						|
  FreeAllList(IniContext->SectionHead, IniContext->CommentHead);
 | 
						|
 | 
						|
  return;
 | 
						|
}
 |