REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			3421 lines
		
	
	
		
			102 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3421 lines
		
	
	
		
			102 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.
 | 
						|
 | 
						|
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "HiiDatabase.h"
 | 
						|
 | 
						|
extern HII_DATABASE_PRIVATE_DATA  mPrivate;
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the hex UNICODE %02x encoding of a UEFI device path to binary
 | 
						|
  from <PathHdr> of <MultiKeywordRequest>.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  String                 MultiKeywordRequest string.
 | 
						|
  @param  DevicePathData         Binary of a UEFI device path.
 | 
						|
  @param  NextString             string follow the possible PathHdr string.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  The device path is not valid or the incoming parameter is invalid.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Lake of resources to store necessary structures.
 | 
						|
  @retval EFI_SUCCESS            The device path is retrieved and translated to binary format.
 | 
						|
                                 The Input string not include PathHdr section.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractDevicePath (
 | 
						|
  IN  EFI_STRING  String,
 | 
						|
  OUT UINT8       **DevicePathData,
 | 
						|
  OUT EFI_STRING  *NextString
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                     Length;
 | 
						|
  EFI_STRING                PathHdr;
 | 
						|
  UINT8                     *DevicePathBuffer;
 | 
						|
  CHAR16                    TemStr[2];
 | 
						|
  UINTN                     Index;
 | 
						|
  UINT8                     DigitUint8;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
 | 
						|
  ASSERT (NextString != NULL && DevicePathData != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // KeywordRequest == NULL case.
 | 
						|
  //
 | 
						|
  if (String == NULL) {
 | 
						|
    *DevicePathData = NULL;
 | 
						|
    *NextString     = NULL;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip '&' if exist.
 | 
						|
  //
 | 
						|
  if (*String == L'&') {
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the 'PATH=' of <PathHdr>.
 | 
						|
  //
 | 
						|
  if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {
 | 
						|
    if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Not include PathHdr, return success and DevicePath = NULL.
 | 
						|
      //
 | 
						|
      *DevicePathData = NULL;
 | 
						|
      *NextString     = String;
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether path data does exist.
 | 
						|
  //
 | 
						|
  String += StrLen (L"PATH=");
 | 
						|
  if (*String == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  PathHdr = String;
 | 
						|
 | 
						|
  //
 | 
						|
  // The content between 'PATH=' of <ConfigHdr> and '&' of next element
 | 
						|
  // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding
 | 
						|
  // of UEFI device path.
 | 
						|
  //
 | 
						|
  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++) {
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Save the return next keyword string value.
 | 
						|
  //
 | 
						|
  *NextString = String;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check DevicePath Length
 | 
						|
  //
 | 
						|
  if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order
 | 
						|
  // as the device path resides in RAM memory.
 | 
						|
  // Translate the data into binary.
 | 
						|
  //
 | 
						|
  DevicePathBuffer = (UINT8 *)AllocateZeroPool ((Length + 1) / 2);
 | 
						|
  if (DevicePathBuffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert DevicePath
 | 
						|
  //
 | 
						|
  ZeroMem (TemStr, sizeof (TemStr));
 | 
						|
  for (Index = 0; Index < Length; Index++) {
 | 
						|
    TemStr[0]  = PathHdr[Index];
 | 
						|
    DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
 | 
						|
    if ((Index & 1) == 0) {
 | 
						|
      DevicePathBuffer[Index/2] = DigitUint8;
 | 
						|
    } else {
 | 
						|
      DevicePathBuffer[Index/2] = (UINT8)((DevicePathBuffer[Index/2] << 4) + DigitUint8);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate DevicePath
 | 
						|
  //
 | 
						|
  DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathBuffer;
 | 
						|
  while (!IsDevicePathEnd (DevicePath)) {
 | 
						|
    if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {
 | 
						|
      //
 | 
						|
      // Invalid device path
 | 
						|
      //
 | 
						|
      FreePool (DevicePathBuffer);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    DevicePath = NextDevicePathNode (DevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // return the device path
 | 
						|
  //
 | 
						|
  *DevicePathData = DevicePathBuffer;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get NameSpace from the input NameSpaceId string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  String                 <NameSpaceId> format string.
 | 
						|
  @param  NameSpace              Return the name space string.
 | 
						|
  @param  NextString             Return the next string follow namespace.
 | 
						|
 | 
						|
  @retval   EFI_SUCCESS             Get the namespace string success.
 | 
						|
  @retval   EFI_INVALID_PARAMETER   The NameSpaceId string not follow spec definition.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractNameSpace (
 | 
						|
  IN  EFI_STRING  String,
 | 
						|
  OUT CHAR8       **NameSpace,
 | 
						|
  OUT EFI_STRING  *NextString
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16  *TmpPtr;
 | 
						|
  UINTN   NameSpaceSize;
 | 
						|
 | 
						|
  ASSERT (NameSpace != NULL);
 | 
						|
 | 
						|
  TmpPtr = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Input NameSpaceId == NULL
 | 
						|
  //
 | 
						|
  if (String == NULL) {
 | 
						|
    *NameSpace = NULL;
 | 
						|
    if (NextString != NULL) {
 | 
						|
      *NextString = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip '&' if exist.
 | 
						|
  //
 | 
						|
  if (*String == L'&') {
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  String += StrLen (L"NAMESPACE=");
 | 
						|
 | 
						|
  TmpPtr = StrStr (String, L"&");
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (NextString != NULL) {
 | 
						|
    *NextString = String + StrLen (String);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Input NameSpace is unicode string. The language in String package is ascii string.
 | 
						|
  // Here will convert the unicode string to ascii and save it.
 | 
						|
  //
 | 
						|
  NameSpaceSize = StrLen (String) + 1;
 | 
						|
  *NameSpace    = AllocatePool (NameSpaceSize);
 | 
						|
  if (*NameSpace == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeStrToAsciiStrS (String, *NameSpace, NameSpaceSize);
 | 
						|
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = L'&';
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get Keyword from the input KeywordRequest string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  String                 KeywordRequestformat string.
 | 
						|
  @param  Keyword                return the extract keyword string.
 | 
						|
  @param  NextString             return the next string follow this keyword section.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Success to get the keyword string.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Parse the input string return error.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractKeyword (
 | 
						|
  IN  EFI_STRING  String,
 | 
						|
  OUT EFI_STRING  *Keyword,
 | 
						|
  OUT EFI_STRING  *NextString
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STRING  TmpPtr;
 | 
						|
 | 
						|
  ASSERT ((Keyword != NULL) && (NextString != NULL));
 | 
						|
 | 
						|
  TmpPtr = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // KeywordRequest == NULL case.
 | 
						|
  //
 | 
						|
  if (String == NULL) {
 | 
						|
    *Keyword    = NULL;
 | 
						|
    *NextString = NULL;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip '&' if exist.
 | 
						|
  //
 | 
						|
  if (*String == L'&') {
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  String += StrLen (L"KEYWORD=");
 | 
						|
 | 
						|
  TmpPtr = StrStr (String, L"&");
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  *NextString = String + StrLen (String);
 | 
						|
 | 
						|
  *Keyword = AllocateCopyPool (StrSize (String), String);
 | 
						|
  if (*Keyword == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = L'&';
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get value from the input KeywordRequest string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  String                 KeywordRequestformat string.
 | 
						|
  @param  Value                  return the extract value string.
 | 
						|
  @param  NextString             return the next string follow this keyword section.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Success to get the keyword string.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Parse the input string return error.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractValue (
 | 
						|
  IN  EFI_STRING  String,
 | 
						|
  OUT EFI_STRING  *Value,
 | 
						|
  OUT EFI_STRING  *NextString
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STRING  TmpPtr;
 | 
						|
 | 
						|
  ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip '&' if exist.
 | 
						|
  //
 | 
						|
  if (*String == L'&') {
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  String += StrLen (L"VALUE=");
 | 
						|
 | 
						|
  TmpPtr = StrStr (String, L"&");
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  *NextString = String + StrLen (String);
 | 
						|
 | 
						|
  *Value = AllocateCopyPool (StrSize (String), String);
 | 
						|
  if (*Value == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TmpPtr != NULL) {
 | 
						|
    *TmpPtr = L'&';
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get filter from the input KeywordRequest string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  String                 KeywordRequestformat string.
 | 
						|
  @param  FilterFlags            return the filter condition.
 | 
						|
  @param  NextString             return the next string follow this keyword section.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Success to get the keyword string.
 | 
						|
  @retval EFI_INVALID_PARAMETER  Parse the input string return error.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
ExtractFilter (
 | 
						|
  IN  EFI_STRING  String,
 | 
						|
  OUT UINT8       *FilterFlags,
 | 
						|
  OUT EFI_STRING  *NextString
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16   *PathPtr;
 | 
						|
  CHAR16   *KeywordPtr;
 | 
						|
  BOOLEAN  RetVal;
 | 
						|
 | 
						|
  ASSERT ((FilterFlags != NULL) && (NextString != NULL));
 | 
						|
 | 
						|
  //
 | 
						|
  // String end, no filter section.
 | 
						|
  //
 | 
						|
  if (String == NULL) {
 | 
						|
    *NextString = NULL;
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *FilterFlags = 0;
 | 
						|
  RetVal       = TRUE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip '&' if exist.
 | 
						|
  //
 | 
						|
  if (*String == L'&') {
 | 
						|
    String++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {
 | 
						|
    //
 | 
						|
    // Find ReadOnly filter.
 | 
						|
    //
 | 
						|
    *FilterFlags |= EFI_KEYWORD_FILTER_READONY;
 | 
						|
    String       += StrLen (L"ReadOnly");
 | 
						|
  } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {
 | 
						|
    //
 | 
						|
    // Find ReadWrite filter.
 | 
						|
    //
 | 
						|
    *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;
 | 
						|
    String       += StrLen (L"ReadWrite");
 | 
						|
  } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {
 | 
						|
    //
 | 
						|
    // Find Buffer Filter.
 | 
						|
    //
 | 
						|
    *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;
 | 
						|
    String       += StrLen (L"Buffer");
 | 
						|
  } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {
 | 
						|
    //
 | 
						|
    // Find Numeric Filter
 | 
						|
    //
 | 
						|
    String += StrLen (L"Numeric");
 | 
						|
    if (*String != L':') {
 | 
						|
      *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;
 | 
						|
    } else {
 | 
						|
      String++;
 | 
						|
      switch (*String) {
 | 
						|
        case L'1':
 | 
						|
          *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;
 | 
						|
          break;
 | 
						|
        case L'2':
 | 
						|
          *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;
 | 
						|
          break;
 | 
						|
        case L'4':
 | 
						|
          *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;
 | 
						|
          break;
 | 
						|
        case L'8':
 | 
						|
          *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          ASSERT (FALSE);
 | 
						|
          break;
 | 
						|
      }
 | 
						|
 | 
						|
      String++;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Check whether other filter item defined by Platform.
 | 
						|
    //
 | 
						|
    if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||
 | 
						|
        (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // New KeywordRequest start, no platform defined filter.
 | 
						|
      //
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Platform defined filter rule.
 | 
						|
      // Just skip platform defined filter rule, return success.
 | 
						|
      //
 | 
						|
      PathPtr    = StrStr (String, L"&PATH");
 | 
						|
      KeywordPtr = StrStr (String, L"&KEYWORD");
 | 
						|
      if ((PathPtr != NULL) && (KeywordPtr != NULL)) {
 | 
						|
        //
 | 
						|
        // If both sections exist, return the first follow string.
 | 
						|
        //
 | 
						|
        String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;
 | 
						|
      } else if (PathPtr != NULL) {
 | 
						|
        //
 | 
						|
        // Should not exist PathPtr != NULL && KeywordPtr == NULL case.
 | 
						|
        //
 | 
						|
        ASSERT (FALSE);
 | 
						|
      } else if (KeywordPtr != NULL) {
 | 
						|
        //
 | 
						|
        // Just to the next keyword section.
 | 
						|
        //
 | 
						|
        String = KeywordPtr;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Only has platform defined filter section, just skip it.
 | 
						|
        //
 | 
						|
        String += StrLen (String);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    RetVal = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *NextString = String;
 | 
						|
 | 
						|
  return RetVal;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Extract Readonly flag from opcode.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  OpCodeData             Input opcode for this question.
 | 
						|
 | 
						|
  @retval TRUE                   This question is readonly.
 | 
						|
  @retval FALSE                  This question is not readonly.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
ExtractReadOnlyFromOpCode (
 | 
						|
  IN  UINT8  *OpCodeData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IFR_QUESTION_HEADER  *QuestionHdr;
 | 
						|
 | 
						|
  ASSERT (OpCodeData != NULL);
 | 
						|
 | 
						|
  QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
 | 
						|
 | 
						|
  return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create a circuit to check the filter section.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  OpCodeData             The question binary ifr data.
 | 
						|
  @param  KeywordRequest         KeywordRequestformat string.
 | 
						|
  @param  NextString             return the next string follow this keyword section.
 | 
						|
  @param  ReadOnly               Return whether this question is read only.
 | 
						|
 | 
						|
  @retval KEYWORD_HANDLER_NO_ERROR                     Success validate.
 | 
						|
  @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED  Validate fail.
 | 
						|
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
ValidateFilter (
 | 
						|
  IN  UINT8    *OpCodeData,
 | 
						|
  IN  CHAR16   *KeywordRequest,
 | 
						|
  OUT CHAR16   **NextString,
 | 
						|
  OUT BOOLEAN  *ReadOnly
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16                   *NextFilter;
 | 
						|
  CHAR16                   *StringPtr;
 | 
						|
  UINT8                    FilterFlags;
 | 
						|
  EFI_IFR_QUESTION_HEADER  *QuestionHdr;
 | 
						|
  EFI_IFR_OP_HEADER        *OpCodeHdr;
 | 
						|
  UINT8                    Flags;
 | 
						|
  UINT32                   RetVal;
 | 
						|
 | 
						|
  RetVal    = KEYWORD_HANDLER_NO_ERROR;
 | 
						|
  StringPtr = KeywordRequest;
 | 
						|
 | 
						|
  OpCodeHdr   = (EFI_IFR_OP_HEADER *)OpCodeData;
 | 
						|
  QuestionHdr = (EFI_IFR_QUESTION_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
 | 
						|
  if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
 | 
						|
    Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));
 | 
						|
  } else {
 | 
						|
    Flags = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get ReadOnly flag from Question.
 | 
						|
  //
 | 
						|
  *ReadOnly = ExtractReadOnlyFromOpCode (OpCodeData);
 | 
						|
 | 
						|
  while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {
 | 
						|
    switch (FilterFlags) {
 | 
						|
      case EFI_KEYWORD_FILTER_READONY:
 | 
						|
        if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {
 | 
						|
          RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_KEYWORD_FILTER_REAWRITE:
 | 
						|
        if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {
 | 
						|
          RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_KEYWORD_FILTER_BUFFER:
 | 
						|
        //
 | 
						|
        // Only these three opcode use numeric value type.
 | 
						|
        //
 | 
						|
        if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) || (OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP)) {
 | 
						|
          RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_KEYWORD_FILTER_NUMERIC:
 | 
						|
        if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
 | 
						|
          RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_KEYWORD_FILTER_NUMERIC_1:
 | 
						|
      case EFI_KEYWORD_FILTER_NUMERIC_2:
 | 
						|
      case EFI_KEYWORD_FILTER_NUMERIC_4:
 | 
						|
      case EFI_KEYWORD_FILTER_NUMERIC_8:
 | 
						|
        if ((OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP) && (OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP) && (OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP)) {
 | 
						|
          RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // For numeric and oneof, it has flags field to specify the detail numeric type.
 | 
						|
        //
 | 
						|
        if ((OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP) || (OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP)) {
 | 
						|
          switch (Flags & EFI_IFR_NUMERIC_SIZE) {
 | 
						|
            case EFI_IFR_NUMERIC_SIZE_1:
 | 
						|
              if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {
 | 
						|
                RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
                goto Done;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
 | 
						|
            case EFI_IFR_NUMERIC_SIZE_2:
 | 
						|
              if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {
 | 
						|
                RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
                goto Done;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
 | 
						|
            case EFI_IFR_NUMERIC_SIZE_4:
 | 
						|
              if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {
 | 
						|
                RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
                goto Done;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
 | 
						|
            case EFI_IFR_NUMERIC_SIZE_8:
 | 
						|
              if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {
 | 
						|
                RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
                goto Done;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
 | 
						|
            default:
 | 
						|
              ASSERT (FALSE);
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        ASSERT (FALSE);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Jump to the next filter.
 | 
						|
    //
 | 
						|
    StringPtr = NextFilter;
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  //
 | 
						|
  // The current filter which is processing.
 | 
						|
  //
 | 
						|
  *NextString = StringPtr;
 | 
						|
 | 
						|
  return RetVal;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get HII_DATABASE_RECORD from the input device path info.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  DevicePath             UEFI device path protocol.
 | 
						|
 | 
						|
  @retval Internal data base record.
 | 
						|
 | 
						|
**/
 | 
						|
HII_DATABASE_RECORD *
 | 
						|
GetRecordFromDevicePath (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY           *Link;
 | 
						|
  UINT8                *DevicePathPkg;
 | 
						|
  UINT8                *CurrentDevicePath;
 | 
						|
  UINTN                DevicePathSize;
 | 
						|
  HII_DATABASE_RECORD  *TempDatabase;
 | 
						|
 | 
						|
  ASSERT (DevicePath != NULL);
 | 
						|
 | 
						|
  for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
 | 
						|
    TempDatabase  = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
 | 
						|
    DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;
 | 
						|
    if (DevicePathPkg != NULL) {
 | 
						|
      CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
      DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)CurrentDevicePath);
 | 
						|
      if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {
 | 
						|
        return TempDatabase;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Calculate the size of StringSrc and output it. Also copy string text from src
 | 
						|
  to dest.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  StringSrc              Points to current null-terminated string.
 | 
						|
  @param  BufferSize             Length of the buffer.
 | 
						|
  @param  StringDest             Buffer to store the string text.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The string text was outputted successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Out of resource.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetUnicodeStringTextAndSize (
 | 
						|
  IN  UINT8       *StringSrc,
 | 
						|
  OUT UINTN       *BufferSize,
 | 
						|
  OUT EFI_STRING  *StringDest
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  StringSize;
 | 
						|
  UINT8  *StringPtr;
 | 
						|
 | 
						|
  ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);
 | 
						|
 | 
						|
  StringSize = sizeof (CHAR16);
 | 
						|
  StringPtr  = StringSrc;
 | 
						|
  while (ReadUnaligned16 ((UINT16 *)StringPtr) != 0) {
 | 
						|
    StringSize += sizeof (CHAR16);
 | 
						|
    StringPtr  += sizeof (CHAR16);
 | 
						|
  }
 | 
						|
 | 
						|
  *StringDest = AllocatePool (StringSize);
 | 
						|
  if (*StringDest == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (*StringDest, StringSrc, StringSize);
 | 
						|
 | 
						|
  *BufferSize = StringSize;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the string id for the input keyword.
 | 
						|
 | 
						|
  @param  StringPackage           Hii string package instance.
 | 
						|
  @param  KeywordValue            Input keyword value.
 | 
						|
  @param  StringId                The string's id, which is unique within PackageList.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The string text and font is retrieved
 | 
						|
                                  successfully.
 | 
						|
  @retval EFI_NOT_FOUND           The specified text or font info can not be found
 | 
						|
                                  out.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the
 | 
						|
                                  task.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetStringIdFromString (
 | 
						|
  IN HII_STRING_PACKAGE_INSTANCE  *StringPackage,
 | 
						|
  IN CHAR16                       *KeywordValue,
 | 
						|
  OUT EFI_STRING_ID               *StringId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                    *BlockHdr;
 | 
						|
  EFI_STRING_ID            CurrentStringId;
 | 
						|
  UINTN                    BlockSize;
 | 
						|
  UINTN                    Index;
 | 
						|
  UINT8                    *StringTextPtr;
 | 
						|
  UINTN                    Offset;
 | 
						|
  UINT16                   StringCount;
 | 
						|
  UINT16                   SkipCount;
 | 
						|
  UINT8                    Length8;
 | 
						|
  EFI_HII_SIBT_EXT2_BLOCK  Ext2;
 | 
						|
  UINT32                   Length32;
 | 
						|
  UINTN                    StringSize;
 | 
						|
  CHAR16                   *String;
 | 
						|
  CHAR8                    *AsciiKeywordValue;
 | 
						|
  UINTN                    KeywordValueSize;
 | 
						|
  EFI_STATUS               Status;
 | 
						|
 | 
						|
  ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);
 | 
						|
  ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
  CurrentStringId = 1;
 | 
						|
  Status          = EFI_SUCCESS;
 | 
						|
  String          = NULL;
 | 
						|
  BlockHdr        = StringPackage->StringBlock;
 | 
						|
  BlockSize       = 0;
 | 
						|
  Offset          = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make a ascii keyword value for later use.
 | 
						|
  //
 | 
						|
  KeywordValueSize  = StrLen (KeywordValue) + 1;
 | 
						|
  AsciiKeywordValue = AllocatePool (KeywordValueSize);
 | 
						|
  if (AsciiKeywordValue == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeStrToAsciiStrS (KeywordValue, AsciiKeywordValue, KeywordValueSize);
 | 
						|
 | 
						|
  while (*BlockHdr != EFI_HII_SIBT_END) {
 | 
						|
    switch (*BlockHdr) {
 | 
						|
      case EFI_HII_SIBT_STRING_SCSU:
 | 
						|
        Offset        = sizeof (EFI_HII_STRING_BLOCK);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        BlockSize    += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
        if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
 | 
						|
          *StringId = CurrentStringId;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_SCSU_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
 | 
						|
          *StringId = CurrentStringId;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_SCSU:
 | 
						|
        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
 | 
						|
        BlockSize    += StringTextPtr - BlockHdr;
 | 
						|
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
 | 
						|
            *StringId = CurrentStringId;
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_SCSU_FONT:
 | 
						|
        CopyMem (
 | 
						|
          &StringCount,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT16)
 | 
						|
          );
 | 
						|
        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
 | 
						|
        BlockSize    += StringTextPtr - BlockHdr;
 | 
						|
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          BlockSize += AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          if (AsciiStrCmp (AsciiKeywordValue, (CHAR8 *)StringTextPtr) == 0) {
 | 
						|
            *StringId = CurrentStringId;
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_UCS2:
 | 
						|
        Offset        = sizeof (EFI_HII_STRING_BLOCK);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        //
 | 
						|
        // Use StringSize to store the size of the specified string, including the NULL
 | 
						|
        // terminator.
 | 
						|
        //
 | 
						|
        Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        ASSERT (String != NULL);
 | 
						|
        if (StrCmp (KeywordValue, String) == 0) {
 | 
						|
          *StringId = CurrentStringId;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + StringSize;
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_UCS2_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        //
 | 
						|
        // Use StringSize to store the size of the specified string, including the NULL
 | 
						|
        // terminator.
 | 
						|
        //
 | 
						|
        Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        ASSERT (String != NULL);
 | 
						|
        if (StrCmp (KeywordValue, String) == 0) {
 | 
						|
          *StringId = CurrentStringId;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + StringSize;
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_UCS2:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        BlockSize    += Offset;
 | 
						|
        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          ASSERT (String != NULL);
 | 
						|
          BlockSize += StringSize;
 | 
						|
          if (StrCmp (KeywordValue, String) == 0) {
 | 
						|
            *StringId = CurrentStringId;
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          StringTextPtr = StringTextPtr + StringSize;
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_UCS2_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        BlockSize    += Offset;
 | 
						|
        CopyMem (
 | 
						|
          &StringCount,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT16)
 | 
						|
          );
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          ASSERT (String != NULL);
 | 
						|
          BlockSize += StringSize;
 | 
						|
          if (StrCmp (KeywordValue, String) == 0) {
 | 
						|
            *StringId = CurrentStringId;
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          StringTextPtr = StringTextPtr + StringSize;
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_DUPLICATE:
 | 
						|
        BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_SKIP1:
 | 
						|
        SkipCount       = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
 | 
						|
        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
 | 
						|
        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_SKIP2:
 | 
						|
        CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
 | 
						|
        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT1:
 | 
						|
        CopyMem (
 | 
						|
          &Length8,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT8)
 | 
						|
          );
 | 
						|
        BlockSize += Length8;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT2:
 | 
						|
        CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
 | 
						|
        BlockSize += Ext2.Length;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT4:
 | 
						|
        CopyMem (
 | 
						|
          &Length32,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT32)
 | 
						|
          );
 | 
						|
 | 
						|
        BlockSize += Length32;
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (String != NULL) {
 | 
						|
      FreePool (String);
 | 
						|
      String = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    BlockHdr = StringPackage->StringBlock + BlockSize;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_NOT_FOUND;
 | 
						|
 | 
						|
Done:
 | 
						|
  if (AsciiKeywordValue != NULL) {
 | 
						|
    FreePool (AsciiKeywordValue);
 | 
						|
  }
 | 
						|
 | 
						|
  if (String != NULL) {
 | 
						|
    FreePool (String);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the next valid string id for the input string id.
 | 
						|
 | 
						|
  @param  StringPackage           Hii string package instance.
 | 
						|
  @param  StringId                The current string id which is already got.
 | 
						|
                                  1 means just begin to get the string id.
 | 
						|
  @param  KeywordValue            Return the string for the next string id.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_STRING_ID           Not 0 means a valid stringid found.
 | 
						|
                                  0 means not found a valid string id.
 | 
						|
**/
 | 
						|
EFI_STRING_ID
 | 
						|
GetNextStringId (
 | 
						|
  IN  HII_STRING_PACKAGE_INSTANCE  *StringPackage,
 | 
						|
  IN  EFI_STRING_ID                StringId,
 | 
						|
  OUT EFI_STRING                   *KeywordValue
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                    *BlockHdr;
 | 
						|
  EFI_STRING_ID            CurrentStringId;
 | 
						|
  UINTN                    BlockSize;
 | 
						|
  UINTN                    Index;
 | 
						|
  UINT8                    *StringTextPtr;
 | 
						|
  UINTN                    Offset;
 | 
						|
  UINT16                   StringCount;
 | 
						|
  UINT16                   SkipCount;
 | 
						|
  UINT8                    Length8;
 | 
						|
  EFI_HII_SIBT_EXT2_BLOCK  Ext2;
 | 
						|
  UINT32                   Length32;
 | 
						|
  BOOLEAN                  FindString;
 | 
						|
  UINTN                    StringSize;
 | 
						|
  CHAR16                   *String;
 | 
						|
 | 
						|
  ASSERT (StringPackage != NULL);
 | 
						|
  ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
  CurrentStringId = 1;
 | 
						|
  FindString      = FALSE;
 | 
						|
  String          = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the string blocks to get the string text and font.
 | 
						|
  //
 | 
						|
  BlockHdr  = StringPackage->StringBlock;
 | 
						|
  BlockSize = 0;
 | 
						|
  Offset    = 0;
 | 
						|
  while (*BlockHdr != EFI_HII_SIBT_END) {
 | 
						|
    switch (*BlockHdr) {
 | 
						|
      case EFI_HII_SIBT_STRING_SCSU:
 | 
						|
        Offset        = sizeof (EFI_HII_STRING_BLOCK);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
 | 
						|
        if (FindString) {
 | 
						|
          StringSize    = AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
 | 
						|
          if (*KeywordValue == NULL) {
 | 
						|
            return 0;
 | 
						|
          }
 | 
						|
 | 
						|
          AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
 | 
						|
          return CurrentStringId;
 | 
						|
        } else if (CurrentStringId == StringId) {
 | 
						|
          FindString = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_SCSU_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
 | 
						|
        if (FindString) {
 | 
						|
          StringSize    = AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
 | 
						|
          if (*KeywordValue == NULL) {
 | 
						|
            return 0;
 | 
						|
          }
 | 
						|
 | 
						|
          AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
 | 
						|
          return CurrentStringId;
 | 
						|
        } else if (CurrentStringId == StringId) {
 | 
						|
          FindString = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_SCSU:
 | 
						|
        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
 | 
						|
        BlockSize    += StringTextPtr - BlockHdr;
 | 
						|
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          if (FindString) {
 | 
						|
            StringSize    = AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
            *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
 | 
						|
            if (*KeywordValue == NULL) {
 | 
						|
              return 0;
 | 
						|
            }
 | 
						|
 | 
						|
            AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
 | 
						|
            return CurrentStringId;
 | 
						|
          } else if (CurrentStringId == StringId) {
 | 
						|
            FindString = TRUE;
 | 
						|
          }
 | 
						|
 | 
						|
          BlockSize    += AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_SCSU_FONT:
 | 
						|
        CopyMem (
 | 
						|
          &StringCount,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT16)
 | 
						|
          );
 | 
						|
        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
 | 
						|
        BlockSize    += StringTextPtr - BlockHdr;
 | 
						|
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          if (FindString) {
 | 
						|
            StringSize    = AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
            *KeywordValue = AllocatePool (StringSize * sizeof (CHAR16));
 | 
						|
            if (*KeywordValue == NULL) {
 | 
						|
              return 0;
 | 
						|
            }
 | 
						|
 | 
						|
            AsciiStrToUnicodeStrS ((CHAR8 *)StringTextPtr, *KeywordValue, StringSize);
 | 
						|
            return CurrentStringId;
 | 
						|
          } else if (CurrentStringId == StringId) {
 | 
						|
            FindString = TRUE;
 | 
						|
          }
 | 
						|
 | 
						|
          BlockSize    += AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr);
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_UCS2:
 | 
						|
        Offset        = sizeof (EFI_HII_STRING_BLOCK);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        //
 | 
						|
        // Use StringSize to store the size of the specified string, including the NULL
 | 
						|
        // terminator.
 | 
						|
        //
 | 
						|
        GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
        if (FindString && (String != NULL) && (*String != L'\0')) {
 | 
						|
          //
 | 
						|
          // String protocol use this type for the string id which has value for other package.
 | 
						|
          // It will allocate an empty string block for this string id. so here we also check
 | 
						|
          // *String != L'\0' to prohibit this case.
 | 
						|
          //
 | 
						|
          *KeywordValue = String;
 | 
						|
          return CurrentStringId;
 | 
						|
        } else if (CurrentStringId == StringId) {
 | 
						|
          FindString = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + StringSize;
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRING_UCS2_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        //
 | 
						|
        // Use StringSize to store the size of the specified string, including the NULL
 | 
						|
        // terminator.
 | 
						|
        //
 | 
						|
        GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
        if (FindString) {
 | 
						|
          *KeywordValue = String;
 | 
						|
          return CurrentStringId;
 | 
						|
        } else if (CurrentStringId == StringId) {
 | 
						|
          FindString = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
        BlockSize += Offset + StringSize;
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_UCS2:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        BlockSize    += Offset;
 | 
						|
        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
 | 
						|
          if (FindString) {
 | 
						|
            *KeywordValue = String;
 | 
						|
            return CurrentStringId;
 | 
						|
          } else if (CurrentStringId == StringId) {
 | 
						|
            FindString = TRUE;
 | 
						|
          }
 | 
						|
 | 
						|
          BlockSize    += StringSize;
 | 
						|
          StringTextPtr = StringTextPtr + StringSize;
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_STRINGS_UCS2_FONT:
 | 
						|
        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
 | 
						|
        StringTextPtr = BlockHdr + Offset;
 | 
						|
        BlockSize    += Offset;
 | 
						|
        CopyMem (
 | 
						|
          &StringCount,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT16)
 | 
						|
          );
 | 
						|
        for (Index = 0; Index < StringCount; Index++) {
 | 
						|
          GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);
 | 
						|
          if (FindString) {
 | 
						|
            *KeywordValue = String;
 | 
						|
            return CurrentStringId;
 | 
						|
          } else if (CurrentStringId == StringId) {
 | 
						|
            FindString = TRUE;
 | 
						|
          }
 | 
						|
 | 
						|
          BlockSize    += StringSize;
 | 
						|
          StringTextPtr = StringTextPtr + StringSize;
 | 
						|
          CurrentStringId++;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_DUPLICATE:
 | 
						|
        BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
 | 
						|
        CurrentStringId++;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_SKIP1:
 | 
						|
        SkipCount       = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
 | 
						|
        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
 | 
						|
        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_SKIP2:
 | 
						|
        CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
 | 
						|
        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
 | 
						|
        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT1:
 | 
						|
        CopyMem (
 | 
						|
          &Length8,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT8)
 | 
						|
          );
 | 
						|
        BlockSize += Length8;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT2:
 | 
						|
        CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
 | 
						|
        BlockSize += Ext2.Length;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HII_SIBT_EXT4:
 | 
						|
        CopyMem (
 | 
						|
          &Length32,
 | 
						|
          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),
 | 
						|
          sizeof (UINT32)
 | 
						|
          );
 | 
						|
 | 
						|
        BlockSize += Length32;
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (String != NULL) {
 | 
						|
      FreePool (String);
 | 
						|
      String = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    BlockHdr = StringPackage->StringBlock + BlockSize;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get string package from the input NameSpace string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.
 | 
						|
  @param  NameSpace                      NameSpace format string.
 | 
						|
  @param  KeywordValue                   Keyword value.
 | 
						|
  @param  StringId                       String Id for this keyword.
 | 
						|
 | 
						|
  @retval KEYWORD_HANDLER_NO_ERROR                     Get String id successfully.
 | 
						|
  @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND            Not found the string id in the string package.
 | 
						|
  @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND       Not found the string package for this namespace.
 | 
						|
  @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR   Out of resource error.
 | 
						|
 | 
						|
**/
 | 
						|
UINT32
 | 
						|
GetStringIdFromRecord (
 | 
						|
  IN HII_DATABASE_RECORD  *DatabaseRecord,
 | 
						|
  IN CHAR8                **NameSpace,
 | 
						|
  IN CHAR16               *KeywordValue,
 | 
						|
  OUT EFI_STRING_ID       *StringId
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
 | 
						|
  HII_STRING_PACKAGE_INSTANCE         *StringPackage;
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  CHAR8                               *Name;
 | 
						|
  UINT32                              RetVal;
 | 
						|
 | 
						|
  ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);
 | 
						|
 | 
						|
  PackageListNode = DatabaseRecord->PackageList;
 | 
						|
  RetVal          = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
 | 
						|
 | 
						|
  if (*NameSpace != NULL) {
 | 
						|
    Name = *NameSpace;
 | 
						|
  } else {
 | 
						|
    Name = UEFI_CONFIG_LANG;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {
 | 
						|
    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
    if (AsciiStrnCmp (Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {
 | 
						|
      Status = GetStringIdFromString (StringPackage, KeywordValue, StringId);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
 | 
						|
      } else {
 | 
						|
        if (*NameSpace == NULL) {
 | 
						|
          *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
 | 
						|
          if (*NameSpace == NULL) {
 | 
						|
            return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        return KEYWORD_HANDLER_NO_ERROR;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return RetVal;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Tell whether this Operand is an Statement OpCode.
 | 
						|
 | 
						|
  @param  Operand                Operand of an IFR OpCode.
 | 
						|
 | 
						|
  @retval TRUE                   This is an Statement OpCode.
 | 
						|
  @retval FALSE                  Not an Statement OpCode.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsStatementOpCode (
 | 
						|
  IN UINT8  Operand
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((Operand == EFI_IFR_SUBTITLE_OP) ||
 | 
						|
      (Operand == EFI_IFR_TEXT_OP) ||
 | 
						|
      (Operand == EFI_IFR_RESET_BUTTON_OP) ||
 | 
						|
      (Operand == EFI_IFR_REF_OP) ||
 | 
						|
      (Operand == EFI_IFR_ACTION_OP) ||
 | 
						|
      (Operand == EFI_IFR_NUMERIC_OP) ||
 | 
						|
      (Operand == EFI_IFR_ORDERED_LIST_OP) ||
 | 
						|
      (Operand == EFI_IFR_CHECKBOX_OP) ||
 | 
						|
      (Operand == EFI_IFR_STRING_OP) ||
 | 
						|
      (Operand == EFI_IFR_PASSWORD_OP) ||
 | 
						|
      (Operand == EFI_IFR_DATE_OP) ||
 | 
						|
      (Operand == EFI_IFR_TIME_OP) ||
 | 
						|
      (Operand == EFI_IFR_GUID_OP) ||
 | 
						|
      (Operand == EFI_IFR_ONE_OF_OP))
 | 
						|
  {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Tell whether this Operand is an Statement OpCode.
 | 
						|
 | 
						|
  @param  Operand                Operand of an IFR OpCode.
 | 
						|
 | 
						|
  @retval TRUE                   This is an Statement OpCode.
 | 
						|
  @retval FALSE                  Not an Statement OpCode.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsStorageOpCode (
 | 
						|
  IN UINT8  Operand
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((Operand == EFI_IFR_VARSTORE_OP) ||
 | 
						|
      (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||
 | 
						|
      (Operand == EFI_IFR_VARSTORE_EFI_OP))
 | 
						|
  {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Base on the prompt string id to find the question.
 | 
						|
 | 
						|
  @param  FormPackage            The input form package.
 | 
						|
  @param  KeywordStrId           The input prompt string id for one question.
 | 
						|
 | 
						|
  @retval  the opcode for the question.
 | 
						|
 | 
						|
**/
 | 
						|
UINT8 *
 | 
						|
FindQuestionFromStringId (
 | 
						|
  IN HII_IFR_PACKAGE_INSTANCE  *FormPackage,
 | 
						|
  IN EFI_STRING_ID             KeywordStrId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                     *OpCodeData;
 | 
						|
  UINT32                    Offset;
 | 
						|
  EFI_IFR_STATEMENT_HEADER  *StatementHeader;
 | 
						|
  EFI_IFR_OP_HEADER         *OpCodeHeader;
 | 
						|
  UINT32                    FormDataLen;
 | 
						|
 | 
						|
  ASSERT (FormPackage != NULL);
 | 
						|
 | 
						|
  FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
  Offset      = 0;
 | 
						|
  while (Offset < FormDataLen) {
 | 
						|
    OpCodeData   = FormPackage->IfrData + Offset;
 | 
						|
    OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
 | 
						|
 | 
						|
    if (IsStatementOpCode (OpCodeHeader->OpCode)) {
 | 
						|
      StatementHeader = (EFI_IFR_STATEMENT_HEADER *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER));
 | 
						|
      if (StatementHeader->Prompt == KeywordStrId) {
 | 
						|
        return OpCodeData;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Offset += OpCodeHeader->Length;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Base on the varstore id to find the storage info.
 | 
						|
 | 
						|
  @param  FormPackage            The input form package.
 | 
						|
  @param  VarStoreId             The input storage id.
 | 
						|
 | 
						|
  @retval  the opcode for the storage.
 | 
						|
 | 
						|
**/
 | 
						|
UINT8 *
 | 
						|
FindStorageFromVarId (
 | 
						|
  IN HII_IFR_PACKAGE_INSTANCE  *FormPackage,
 | 
						|
  IN EFI_VARSTORE_ID           VarStoreId
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8              *OpCodeData;
 | 
						|
  UINT32             Offset;
 | 
						|
  EFI_IFR_OP_HEADER  *OpCodeHeader;
 | 
						|
  UINT32             FormDataLen;
 | 
						|
 | 
						|
  ASSERT (FormPackage != NULL);
 | 
						|
 | 
						|
  FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
  Offset      = 0;
 | 
						|
  while (Offset < FormDataLen) {
 | 
						|
    OpCodeData   = FormPackage->IfrData + Offset;
 | 
						|
    OpCodeHeader = (EFI_IFR_OP_HEADER *)OpCodeData;
 | 
						|
 | 
						|
    if (IsStorageOpCode (OpCodeHeader->OpCode)) {
 | 
						|
      switch (OpCodeHeader->OpCode) {
 | 
						|
        case EFI_IFR_VARSTORE_OP:
 | 
						|
          if (VarStoreId == ((EFI_IFR_VARSTORE *)OpCodeData)->VarStoreId) {
 | 
						|
            return OpCodeData;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
 | 
						|
        case EFI_IFR_VARSTORE_NAME_VALUE_OP:
 | 
						|
          if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->VarStoreId) {
 | 
						|
            return OpCodeData;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
 | 
						|
        case EFI_IFR_VARSTORE_EFI_OP:
 | 
						|
          if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *)OpCodeData)->VarStoreId) {
 | 
						|
            return OpCodeData;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Offset += OpCodeHeader->Length;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get width info for one question.
 | 
						|
 | 
						|
  @param  OpCodeData            The input opcode for one question.
 | 
						|
 | 
						|
  @retval  the width info for one question.
 | 
						|
 | 
						|
**/
 | 
						|
UINT16
 | 
						|
GetWidth (
 | 
						|
  IN UINT8  *OpCodeData
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  *NextOpCodeData;
 | 
						|
 | 
						|
  ASSERT (OpCodeData != NULL);
 | 
						|
 | 
						|
  switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
 | 
						|
    case EFI_IFR_REF_OP:
 | 
						|
      return (UINT16)sizeof (EFI_HII_REF);
 | 
						|
 | 
						|
    case EFI_IFR_ONE_OF_OP:
 | 
						|
    case EFI_IFR_NUMERIC_OP:
 | 
						|
      switch (((EFI_IFR_ONE_OF *)OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {
 | 
						|
        case EFI_IFR_NUMERIC_SIZE_1:
 | 
						|
          return (UINT16)sizeof (UINT8);
 | 
						|
 | 
						|
        case EFI_IFR_NUMERIC_SIZE_2:
 | 
						|
          return (UINT16)sizeof (UINT16);
 | 
						|
 | 
						|
        case EFI_IFR_NUMERIC_SIZE_4:
 | 
						|
          return (UINT16)sizeof (UINT32);
 | 
						|
 | 
						|
        case EFI_IFR_NUMERIC_SIZE_8:
 | 
						|
          return (UINT16)sizeof (UINT64);
 | 
						|
 | 
						|
        default:
 | 
						|
          ASSERT (FALSE);
 | 
						|
          return 0;
 | 
						|
      }
 | 
						|
 | 
						|
    case EFI_IFR_ORDERED_LIST_OP:
 | 
						|
      NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *)OpCodeData)->Header.Length;
 | 
						|
      //
 | 
						|
      // OneOfOption must follow the orderedlist opcode.
 | 
						|
      //
 | 
						|
      ASSERT (((EFI_IFR_OP_HEADER *)NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);
 | 
						|
      switch (((EFI_IFR_ONE_OF_OPTION *)NextOpCodeData)->Type) {
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_8:
 | 
						|
          return (UINT16)sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
 | 
						|
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_16:
 | 
						|
          return (UINT16)sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
 | 
						|
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_32:
 | 
						|
          return (UINT16)sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
 | 
						|
 | 
						|
        case EFI_IFR_TYPE_NUM_SIZE_64:
 | 
						|
          return (UINT16)sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *)OpCodeData)->MaxContainers;
 | 
						|
 | 
						|
        default:
 | 
						|
          ASSERT (FALSE);
 | 
						|
          return 0;
 | 
						|
      }
 | 
						|
 | 
						|
    case EFI_IFR_CHECKBOX_OP:
 | 
						|
      return (UINT16)sizeof (BOOLEAN);
 | 
						|
 | 
						|
    case EFI_IFR_PASSWORD_OP:
 | 
						|
      return (UINT16)((UINTN)((EFI_IFR_PASSWORD *)OpCodeData)->MaxSize * sizeof (CHAR16));
 | 
						|
 | 
						|
    case EFI_IFR_STRING_OP:
 | 
						|
      return (UINT16)((UINTN)((EFI_IFR_STRING *)OpCodeData)->MaxSize * sizeof (CHAR16));
 | 
						|
 | 
						|
    case EFI_IFR_DATE_OP:
 | 
						|
      return (UINT16)sizeof (EFI_HII_DATE);
 | 
						|
 | 
						|
    case EFI_IFR_TIME_OP:
 | 
						|
      return (UINT16)sizeof (EFI_HII_TIME);
 | 
						|
 | 
						|
    default:
 | 
						|
      ASSERT (FALSE);
 | 
						|
      return 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Converts all hex string characters in range ['A'..'F'] to ['a'..'f'] for
 | 
						|
  hex digits that appear between a '=' and a '&' in a config string.
 | 
						|
 | 
						|
  If ConfigString is NULL, then ASSERT().
 | 
						|
 | 
						|
  @param[in] ConfigString  Pointer to a Null-terminated Unicode string.
 | 
						|
 | 
						|
  @return  Pointer to the Null-terminated Unicode result string.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STRING
 | 
						|
EFIAPI
 | 
						|
InternalLowerConfigString (
 | 
						|
  IN EFI_STRING  ConfigString
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STRING  String;
 | 
						|
  BOOLEAN     Lower;
 | 
						|
 | 
						|
  ASSERT (ConfigString != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert all hex digits in range [A-F] in the configuration header to [a-f]
 | 
						|
  //
 | 
						|
  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
 | 
						|
    if (*String == L'=') {
 | 
						|
      Lower = TRUE;
 | 
						|
    } else if (*String == L'&') {
 | 
						|
      Lower = FALSE;
 | 
						|
    } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
 | 
						|
      *String = (CHAR16)(*String - L'A' + L'a');
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ConfigString;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Allocates and returns a Null-terminated Unicode <ConfigHdr> string.
 | 
						|
 | 
						|
  The format of a <ConfigHdr> is as follows:
 | 
						|
 | 
						|
    GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
 | 
						|
 | 
						|
  @param[in]  OpCodeData    The opcode for the storage.
 | 
						|
  @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol
 | 
						|
                            that is the routing information PATH.  Each byte of
 | 
						|
                            the Device Path associated with DriverHandle is converted
 | 
						|
                            to a 2 Unicode character hexadecimal string.
 | 
						|
 | 
						|
  @retval NULL   DriverHandle does not support the Device Path Protocol.
 | 
						|
  @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STRING
 | 
						|
ConstructConfigHdr (
 | 
						|
  IN UINT8       *OpCodeData,
 | 
						|
  IN EFI_HANDLE  DriverHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                     NameLength;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  UINTN                     DevicePathSize;
 | 
						|
  CHAR16                    *String;
 | 
						|
  CHAR16                    *ReturnString;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINT8                     *Buffer;
 | 
						|
  CHAR16                    *Name;
 | 
						|
  CHAR8                     *AsciiName;
 | 
						|
  UINTN                     NameSize;
 | 
						|
  EFI_GUID                  *Guid;
 | 
						|
  UINTN                     MaxLen;
 | 
						|
 | 
						|
  ASSERT (OpCodeData != NULL);
 | 
						|
 | 
						|
  switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {
 | 
						|
    case EFI_IFR_VARSTORE_OP:
 | 
						|
      Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *)OpCodeData)->Guid;
 | 
						|
      AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE *)OpCodeData)->Name;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_IFR_VARSTORE_NAME_VALUE_OP:
 | 
						|
      Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *)OpCodeData)->Guid;
 | 
						|
      AsciiName = NULL;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_IFR_VARSTORE_EFI_OP:
 | 
						|
      Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Guid;
 | 
						|
      AsciiName = (CHAR8 *)((EFI_IFR_VARSTORE_EFI *)OpCodeData)->Name;
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      ASSERT (FALSE);
 | 
						|
      Guid      = NULL;
 | 
						|
      AsciiName = NULL;
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (AsciiName != NULL) {
 | 
						|
    NameSize = AsciiStrSize (AsciiName);
 | 
						|
    Name     = AllocateZeroPool (NameSize * sizeof (CHAR16));
 | 
						|
    ASSERT (Name != NULL);
 | 
						|
    AsciiStrToUnicodeStrS (AsciiName, Name, NameSize);
 | 
						|
  } else {
 | 
						|
    Name = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the length of Name in Unicode characters.
 | 
						|
  // If Name is NULL, then the length is 0.
 | 
						|
  //
 | 
						|
  NameLength = 0;
 | 
						|
  if (Name != NULL) {
 | 
						|
    NameLength = StrLen (Name);
 | 
						|
  }
 | 
						|
 | 
						|
  DevicePath     = NULL;
 | 
						|
  DevicePathSize = 0;
 | 
						|
  //
 | 
						|
  // Retrieve DevicePath Protocol associated with DriverHandle
 | 
						|
  //
 | 
						|
  if (DriverHandle != NULL) {
 | 
						|
    DevicePath = DevicePathFromHandle (DriverHandle);
 | 
						|
    if (DevicePath == NULL) {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Compute the size of the device path in bytes
 | 
						|
    //
 | 
						|
    DevicePathSize = GetDevicePathSize (DevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
 | 
						|
  // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
 | 
						|
  //
 | 
						|
  MaxLen = 5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1;
 | 
						|
  String = AllocateZeroPool (MaxLen * sizeof (CHAR16));
 | 
						|
  if (String == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Start with L"GUID="
 | 
						|
  //
 | 
						|
  StrCpyS (String, MaxLen, L"GUID=");
 | 
						|
  ReturnString = String;
 | 
						|
  String      += StrLen (String);
 | 
						|
 | 
						|
  if (Guid != NULL) {
 | 
						|
    //
 | 
						|
    // Append Guid converted to <HexCh>32
 | 
						|
    //
 | 
						|
    for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
 | 
						|
      UnicodeValueToStringS (
 | 
						|
        String,
 | 
						|
        MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
 | 
						|
        PREFIX_ZERO | RADIX_HEX,
 | 
						|
        *(Buffer++),
 | 
						|
        2
 | 
						|
        );
 | 
						|
      String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append L"&NAME="
 | 
						|
  //
 | 
						|
  StrCatS (ReturnString, MaxLen, L"&NAME=");
 | 
						|
  String += StrLen (String);
 | 
						|
 | 
						|
  if (Name != NULL) {
 | 
						|
    //
 | 
						|
    // Append Name converted to <Char>NameLength
 | 
						|
    //
 | 
						|
    for ( ; *Name != L'\0'; Name++) {
 | 
						|
      UnicodeValueToStringS (
 | 
						|
        String,
 | 
						|
        MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
 | 
						|
        PREFIX_ZERO | RADIX_HEX,
 | 
						|
        *Name,
 | 
						|
        4
 | 
						|
        );
 | 
						|
      String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append L"&PATH="
 | 
						|
  //
 | 
						|
  StrCatS (ReturnString, MaxLen, L"&PATH=");
 | 
						|
  String += StrLen (String);
 | 
						|
 | 
						|
  //
 | 
						|
  // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
 | 
						|
  //
 | 
						|
  for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
 | 
						|
    UnicodeValueToStringS (
 | 
						|
      String,
 | 
						|
      MaxLen * sizeof (CHAR16) - ((UINTN)String - (UINTN)ReturnString),
 | 
						|
      PREFIX_ZERO | RADIX_HEX,
 | 
						|
      *(Buffer++),
 | 
						|
      2
 | 
						|
      );
 | 
						|
    String += StrnLenS (String, MaxLen - ((UINTN)String - (UINTN)ReturnString) / sizeof (CHAR16));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Null terminate the Unicode string
 | 
						|
  //
 | 
						|
  *String = L'\0';
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert all hex digits in range [A-F] in the configuration header to [a-f]
 | 
						|
  //
 | 
						|
  return InternalLowerConfigString (ReturnString);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate the Config request element for one question.
 | 
						|
 | 
						|
  @param   Name    The name info for one question.
 | 
						|
  @param   Offset  The offset info for one question.
 | 
						|
  @param   Width   The width info for one question.
 | 
						|
 | 
						|
  @return  Pointer to the Null-terminated Unicode request element string.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STRING
 | 
						|
ConstructRequestElement (
 | 
						|
  IN CHAR16  *Name,
 | 
						|
  IN UINT16  Offset,
 | 
						|
  IN UINT16  Width
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16  *StringPtr;
 | 
						|
  UINTN   Length;
 | 
						|
 | 
						|
  if (Name != NULL) {
 | 
						|
    //
 | 
						|
    // Add <BlockName> length for each Name
 | 
						|
    //
 | 
						|
    // <BlockName> ::= Name + \0
 | 
						|
    //                 StrLen(Name) | 1
 | 
						|
    //
 | 
						|
    Length = StrLen (Name) + 1;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Add <BlockName> length for each Offset/Width pair
 | 
						|
    //
 | 
						|
    // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0
 | 
						|
    //                 |  7   | 4 |   7  | 4 |  1
 | 
						|
    //
 | 
						|
    Length = (7 + 4 + 7 + 4 + 1);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate buffer for the entire <ConfigRequest>
 | 
						|
  //
 | 
						|
  StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));
 | 
						|
  ASSERT (StringPtr != NULL);
 | 
						|
 | 
						|
  if (Name != NULL) {
 | 
						|
    //
 | 
						|
    // Append Name\0
 | 
						|
    //
 | 
						|
    UnicodeSPrint (
 | 
						|
      StringPtr,
 | 
						|
      (StrLen (Name) + 1) * sizeof (CHAR16),
 | 
						|
      L"%s",
 | 
						|
      Name
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Append OFFSET=XXXX&WIDTH=YYYY\0
 | 
						|
    //
 | 
						|
    UnicodeSPrint (
 | 
						|
      StringPtr,
 | 
						|
      (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
 | 
						|
      L"OFFSET=%04X&WIDTH=%04X",
 | 
						|
      Offset,
 | 
						|
      Width
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  return StringPtr;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get string value for question's name field.
 | 
						|
 | 
						|
  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.
 | 
						|
  @param  NameId                         The string id for the name field.
 | 
						|
 | 
						|
  @retval Name string.
 | 
						|
 | 
						|
**/
 | 
						|
CHAR16 *
 | 
						|
GetNameFromId (
 | 
						|
  IN HII_DATABASE_RECORD  *DatabaseRecord,
 | 
						|
  IN EFI_STRING_ID        NameId
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16      *Name;
 | 
						|
  CHAR8       *PlatformLanguage;
 | 
						|
  CHAR8       *SupportedLanguages;
 | 
						|
  CHAR8       *BestLanguage;
 | 
						|
  UINTN       StringSize;
 | 
						|
  CHAR16      TempString;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Name               = NULL;
 | 
						|
  BestLanguage       = NULL;
 | 
						|
  PlatformLanguage   = NULL;
 | 
						|
  SupportedLanguages = NULL;
 | 
						|
 | 
						|
  GetEfiGlobalVariable2 (L"PlatformLang", (VOID **)&PlatformLanguage, NULL);
 | 
						|
  SupportedLanguages = GetSupportedLanguages (DatabaseRecord->Handle);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the best matching language from SupportedLanguages
 | 
						|
  //
 | 
						|
  BestLanguage = GetBestLanguage (
 | 
						|
                   SupportedLanguages,
 | 
						|
                   FALSE,                                             // RFC 4646 mode
 | 
						|
                   PlatformLanguage != NULL ? PlatformLanguage : "",  // Highest priority
 | 
						|
                   SupportedLanguages,                                // Lowest priority
 | 
						|
                   NULL
 | 
						|
                   );
 | 
						|
  if (BestLanguage == NULL) {
 | 
						|
    BestLanguage = AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");
 | 
						|
    ASSERT (BestLanguage != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  StringSize = 0;
 | 
						|
  Status     = mPrivate.HiiString.GetString (
 | 
						|
                                    &mPrivate.HiiString,
 | 
						|
                                    BestLanguage,
 | 
						|
                                    DatabaseRecord->Handle,
 | 
						|
                                    NameId,
 | 
						|
                                    &TempString,
 | 
						|
                                    &StringSize,
 | 
						|
                                    NULL
 | 
						|
                                    );
 | 
						|
  if (Status != EFI_BUFFER_TOO_SMALL) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Name = AllocateZeroPool (StringSize);
 | 
						|
  if (Name == NULL) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = mPrivate.HiiString.GetString (
 | 
						|
                                &mPrivate.HiiString,
 | 
						|
                                BestLanguage,
 | 
						|
                                DatabaseRecord->Handle,
 | 
						|
                                NameId,
 | 
						|
                                Name,
 | 
						|
                                &StringSize,
 | 
						|
                                NULL
 | 
						|
                                );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (Name);
 | 
						|
    Name = NULL;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  if (SupportedLanguages != NULL) {
 | 
						|
    FreePool (SupportedLanguages);
 | 
						|
  }
 | 
						|
 | 
						|
  if (BestLanguage != NULL) {
 | 
						|
    FreePool (BestLanguage);
 | 
						|
  }
 | 
						|
 | 
						|
  if (PlatformLanguage != NULL) {
 | 
						|
    FreePool (PlatformLanguage);
 | 
						|
  }
 | 
						|
 | 
						|
  return Name;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Base on the input parameter to generate the ConfigRequest string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.
 | 
						|
  @param  KeywordStrId                   Keyword string id.
 | 
						|
  @param  OpCodeData                     The IFR data for this question.
 | 
						|
  @param  ConfigRequest                  Return the generate ConfigRequest string.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Generate ConfigResp string success.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      System out of memory resource error.
 | 
						|
  @retval EFI_NOT_FOUND             Not found the question which use this string id
 | 
						|
                                    as the prompt string id.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractConfigRequest (
 | 
						|
  IN  HII_DATABASE_RECORD  *DatabaseRecord,
 | 
						|
  IN  EFI_STRING_ID        KeywordStrId,
 | 
						|
  OUT UINT8                **OpCodeData,
 | 
						|
  OUT EFI_STRING           *ConfigRequest
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
 | 
						|
  HII_IFR_PACKAGE_INSTANCE            *FormPackage;
 | 
						|
  EFI_IFR_QUESTION_HEADER             *Header;
 | 
						|
  UINT8                               *Storage;
 | 
						|
  UINT8                               *OpCode;
 | 
						|
  CHAR16                              *Name;
 | 
						|
  UINT16                              Offset;
 | 
						|
  UINT16                              Width;
 | 
						|
  CHAR16                              *ConfigHdr;
 | 
						|
  CHAR16                              *RequestElement;
 | 
						|
  UINTN                               MaxLen;
 | 
						|
  CHAR16                              *StringPtr;
 | 
						|
 | 
						|
  ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);
 | 
						|
 | 
						|
  OpCode = NULL;
 | 
						|
  Name   = NULL;
 | 
						|
  Width  = 0;
 | 
						|
  Offset = 0;
 | 
						|
 | 
						|
  PackageListNode = DatabaseRecord->PackageList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the languages in the specified packagelist.
 | 
						|
  //
 | 
						|
  for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
 | 
						|
    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
    OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
 | 
						|
    if (OpCode != NULL) {
 | 
						|
      *OpCodeData = OpCode;
 | 
						|
      Header      = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
 | 
						|
      //
 | 
						|
      // Header->VarStoreId == 0 means no storage for this question.
 | 
						|
      //
 | 
						|
      ASSERT (Header->VarStoreId != 0);
 | 
						|
      DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
 | 
						|
 | 
						|
      Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
 | 
						|
      ASSERT (Storage != NULL);
 | 
						|
 | 
						|
      if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
 | 
						|
        Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
 | 
						|
      } else {
 | 
						|
        Offset = Header->VarStoreInfo.VarOffset;
 | 
						|
        Width  = GetWidth (OpCode);
 | 
						|
      }
 | 
						|
 | 
						|
      RequestElement = ConstructRequestElement (Name, Offset, Width);
 | 
						|
      ConfigHdr      = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
 | 
						|
      ASSERT (ConfigHdr != NULL);
 | 
						|
 | 
						|
      MaxLen         = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1;
 | 
						|
      *ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
 | 
						|
      if (*ConfigRequest == NULL) {
 | 
						|
        FreePool (ConfigHdr);
 | 
						|
        FreePool (RequestElement);
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      StringPtr = *ConfigRequest;
 | 
						|
 | 
						|
      StrCpyS (StringPtr, MaxLen, ConfigHdr);
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, L"&");
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, RequestElement);
 | 
						|
 | 
						|
      FreePool (ConfigHdr);
 | 
						|
      FreePool (RequestElement);
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Base on the input parameter to generate the ConfigResp string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.
 | 
						|
  @param  KeywordStrId                   Keyword string id.
 | 
						|
  @param  ValueElement                   The value for the question which use keyword string id
 | 
						|
                                         as the prompt string id.
 | 
						|
  @param  OpCodeData                     The IFR data for this question.
 | 
						|
  @param  ConfigResp                     Return the generate ConfigResp string.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Generate ConfigResp string success.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES      System out of memory resource error.
 | 
						|
  @retval EFI_NOT_FOUND             Not found the question which use this string id
 | 
						|
                                    as the prompt string id.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractConfigResp (
 | 
						|
  IN  HII_DATABASE_RECORD  *DatabaseRecord,
 | 
						|
  IN  EFI_STRING_ID        KeywordStrId,
 | 
						|
  IN  EFI_STRING           ValueElement,
 | 
						|
  OUT UINT8                **OpCodeData,
 | 
						|
  OUT EFI_STRING           *ConfigResp
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
 | 
						|
  HII_IFR_PACKAGE_INSTANCE            *FormPackage;
 | 
						|
  EFI_IFR_QUESTION_HEADER             *Header;
 | 
						|
  UINT8                               *Storage;
 | 
						|
  UINT8                               *OpCode;
 | 
						|
  CHAR16                              *Name;
 | 
						|
  UINT16                              Offset;
 | 
						|
  UINT16                              Width;
 | 
						|
  CHAR16                              *ConfigHdr;
 | 
						|
  CHAR16                              *RequestElement;
 | 
						|
  UINTN                               MaxLen;
 | 
						|
  CHAR16                              *StringPtr;
 | 
						|
 | 
						|
  ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));
 | 
						|
 | 
						|
  OpCode = NULL;
 | 
						|
  Name   = NULL;
 | 
						|
  Width  = 0;
 | 
						|
  Offset = 0;
 | 
						|
 | 
						|
  PackageListNode = DatabaseRecord->PackageList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search the languages in the specified packagelist.
 | 
						|
  //
 | 
						|
  for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {
 | 
						|
    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
    OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);
 | 
						|
    if (OpCode != NULL) {
 | 
						|
      *OpCodeData = OpCode;
 | 
						|
      Header      = (EFI_IFR_QUESTION_HEADER *)(OpCode + sizeof (EFI_IFR_OP_HEADER));
 | 
						|
      //
 | 
						|
      // Header->VarStoreId == 0 means no storage for this question.
 | 
						|
      //
 | 
						|
      ASSERT (Header->VarStoreId != 0);
 | 
						|
      DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
 | 
						|
 | 
						|
      Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
 | 
						|
      ASSERT (Storage != NULL);
 | 
						|
 | 
						|
      if (((EFI_IFR_OP_HEADER *)Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {
 | 
						|
        Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);
 | 
						|
      } else {
 | 
						|
        Offset = Header->VarStoreInfo.VarOffset;
 | 
						|
        Width  = GetWidth (OpCode);
 | 
						|
      }
 | 
						|
 | 
						|
      RequestElement = ConstructRequestElement (Name, Offset, Width);
 | 
						|
 | 
						|
      ConfigHdr = ConstructConfigHdr (Storage, DatabaseRecord->DriverHandle);
 | 
						|
      ASSERT (ConfigHdr != NULL);
 | 
						|
 | 
						|
      MaxLen      = StrLen (ConfigHdr) + 1 + StrLen (RequestElement) + 1 + StrLen (L"VALUE=") + StrLen (ValueElement) + 1;
 | 
						|
      *ConfigResp = AllocatePool (MaxLen * sizeof (CHAR16));
 | 
						|
      if (*ConfigResp == NULL) {
 | 
						|
        FreePool (ConfigHdr);
 | 
						|
        FreePool (RequestElement);
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      StringPtr = *ConfigResp;
 | 
						|
 | 
						|
      StrCpyS (StringPtr, MaxLen, ConfigHdr);
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, L"&");
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, RequestElement);
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, L"&");
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, L"VALUE=");
 | 
						|
 | 
						|
      StrCatS (StringPtr, MaxLen, ValueElement);
 | 
						|
 | 
						|
      FreePool (ConfigHdr);
 | 
						|
      FreePool (RequestElement);
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the Value section from the Hii driver.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  ConfigRequest                  The input ConfigRequest string.
 | 
						|
  @param  ValueElement                   The respond Value section from the hii driver.
 | 
						|
 | 
						|
  @retval Misc value                     The error status return from ExtractConfig function.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated
 | 
						|
  @retval EFI_SUCCESS                    Get the value section success.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ExtractValueFromDriver (
 | 
						|
  IN  CHAR16  *ConfigRequest,
 | 
						|
  OUT CHAR16  **ValueElement
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_STRING  Result;
 | 
						|
  EFI_STRING  Progress;
 | 
						|
  CHAR16      *StringPtr;
 | 
						|
  CHAR16      *StringEnd;
 | 
						|
 | 
						|
  ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));
 | 
						|
 | 
						|
  Status = mPrivate.ConfigRouting.ExtractConfig (
 | 
						|
                                    &mPrivate.ConfigRouting,
 | 
						|
                                    (EFI_STRING)ConfigRequest,
 | 
						|
                                    &Progress,
 | 
						|
                                    &Result
 | 
						|
                                    );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Value Section and return it.
 | 
						|
  //
 | 
						|
  StringPtr = StrStr (Result, L"&VALUE=");
 | 
						|
  ASSERT (StringPtr != NULL);
 | 
						|
  StringEnd = StrStr (StringPtr + 1, L"&");
 | 
						|
  if (StringEnd != NULL) {
 | 
						|
    *StringEnd = L'\0';
 | 
						|
  }
 | 
						|
 | 
						|
  *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);
 | 
						|
  if (*ValueElement == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  if (StringEnd != NULL) {
 | 
						|
    *StringEnd = L'&';
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Result);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get EFI_STRING_ID info from the input device path, namespace and keyword.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  DevicePath                     Input device path info.
 | 
						|
  @param  NameSpace                      NameSpace format string.
 | 
						|
  @param  KeywordData                    Keyword used to get string id.
 | 
						|
  @param  ProgressErr                    Return extra error type.
 | 
						|
  @param  KeywordStringId                Return EFI_STRING_ID.
 | 
						|
  @param  DataBaseRecord                 DataBase record data for this driver.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER          Can't find the database record base on the input device path or namespace.
 | 
						|
  @retval EFI_NOT_FOUND                  Can't find the EFI_STRING_ID for the keyword.
 | 
						|
  @retval EFI_SUCCESS                    Find the EFI_STRING_ID.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetStringIdFromDatabase (
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL  **DevicePath,
 | 
						|
  IN  CHAR8                     **NameSpace,
 | 
						|
  IN  CHAR16                    *KeywordData,
 | 
						|
  OUT UINT32                    *ProgressErr,
 | 
						|
  OUT EFI_STRING_ID             *KeywordStringId,
 | 
						|
  OUT HII_DATABASE_RECORD       **DataBaseRecord
 | 
						|
  )
 | 
						|
{
 | 
						|
  HII_DATABASE_RECORD       *Record;
 | 
						|
  LIST_ENTRY                *Link;
 | 
						|
  BOOLEAN                   FindNameSpace;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DestDevicePath;
 | 
						|
  UINT8                     *DevicePathPkg;
 | 
						|
  UINTN                     DevicePathSize;
 | 
						|
 | 
						|
  ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));
 | 
						|
 | 
						|
  FindNameSpace = FALSE;
 | 
						|
 | 
						|
  if (*DevicePath != NULL) {
 | 
						|
    //
 | 
						|
    // Get DataBaseRecord from device path protocol.
 | 
						|
    //
 | 
						|
    Record = GetRecordFromDevicePath (*DevicePath);
 | 
						|
    if (Record == NULL) {
 | 
						|
      //
 | 
						|
      // Can't find the DatabaseRecord base on the input device path info.
 | 
						|
      // NEED TO CONFIRM the return ProgressErr.
 | 
						|
      //
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get string id from the record.
 | 
						|
    //
 | 
						|
    *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
 | 
						|
    switch (*ProgressErr) {
 | 
						|
      case KEYWORD_HANDLER_NO_ERROR:
 | 
						|
        *DataBaseRecord = Record;
 | 
						|
        return EFI_SUCCESS;
 | 
						|
 | 
						|
      case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
 | 
						|
      default:
 | 
						|
        ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);
 | 
						|
        return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Find driver which matches the routing data.
 | 
						|
    //
 | 
						|
    for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
 | 
						|
      Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
 | 
						|
 | 
						|
      *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);
 | 
						|
      if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {
 | 
						|
        *DataBaseRecord = Record;
 | 
						|
 | 
						|
        if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {
 | 
						|
          DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));
 | 
						|
          DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DestDevicePath);
 | 
						|
          *DevicePath    = AllocateCopyPool (DevicePathSize, DestDevicePath);
 | 
						|
          if (*DevicePath == NULL) {
 | 
						|
            return EFI_OUT_OF_RESOURCES;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Need to verify this ASSERT.
 | 
						|
          //
 | 
						|
          ASSERT (FALSE);
 | 
						|
        }
 | 
						|
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {
 | 
						|
        FindNameSpace = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.
 | 
						|
    // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.
 | 
						|
    //
 | 
						|
    if (FindNameSpace) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    } else {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate the KeywordResp String.
 | 
						|
 | 
						|
  <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']
 | 
						|
 | 
						|
  @param  NameSpace                      NameSpace format string.
 | 
						|
  @param  DevicePath                     Input device path info.
 | 
						|
  @param  KeywordData                    Keyword used to get string id.
 | 
						|
  @param  ValueStr                       The value section for the keyword.
 | 
						|
  @param  ReadOnly                       Whether this value is readonly.
 | 
						|
  @param  KeywordResp                    Return the point to the KeywordResp string.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.
 | 
						|
  @retval EFI_SUCCESS                    Generate the KeywordResp string.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GenerateKeywordResp (
 | 
						|
  IN  CHAR8                     *NameSpace,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
 | 
						|
  IN  EFI_STRING                KeywordData,
 | 
						|
  IN  EFI_STRING                ValueStr,
 | 
						|
  IN  BOOLEAN                   ReadOnly,
 | 
						|
  OUT EFI_STRING                *KeywordResp
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   RespStrLen;
 | 
						|
  CHAR16  *RespStr;
 | 
						|
  CHAR16  *PathHdr;
 | 
						|
  CHAR16  *UnicodeNameSpace;
 | 
						|
  UINTN   NameSpaceLength;
 | 
						|
 | 
						|
  ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));
 | 
						|
 | 
						|
  //
 | 
						|
  // 1. Calculate the string length.
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // 1.1 NameSpaceId size.
 | 
						|
  // 'NAMESPACE='<String>
 | 
						|
  //
 | 
						|
  NameSpaceLength  = AsciiStrLen (NameSpace);
 | 
						|
  RespStrLen       = 10 + NameSpaceLength;
 | 
						|
  UnicodeNameSpace = AllocatePool ((NameSpaceLength + 1) * sizeof (CHAR16));
 | 
						|
  if (UnicodeNameSpace == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  AsciiStrToUnicodeStrS (NameSpace, UnicodeNameSpace, NameSpaceLength + 1);
 | 
						|
 | 
						|
  //
 | 
						|
  // 1.2 PathHdr size.
 | 
						|
  // PATH=<UEFI binary Device Path represented as hex number>'&'
 | 
						|
  // Attention: The output include the '&' at the end.
 | 
						|
  //
 | 
						|
  GenerateSubStr (
 | 
						|
    L"&PATH=",
 | 
						|
    GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)DevicePath),
 | 
						|
    (VOID *)DevicePath,
 | 
						|
    1,
 | 
						|
    &PathHdr
 | 
						|
    );
 | 
						|
  RespStrLen += StrLen (PathHdr);
 | 
						|
 | 
						|
  //
 | 
						|
  // 1.3 Keyword section.
 | 
						|
  // 'KEYWORD='<String>[':'<DecCh>(1/4)]
 | 
						|
  //
 | 
						|
  RespStrLen += 8 + StrLen (KeywordData);
 | 
						|
 | 
						|
  //
 | 
						|
  // 1.4 Value section.
 | 
						|
  // ValueStr = '&VALUE='<Number>
 | 
						|
  //
 | 
						|
  RespStrLen += StrLen (ValueStr);
 | 
						|
 | 
						|
  //
 | 
						|
  // 1.5 ReadOnly Section.
 | 
						|
  // '&READONLY'
 | 
						|
  //
 | 
						|
  if (ReadOnly) {
 | 
						|
    RespStrLen += 9;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 2. Allocate the buffer and create the KeywordResp string include '\0'.
 | 
						|
  //
 | 
						|
  RespStrLen  += 1;
 | 
						|
  *KeywordResp = AllocatePool (RespStrLen * sizeof (CHAR16));
 | 
						|
  if (*KeywordResp == NULL) {
 | 
						|
    if (UnicodeNameSpace != NULL) {
 | 
						|
      FreePool (UnicodeNameSpace);
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  RespStr = *KeywordResp;
 | 
						|
 | 
						|
  //
 | 
						|
  // 2.1 Copy NameSpaceId section.
 | 
						|
  //
 | 
						|
  StrCpyS (RespStr, RespStrLen, L"NAMESPACE=");
 | 
						|
 | 
						|
  StrCatS (RespStr, RespStrLen, UnicodeNameSpace);
 | 
						|
 | 
						|
  //
 | 
						|
  // 2.2 Copy PathHdr section.
 | 
						|
  //
 | 
						|
  StrCatS (RespStr, RespStrLen, PathHdr);
 | 
						|
 | 
						|
  //
 | 
						|
  // 2.3 Copy Keyword section.
 | 
						|
  //
 | 
						|
  StrCatS (RespStr, RespStrLen, L"KEYWORD=");
 | 
						|
 | 
						|
  StrCatS (RespStr, RespStrLen, KeywordData);
 | 
						|
 | 
						|
  //
 | 
						|
  // 2.4 Copy the Value section.
 | 
						|
  //
 | 
						|
  StrCatS (RespStr, RespStrLen, ValueStr);
 | 
						|
 | 
						|
  //
 | 
						|
  // 2.5 Copy ReadOnly section if exist.
 | 
						|
  //
 | 
						|
  if (ReadOnly) {
 | 
						|
    StrCatS (RespStr, RespStrLen, L"&READONLY");
 | 
						|
  }
 | 
						|
 | 
						|
  if (UnicodeNameSpace != NULL) {
 | 
						|
    FreePool (UnicodeNameSpace);
 | 
						|
  }
 | 
						|
 | 
						|
  if (PathHdr != NULL) {
 | 
						|
    FreePool (PathHdr);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Merge the KeywordResp String to MultiKeywordResp string.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  MultiKeywordResp               The existed multikeywordresp string.
 | 
						|
  @param  KeywordResp                    The input keywordResp string.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.
 | 
						|
  @retval EFI_SUCCESS                    Generate the MultiKeywordResp string.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
MergeToMultiKeywordResp (
 | 
						|
  IN OUT EFI_STRING  *MultiKeywordResp,
 | 
						|
  IN     EFI_STRING  *KeywordResp
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       MultiKeywordRespLen;
 | 
						|
  EFI_STRING  StringPtr;
 | 
						|
 | 
						|
  if (*MultiKeywordResp == NULL) {
 | 
						|
    *MultiKeywordResp = *KeywordResp;
 | 
						|
    *KeywordResp      = NULL;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);
 | 
						|
 | 
						|
  StringPtr = ReallocatePool (
 | 
						|
                StrSize (*MultiKeywordResp),
 | 
						|
                MultiKeywordRespLen,
 | 
						|
                *MultiKeywordResp
 | 
						|
                );
 | 
						|
  if (StringPtr == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  *MultiKeywordResp = StringPtr;
 | 
						|
 | 
						|
  StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), L"&");
 | 
						|
 | 
						|
  StrCatS (StringPtr, MultiKeywordRespLen / sizeof (CHAR16), *KeywordResp);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Enumerate all keyword in the system.
 | 
						|
 | 
						|
  If error occur when parse one keyword, just skip it and parse the next one.
 | 
						|
 | 
						|
  This is a internal function.
 | 
						|
 | 
						|
  @param  NameSpace                      The namespace used to search the string.
 | 
						|
  @param  MultiResp                      Return the MultiKeywordResp string for the system.
 | 
						|
  @param  ProgressErr                    Return the error status.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.
 | 
						|
  @retval EFI_SUCCESS                    Generate the MultiKeywordResp string.
 | 
						|
  @retval EFI_NOT_FOUND                  No keyword found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EnumerateAllKeywords (
 | 
						|
  IN  CHAR8       *NameSpace,
 | 
						|
  OUT EFI_STRING  *MultiResp,
 | 
						|
  OUT UINT32      *ProgressErr
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  LIST_ENTRY                          *StringLink;
 | 
						|
  UINT8                               *DevicePathPkg;
 | 
						|
  UINT8                               *DevicePath;
 | 
						|
  HII_DATABASE_RECORD                 *DataBaseRecord;
 | 
						|
  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;
 | 
						|
  HII_STRING_PACKAGE_INSTANCE         *StringPackage;
 | 
						|
  CHAR8                               *LocalNameSpace;
 | 
						|
  EFI_STRING_ID                       NextStringId;
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  UINT8                               *OpCode;
 | 
						|
  CHAR16                              *ConfigRequest;
 | 
						|
  CHAR16                              *ValueElement;
 | 
						|
  CHAR16                              *KeywordResp;
 | 
						|
  CHAR16                              *MultiKeywordResp;
 | 
						|
  CHAR16                              *KeywordData;
 | 
						|
  BOOLEAN                             ReadOnly;
 | 
						|
  BOOLEAN                             FindKeywordPackages;
 | 
						|
 | 
						|
  DataBaseRecord      = NULL;
 | 
						|
  Status              = EFI_SUCCESS;
 | 
						|
  MultiKeywordResp    = NULL;
 | 
						|
  DevicePath          = NULL;
 | 
						|
  LocalNameSpace      = NULL;
 | 
						|
  ConfigRequest       = NULL;
 | 
						|
  ValueElement        = NULL;
 | 
						|
  KeywordResp         = NULL;
 | 
						|
  FindKeywordPackages = FALSE;
 | 
						|
 | 
						|
  if (NameSpace == NULL) {
 | 
						|
    NameSpace = UEFI_CONFIG_LANG;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find driver which matches the routing data.
 | 
						|
  //
 | 
						|
  for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {
 | 
						|
    DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
 | 
						|
    if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {
 | 
						|
      DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);
 | 
						|
    }
 | 
						|
 | 
						|
    PackageListNode = DataBaseRecord->PackageList;
 | 
						|
 | 
						|
    for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {
 | 
						|
      StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
 | 
						|
 | 
						|
      //
 | 
						|
      // Check whether has keyword string package.
 | 
						|
      //
 | 
						|
      if (AsciiStrnCmp (NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {
 | 
						|
        FindKeywordPackages = TRUE;
 | 
						|
        //
 | 
						|
        // Keep the NameSpace string.
 | 
						|
        //
 | 
						|
        LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);
 | 
						|
        if (LocalNameSpace == NULL) {
 | 
						|
          return EFI_OUT_OF_RESOURCES;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // 1 means just begin the enumerate the valid string ids.
 | 
						|
        // StringId == 1 is always used to save the language for this string package.
 | 
						|
        // Any valid string start from 2. so here initial it to 1.
 | 
						|
        //
 | 
						|
        NextStringId = 1;
 | 
						|
 | 
						|
        //
 | 
						|
        // Enumerate all valid stringid in the package.
 | 
						|
        //
 | 
						|
        while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {
 | 
						|
          //
 | 
						|
          // 3.3 Construct the ConfigRequest string.
 | 
						|
          //
 | 
						|
          Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            //
 | 
						|
            // If can't generate ConfigRequest for this question, skip it and start the next.
 | 
						|
            //
 | 
						|
            goto Error;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // 3.4 Extract Value for the input keyword.
 | 
						|
          //
 | 
						|
          Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            if (Status != EFI_OUT_OF_RESOURCES) {
 | 
						|
              //
 | 
						|
              // If can't generate ConfigRequest for this question, skip it and start the next.
 | 
						|
              //
 | 
						|
              goto Error;
 | 
						|
            }
 | 
						|
 | 
						|
            //
 | 
						|
            // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
 | 
						|
            //
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // Extract readonly flag from opcode.
 | 
						|
          //
 | 
						|
          ReadOnly = ExtractReadOnlyFromOpCode (OpCode);
 | 
						|
 | 
						|
          //
 | 
						|
          // 5. Generate KeywordResp string.
 | 
						|
          //
 | 
						|
          ASSERT (DevicePath != NULL);
 | 
						|
          Status = GenerateKeywordResp (LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
 | 
						|
          if (Status != EFI_SUCCESS) {
 | 
						|
            //
 | 
						|
            // If EFI_OUT_OF_RESOURCES error occur, no need to continue.
 | 
						|
            //
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // 6. Merge to the MultiKeywordResp string.
 | 
						|
          //
 | 
						|
          Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            goto Done;
 | 
						|
          }
 | 
						|
 | 
						|
Error:
 | 
						|
          //
 | 
						|
          // Clean the temp buffer to later use again.
 | 
						|
          //
 | 
						|
          if (ConfigRequest != NULL) {
 | 
						|
            FreePool (ConfigRequest);
 | 
						|
            ConfigRequest = NULL;
 | 
						|
          }
 | 
						|
 | 
						|
          if (ValueElement != NULL) {
 | 
						|
            FreePool (ValueElement);
 | 
						|
            ValueElement = NULL;
 | 
						|
          }
 | 
						|
 | 
						|
          if (KeywordResp != NULL) {
 | 
						|
            FreePool (KeywordResp);
 | 
						|
            KeywordResp = NULL;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (LocalNameSpace != NULL) {
 | 
						|
          FreePool (LocalNameSpace);
 | 
						|
          LocalNameSpace = NULL;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // return the already get MultiKeywordString even error occurred.
 | 
						|
  //
 | 
						|
  if (MultiKeywordResp == NULL) {
 | 
						|
    Status = EFI_NOT_FOUND;
 | 
						|
    if (!FindKeywordPackages) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;
 | 
						|
    } else {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_KEYWORD_NOT_FOUND;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  *MultiResp = MultiKeywordResp;
 | 
						|
 | 
						|
Done:
 | 
						|
  if (LocalNameSpace != NULL) {
 | 
						|
    FreePool (LocalNameSpace);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigRequest != NULL) {
 | 
						|
    FreePool (ConfigRequest);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ValueElement != NULL) {
 | 
						|
    FreePool (ValueElement);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This function accepts a <MultiKeywordResp> formatted string, finds the associated
 | 
						|
  keyword owners, creates a <MultiConfigResp> string from it and forwards it to the
 | 
						|
  EFI_HII_ROUTING_PROTOCOL.RouteConfig function.
 | 
						|
 | 
						|
  If there is an issue in resolving the contents of the KeywordString, then the
 | 
						|
  function returns an error and also sets the Progress and ProgressErr with the
 | 
						|
  appropriate information about where the issue occurred and additional data about
 | 
						|
  the nature of the issue.
 | 
						|
 | 
						|
  In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND
 | 
						|
  error is generated during processing the second or later keyword element, the system
 | 
						|
  storage associated with earlier keywords is not modified. All elements of the
 | 
						|
  KeywordString must successfully pass all tests for format and access prior to making
 | 
						|
  any modifications to storage.
 | 
						|
 | 
						|
  In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString
 | 
						|
  containing multiple keywords, the state of storage associated with earlier keywords
 | 
						|
  is undefined.
 | 
						|
 | 
						|
 | 
						|
  @param This             Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
 | 
						|
 | 
						|
  @param KeywordString    A null-terminated string in <MultiKeywordResp> format.
 | 
						|
 | 
						|
  @param Progress         On return, points to a character in the KeywordString.
 | 
						|
                          Points to the string's NULL terminator if the request
 | 
						|
                          was successful. Points to the most recent '&' before
 | 
						|
                          the first failing name / value pair (or the beginning
 | 
						|
                          of the string if the failure is in the first name / value
 | 
						|
                          pair) if the request was not successful.
 | 
						|
 | 
						|
  @param ProgressErr      If during the processing of the KeywordString there was
 | 
						|
                          a failure, this parameter gives additional information
 | 
						|
                          about the possible source of the problem. The various
 | 
						|
                          errors are defined in "Related Definitions" below.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The specified action was completed successfully.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:
 | 
						|
                                  1. KeywordString is NULL.
 | 
						|
                                  2. Parsing of the KeywordString resulted in an
 | 
						|
                                     error. See Progress and ProgressErr for more data.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND           An element of the KeywordString was not found.
 | 
						|
                                  See ProgressErr for more data.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
 | 
						|
                                  See ProgressErr for more data.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED       The action violated system policy. See ProgressErr
 | 
						|
                                  for more data.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR        An unexpected system error occurred. See ProgressErr
 | 
						|
                                  for more data.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiConfigKeywordHandlerSetData (
 | 
						|
  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL  *This,
 | 
						|
  IN CONST EFI_STRING                     KeywordString,
 | 
						|
  OUT EFI_STRING                          *Progress,
 | 
						|
  OUT UINT32                              *ProgressErr
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                     *NameSpace;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  CHAR16                    *StringPtr;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  CHAR16                    *NextStringPtr;
 | 
						|
  CHAR16                    *KeywordData;
 | 
						|
  EFI_STRING_ID             KeywordStringId;
 | 
						|
  UINT32                    RetVal;
 | 
						|
  HII_DATABASE_RECORD       *DataBaseRecord;
 | 
						|
  UINT8                     *OpCode;
 | 
						|
  CHAR16                    *ConfigResp;
 | 
						|
  CHAR16                    *MultiConfigResp;
 | 
						|
  CHAR16                    *ValueElement;
 | 
						|
  BOOLEAN                   ReadOnly;
 | 
						|
  EFI_STRING                InternalProgress;
 | 
						|
  CHAR16                    *TempString;
 | 
						|
  CHAR16                    *KeywordStartPos;
 | 
						|
 | 
						|
  if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (KeywordString == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress       = KeywordString;
 | 
						|
  *ProgressErr    = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
 | 
						|
  Status          = EFI_SUCCESS;
 | 
						|
  MultiConfigResp = NULL;
 | 
						|
  NameSpace       = NULL;
 | 
						|
  DevicePath      = NULL;
 | 
						|
  KeywordData     = NULL;
 | 
						|
  ValueElement    = NULL;
 | 
						|
  ConfigResp      = NULL;
 | 
						|
  KeywordStartPos = NULL;
 | 
						|
  KeywordStringId = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use temp string to avoid changing input string buffer.
 | 
						|
  //
 | 
						|
  TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
 | 
						|
  ASSERT (TempString != NULL);
 | 
						|
  StringPtr = TempString;
 | 
						|
 | 
						|
  while ((StringPtr != NULL) && (*StringPtr != L'\0')) {
 | 
						|
    //
 | 
						|
    // 1. Get NameSpace from NameSpaceId keyword.
 | 
						|
    //
 | 
						|
    Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    ASSERT (NameSpace != NULL);
 | 
						|
    //
 | 
						|
    // 1.1 Check whether the input namespace is valid.
 | 
						|
    //
 | 
						|
    if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      Status       = EFI_INVALID_PARAMETER;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    StringPtr = NextStringPtr;
 | 
						|
 | 
						|
    //
 | 
						|
    // 2. Get possible Device Path info from KeywordString.
 | 
						|
    //
 | 
						|
    Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    StringPtr = NextStringPtr;
 | 
						|
 | 
						|
    //
 | 
						|
    // 3. Extract keyword from the KeywordRequest string.
 | 
						|
    //
 | 
						|
    KeywordStartPos = StringPtr;
 | 
						|
    Status          = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Can't find Keyword base on the input device path info.
 | 
						|
      //
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      Status       = EFI_INVALID_PARAMETER;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    StringPtr = NextStringPtr;
 | 
						|
 | 
						|
    //
 | 
						|
    // 4. Extract Value from the KeywordRequest string.
 | 
						|
    //
 | 
						|
    Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Can't find Value base on the input device path info.
 | 
						|
      //
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      Status       = EFI_INVALID_PARAMETER;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    StringPtr = NextStringPtr;
 | 
						|
 | 
						|
    //
 | 
						|
    // 5. Find READONLY tag.
 | 
						|
    //
 | 
						|
    if ((StringPtr != NULL) && (StrnCmp (StringPtr, L"&READONLY", StrLen (L"&READONLY")) == 0)) {
 | 
						|
      ReadOnly   = TRUE;
 | 
						|
      StringPtr += StrLen (L"&READONLY");
 | 
						|
    } else {
 | 
						|
      ReadOnly = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 6. Get EFI_STRING_ID for the input keyword.
 | 
						|
    //
 | 
						|
    Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      *ProgressErr = RetVal;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 7. Construct the ConfigRequest string.
 | 
						|
    //
 | 
						|
    Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 8. Check the readonly flag.
 | 
						|
    //
 | 
						|
    if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {
 | 
						|
      //
 | 
						|
      // Extracting readonly flag form opcode and extracting "READONLY" tag form KeywordString should have the same results.
 | 
						|
      // If not, the input KeywordString must be incorrect, return the error status to caller.
 | 
						|
      //
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;
 | 
						|
      Status       = EFI_INVALID_PARAMETER;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ReadOnly) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_ACCESS_NOT_PERMITTED;
 | 
						|
      Status       = EFI_ACCESS_DENIED;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 9. Merge to the MultiKeywordResp string.
 | 
						|
    //
 | 
						|
    Status = MergeToMultiKeywordResp (&MultiConfigResp, &ConfigResp);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 10. Clean the temp buffer point.
 | 
						|
    //
 | 
						|
    FreePool (NameSpace);
 | 
						|
    FreePool (DevicePath);
 | 
						|
    FreePool (KeywordData);
 | 
						|
    FreePool (ValueElement);
 | 
						|
    NameSpace    = NULL;
 | 
						|
    DevicePath   = NULL;
 | 
						|
    KeywordData  = NULL;
 | 
						|
    ValueElement = NULL;
 | 
						|
    if (ConfigResp != NULL) {
 | 
						|
      FreePool (ConfigResp);
 | 
						|
      ConfigResp = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    KeywordStartPos = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 11. Set value to driver.
 | 
						|
  //
 | 
						|
  Status = mPrivate.ConfigRouting.RouteConfig (
 | 
						|
                                    &mPrivate.ConfigRouting,
 | 
						|
                                    (EFI_STRING)MultiConfigResp,
 | 
						|
                                    &InternalProgress
 | 
						|
                                    );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
 | 
						|
 | 
						|
Done:
 | 
						|
  if (KeywordStartPos != NULL) {
 | 
						|
    *Progress = KeywordString + (KeywordStartPos - TempString);
 | 
						|
  } else {
 | 
						|
    *Progress = KeywordString + (StringPtr - TempString);
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (TempString != NULL);
 | 
						|
  FreePool (TempString);
 | 
						|
  if (NameSpace != NULL) {
 | 
						|
    FreePool (NameSpace);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DevicePath != NULL) {
 | 
						|
    FreePool (DevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  if (KeywordData != NULL) {
 | 
						|
    FreePool (KeywordData);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ValueElement != NULL) {
 | 
						|
    FreePool (ValueElement);
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigResp != NULL) {
 | 
						|
    FreePool (ConfigResp);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((MultiConfigResp != NULL) && (MultiConfigResp != ConfigResp)) {
 | 
						|
    FreePool (MultiConfigResp);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This function accepts a <MultiKeywordRequest> formatted string, finds the underlying
 | 
						|
  keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the
 | 
						|
  EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.
 | 
						|
 | 
						|
  If there is an issue in resolving the contents of the KeywordString, then the function
 | 
						|
  returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the
 | 
						|
  appropriate information about where the issue occurred and additional data about the
 | 
						|
  nature of the issue.
 | 
						|
 | 
						|
  In the case when KeywordString is NULL, or contains multiple keywords, or when
 | 
						|
  EFI_NOT_FOUND is generated while processing the keyword elements, the Results string
 | 
						|
  contains values returned for all keywords processed prior to the keyword generating the
 | 
						|
  error but no values for the keyword with error or any following keywords.
 | 
						|
 | 
						|
 | 
						|
  @param This           Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.
 | 
						|
 | 
						|
  @param NameSpaceId    A null-terminated string containing the platform configuration
 | 
						|
                        language to search through in the system. If a NULL is passed
 | 
						|
                        in, then it is assumed that any platform configuration language
 | 
						|
                        with the prefix of "x-UEFI-" are searched.
 | 
						|
 | 
						|
  @param KeywordString  A null-terminated string in <MultiKeywordRequest> format. If a
 | 
						|
                        NULL is passed in the KeywordString field, all of the known
 | 
						|
                        keywords in the system for the NameSpaceId specified are
 | 
						|
                        returned in the Results field.
 | 
						|
 | 
						|
  @param Progress       On return, points to a character in the KeywordString. Points
 | 
						|
                        to the string's NULL terminator if the request was successful.
 | 
						|
                        Points to the most recent '&' before the first failing name / value
 | 
						|
                        pair (or the beginning of the string if the failure is in the first
 | 
						|
                        name / value pair) if the request was not successful.
 | 
						|
 | 
						|
  @param ProgressErr    If during the processing of the KeywordString there was a
 | 
						|
                        failure, this parameter gives additional information about the
 | 
						|
                        possible source of the problem. See the definitions in SetData()
 | 
						|
                        for valid value definitions.
 | 
						|
 | 
						|
  @param Results        A null-terminated string in <MultiKeywordResp> format is returned
 | 
						|
                        which has all the values filled in for the keywords in the
 | 
						|
                        KeywordString. This is a callee-allocated field, and must be freed
 | 
						|
                        by the caller after being used.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The specified action was completed successfully.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:
 | 
						|
                                  1.Progress, ProgressErr, or Results is NULL.
 | 
						|
                                  2.Parsing of the KeywordString resulted in an error. See
 | 
						|
                                    Progress and ProgressErr for more data.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND           An element of the KeywordString was not found. See
 | 
						|
                                  ProgressErr for more data.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND           The NamespaceId specified was not found.  See ProgressErr
 | 
						|
                                  for more data.
 | 
						|
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.  See
 | 
						|
                                  ProgressErr for more data.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED       The action violated system policy.  See ProgressErr for
 | 
						|
                                  more data.
 | 
						|
 | 
						|
  @retval EFI_DEVICE_ERROR        An unexpected system error occurred.  See ProgressErr
 | 
						|
                                  for more data.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EfiConfigKeywordHandlerGetData (
 | 
						|
  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL  *This,
 | 
						|
  IN CONST EFI_STRING                     NameSpaceId  OPTIONAL,
 | 
						|
  IN CONST EFI_STRING                     KeywordString  OPTIONAL,
 | 
						|
  OUT EFI_STRING                          *Progress,
 | 
						|
  OUT UINT32                              *ProgressErr,
 | 
						|
  OUT EFI_STRING                          *Results
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                     *NameSpace;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  HII_DATABASE_RECORD       *DataBaseRecord;
 | 
						|
  CHAR16                    *StringPtr;
 | 
						|
  CHAR16                    *NextStringPtr;
 | 
						|
  CHAR16                    *KeywordData;
 | 
						|
  EFI_STRING_ID             KeywordStringId;
 | 
						|
  UINT8                     *OpCode;
 | 
						|
  CHAR16                    *ConfigRequest;
 | 
						|
  CHAR16                    *ValueElement;
 | 
						|
  UINT32                    RetVal;
 | 
						|
  BOOLEAN                   ReadOnly;
 | 
						|
  CHAR16                    *KeywordResp;
 | 
						|
  CHAR16                    *MultiKeywordResp;
 | 
						|
  CHAR16                    *TempString;
 | 
						|
 | 
						|
  if ((This == NULL) || (Progress == NULL) || (ProgressErr == NULL) || (Results == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *ProgressErr     = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;
 | 
						|
  Status           = EFI_SUCCESS;
 | 
						|
  DevicePath       = NULL;
 | 
						|
  NameSpace        = NULL;
 | 
						|
  KeywordData      = NULL;
 | 
						|
  ConfigRequest    = NULL;
 | 
						|
  StringPtr        = KeywordString;
 | 
						|
  ReadOnly         = FALSE;
 | 
						|
  MultiKeywordResp = NULL;
 | 
						|
  KeywordStringId  = 0;
 | 
						|
  TempString       = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Use temp string to avoid changing input string buffer.
 | 
						|
  //
 | 
						|
  if (NameSpaceId != NULL) {
 | 
						|
    TempString = AllocateCopyPool (StrSize (NameSpaceId), NameSpaceId);
 | 
						|
    ASSERT (TempString != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 1. Get NameSpace from NameSpaceId keyword.
 | 
						|
  //
 | 
						|
  Status = ExtractNameSpace (TempString, &NameSpace, NULL);
 | 
						|
  if (TempString != NULL) {
 | 
						|
    FreePool (TempString);
 | 
						|
    TempString = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 1.1 Check whether the input namespace is valid.
 | 
						|
  //
 | 
						|
  if (NameSpace != NULL) {
 | 
						|
    if (AsciiStrnCmp (NameSpace, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) != 0) {
 | 
						|
      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (KeywordString != NULL) {
 | 
						|
    //
 | 
						|
    // Use temp string to avoid changing input string buffer.
 | 
						|
    //
 | 
						|
    TempString = AllocateCopyPool (StrSize (KeywordString), KeywordString);
 | 
						|
    ASSERT (TempString != NULL);
 | 
						|
    StringPtr = TempString;
 | 
						|
 | 
						|
    while (*StringPtr != L'\0') {
 | 
						|
      //
 | 
						|
      // 2. Get possible Device Path info from KeywordString.
 | 
						|
      //
 | 
						|
      Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      StringPtr = NextStringPtr;
 | 
						|
 | 
						|
      //
 | 
						|
      // 3. Process Keyword section from the input keywordRequest string.
 | 
						|
      //
 | 
						|
      // 3.1 Extract keyword from the KeywordRequest string.
 | 
						|
      //
 | 
						|
      Status = ExtractKeyword (StringPtr, &KeywordData, &NextStringPtr);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // Can't find Keyword base on the input device path info.
 | 
						|
        //
 | 
						|
        *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;
 | 
						|
        Status       = EFI_INVALID_PARAMETER;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // 3.2 Get EFI_STRING_ID for the input keyword.
 | 
						|
      //
 | 
						|
      Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        *ProgressErr = RetVal;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // 3.3 Construct the ConfigRequest string.
 | 
						|
      //
 | 
						|
      Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // 3.4 Extract Value for the input keyword.
 | 
						|
      //
 | 
						|
      Status = ExtractValueFromDriver (ConfigRequest, &ValueElement);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        if (Status != EFI_OUT_OF_RESOURCES) {
 | 
						|
          Status = EFI_DEVICE_ERROR;
 | 
						|
        }
 | 
						|
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      StringPtr = NextStringPtr;
 | 
						|
 | 
						|
      //
 | 
						|
      // 4. Process the possible filter section.
 | 
						|
      //
 | 
						|
      RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);
 | 
						|
      if (RetVal != KEYWORD_HANDLER_NO_ERROR) {
 | 
						|
        *ProgressErr = RetVal;
 | 
						|
        Status       = EFI_INVALID_PARAMETER;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      StringPtr = NextStringPtr;
 | 
						|
 | 
						|
      //
 | 
						|
      // 5. Generate KeywordResp string.
 | 
						|
      //
 | 
						|
      Status = GenerateKeywordResp (NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);
 | 
						|
      if (Status != EFI_SUCCESS) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // 6. Merge to the MultiKeywordResp string.
 | 
						|
      //
 | 
						|
      Status = MergeToMultiKeywordResp (&MultiKeywordResp, &KeywordResp);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // 7. Update return value.
 | 
						|
      //
 | 
						|
      *Results = MultiKeywordResp;
 | 
						|
 | 
						|
      //
 | 
						|
      // 8. Clean the temp buffer.
 | 
						|
      //
 | 
						|
      FreePool (DevicePath);
 | 
						|
      FreePool (KeywordData);
 | 
						|
      FreePool (ValueElement);
 | 
						|
      FreePool (ConfigRequest);
 | 
						|
      DevicePath    = NULL;
 | 
						|
      KeywordData   = NULL;
 | 
						|
      ValueElement  = NULL;
 | 
						|
      ConfigRequest = NULL;
 | 
						|
      if (KeywordResp != NULL) {
 | 
						|
        FreePool (KeywordResp);
 | 
						|
        KeywordResp = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Enumerate all keyword in the system.
 | 
						|
    //
 | 
						|
    Status = EnumerateAllKeywords (NameSpace, &MultiKeywordResp, ProgressErr);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    *Results = MultiKeywordResp;
 | 
						|
  }
 | 
						|
 | 
						|
  *ProgressErr = KEYWORD_HANDLER_NO_ERROR;
 | 
						|
 | 
						|
Done:
 | 
						|
  *Progress = KeywordString + (StringPtr - TempString);
 | 
						|
 | 
						|
  if (TempString != NULL) {
 | 
						|
    FreePool (TempString);
 | 
						|
  }
 | 
						|
 | 
						|
  if (NameSpace != NULL) {
 | 
						|
    FreePool (NameSpace);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DevicePath != NULL) {
 | 
						|
    FreePool (DevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  if (KeywordData != NULL) {
 | 
						|
    FreePool (KeywordData);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |