]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Implement UEFI25 HII Config keyword handler protocol.
authorEric Dong <eric.dong@intel.com>
Wed, 13 May 2015 08:35:29 +0000 (08:35 +0000)
committerydong10 <ydong10@Edk2>
Wed, 13 May 2015 08:35:29 +0000 (08:35 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@hp.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17428 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c [new file with mode: 0644]
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseEntry.c

diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
new file mode 100644 (file)
index 0000000..6a71540
--- /dev/null
@@ -0,0 +1,3234 @@
+/** @file\r
+Implementation of interfaces function for EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "HiiDatabase.h"\r
+\r
+extern HII_DATABASE_PRIVATE_DATA mPrivate;\r
+\r
+/**\r
+  Convert the hex UNICODE %02x encoding of a UEFI device path to binary\r
+  from <PathHdr> of <MultiKeywordRequest>.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 MultiKeywordRequest string.\r
+  @param  DevicePathData         Binary of a UEFI device path.\r
+  @param  NextString             string follow the possible PathHdr string.\r
+\r
+  @retval EFI_INVALID_PARAMETER  The device path is not valid or the incoming parameter is invalid.\r
+  @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.\r
+  @retval EFI_SUCCESS            The device path is retrieved and translated to binary format.\r
+                                 The Input string not include PathHdr section.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractDevicePath (\r
+  IN  EFI_STRING                   String,\r
+  OUT UINT8                        **DevicePathData,\r
+  OUT EFI_STRING                   *NextString\r
+  )\r
+{\r
+  UINTN                    Length;\r
+  EFI_STRING               PathHdr;\r
+  UINT8                    *DevicePathBuffer;\r
+  CHAR16                   TemStr[2];\r
+  UINTN                    Index;\r
+  UINT8                    DigitUint8;\r
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+\r
+  ASSERT (NextString != NULL && DevicePathData != NULL);\r
+\r
+  //\r
+  // KeywordRequest == NULL case.\r
+  //\r
+  if (String == NULL) {\r
+    *DevicePathData = NULL;\r
+    *NextString = NULL;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Skip '&' if exist.\r
+  //\r
+  if (*String == L'&') {\r
+    String ++;\r
+  }\r
+\r
+  //\r
+  // Find the 'PATH=' of <PathHdr>.\r
+  //\r
+  if (StrnCmp (String, L"PATH=", StrLen (L"PATH=")) != 0) {\r
+    if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
+      return EFI_INVALID_PARAMETER;\r
+    } else {\r
+      //\r
+      // Not include PathHdr, return success and DevicePath = NULL.\r
+      //\r
+      *DevicePathData = NULL;\r
+      *NextString = String;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check whether path data does exist.\r
+  //\r
+  String += StrLen (L"PATH=");\r
+  if (*String == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  PathHdr = String;\r
+\r
+  //\r
+  // The content between 'PATH=' of <ConfigHdr> and '&' of next element\r
+  // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding\r
+  // of UEFI device path.\r
+  //\r
+  for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);\r
+\r
+  //\r
+  // Save the return next keyword string value.\r
+  //\r
+  *NextString = String;\r
+\r
+  //\r
+  // Check DevicePath Length\r
+  //\r
+  if (((Length + 1) / 2) < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // The data in <PathHdr> is encoded as hex UNICODE %02x bytes in the same order\r
+  // as the device path resides in RAM memory.\r
+  // Translate the data into binary.\r
+  //\r
+  DevicePathBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);\r
+  if (DevicePathBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  //\r
+  // Convert DevicePath\r
+  //\r
+  ZeroMem (TemStr, sizeof (TemStr));\r
+  for (Index = 0; Index < Length; Index ++) {\r
+    TemStr[0] = PathHdr[Index];\r
+    DigitUint8 = (UINT8) StrHexToUint64 (TemStr);\r
+    if ((Index & 1) == 0) {\r
+      DevicePathBuffer [Index/2] = DigitUint8;\r
+    } else {\r
+      DevicePathBuffer [Index/2] = (UINT8) ((DevicePathBuffer [Index/2] << 4) + DigitUint8);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Validate DevicePath\r
+  //\r
+  DevicePath  = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathBuffer;\r
+  while (!IsDevicePathEnd (DevicePath)) {\r
+    if ((DevicePath->Type == 0) || (DevicePath->SubType == 0) || (DevicePathNodeLength (DevicePath) < sizeof (EFI_DEVICE_PATH_PROTOCOL))) {\r
+      //\r
+      // Invalid device path\r
+      //\r
+      FreePool (DevicePathBuffer);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    DevicePath = NextDevicePathNode (DevicePath);\r
+  }\r
+\r
+  //\r
+  // return the device path\r
+  //\r
+  *DevicePathData = DevicePathBuffer;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get NameSpace from the input NameSpaceId string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 <NameSpaceId> format string.\r
+  @param  NameSpace              Return the name space string.\r
+  @param  NextString             Return the next string follow namespace.\r
+\r
+  @retval   EFI_SUCCESS             Get the namespace string success.\r
+  @retval   EFI_INVALID_PARAMETER   The NameSpaceId string not follow spec definition.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractNameSpace (\r
+  IN  EFI_STRING                   String,\r
+  OUT CHAR8                        **NameSpace,\r
+  OUT EFI_STRING                   *NextString\r
+  )\r
+{\r
+  CHAR16    *TmpPtr;\r
+\r
+  ASSERT (NameSpace != NULL);\r
+\r
+  TmpPtr = NULL;\r
+\r
+  //\r
+  // Input NameSpaceId == NULL\r
+  //\r
+  if (String == NULL) {\r
+    *NameSpace = NULL;\r
+    if (NextString != NULL) {\r
+      *NextString = NULL;\r
+    }\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Skip '&' if exist.\r
+  //\r
+  if (*String == L'&') {\r
+    String++;\r
+  }\r
+\r
+  if (StrnCmp (String, L"NAMESPACE=", StrLen (L"NAMESPACE=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  String += StrLen (L"NAMESPACE=");\r
+\r
+  TmpPtr = StrStr (String, L"&");\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = 0; \r
+  }\r
+  if (NextString != NULL) {\r
+    *NextString = String + StrLen (String);\r
+  }\r
+\r
+  //\r
+  // Input NameSpace is unicode string. The language in String package is ascii string.\r
+  // Here will convert the unicode string to ascii and save it.\r
+  //\r
+  *NameSpace = AllocatePool (StrLen (String) + 1);\r
+  if (*NameSpace == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  UnicodeStrToAsciiStr (String, *NameSpace);\r
+\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = L'&'; \r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get Keyword from the input KeywordRequest string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 KeywordRequestformat string.\r
+  @param  Keyword                return the extract keyword string.\r
+  @param  NextString             return the next string follow this keyword sectin.\r
+\r
+  @retval EFI_SUCCESS            Success to get the keyword string.\r
+  @retval EFI_INVALID_PARAMETER  Parsr the input string return error.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractKeyword (\r
+  IN  EFI_STRING                   String,\r
+  OUT EFI_STRING                   *Keyword,\r
+  OUT EFI_STRING                   *NextString\r
+  )\r
+{\r
+  EFI_STRING  TmpPtr;\r
+\r
+  ASSERT ((Keyword != NULL) && (NextString != NULL));\r
+  \r
+  TmpPtr = NULL;\r
+\r
+  //\r
+  // KeywordRequest == NULL case.\r
+  //\r
+  if (String == NULL) {\r
+    *Keyword = NULL;\r
+    *NextString = NULL;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Skip '&' if exist.\r
+  //\r
+  if (*String == L'&') {\r
+    String++;\r
+  }\r
+\r
+  if (StrnCmp (String, L"KEYWORD=", StrLen (L"KEYWORD=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  String += StrLen (L"KEYWORD=");\r
+  \r
+  TmpPtr = StrStr (String, L"&");\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = 0; \r
+  }\r
+  *NextString = String + StrLen (String);\r
+\r
+  *Keyword = AllocateCopyPool (StrSize (String), String);\r
+  if (*Keyword == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = L'&';\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get value from the input KeywordRequest string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 KeywordRequestformat string.\r
+  @param  Value                  return the extract value string.\r
+  @param  NextString             return the next string follow this keyword sectin.\r
+\r
+  @retval EFI_SUCCESS            Success to get the keyword string.\r
+  @retval EFI_INVALID_PARAMETER  Parsr the input string return error.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractValue (\r
+  IN  EFI_STRING                   String,\r
+  OUT EFI_STRING                   *Value,\r
+  OUT EFI_STRING                   *NextString\r
+  )\r
+{\r
+  EFI_STRING  TmpPtr;\r
+\r
+  ASSERT ((Value != NULL) && (NextString != NULL) && (String != NULL));\r
+\r
+  //\r
+  // Skip '&' if exist.\r
+  //\r
+  if (*String == L'&') {\r
+    String++;\r
+  }\r
+\r
+  if (StrnCmp (String, L"VALUE=", StrLen (L"VALUE=")) != 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  String += StrLen (L"VALUE=");\r
+  \r
+  TmpPtr = StrStr (String, L"&");\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = 0; \r
+  }\r
+  *NextString = String + StrLen (String);\r
+\r
+  *Value = AllocateCopyPool (StrSize (String), String);\r
+  if (*Value == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (TmpPtr != NULL) {\r
+    *TmpPtr = L'&';\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get filter from the input KeywordRequest string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 KeywordRequestformat string.\r
+  @param  FilterFlags            return the filter condition.\r
+  @param  NextString             return the next string follow this keyword sectin.\r
+\r
+  @retval EFI_SUCCESS            Success to get the keyword string.\r
+  @retval EFI_INVALID_PARAMETER  Parsr the input string return error.\r
+\r
+**/\r
+BOOLEAN\r
+ExtractFilter (\r
+  IN  EFI_STRING                   String,\r
+  OUT UINT8                        *FilterFlags,\r
+  OUT EFI_STRING                   *NextString\r
+  )\r
+{\r
+  CHAR16      *PathPtr;\r
+  CHAR16      *KeywordPtr;\r
+  BOOLEAN     RetVal; \r
+\r
+  ASSERT ((FilterFlags != NULL) && (NextString != NULL));\r
+\r
+  //\r
+  // String end, no filter section.\r
+  //\r
+  if (String == NULL) {\r
+    *NextString = NULL;\r
+    return FALSE;\r
+  }\r
+  \r
+  *FilterFlags = 0;\r
+  RetVal = TRUE;\r
+\r
+  //\r
+  // Skip '&' if exist.\r
+  //\r
+  if (*String == L'&') {\r
+    String++;\r
+  }\r
+\r
+  if (StrnCmp (String, L"ReadOnly", StrLen (L"ReadOnly")) == 0) {\r
+    //\r
+    // Find ReadOnly filter.\r
+    //\r
+    *FilterFlags |= EFI_KEYWORD_FILTER_READONY;\r
+    String += StrLen (L"ReadOnly");\r
+  } else if (StrnCmp (String, L"ReadWrite", StrLen (L"ReadWrite")) == 0) {\r
+    //\r
+    // Find ReadWrite filter.\r
+    //\r
+    *FilterFlags |= EFI_KEYWORD_FILTER_REAWRITE;\r
+    String += StrLen (L"ReadWrite");\r
+  } else if (StrnCmp (String, L"Buffer", StrLen (L"Buffer")) == 0) {\r
+    //\r
+    // Find Buffer Filter.\r
+    //\r
+    *FilterFlags |= EFI_KEYWORD_FILTER_BUFFER;\r
+    String += StrLen (L"Buffer");\r
+  } else if (StrnCmp (String, L"Numeric", StrLen (L"Numeric")) == 0) {\r
+    //\r
+    // Find Numeric Filter\r
+    //\r
+    String += StrLen (L"Numeric");\r
+    if (*String != L':') {\r
+      *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC;\r
+    } else {\r
+      String++;\r
+      switch (*String) {\r
+      case L'1':\r
+        *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_1;\r
+        break;\r
+      case L'2':\r
+        *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_2;\r
+        break;\r
+      case L'4':\r
+        *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_4;\r
+        break;\r
+      case L'8':\r
+        *FilterFlags |= EFI_KEYWORD_FILTER_NUMERIC_8;\r
+        break;\r
+      default:\r
+        ASSERT (FALSE);\r
+        break;\r
+      }\r
+      String++;\r
+    }\r
+  } else {\r
+    //\r
+    // Check whether other filter item defined by Platform.\r
+    //\r
+    if ((StrnCmp (String, L"&PATH", StrLen (L"&PATH")) == 0) ||\r
+        (StrnCmp (String, L"&KEYWORD", StrLen (L"&KEYWORD")) == 0)) {\r
+      //\r
+      // New KeywordRequest start, no platform defined filter.\r
+      //\r
+    } else {\r
+      //\r
+      // Platform defined filter rule.\r
+      // Just skip platform defined filter rule, return success.\r
+      //\r
+      PathPtr = StrStr(String, L"&PATH");\r
+      KeywordPtr = StrStr(String, L"&KEYWORD");\r
+      if (PathPtr != NULL && KeywordPtr != NULL) {\r
+        //\r
+        // If both sections exist, return the first follow string.\r
+        //\r
+        String = KeywordPtr > PathPtr ? PathPtr : KeywordPtr;\r
+      } else if (PathPtr != NULL) {\r
+        //\r
+        // Should not exist PathPtr != NULL && KeywordPtr == NULL case.\r
+        //\r
+        ASSERT (FALSE);\r
+      } else if (KeywordPtr != NULL) {\r
+        //\r
+        // Just to the next keyword section.\r
+        //\r
+        String = KeywordPtr;\r
+      } else {\r
+        //\r
+        // Only has paltform defined filter section, just skip it.\r
+        //\r
+        String += StrLen (String);\r
+      }\r
+    }\r
+    RetVal = FALSE;\r
+  }\r
+\r
+  *NextString = String;\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Extract Readonly flag from opcode.\r
+\r
+  This is a internal function.\r
+\r
+  @param  OpCodeData             Input opcode for this question.\r
+\r
+  @retval TRUE                   This question is readonly.\r
+  @retval FALSE                  This question is not readonly.\r
+\r
+**/\r
+BOOLEAN\r
+ExtractReadOnlyFromOpCode (\r
+  IN  UINT8         *OpCodeData\r
+  )\r
+{\r
+  EFI_IFR_QUESTION_HEADER   *QuestionHdr;\r
+\r
+  ASSERT (OpCodeData != NULL);\r
+\r
+  QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+\r
+  return (QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0;\r
+}\r
+\r
+/**\r
+  Create a circuit to check the filter section.\r
+\r
+  This is a internal function.\r
+\r
+  @param  OpCodeData             The questin binary ifr data.\r
+  @param  KeywordRequest         KeywordRequestformat string.\r
+  @param  NextString             return the next string follow this keyword sectin.\r
+  @param  ReadOnly               Return whether this question is read only.\r
+\r
+  @retval KEYWORD_HANDLER_NO_ERROR                     Success validate.\r
+  @retval KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED  Validate fail.\r
+\r
+**/\r
+UINT32\r
+ValidateFilter (\r
+  IN  UINT8         *OpCodeData,\r
+  IN  CHAR16        *KeywordRequest,\r
+  OUT CHAR16        **NextString,\r
+  OUT BOOLEAN       *ReadOnly\r
+  )\r
+{\r
+  CHAR16                    *NextFilter;\r
+  CHAR16                    *StringPtr;\r
+  UINT8                     FilterFlags;\r
+  EFI_IFR_QUESTION_HEADER   *QuestionHdr;\r
+  EFI_IFR_OP_HEADER         *OpCodeHdr;\r
+  UINT8                     Flags;\r
+  UINT32                    RetVal;\r
+\r
+  RetVal = KEYWORD_HANDLER_NO_ERROR;\r
+  StringPtr = KeywordRequest;\r
+\r
+  OpCodeHdr = (EFI_IFR_OP_HEADER *) OpCodeData;\r
+  QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+  if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
+    Flags = *(OpCodeData + sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER));\r
+  } else {\r
+    Flags = 0;\r
+  }\r
+\r
+  //\r
+  // Get ReadOnly flag from Question.\r
+  // \r
+  *ReadOnly = ExtractReadOnlyFromOpCode(OpCodeData);\r
+\r
+  while (ExtractFilter (StringPtr, &FilterFlags, &NextFilter)) {\r
+    switch (FilterFlags) {\r
+    case EFI_KEYWORD_FILTER_READONY:\r
+      if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) == 0) {\r
+        RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+        goto Done;\r
+      }\r
+      break;\r
+\r
+    case EFI_KEYWORD_FILTER_REAWRITE:\r
+      if ((QuestionHdr->Flags & EFI_IFR_FLAG_READ_ONLY) != 0) {\r
+        RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+        goto Done;\r
+      }\r
+      break;\r
+\r
+    case EFI_KEYWORD_FILTER_BUFFER:\r
+      //\r
+      // Only these three opcode use numeric value type.\r
+      //\r
+      if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP || OpCodeHdr->OpCode == EFI_IFR_CHECKBOX_OP) {\r
+        RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+        goto Done;\r
+      }\r
+      break;\r
+\r
+    case EFI_KEYWORD_FILTER_NUMERIC:\r
+      if (OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP && OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP && OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP) {\r
+        RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+        goto Done;\r
+      }\r
+      break;\r
+\r
+    case EFI_KEYWORD_FILTER_NUMERIC_1:\r
+    case EFI_KEYWORD_FILTER_NUMERIC_2:\r
+    case EFI_KEYWORD_FILTER_NUMERIC_4:\r
+    case EFI_KEYWORD_FILTER_NUMERIC_8:\r
+      if (OpCodeHdr->OpCode != EFI_IFR_ONE_OF_OP && OpCodeHdr->OpCode != EFI_IFR_NUMERIC_OP && OpCodeHdr->OpCode != EFI_IFR_CHECKBOX_OP) {\r
+        RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // For numeric and oneof, it has flags field to specify the detail numeric type.\r
+      //\r
+      if (OpCodeHdr->OpCode == EFI_IFR_ONE_OF_OP || OpCodeHdr->OpCode == EFI_IFR_NUMERIC_OP) {\r
+        switch (Flags & EFI_IFR_NUMERIC_SIZE) {\r
+        case EFI_IFR_NUMERIC_SIZE_1:\r
+          if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_1) {\r
+            RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+            goto Done;\r
+          }\r
+          break;\r
+\r
+        case EFI_IFR_NUMERIC_SIZE_2:\r
+          if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_2) {\r
+            RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+            goto Done;\r
+          }\r
+          break;\r
+\r
+        case EFI_IFR_NUMERIC_SIZE_4:\r
+          if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_4) {\r
+            RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+            goto Done;\r
+          }\r
+          break;\r
+\r
+        case EFI_IFR_NUMERIC_SIZE_8:\r
+          if (FilterFlags != EFI_KEYWORD_FILTER_NUMERIC_8) {\r
+            RetVal = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+            goto Done;\r
+          }\r
+          break;\r
+\r
+        default:\r
+          ASSERT (FALSE);\r
+          break;\r
+        }\r
+      }\r
+      break;\r
+\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Jump to the next filter.\r
+    //\r
+    StringPtr = NextFilter;\r
+  }\r
+  \r
+Done:\r
+  //\r
+  // The current filter which is processing.\r
+  //\r
+  *NextString = StringPtr;\r
+\r
+  return RetVal;\r
+}\r
+\r
+/**\r
+  Get HII_DATABASE_RECORD from the input device path info.\r
+\r
+  This is a internal function.\r
+\r
+  @param  DevicePath             UEFI device path protocol.\r
+\r
+  @retval Internal data base record.\r
+\r
+**/\r
+HII_DATABASE_RECORD *\r
+GetRecordFromDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *DevicePath\r
+  )\r
+{\r
+  LIST_ENTRY             *Link;\r
+  UINT8                  *DevicePathPkg;\r
+  UINT8                  *CurrentDevicePath;\r
+  UINTN                  DevicePathSize;\r
+  HII_DATABASE_RECORD    *TempDatabase;\r
+\r
+  ASSERT (DevicePath != NULL);\r
+\r
+  for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
+    TempDatabase = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    DevicePathPkg = TempDatabase->PackageList->DevicePathPkg;\r
+    if (DevicePathPkg != NULL) {\r
+      CurrentDevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+      DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) CurrentDevicePath);\r
+      if ((CompareMem (DevicePath, CurrentDevicePath, DevicePathSize) == 0)) {\r
+        return TempDatabase;\r
+      }\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Calculate the size of StringSrc and output it. Also copy string text from src \r
+  to dest.\r
+\r
+  This is a internal function.\r
+\r
+  @param  StringSrc              Points to current null-terminated string.\r
+  @param  BufferSize             Length of the buffer.\r
+  @param  StringDest             Buffer to store the string text. \r
+\r
+  @retval EFI_SUCCESS            The string text was outputed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES   Out of resource.\r
+\r
+**/\r
+EFI_STATUS\r
+GetUnicodeStringTextAndSize (\r
+  IN  UINT8            *StringSrc,\r
+  OUT UINTN            *BufferSize,\r
+  OUT EFI_STRING       *StringDest\r
+  )\r
+{\r
+  UINTN  StringSize;\r
+  UINT8  *StringPtr;\r
+\r
+  ASSERT (StringSrc != NULL && BufferSize != NULL && StringDest != NULL);\r
+\r
+  StringSize = sizeof (CHAR16);\r
+  StringPtr  = StringSrc;\r
+  while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) {\r
+    StringSize += sizeof (CHAR16);\r
+    StringPtr += sizeof (CHAR16);\r
+  }\r
+\r
+  *StringDest = AllocatePool (StringSize);\r
+  if (*StringDest == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  CopyMem (*StringDest, StringSrc, StringSize);\r
+\r
+  *BufferSize = StringSize;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Find the string id for the input keyword.\r
+\r
+  @param  StringPackage           Hii string package instance.\r
+  @param  KeywordValue            Input keyword value.\r
+  @param  StringId                The string's id, which is unique within PackageList.\r
+\r
+\r
+  @retval EFI_SUCCESS             The string text and font is retrieved\r
+                                  successfully.\r
+  @retval EFI_NOT_FOUND           The specified text or font info can not be found\r
+                                  out.\r
+  @retval EFI_OUT_OF_RESOURCES    The system is out of resources to accomplish the\r
+                                  task.\r
+**/\r
+EFI_STATUS\r
+GetStringIdFromString (\r
+  IN HII_STRING_PACKAGE_INSTANCE      *StringPackage,\r
+  IN CHAR16                           *KeywordValue,\r
+  OUT EFI_STRING_ID                   *StringId\r
+  )\r
+{\r
+  UINT8                                *BlockHdr;\r
+  EFI_STRING_ID                        CurrentStringId;\r
+  UINTN                                BlockSize;\r
+  UINTN                                Index;\r
+  UINT8                                *StringTextPtr;\r
+  UINTN                                Offset;\r
+  UINT16                               StringCount;\r
+  UINT16                               SkipCount;\r
+  UINT8                                Length8;\r
+  EFI_HII_SIBT_EXT2_BLOCK              Ext2;\r
+  UINT32                               Length32;\r
+  UINTN                                StringSize;\r
+  CHAR16                               *String;\r
+  CHAR8                                *AsciiKeywordValue;\r
+  EFI_STATUS                           Status;\r
+\r
+  ASSERT (StringPackage != NULL && KeywordValue != NULL && StringId != NULL);\r
+  ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+  CurrentStringId = 1;\r
+  Status = EFI_SUCCESS;\r
+  String = NULL;\r
+  BlockHdr = StringPackage->StringBlock;\r
+  BlockSize = 0;\r
+  Offset = 0;\r
+\r
+  //\r
+  // Make a ascii keyword value for later use.\r
+  //\r
+  AsciiKeywordValue = AllocatePool (StrLen (KeywordValue) + 1);\r
+  if (AsciiKeywordValue == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  UnicodeStrToAsciiStr(KeywordValue, AsciiKeywordValue);\r
+\r
+  while (*BlockHdr != EFI_HII_SIBT_END) {\r
+    switch (*BlockHdr) {\r
+    case EFI_HII_SIBT_STRING_SCSU:\r
+      Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      if (AsciiStrCmp(AsciiKeywordValue, StringTextPtr) == 0) {\r
+        *StringId = CurrentStringId;\r
+        goto Done;\r
+      }\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      if (AsciiStrCmp(AsciiKeywordValue, StringTextPtr) == 0) {\r
+        *StringId = CurrentStringId;\r
+        goto Done;\r
+      }\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU:\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        if (AsciiStrCmp(AsciiKeywordValue, StringTextPtr) == 0) {\r
+          *StringId = CurrentStringId;\r
+          goto Done;\r
+        }\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+      CopyMem (\r
+        &StringCount,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT16)\r
+        );\r
+      StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        if (AsciiStrCmp(AsciiKeywordValue, StringTextPtr) == 0) {\r
+          *StringId = CurrentStringId;\r
+          goto Done;\r
+        }\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2:\r
+      Offset        = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StringSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      \r
+      if (StrCmp(KeywordValue, String) == 0) {\r
+        *StringId = CurrentStringId;\r
+        goto Done;\r
+      }\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StringSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      \r
+      if (StrCmp(KeywordValue, String) == 0) {\r
+        *StringId = CurrentStringId;\r
+        goto Done;\r
+      }\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        BlockSize += StringSize;\r
+        if (StrCmp(KeywordValue, String) == 0) {\r
+          *StringId = CurrentStringId;\r
+          goto Done;\r
+        }\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (\r
+        &StringCount,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT16)\r
+        );\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        Status = GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
+\r
+        BlockSize += StringSize;\r
+        if (StrCmp(KeywordValue, String) == 0) {\r
+          *StringId = CurrentStringId;\r
+          goto Done;\r
+        }\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_DUPLICATE:\r
+      BlockSize       += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP1:\r
+      SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP2:\r
+      CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT1:\r
+      CopyMem (\r
+        &Length8,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT8)\r
+        );\r
+      BlockSize += Length8;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT2:\r
+      CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+      BlockSize += Ext2.Length;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT4:\r
+      CopyMem (\r
+        &Length32,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT32)\r
+        );\r
+\r
+      BlockSize += Length32;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    if (String != NULL) {\r
+      FreePool (String);\r
+      String = NULL;\r
+    }\r
+\r
+    BlockHdr  = StringPackage->StringBlock + BlockSize;\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+Done:\r
+  if (AsciiKeywordValue != NULL) {\r
+    FreePool (AsciiKeywordValue);\r
+  }\r
+  if (String != NULL) {\r
+    FreePool (String);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Find the next valid string id for the input string id.\r
+\r
+  @param  StringPackage           Hii string package instance.\r
+  @param  StringId                The current string id which is already got.\r
+                                  1 means just begin to get the string id.\r
+  @param  KeywordValue            Return the string for the next string id.\r
+\r
+\r
+  @retval EFI_STRING_ID           Not 0 means a valid stringid found.\r
+                                  0 means not found a valid string id.\r
+**/\r
+EFI_STRING_ID\r
+GetNextStringId (\r
+  IN  HII_STRING_PACKAGE_INSTANCE      *StringPackage,\r
+  IN  EFI_STRING_ID                    StringId,\r
+  OUT EFI_STRING                       *KeywordValue\r
+  )\r
+{\r
+  UINT8                                *BlockHdr;\r
+  EFI_STRING_ID                        CurrentStringId;\r
+  UINTN                                BlockSize;\r
+  UINTN                                Index;\r
+  UINT8                                *StringTextPtr;\r
+  UINTN                                Offset;\r
+  UINT16                               StringCount;\r
+  UINT16                               SkipCount;\r
+  UINT8                                Length8;\r
+  EFI_HII_SIBT_EXT2_BLOCK              Ext2;\r
+  UINT32                               Length32;\r
+  BOOLEAN                              FindString;\r
+  UINTN                                StringSize;\r
+  CHAR16                               *String;\r
+\r
+  ASSERT (StringPackage != NULL);\r
+  ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+  CurrentStringId = 1;\r
+  FindString = FALSE;\r
+  String = NULL;\r
+\r
+  //\r
+  // Parse the string blocks to get the string text and font.\r
+  //\r
+  BlockHdr  = StringPackage->StringBlock;\r
+  BlockSize = 0;\r
+  Offset    = 0;\r
+  while (*BlockHdr != EFI_HII_SIBT_END) {\r
+    switch (*BlockHdr) {\r
+    case EFI_HII_SIBT_STRING_SCSU:\r
+      Offset = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      \r
+      if (FindString) {\r
+        *KeywordValue = AllocatePool (AsciiStrSize ((CHAR8 *) StringTextPtr) * sizeof (CHAR16));\r
+        if (*KeywordValue == NULL) {\r
+          return 0;\r
+        }\r
+        AsciiStrToUnicodeStr(StringTextPtr, *KeywordValue);\r
+        return CurrentStringId;\r
+      } else if (CurrentStringId == StringId) {\r
+        FindString = TRUE;\r
+      }\r
+\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_SCSU_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      \r
+      if (FindString) {\r
+        *KeywordValue = AllocatePool (AsciiStrSize ((CHAR8 *) StringTextPtr) * sizeof (CHAR16));\r
+        if (*KeywordValue == NULL) {\r
+          return 0;\r
+        }\r
+        AsciiStrToUnicodeStr(StringTextPtr, *KeywordValue);\r
+        return CurrentStringId;\r
+      } else if (CurrentStringId == StringId) {\r
+        FindString = TRUE;\r
+      }\r
+\r
+      BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU:\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        if (FindString) {\r
+          *KeywordValue = AllocatePool (AsciiStrSize ((CHAR8 *) StringTextPtr) * sizeof (CHAR16));\r
+          if (*KeywordValue == NULL) {\r
+            return 0;\r
+          }\r
+          AsciiStrToUnicodeStr(StringTextPtr, *KeywordValue);\r
+          return CurrentStringId;\r
+        } else if (CurrentStringId == StringId) {\r
+          FindString = TRUE;\r
+        }\r
+\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_SCSU_FONT:\r
+      CopyMem (\r
+        &StringCount,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT16)\r
+        );\r
+      StringTextPtr = (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));\r
+      BlockSize += StringTextPtr - BlockHdr;\r
+\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        if (FindString) {\r
+          *KeywordValue = AllocatePool (AsciiStrSize ((CHAR8 *) StringTextPtr) * sizeof (CHAR16));\r
+          if (*KeywordValue == NULL) {\r
+            return 0;\r
+          }\r
+          AsciiStrToUnicodeStr(StringTextPtr, *KeywordValue);\r
+          return CurrentStringId;\r
+        } else if (CurrentStringId == StringId) {\r
+          FindString = TRUE;\r
+        }\r
+\r
+        BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2:\r
+      Offset        = sizeof (EFI_HII_STRING_BLOCK);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StringSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+      if (FindString && (String != NULL) && (*String != L'\0')) {\r
+        //\r
+        // String protocol use this type for the string id which has value for other package.\r
+        // It will allocate an empty string block for this string id. so here we also check\r
+        // *String != L'\0' to prohibit this case.\r
+        //\r
+        *KeywordValue = String;\r
+        return CurrentStringId;\r
+      } else if (CurrentStringId == StringId) {\r
+        FindString = TRUE;\r
+      }\r
+\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRING_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      //\r
+      // Use StringSize to store the size of the specified string, including the NULL\r
+      // terminator.\r
+      //\r
+      GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+      if (FindString) {\r
+        *KeywordValue = String;\r
+        return CurrentStringId;\r
+      } else if (CurrentStringId == StringId) {\r
+        FindString = TRUE;\r
+      }\r
+\r
+      BlockSize += Offset + StringSize;\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);        \r
+\r
+        if (FindString) {\r
+          *KeywordValue = String;\r
+          return CurrentStringId;\r
+        } else if (CurrentStringId == StringId) {\r
+          FindString = TRUE;\r
+        }\r
+\r
+        BlockSize += StringSize;\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_STRINGS_UCS2_FONT:\r
+      Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);\r
+      StringTextPtr = BlockHdr + Offset;\r
+      BlockSize += Offset;\r
+      CopyMem (\r
+        &StringCount,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT16)\r
+        );\r
+      for (Index = 0; Index < StringCount; Index++) {\r
+        GetUnicodeStringTextAndSize (StringTextPtr, &StringSize, &String);\r
+        if (FindString) {\r
+          *KeywordValue = String;\r
+          return CurrentStringId;\r
+        } else if (CurrentStringId == StringId) {\r
+          FindString = TRUE;\r
+        }\r
+\r
+        BlockSize += StringSize;\r
+        StringTextPtr = StringTextPtr + StringSize;\r
+        CurrentStringId++;\r
+      }\r
+      break;\r
+\r
+    case EFI_HII_SIBT_DUPLICATE:\r
+      BlockSize       += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);\r
+      CurrentStringId++;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP1:\r
+      SkipCount = (UINT16) (*(UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_SKIP2:\r
+      CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));\r
+      CurrentStringId = (UINT16) (CurrentStringId + SkipCount);\r
+      BlockSize       +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT1:\r
+      CopyMem (\r
+        &Length8,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT8)\r
+        );\r
+      BlockSize += Length8;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT2:\r
+      CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));\r
+      BlockSize += Ext2.Length;\r
+      break;\r
+\r
+    case EFI_HII_SIBT_EXT4:\r
+      CopyMem (\r
+        &Length32,\r
+        (UINT8*)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8)),\r
+        sizeof (UINT32)\r
+        );\r
+\r
+      BlockSize += Length32;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    if (String != NULL) {\r
+      FreePool (String);\r
+      String = NULL;\r
+    }\r
+\r
+    BlockHdr  = StringPackage->StringBlock + BlockSize;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Get string package from the input NameSpace string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.\r
+  @param  NameSpace                      NameSpace format string.\r
+  @param  KeywordValue                   Keyword value.\r
+  @param  StringId                       String Id for this keyword.\r
+\r
+  @retval KEYWORD_HANDLER_NO_ERROR                     Get String id succes.\r
+  @retval KEYWORD_HANDLER_KEYWORD_NOT_FOUND            Not found the string id in the string package.\r
+  @retval KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND       Not found the string package for this namespace.\r
+  @retval KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR   Out of resource error.\r
+\r
+**/\r
+UINT32\r
+GetStringIdFromRecord (\r
+  IN HII_DATABASE_RECORD   *DatabaseRecord,\r
+  IN CHAR8                 **NameSpace,\r
+  IN CHAR16                *KeywordValue,\r
+  OUT EFI_STRING_ID        *StringId\r
+  )\r
+{\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  EFI_STATUS                          Status;\r
+  CHAR8                               *Name;\r
+\r
+  ASSERT (DatabaseRecord != NULL && NameSpace != NULL && KeywordValue != NULL);\r
+\r
+  PackageListNode = DatabaseRecord->PackageList;\r
+\r
+  if (*NameSpace != NULL) {\r
+    Name = *NameSpace;\r
+  } else {\r
+    Name = UEFI_CONFIG_LANG;\r
+  }\r
+\r
+  for (Link = PackageListNode->StringPkgHdr.ForwardLink; Link != &PackageListNode->StringPkgHdr; Link = Link->ForwardLink) {\r
+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+    if (AsciiStrnCmp(Name, StringPackage->StringPkgHdr->Language, AsciiStrLen (Name)) == 0) {\r
+      Status = GetStringIdFromString (StringPackage, KeywordValue, StringId); \r
+      if (EFI_ERROR (Status)) {\r
+        return KEYWORD_HANDLER_KEYWORD_NOT_FOUND;\r
+      } else {\r
+        if (*NameSpace == NULL) {\r
+          *NameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
+          if (*NameSpace == NULL) {\r
+            return KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
+          }\r
+        }\r
+        return KEYWORD_HANDLER_NO_ERROR;\r
+      }\r
+    }\r
+  }\r
+\r
+  return KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an Statement OpCode.\r
+\r
+  @param  Operand                Operand of an IFR OpCode.\r
+\r
+  @retval TRUE                   This is an Statement OpCode.\r
+  @retval FALSE                  Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsStatementOpCode (\r
+  IN UINT8              Operand\r
+  )\r
+{\r
+  if ((Operand == EFI_IFR_SUBTITLE_OP) ||\r
+      (Operand == EFI_IFR_TEXT_OP) ||\r
+      (Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
+      (Operand == EFI_IFR_REF_OP) ||\r
+      (Operand == EFI_IFR_ACTION_OP) ||\r
+      (Operand == EFI_IFR_NUMERIC_OP) ||\r
+      (Operand == EFI_IFR_ORDERED_LIST_OP) ||\r
+      (Operand == EFI_IFR_CHECKBOX_OP) ||\r
+      (Operand == EFI_IFR_STRING_OP) ||\r
+      (Operand == EFI_IFR_PASSWORD_OP) ||\r
+      (Operand == EFI_IFR_DATE_OP) ||\r
+      (Operand == EFI_IFR_TIME_OP) ||\r
+      (Operand == EFI_IFR_GUID_OP) ||\r
+      (Operand == EFI_IFR_ONE_OF_OP)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Tell whether this Operand is an Statement OpCode.\r
+\r
+  @param  Operand                Operand of an IFR OpCode.\r
+\r
+  @retval TRUE                   This is an Statement OpCode.\r
+  @retval FALSE                  Not an Statement OpCode.\r
+\r
+**/\r
+BOOLEAN\r
+IsStorageOpCode (\r
+  IN UINT8              Operand\r
+  )\r
+{\r
+  if ((Operand == EFI_IFR_VARSTORE_OP) ||\r
+      (Operand == EFI_IFR_VARSTORE_NAME_VALUE_OP) ||\r
+      (Operand == EFI_IFR_VARSTORE_EFI_OP)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Base on the prompt string id to find the question.\r
+\r
+  @param  FormPackage            The input form package.\r
+  @param  KeywordStrId           The input prompt string id for one question.\r
+\r
+  @retval  the opcode for the question.\r
+\r
+**/\r
+UINT8 * \r
+FindQuestionFromStringId (\r
+  IN HII_IFR_PACKAGE_INSTANCE      *FormPackage,\r
+  IN EFI_STRING_ID                 KeywordStrId \r
+  )\r
+{\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  EFI_IFR_STATEMENT_HEADER     *StatementHeader;\r
+  EFI_IFR_OP_HEADER            *OpCodeHeader;\r
+  UINT32                       FormDataLen;\r
+\r
+  ASSERT (FormPackage != NULL);\r
+\r
+  FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
+  Offset = 0;\r
+  while (Offset < FormDataLen) {\r
+    OpCodeData = FormPackage->IfrData + Offset;\r
+    OpCodeHeader = (EFI_IFR_OP_HEADER *) OpCodeData;\r
+\r
+    if (IsStatementOpCode(OpCodeHeader->OpCode)) {\r
+      StatementHeader = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
+      if (StatementHeader->Prompt == KeywordStrId) {\r
+        return OpCodeData;\r
+      }\r
+    }\r
+\r
+    Offset += OpCodeHeader->Length;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Base on the varstore id to find the storage info.\r
+\r
+  @param  FormPackage            The input form package.\r
+  @param  VarStoreId             The input storage id.\r
+\r
+  @retval  the opcode for the storage.\r
+\r
+**/\r
+UINT8 *\r
+FindStorageFromVarId (\r
+  IN HII_IFR_PACKAGE_INSTANCE      *FormPackage,\r
+  IN EFI_VARSTORE_ID               VarStoreId\r
+  )\r
+{\r
+  UINT8                        *OpCodeData;\r
+  UINT32                       Offset;\r
+  EFI_IFR_OP_HEADER            *OpCodeHeader;\r
+  UINT32                       FormDataLen;\r
+\r
+  ASSERT (FormPackage != NULL);\r
+\r
+  FormDataLen = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);\r
+  Offset = 0;\r
+  while (Offset < FormDataLen) {\r
+    OpCodeData = FormPackage->IfrData + Offset;\r
+    OpCodeHeader = (EFI_IFR_OP_HEADER *) OpCodeData;\r
+\r
+    if (IsStorageOpCode(OpCodeHeader->OpCode)) {\r
+      switch (OpCodeHeader->OpCode) {\r
+      case EFI_IFR_VARSTORE_OP:\r
+        if (VarStoreId == ((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId) {\r
+          return OpCodeData;\r
+        }\r
+        break;\r
+\r
+      case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+        if (VarStoreId == ((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId) {\r
+          return OpCodeData;\r
+        }\r
+        break;\r
+\r
+      case EFI_IFR_VARSTORE_EFI_OP:\r
+        if (VarStoreId == ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId) {\r
+          return OpCodeData;\r
+        }\r
+        break;\r
+\r
+      default:\r
+        break;\r
+      }\r
+    }\r
+\r
+    Offset += OpCodeHeader->Length;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get width info for one question.\r
+\r
+  @param  OpCodeData            The input opcode for one question.\r
+\r
+  @retval  the width info for one question.\r
+\r
+**/\r
+UINT16 \r
+GetWidth (\r
+  IN UINT8        *OpCodeData\r
+  )\r
+{\r
+  UINT8      *NextOpCodeData;\r
+\r
+  ASSERT (OpCodeData != NULL);\r
+\r
+  switch (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode) {\r
+  case EFI_IFR_REF_OP:\r
+    return (UINT16) sizeof (EFI_HII_REF);\r
+\r
+  case EFI_IFR_ONE_OF_OP:\r
+  case EFI_IFR_NUMERIC_OP:\r
+    switch (((EFI_IFR_ONE_OF *) OpCodeData)->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+    case EFI_IFR_NUMERIC_SIZE_1:\r
+      return (UINT16) sizeof (UINT8);\r
+    \r
+    case EFI_IFR_NUMERIC_SIZE_2:\r
+      return  (UINT16) sizeof (UINT16);\r
+    \r
+    case EFI_IFR_NUMERIC_SIZE_4:\r
+      return (UINT16) sizeof (UINT32);\r
+    \r
+    case EFI_IFR_NUMERIC_SIZE_8:\r
+      return (UINT16) sizeof (UINT64);\r
+    \r
+    default:\r
+      ASSERT (FALSE);\r
+      return 0;\r
+    }\r
+\r
+  case EFI_IFR_ORDERED_LIST_OP:\r
+    NextOpCodeData = OpCodeData + ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Header.Length;\r
+    //\r
+    // OneOfOption must follow the orderedlist opcode.\r
+    //\r
+    ASSERT (((EFI_IFR_OP_HEADER *) NextOpCodeData)->OpCode == EFI_IFR_ONE_OF_OPTION_OP);\r
+    switch (((EFI_IFR_ONE_OF_OPTION *) NextOpCodeData)->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      return (UINT16) sizeof (UINT8) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
+    \r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      return (UINT16) sizeof (UINT16) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers ;\r
+    \r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      return (UINT16) sizeof (UINT32) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
+    \r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      return (UINT16) sizeof (UINT64) * ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;\r
+      break;\r
+    \r
+    default:\r
+      ASSERT (FALSE);\r
+      return 0;\r
+    }\r
+\r
+  case EFI_IFR_CHECKBOX_OP:\r
+    return (UINT16) sizeof (BOOLEAN);\r
+    \r
+  case EFI_IFR_PASSWORD_OP:\r
+  case EFI_IFR_STRING_OP:\r
+    return (UINT16)((UINTN) ((EFI_IFR_STRING *) OpCodeData)->MaxSize * sizeof (CHAR16));\r
+\r
+  case EFI_IFR_DATE_OP:\r
+    return (UINT16) sizeof (EFI_HII_DATE);\r
+\r
+  case EFI_IFR_TIME_OP:\r
+    return (UINT16) sizeof (EFI_HII_TIME);\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+    return 0;\r
+  }\r
+}\r
+\r
+/**\r
+  Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for \r
+  hex digits that appear between a '=' and a '&' in a config string.\r
+\r
+  If ConfigString is NULL, then ASSERT().\r
+\r
+  @param[in] ConfigString  Pointer to a Null-terminated Unicode string.\r
+\r
+  @return  Pointer to the Null-terminated Unicode result string.\r
+\r
+**/\r
+EFI_STRING\r
+EFIAPI\r
+InternalLowerConfigString (\r
+  IN EFI_STRING  ConfigString\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+  BOOLEAN     Lower;\r
+\r
+  ASSERT (ConfigString != NULL);\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {\r
+    if (*String == L'=') {\r
+      Lower = TRUE;\r
+    } else if (*String == L'&') {\r
+      Lower = FALSE;\r
+    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
+      *String = (CHAR16) (*String - L'A' + L'a');\r
+    }\r
+  }\r
+\r
+  return ConfigString;\r
+}\r
+\r
+/**\r
+  Allocates and returns a Null-terminated Unicode <ConfigHdr> string.\r
+  \r
+  The format of a <ConfigHdr> is as follows:\r
+\r
+    GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>\r
+\r
+  @param[in]  OpCodeData    The opcode for the storage.                  \r
+  @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol\r
+                            that is the routing information PATH.  Each byte of\r
+                            the Device Path associated with DriverHandle is converted\r
+                            to a 2 Unicode character hexidecimal string.\r
+\r
+  @retval NULL   DriverHandle does not support the Device Path Protocol.\r
+  @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string\r
+\r
+**/\r
+EFI_STRING\r
+ConstructConfigHdr (\r
+  IN UINT8           *OpCodeData,\r
+  IN EFI_HANDLE      DriverHandle\r
+  )\r
+{\r
+  UINTN                     NameLength;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  UINTN                     DevicePathSize;\r
+  CHAR16                    *String;\r
+  CHAR16                    *ReturnString;\r
+  UINTN                     Index;\r
+  UINT8                     *Buffer;\r
+  CHAR16                    *Name;\r
+  CHAR8                     *AsciiName;\r
+  EFI_GUID                  *Guid;\r
+\r
+  ASSERT (OpCodeData != NULL);\r
+\r
+  switch (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode) {\r
+  case EFI_IFR_VARSTORE_OP:\r
+    Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE *) OpCodeData)->Guid;\r
+    AsciiName = ((EFI_IFR_VARSTORE *) OpCodeData)->Name;\r
+    break;\r
+  \r
+  case EFI_IFR_VARSTORE_NAME_VALUE_OP:\r
+    Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;\r
+    AsciiName = NULL;\r
+    break;\r
+  \r
+  case EFI_IFR_VARSTORE_EFI_OP:\r
+    Guid      = (EFI_GUID *)(UINTN *)&((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;\r
+    AsciiName = ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;\r
+    break;\r
+  \r
+  default:\r
+    ASSERT (FALSE);\r
+    Guid      = NULL;\r
+    AsciiName = NULL;\r
+    break;\r
+  }\r
+\r
+  if (AsciiName != NULL) {\r
+    Name = AllocateZeroPool (AsciiStrSize (AsciiName) * 2);\r
+    ASSERT (Name != NULL);\r
+    AsciiStrToUnicodeStr(AsciiName, Name);\r
+  } else {\r
+    Name = NULL;\r
+  }\r
+\r
+  //\r
+  // Compute the length of Name in Unicode characters.  \r
+  // If Name is NULL, then the length is 0.\r
+  //\r
+  NameLength = 0;\r
+  if (Name != NULL) {\r
+    NameLength = StrLen (Name);\r
+  }\r
+\r
+  DevicePath = NULL;\r
+  DevicePathSize = 0;\r
+  //\r
+  // Retrieve DevicePath Protocol associated with DriverHandle\r
+  //\r
+  if (DriverHandle != NULL) {\r
+    DevicePath = DevicePathFromHandle (DriverHandle);\r
+    if (DevicePath == NULL) {\r
+      return NULL;\r
+    }\r
+    //\r
+    // Compute the size of the device path in bytes\r
+    //\r
+    DevicePathSize = GetDevicePathSize (DevicePath);\r
+  }\r
+\r
+  //\r
+  // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>\r
+  // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |\r
+  //\r
+  String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));\r
+  if (String == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Start with L"GUID="\r
+  //\r
+  ReturnString = StrCpy (String, L"GUID=");\r
+  String += StrLen (String);\r
+\r
+  if (Guid != NULL) {\r
+    //\r
+    // Append Guid converted to <HexCh>32\r
+    //\r
+    for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Append L"&NAME="\r
+  //\r
+  StrCpy (String, L"&NAME=");\r
+  String += StrLen (String);\r
+\r
+  if (Name != NULL) {\r
+    //\r
+    // Append Name converted to <Char>NameLength\r
+    //\r
+    for (; *Name != L'\0'; Name++) {\r
+      String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Append L"&PATH="\r
+  //\r
+  StrCpy (String, L"&PATH=");\r
+  String += StrLen (String);\r
+\r
+  //\r
+  // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize\r
+  //\r
+  for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {\r
+    String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);\r
+  }\r
+\r
+  //\r
+  // Null terminate the Unicode string\r
+  //\r
+  *String = L'\0';\r
+\r
+  //\r
+  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
+  //\r
+  return InternalLowerConfigString (ReturnString);\r
+}\r
+\r
+/**\r
+  Generate the Config request element for one question.\r
+\r
+  @param   Name    The name info for one question.\r
+  @param   Offset  The offset info for one question.\r
+  @param   Width   The width info for one question.\r
+\r
+  @return  Pointer to the Null-terminated Unicode request element string.\r
+\r
+**/\r
+EFI_STRING\r
+ConstructRequestElement (\r
+  IN CHAR16      *Name,\r
+  IN UINT16      Offset,\r
+  IN UINT16      Width  \r
+  )\r
+{\r
+  CHAR16    *StringPtr;\r
+  UINTN     Length;\r
+  \r
+  if (Name != NULL) {\r
+    //\r
+    // Add <BlockName> length for each Name\r
+    //\r
+    // <BlockName> ::= Name + \0\r
+    //                 StrLen(Name) | 1\r
+    //\r
+    Length = StrLen (Name) + 1;\r
+  } else {\r
+    //\r
+    // Add <BlockName> length for each Offset/Width pair\r
+    //\r
+    // <BlockName> ::= OFFSET=1234&WIDTH=1234 + \0\r
+    //                 |  7   | 4 |   7  | 4 |  1\r
+    //\r
+    Length = (7 + 4 + 7 + 4 + 1);\r
+  }\r
+\r
+  //\r
+  // Allocate buffer for the entire <ConfigRequest>\r
+  //\r
+  StringPtr = AllocateZeroPool (Length * sizeof (CHAR16));\r
+  ASSERT (StringPtr != NULL);\r
+\r
+  if (Name != NULL) {\r
+    //\r
+    // Append Name\0\r
+    //\r
+    UnicodeSPrint (\r
+      StringPtr,\r
+      (StrLen (Name) + 1) * sizeof (CHAR16),\r
+      L"%s",\r
+      Name\r
+    );\r
+  } else {\r
+    //\r
+    // Append OFFSET=XXXX&WIDTH=YYYY\0\r
+    //\r
+    UnicodeSPrint (\r
+      StringPtr, \r
+      (7 + 4 + 7 + 4 + 1) * sizeof (CHAR16), \r
+      L"OFFSET=%04X&WIDTH=%04X", \r
+      Offset, \r
+      Width\r
+    );\r
+  }\r
+\r
+  return StringPtr;\r
+}\r
+\r
+/**\r
+  Get string value for question's name field.\r
+\r
+  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.\r
+  @param  NameId                         The string id for the name field.\r
+\r
+  @retval Name string.\r
+\r
+**/\r
+CHAR16 *\r
+GetNameFromId (\r
+  IN HII_DATABASE_RECORD   *DatabaseRecord,\r
+  IN EFI_STRING_ID         NameId\r
+  )\r
+{\r
+  CHAR16      *Name;\r
+  CHAR8       *PlatformLanguage;\r
+  CHAR8       *SupportedLanguages;\r
+  CHAR8       *BestLanguage;\r
+  UINTN       StringSize;\r
+  CHAR16      TempString;\r
+  EFI_STATUS  Status;\r
+\r
+  Name = NULL;\r
+  BestLanguage = NULL;\r
+  PlatformLanguage = NULL; \r
+  SupportedLanguages = NULL;\r
+\r
+  GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);\r
+  SupportedLanguages = GetSupportedLanguages(DatabaseRecord->Handle);\r
+\r
+  //\r
+  // Get the best matching language from SupportedLanguages\r
+  //\r
+  BestLanguage = GetBestLanguage (\r
+                   SupportedLanguages, \r
+                   FALSE,                                             // RFC 4646 mode\r
+                   PlatformLanguage != NULL ? PlatformLanguage : "",  // Highest priority\r
+                   SupportedLanguages,                                // Lowest priority \r
+                   NULL\r
+                   );\r
+  if (BestLanguage == NULL) {\r
+    BestLanguage = AllocateCopyPool (AsciiStrLen ("en-US"), "en-US");\r
+    ASSERT (BestLanguage != NULL);\r
+  }\r
+\r
+  StringSize = 0;\r
+  Status = mPrivate.HiiString.GetString (\r
+                                 &mPrivate.HiiString,\r
+                                 BestLanguage,\r
+                                 DatabaseRecord->Handle,\r
+                                 NameId,\r
+                                 &TempString,\r
+                                 &StringSize,\r
+                                 NULL\r
+                                 );\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    goto Done;\r
+  }\r
+\r
+  Name = AllocateZeroPool (StringSize);\r
+  if (Name == NULL) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = mPrivate.HiiString.GetString (\r
+                          &mPrivate.HiiString,\r
+                          BestLanguage,\r
+                          DatabaseRecord->Handle,\r
+                          NameId,\r
+                          Name,\r
+                          &StringSize,\r
+                          NULL\r
+                          );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Name);\r
+    Name = NULL;\r
+    goto Done;\r
+  }\r
+\r
+Done:\r
+  if (SupportedLanguages != NULL) {\r
+    FreePool(SupportedLanguages);\r
+  }\r
+  if (BestLanguage != NULL) {\r
+    FreePool (BestLanguage);\r
+  }\r
+  if (PlatformLanguage != NULL) {\r
+    FreePool (PlatformLanguage);\r
+  }\r
+\r
+  return Name;\r
+}\r
+\r
+/**\r
+  Base on the input parameter to generate the ConfigRequest string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.\r
+  @param  KeywordStrId                   Keyword string id.\r
+  @param  OpCodeData                     The IFR data for this question.\r
+  @param  ConfigRequest                  Return the generate ConfigRequest string.\r
+\r
+  @retval EFI_SUCCESS               Generate ConfigResp string success.\r
+  @retval EFI_OUT_OF_RESOURCES      System out of memory resource error.\r
+  @retval EFI_NOT_FOUND             Not found the question which use this string id\r
+                                    as the prompt string id.\r
+**/\r
+EFI_STATUS\r
+ExtractConfigRequest (\r
+  IN  HII_DATABASE_RECORD   *DatabaseRecord,\r
+  IN  EFI_STRING_ID         KeywordStrId,\r
+  OUT UINT8                 **OpCodeData,\r
+  OUT EFI_STRING            *ConfigRequest\r
+  ) \r
+{\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_IFR_PACKAGE_INSTANCE            *FormPackage;\r
+  EFI_IFR_QUESTION_HEADER             *Header;\r
+  UINT8                               *Storage;\r
+  UINT8                               *OpCode;\r
+  CHAR16                              *Name;\r
+  UINT16                              Offset;\r
+  UINT16                              Width;\r
+  CHAR16                              *ConfigHdr;\r
+  CHAR16                              *RequestElement;\r
+  UINTN                               Length;\r
+  CHAR16                              *StringPtr;\r
+\r
+  ASSERT (DatabaseRecord != NULL && OpCodeData != NULL && ConfigRequest != NULL);\r
+\r
+  OpCode = NULL;\r
+  Name   = NULL;\r
+  Width  = 0;\r
+  Offset = 0;\r
+\r
+  PackageListNode = DatabaseRecord->PackageList;\r
+\r
+  //\r
+  // Search the languages in the specified packagelist.\r
+  //\r
+  for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
+    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
+\r
+    OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
+    if (OpCode != NULL) {\r
+      *OpCodeData = OpCode;\r
+      Header = (EFI_IFR_QUESTION_HEADER *) (OpCode + sizeof (EFI_IFR_OP_HEADER));\r
+      //\r
+      // Header->VarStoreId == 0 means no storage for this question.\r
+      //\r
+      ASSERT (Header->VarStoreId != 0);\r
+      DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
+      \r
+      Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
+      ASSERT (Storage != NULL);\r
+\r
+      if (((EFI_IFR_OP_HEADER *) Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
+        Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
+      } else {\r
+        Offset = Header->VarStoreInfo.VarOffset;\r
+        Width = GetWidth (OpCode);\r
+      }\r
+      RequestElement = ConstructRequestElement(Name, Offset, Width);\r
+      ConfigHdr = ConstructConfigHdr(Storage, DatabaseRecord->DriverHandle);\r
+\r
+      Length = (StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1) * sizeof (CHAR16);\r
+      *ConfigRequest = AllocatePool (Length);\r
+      if (*ConfigRequest == NULL) {\r
+        FreePool (ConfigHdr);\r
+        FreePool (RequestElement);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      StringPtr = *ConfigRequest;\r
+\r
+      StrCpy (StringPtr, ConfigHdr);\r
+      StringPtr += StrLen (StringPtr);\r
+\r
+      *StringPtr = L'&';\r
+      StringPtr++;\r
+\r
+      StrCpy (StringPtr, RequestElement);\r
+      StringPtr += StrLen (StringPtr);\r
+      *StringPtr = L'\0';\r
+\r
+      FreePool (ConfigHdr);\r
+      FreePool (RequestElement);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Base on the input parameter to generate the ConfigResp string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  DatabaseRecord                 HII_DATABASE_RECORD format string.\r
+  @param  KeywordStrId                   Keyword string id.\r
+  @param  ValueElement                   The value for the question which use keyword string id\r
+                                         as the prompt string id.\r
+  @param  OpCodeData                     The IFR data for this question.\r
+  @param  ConfigResp                     Return the generate ConfigResp string.\r
+\r
+  @retval EFI_SUCCESS               Generate ConfigResp string success.\r
+  @retval EFI_OUT_OF_RESOURCES      System out of memory resource error.\r
+  @retval EFI_NOT_FOUND             Not found the question which use this string id\r
+                                    as the prompt string id.\r
+**/\r
+EFI_STATUS\r
+ExtractConfigResp (\r
+  IN  HII_DATABASE_RECORD   *DatabaseRecord,\r
+  IN  EFI_STRING_ID         KeywordStrId,\r
+  IN  EFI_STRING            ValueElement,\r
+  OUT UINT8                 **OpCodeData,\r
+  OUT EFI_STRING            *ConfigResp\r
+  ) \r
+{\r
+  LIST_ENTRY                          *Link;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_IFR_PACKAGE_INSTANCE            *FormPackage;\r
+  EFI_IFR_QUESTION_HEADER             *Header;\r
+  UINT8                               *Storage;\r
+  UINT8                               *OpCode;\r
+  CHAR16                              *Name;\r
+  UINT16                              Offset;\r
+  UINT16                              Width;\r
+  CHAR16                              *ConfigHdr;\r
+  CHAR16                              *RequestElement;\r
+  UINTN                               Length;\r
+  CHAR16                              *StringPtr;\r
+\r
+  ASSERT ((DatabaseRecord != NULL) && (OpCodeData != NULL) && (ConfigResp != NULL) && (ValueElement != NULL));\r
+\r
+  OpCode = NULL;\r
+  Name   = NULL;\r
+  Width  = 0;\r
+  Offset = 0;\r
+\r
+  PackageListNode = DatabaseRecord->PackageList;\r
+\r
+  //\r
+  // Search the languages in the specified packagelist.\r
+  //\r
+  for (Link = PackageListNode->FormPkgHdr.ForwardLink; Link != &PackageListNode->FormPkgHdr; Link = Link->ForwardLink) {\r
+    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);\r
+\r
+    OpCode = FindQuestionFromStringId (FormPackage, KeywordStrId);\r
+    if (OpCode != NULL) {\r
+      *OpCodeData = OpCode;\r
+      Header = (EFI_IFR_QUESTION_HEADER *) (OpCode + sizeof (EFI_IFR_OP_HEADER));\r
+      //\r
+      // Header->VarStoreId == 0 means no storage for this question.\r
+      //\r
+      ASSERT (Header->VarStoreId != 0);\r
+      DEBUG ((EFI_D_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));\r
+      \r
+      Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);\r
+      ASSERT (Storage != NULL);\r
+\r
+      if (((EFI_IFR_OP_HEADER *) Storage)->OpCode == EFI_IFR_VARSTORE_NAME_VALUE_OP) {\r
+        Name = GetNameFromId (DatabaseRecord, Header->VarStoreInfo.VarName);\r
+      } else {\r
+        Offset = Header->VarStoreInfo.VarOffset;\r
+        Width  = GetWidth (OpCode);\r
+      }\r
+      RequestElement = ConstructRequestElement(Name, Offset, Width);\r
+\r
+      ConfigHdr = ConstructConfigHdr(Storage, DatabaseRecord->DriverHandle);\r
+\r
+      Length = (StrLen (ConfigHdr) + 1 + StrLen(RequestElement) + 1 + StrLen (L"VALUE=") + StrLen(ValueElement) + 1) * sizeof (CHAR16);\r
+      *ConfigResp = AllocatePool (Length);\r
+      if (*ConfigResp == NULL) {\r
+        FreePool (ConfigHdr);\r
+        FreePool (RequestElement);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      StringPtr = *ConfigResp;\r
+\r
+      StrCpy (StringPtr, ConfigHdr);\r
+      StringPtr += StrLen (StringPtr);\r
+\r
+      *StringPtr = L'&';\r
+      StringPtr++;\r
+\r
+      StrCpy (StringPtr, RequestElement);\r
+      StringPtr += StrLen (StringPtr);\r
+      \r
+      *StringPtr = L'&';\r
+      StringPtr++;\r
+\r
+      StrCpy (StringPtr, L"VALUE=");\r
+      StringPtr += StrLen (StringPtr);\r
+\r
+      StrCpy (StringPtr, ValueElement);\r
+      StringPtr += StrLen (StringPtr);\r
+      *StringPtr = L'\0';\r
+\r
+      FreePool (ConfigHdr);\r
+      FreePool (RequestElement);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Get the Value section from the Hii driver.\r
+\r
+  This is a internal function.\r
+\r
+  @param  ConfigRequest                  The input ConfigRequest string.\r
+  @param  ValueElement                   The respond Value section from the hii driver.\r
+\r
+  @retval Misc value                     The error status return from ExtractConfig function.\r
+  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated\r
+  @retval EFI_SUCCESS                    Get the value section success.\r
+\r
+**/\r
+EFI_STATUS\r
+ExtractValueFromDriver (\r
+  IN  CHAR16           *ConfigRequest,\r
+  OUT CHAR16           **ValueElement\r
+  )\r
+{\r
+  EFI_STATUS   Status;\r
+  EFI_STRING   Result;\r
+  EFI_STRING   Progress;\r
+  CHAR16       *StringPtr;\r
+  CHAR16       *StringEnd;\r
+\r
+  ASSERT ((ConfigRequest != NULL) && (ValueElement != NULL));\r
+\r
+  Status = mPrivate.ConfigRouting.ExtractConfig (\r
+                      &mPrivate.ConfigRouting,\r
+                      (EFI_STRING) ConfigRequest,\r
+                      &Progress,\r
+                      &Result\r
+                      );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Find Value Section and return it.\r
+  //\r
+  StringPtr = StrStr (Result, L"&VALUE=");\r
+  ASSERT (StringPtr != NULL);\r
+  StringEnd = StrStr (StringPtr + 1, L"&");\r
+  if (StringEnd != NULL) {\r
+    *StringEnd = L'\0';\r
+  }\r
+\r
+  *ValueElement = AllocateCopyPool (StrSize (StringPtr), StringPtr);\r
+  if (*ValueElement == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  if (StringEnd != NULL) {\r
+    *StringEnd = L'&';\r
+  }\r
+  FreePool (Result);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get EFI_STRING_ID info from the input device path, namespace and keyword.\r
+\r
+  This is a internal function.\r
+\r
+  @param  DevicePath                     Input device path info.\r
+  @param  NameSpace                      NameSpace format string.\r
+  @param  KeywordData                    Keyword used to get string id.\r
+  @param  ProgressErr                    Return extra error type.\r
+  @param  KeywordStringId                Return EFI_STRING_ID.\r
+  @param  DataBaseRecord                 DataBase record data for this driver.\r
+\r
+  @retval EFI_INVALID_PARAMETER          Can't find the database record base on the input device path or namespace.\r
+  @retval EFI_NOT_FOUND                  Can't find the EFI_STRING_ID for the keyword.\r
+  @retval EFI_SUCCESS                    Find the EFI_STRING_ID.\r
+\r
+**/\r
+EFI_STATUS\r
+GetStringIdFromDatabase (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL            **DevicePath,\r
+  IN  CHAR8                               **NameSpace,\r
+  IN  CHAR16                              *KeywordData,\r
+  OUT UINT32                              *ProgressErr,\r
+  OUT EFI_STRING_ID                       *KeywordStringId,\r
+  OUT HII_DATABASE_RECORD                 **DataBaseRecord\r
+ )\r
+{\r
+  HII_DATABASE_RECORD                 *Record;\r
+  LIST_ENTRY                          *Link;\r
+  BOOLEAN                             FindNameSpace;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DestDevicePath;\r
+  UINT8                               *DevicePathPkg;\r
+  UINTN                               DevicePathSize;\r
+\r
+  ASSERT ((NameSpace != NULL) && (KeywordData != NULL) && (ProgressErr != NULL) && (KeywordStringId != NULL) && (DataBaseRecord != NULL));\r
+\r
+  FindNameSpace = FALSE;\r
+\r
+  if (*DevicePath != NULL) {\r
+    //\r
+    // Get DataBaseRecord from device path protocol.\r
+    //\r
+    Record = GetRecordFromDevicePath(*DevicePath);\r
+    if (Record == NULL) {\r
+      //\r
+      // Can't find the DatabaseRecord base on the input device path info.\r
+      // NEED TO CONFIRM the return ProgressErr.\r
+      //\r
+      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    //\r
+    // Get string id from the record.\r
+    //\r
+    *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
+    switch (*ProgressErr) {\r
+    case KEYWORD_HANDLER_NO_ERROR:\r
+      *DataBaseRecord = Record;\r
+      return EFI_SUCCESS;\r
+\r
+    case KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND:\r
+      return EFI_INVALID_PARAMETER;\r
+\r
+    default:\r
+      ASSERT (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  } else {\r
+    //\r
+    // Find driver which matches the routing data.\r
+    //\r
+    for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
+      Record = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+\r
+      *ProgressErr = GetStringIdFromRecord (Record, NameSpace, KeywordData, KeywordStringId);\r
+      if (*ProgressErr == KEYWORD_HANDLER_NO_ERROR) {\r
+        *DataBaseRecord = Record;\r
+        \r
+        if ((DevicePathPkg = Record->PackageList->DevicePathPkg) != NULL) {\r
+          DestDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER));\r
+          DevicePathSize = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DestDevicePath);\r
+          *DevicePath = AllocateCopyPool (DevicePathSize, DestDevicePath);\r
+          if (*DevicePath == NULL) {\r
+            return EFI_OUT_OF_RESOURCES;\r
+          }\r
+        } else {\r
+          //\r
+          // Need to verify this ASSERT.\r
+          //\r
+          ASSERT (FALSE);\r
+        }\r
+\r
+        return EFI_SUCCESS;\r
+      } else if (*ProgressErr == KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      } else if (*ProgressErr == KEYWORD_HANDLER_KEYWORD_NOT_FOUND) {\r
+        FindNameSpace = TRUE;\r
+      }  \r
+    }\r
+\r
+    //\r
+    // When PathHdr not input, if ever find the namespace, will return KEYWORD_HANDLER_KEYWORD_NOT_FOUND.\r
+    // This is a bit more progress than KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND.\r
+    //\r
+    if (FindNameSpace) {\r
+      return EFI_NOT_FOUND;\r
+    } else {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Genereate the KeywordResp String.\r
+\r
+  <KeywordResp> ::= <NameSpaceId><PathHdr>'&'<Keyword>'&VALUE='<Number>['&READONLY']\r
+\r
+  @param  NameSpace                      NameSpace format string.\r
+  @param  DevicePath                     Input device path info.\r
+  @param  KeywordData                    Keyword used to get string id.\r
+  @param  ValueStr                       The value section for the keyword.\r
+  @param  ReadOnly                       Whether this value is readonly.\r
+  @param  KeywordResp                    Return the point to the KeywordResp string.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.\r
+  @retval EFI_SUCCESS                    Generate the KeywordResp string.\r
+\r
+**/\r
+EFI_STATUS\r
+GenerateKeywordResp (\r
+  IN  CHAR8                          *NameSpace, \r
+  IN  EFI_DEVICE_PATH_PROTOCOL       *DevicePath,\r
+  IN  EFI_STRING                     KeywordData,\r
+  IN  EFI_STRING                     ValueStr,\r
+  IN  BOOLEAN                        ReadOnly,\r
+  OUT EFI_STRING                     *KeywordResp\r
+  )\r
+{\r
+  UINTN     RespStrLen;\r
+  CHAR16    *RespStr;\r
+  CHAR16    *PathHdr;\r
+  CHAR16    *UnicodeNameSpace;\r
+\r
+  ASSERT ((NameSpace != NULL) && (DevicePath != NULL) && (KeywordData != NULL) && (ValueStr != NULL) && (KeywordResp != NULL));\r
+\r
+  //\r
+  // 1. Calculate the string length.\r
+  //\r
+  //\r
+  // 1.1 NameSpaceId size.\r
+  // 'NAMESPACE='<String>\r
+  //\r
+  RespStrLen = 10 + AsciiStrLen (NameSpace);\r
+  UnicodeNameSpace = AllocatePool ((AsciiStrLen (NameSpace) + 1) * sizeof (CHAR16));\r
+  if (UnicodeNameSpace == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  AsciiStrToUnicodeStr(NameSpace, UnicodeNameSpace);\r
+\r
+  //\r
+  // 1.2 PathHdr size.\r
+  // PATH=<UEFI binary Device Path represented as hex number>'&'\r
+  // Attention: The output include the '&' at the end.\r
+  //\r
+  GenerateSubStr (\r
+    L"&PATH=",\r
+    GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),\r
+    (VOID *) DevicePath,\r
+    1,\r
+    &PathHdr\r
+    );\r
+  RespStrLen += StrLen (PathHdr);\r
+\r
+  //\r
+  // 1.3 Keyword setion.\r
+  // 'KEYWORD='<String>[':'<DecCh>(1/4)]\r
+  //\r
+  RespStrLen += 8 + StrLen (KeywordData);\r
+\r
+  //\r
+  // 1.4 Value section.\r
+  // ValueStr = '&VALUE='<Number>\r
+  //\r
+  RespStrLen += StrLen (ValueStr);\r
+\r
+  //\r
+  // 1.5 ReadOnly Section.\r
+  // '&READONLY'\r
+  //\r
+  if (ReadOnly) {\r
+    RespStrLen += 9;\r
+  }\r
+\r
+  //\r
+  // 2. Allocate the buffer and create the KeywordResp string.\r
+  //\r
+  *KeywordResp = AllocatePool ((RespStrLen + 1) * sizeof (CHAR16));\r
+  if (*KeywordResp == NULL) {\r
+    if (UnicodeNameSpace != NULL) {\r
+      FreePool (UnicodeNameSpace);\r
+    }\r
+\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  RespStr = *KeywordResp;\r
+\r
+  //\r
+  // 2.1 Copy NameSpaceId section.\r
+  //\r
+  StrCpy (RespStr, L"NAMESPACE=");\r
+  RespStr += StrLen (RespStr);\r
+  StrCpy (RespStr, UnicodeNameSpace);\r
+  RespStr += StrLen (RespStr);\r
+\r
+  //\r
+  // 2.2 Copy PathHdr section.\r
+  //\r
+  StrCpy (RespStr, PathHdr);\r
+  RespStr += StrLen (RespStr);\r
+\r
+  //\r
+  // 2.3 Copy Keyword section.\r
+  //\r
+  StrCpy (RespStr, L"KEYWORD=");\r
+  RespStr += StrLen (RespStr);\r
+  StrCpy (RespStr, KeywordData);\r
+  RespStr += StrLen (RespStr);\r
+\r
+  //\r
+  // 2.4 Copy the Value section.\r
+  //\r
+  StrCpy (RespStr, ValueStr);\r
+  RespStr += StrLen (RespStr);\r
+\r
+  //\r
+  // 2.5 Copy ReadOnly section if exist.\r
+  //\r
+  if (ReadOnly) {\r
+    StrCpy (RespStr, L"&READONLY");\r
+    RespStr += StrLen (RespStr);\r
+  }\r
+\r
+  //\r
+  // 2.6 Add the end.\r
+  //\r
+  *RespStr = L'\0';\r
+\r
+  if (UnicodeNameSpace != NULL) {\r
+    FreePool (UnicodeNameSpace);\r
+  }\r
+  if (PathHdr != NULL) {\r
+    FreePool (PathHdr);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Merge the KeywordResp String to MultiKeywordResp string.\r
+\r
+  This is a internal function.\r
+\r
+  @param  MultiKeywordResp               The existed multikeywordresp string.\r
+  @param  KeywordResp                    The input keywordResp string.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.\r
+  @retval EFI_SUCCESS                    Generate the MultiKeywordResp string.\r
+\r
+**/\r
+EFI_STATUS\r
+MergeToMultiKeywordResp (\r
+  IN OUT EFI_STRING         *MultiKeywordResp,\r
+  IN     EFI_STRING         *KeywordResp\r
+  )\r
+{\r
+  UINTN       MultiKeywordRespLen;\r
+  EFI_STRING  StringPtr;\r
+\r
+  if (*MultiKeywordResp == NULL) {\r
+    *MultiKeywordResp = *KeywordResp;\r
+    *KeywordResp = NULL;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  MultiKeywordRespLen = (StrLen (*MultiKeywordResp) + 1 + StrLen (*KeywordResp) + 1) * sizeof (CHAR16);\r
+\r
+  StringPtr = AllocateCopyPool (MultiKeywordRespLen, *MultiKeywordResp);\r
+  if (StringPtr == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  FreePool (*MultiKeywordResp);\r
+  *MultiKeywordResp = StringPtr;\r
+\r
+  StringPtr += StrLen (StringPtr);\r
+\r
+  *StringPtr = L'&';\r
+  StringPtr++;\r
+\r
+  StrCpy (StringPtr, *KeywordResp);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enumerate all keyword in the system. \r
+  \r
+  If error occur when parse one keyword, just skip it and parse the next one. \r
+\r
+  This is a internal function.\r
+\r
+  @param  NameSpace                      The namespace used to search the string.\r
+  @param  MultiResp                      Return the MultiKeywordResp string for the system.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES           The memory can't be allocated.\r
+  @retval EFI_SUCCESS                    Generate the MultiKeywordResp string.\r
+  @retval EFI_NOT_FOUND                  No keyword found.\r
+\r
+**/\r
+EFI_STATUS\r
+EnumerateAllKeywords (\r
+  IN  CHAR8             *NameSpace,\r
+  OUT EFI_STRING        *MultiResp\r
+  )\r
+{\r
+  LIST_ENTRY                          *Link;\r
+  LIST_ENTRY                          *StringLink;\r
+  UINT8                               *DevicePathPkg;\r
+  UINT8                               *DevicePath;\r
+  HII_DATABASE_RECORD                 *DataBaseRecord;\r
+  UINTN                               DevicePathSize;\r
+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageListNode;\r
+  HII_STRING_PACKAGE_INSTANCE         *StringPackage;\r
+  CHAR8                               *LocalNameSpace;\r
+  EFI_STRING_ID                       NextStringId;\r
+  EFI_STATUS                          Status;\r
+  CHAR8                               *OpCode;\r
+  CHAR16                              *ConfigRequest;\r
+  CHAR16                              *ValueElement;\r
+  CHAR16                              *KeywordResp;\r
+  CHAR16                              *MultiKeywordResp;\r
+  CHAR16                              *KeywordData;\r
+  BOOLEAN                             ReadOnly;\r
+\r
+  DataBaseRecord   = NULL;\r
+  DevicePathSize   = 0;\r
+  Status           = EFI_SUCCESS;\r
+  MultiKeywordResp = NULL;\r
+  DevicePath       = NULL;\r
+  LocalNameSpace   = NULL;\r
+  ConfigRequest    = NULL;\r
+  ValueElement     = NULL;\r
+  KeywordResp      = NULL;\r
+\r
+  if (NameSpace == NULL) {\r
+    NameSpace = UEFI_CONFIG_LANG;\r
+  }\r
+\r
+  //\r
+  // Find driver which matches the routing data.\r
+  //\r
+  for (Link = mPrivate.DatabaseList.ForwardLink; Link != &mPrivate.DatabaseList; Link = Link->ForwardLink) {\r
+    DataBaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);\r
+    if ((DevicePathPkg = DataBaseRecord->PackageList->DevicePathPkg) != NULL) {\r
+      DevicePath = DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER);\r
+      DevicePathSize    = GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath);\r
+    }\r
+    PackageListNode = DataBaseRecord->PackageList;\r
+\r
+    for (StringLink = PackageListNode->StringPkgHdr.ForwardLink; StringLink != &PackageListNode->StringPkgHdr; StringLink = StringLink->ForwardLink) {\r
+      StringPackage = CR (StringLink, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
+\r
+      //\r
+      // Check whether has keyword string package.\r
+      //\r
+      if (AsciiStrnCmp(NameSpace, StringPackage->StringPkgHdr->Language, AsciiStrLen (NameSpace)) == 0) {\r
+        //\r
+        // Keep the NameSpace string.\r
+        //\r
+        LocalNameSpace = AllocateCopyPool (AsciiStrSize (StringPackage->StringPkgHdr->Language), StringPackage->StringPkgHdr->Language);\r
+        if (LocalNameSpace == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        //\r
+        // 1 means just begin the enumerate the valid string ids.\r
+        // StringId == 1 is always used to save the language for this string package.\r
+        // Any valid string start from 2. so here initial it to 1.\r
+        //\r
+        NextStringId = 1;\r
+        \r
+        //\r
+        // Enumerate all valid stringid in the package.\r
+        //\r
+        while ((NextStringId = GetNextStringId (StringPackage, NextStringId, &KeywordData)) != 0) {\r
+          //\r
+          // 3.3 Construct the ConfigRequest string.\r
+          //\r
+          Status = ExtractConfigRequest (DataBaseRecord, NextStringId, &OpCode, &ConfigRequest);\r
+          if (EFI_ERROR (Status)) {\r
+            //\r
+            // If can't generate ConfigRequest for this question, skip it and start the next.\r
+            //\r
+            goto Error;\r
+          }\r
+          \r
+          //\r
+          // 3.4 Extract Value for the input keyword.\r
+          //\r
+          Status = ExtractValueFromDriver(ConfigRequest, &ValueElement);\r
+          if (EFI_ERROR (Status)) {\r
+            if (Status != EFI_OUT_OF_RESOURCES) {\r
+              //\r
+              // If can't generate ConfigRequest for this question, skip it and start the next.\r
+              //\r
+              goto Error;\r
+            }\r
+            //\r
+            // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
+            //\r
+            goto Done;\r
+          }\r
+\r
+          //\r
+          // Extract readonly flag from opcode.\r
+          //\r
+          ReadOnly = ExtractReadOnlyFromOpCode(OpCode);\r
+\r
+          //\r
+          // 5. Generate KeywordResp string.\r
+          //\r
+          ASSERT (DevicePath != NULL);\r
+          Status = GenerateKeywordResp(LocalNameSpace, (EFI_DEVICE_PATH_PROTOCOL *)DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
+          if (Status != EFI_SUCCESS) {\r
+            //\r
+            // If EFI_OUT_OF_RESOURCES error occur, no need to continue.\r
+            //\r
+            goto Done;\r
+          }\r
+          \r
+          //\r
+          // 6. Merge to the MultiKeywordResp string.\r
+          //\r
+          Status = MergeToMultiKeywordResp(&MultiKeywordResp, &KeywordResp);\r
+          if (EFI_ERROR (Status)) {\r
+            goto Done;\r
+          }\r
+Error:\r
+          //\r
+          // Clean the temp buffer to later use again.\r
+          //\r
+          if (ConfigRequest != NULL) {\r
+            FreePool (ConfigRequest);\r
+            ConfigRequest = NULL;\r
+          }\r
+          if (ValueElement != NULL) {\r
+            FreePool (ValueElement);\r
+            ValueElement = NULL;\r
+          }\r
+          if (KeywordResp != NULL) {\r
+            FreePool (KeywordResp);\r
+            KeywordResp = NULL;\r
+          } \r
+        }\r
+\r
+        if (LocalNameSpace != NULL) {\r
+          FreePool (LocalNameSpace);\r
+          LocalNameSpace = NULL;\r
+        }\r
+      }\r
+    } \r
+  }\r
+\r
+  //\r
+  // return the already get MultiKeywordString even error occured.\r
+  //\r
+  if (MultiKeywordResp == NULL) {\r
+    Status = EFI_NOT_FOUND;\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  *MultiResp = MultiKeywordResp;\r
+  \r
+Done:\r
+  if (LocalNameSpace != NULL) {\r
+    FreePool (LocalNameSpace);\r
+  }\r
+  if (ConfigRequest != NULL) {\r
+    FreePool (ConfigRequest);\r
+  }\r
+  if (ValueElement != NULL) {\r
+    FreePool (ValueElement);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This function accepts a <MultiKeywordResp> formatted string, finds the associated\r
+  keyword owners, creates a <MultiConfigResp> string from it and forwards it to the\r
+  EFI_HII_ROUTING_PROTOCOL.RouteConfig function.\r
+  \r
+  If there is an issue in resolving the contents of the KeywordString, then the \r
+  function returns an error and also sets the Progress and ProgressErr with the \r
+  appropriate information about where the issue occurred and additional data about\r
+  the nature of the issue. \r
+  \r
+  In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND\r
+  error is generated during processing the second or later keyword element, the system\r
+  storage associated with earlier keywords is not modified. All elements of the \r
+  KeywordString must successfully pass all tests for format and access prior to making\r
+  any modifications to storage.\r
+  \r
+  In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString\r
+  containing multiple keywords, the state of storage associated with earlier keywords\r
+  is undefined.\r
+\r
+\r
+  @param This             Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
+\r
+  @param KeywordString    A null-terminated string in <MultiKeywordResp> format. \r
+\r
+  @param Progress         On return, points to a character in the KeywordString. \r
+                          Points to the string's NULL terminator if the request \r
+                          was successful. Points to the most recent '&' before \r
+                          the first failing string element if the request was \r
+                          not successful.\r
+\r
+  @param ProgressErr      If during the processing of the KeywordString there was\r
+                          a failure, this parameter gives additional information \r
+                          about the possible source of the problem. The various \r
+                          errors are defined in "Related Definitions" below.\r
+\r
+\r
+  @retval EFI_SUCCESS             The specified action was completed successfully.\r
+\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:\r
+                                  1. KeywordString is NULL.\r
+                                  2. Parsing of the KeywordString resulted in an \r
+                                     error. See Progress and ProgressErr for more data.\r
+\r
+  @retval EFI_NOT_FOUND           An element of the KeywordString was not found. \r
+                                  See ProgressErr for more data.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.  \r
+                                  See ProgressErr for more data.\r
+                                  \r
+  @retval EFI_ACCESS_DENIED       The action violated system policy. See ProgressErr \r
+                                  for more data.\r
+\r
+  @retval EFI_DEVICE_ERROR        An unexpected system error occurred. See ProgressErr\r
+                                  for more data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+EfiConfigKeywordHandlerSetData (\r
+  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
+  IN CONST EFI_STRING                    KeywordString,\r
+  OUT EFI_STRING                         *Progress,\r
+  OUT UINT32                             *ProgressErr\r
+  )\r
+{\r
+  CHAR8                               *NameSpace;\r
+  EFI_STATUS                          Status;\r
+  CHAR16                              *StringPtr;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  CHAR16                              *NextStringPtr;  \r
+  CHAR16                              *KeywordData;\r
+  EFI_STRING_ID                       KeywordStringId;\r
+  UINT32                              RetVal;\r
+  HII_DATABASE_RECORD                 *DataBaseRecord;\r
+  UINT8                               *OpCode;\r
+  CHAR16                              *ConfigResp;\r
+  CHAR16                              *MultiConfigResp;\r
+  CHAR16                              *ValueElement;\r
+  BOOLEAN                             ReadOnly;\r
+  EFI_STRING                          InternalProgress;\r
+\r
+  if (This == NULL || Progress == NULL || ProgressErr == NULL || KeywordString == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Progress    = KeywordString;\r
+  *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
+  Status       = EFI_SUCCESS;\r
+  StringPtr    = KeywordString;\r
+  MultiConfigResp = NULL;\r
+  NameSpace       = NULL;\r
+  DevicePath      = NULL;\r
+  KeywordData     = NULL;\r
+  ValueElement    = NULL;\r
+  ConfigResp      = NULL;\r
+  KeywordStringId = 0;\r
+\r
+  while ((StringPtr != NULL) && (*StringPtr != L'\0')) {\r
+    //\r
+    // 1. Get NameSpace from NameSpaceId keyword.\r
+    //\r
+    Status = ExtractNameSpace (StringPtr, &NameSpace, &NextStringPtr);\r
+    if (EFI_ERROR (Status)) {\r
+      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+      return Status;\r
+    }\r
+    StringPtr = NextStringPtr;\r
+\r
+    //\r
+    // 2. Get possible Device Path info from KeywordString.\r
+    //\r
+    Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
+    if (EFI_ERROR (Status)) {\r
+      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+      goto Done;\r
+    }\r
+    StringPtr = NextStringPtr;\r
+\r
+    //\r
+    // 3. Extract keyword from the KeywordRequest string.\r
+    //\r
+    Status = ExtractKeyword(StringPtr, &KeywordData, &NextStringPtr);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Can't find Keyword base on the input device path info.\r
+      //\r
+      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr = NextStringPtr;\r
+\r
+    //\r
+    // 4. Extract Value from the KeywordRequest string.\r
+    //\r
+    Status = ExtractValue (StringPtr, &ValueElement, &NextStringPtr);\r
+    if (EFI_ERROR (Status)) {\r
+      //\r
+      // Can't find Value base on the input device path info.\r
+      //\r
+      *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+    StringPtr = NextStringPtr;\r
+\r
+    //\r
+    // 5. Find ReadOnly filter.\r
+    //\r
+    if ((StringPtr != NULL) && StrnCmp (StringPtr, L"&ReadOnly", StrLen (L"&ReadOnly")) == 0) {\r
+      ReadOnly = TRUE;\r
+      StringPtr += StrLen (L"&ReadOnly");\r
+    } else {\r
+      ReadOnly = FALSE;\r
+    }\r
+\r
+    //\r
+    // 6. Get EFI_STRING_ID for the input keyword.\r
+    //\r
+    Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
+    if (EFI_ERROR (Status)) {\r
+      *ProgressErr = RetVal;\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // 7. Construct the ConfigRequest string.\r
+    //\r
+    Status = ExtractConfigResp (DataBaseRecord, KeywordStringId, ValueElement, &OpCode, &ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // 8. Check the readonly flag.\r
+    //\r
+    if (ExtractReadOnlyFromOpCode (OpCode) != ReadOnly) {\r
+      *ProgressErr = KEYWORD_HANDLER_INCOMPATIBLE_VALUE_DETECTED;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;      \r
+    }\r
+    \r
+    //\r
+    // 9. Merge to the MultiKeywordResp string.\r
+    //\r
+    Status = MergeToMultiKeywordResp(&MultiConfigResp, &ConfigResp);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // 10. Clean the temp buffer point.\r
+    //\r
+    FreePool (NameSpace);\r
+    FreePool (DevicePath);\r
+    FreePool (KeywordData);\r
+    FreePool (ValueElement);\r
+    NameSpace = NULL;\r
+    DevicePath = NULL; \r
+    KeywordData = NULL;\r
+    ValueElement = NULL;\r
+    if (ConfigResp != NULL) {\r
+      FreePool (ConfigResp);\r
+      ConfigResp = NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // 11. Set value to driver.\r
+  //\r
+  Status = mPrivate.ConfigRouting.RouteConfig(\r
+                    &mPrivate.ConfigRouting,\r
+                    (EFI_STRING) MultiConfigResp,\r
+                    &InternalProgress\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+  \r
+  *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
+\r
+Done:\r
+  if (NameSpace != NULL) {\r
+    FreePool (NameSpace);\r
+  }\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
+  if (KeywordData != NULL) {\r
+    FreePool (KeywordData);\r
+  }\r
+  if (ValueElement != NULL) {\r
+    FreePool (ValueElement);\r
+  }\r
+  if (ConfigResp != NULL) {\r
+    FreePool (ConfigResp);\r
+  }\r
+  if (MultiConfigResp != NULL && MultiConfigResp != ConfigResp) {\r
+    FreePool (MultiConfigResp);\r
+  }  \r
+  *Progress = StringPtr;\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This function accepts a <MultiKeywordRequest> formatted string, finds the underlying \r
+  keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the\r
+  EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.\r
+  \r
+  If there is an issue in resolving the contents of the KeywordString, then the function\r
+  returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the\r
+  appropriate information about where the issue occurred and additional data about the\r
+  nature of the issue.\r
+  \r
+  In the case when KeywordString is NULL, or contains multiple keywords, or when\r
+  EFI_NOT_FOUND is generated while processing the keyword elements, the Results string\r
+  contains values returned for all keywords processed prior to the keyword generating the \r
+  error but no values for the keyword with error or any following keywords.\r
+\r
+  \r
+  @param This           Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
+  \r
+  @param NameSpaceId    A null-terminated string containing the platform configuration\r
+                        language to search through in the system. If a NULL is passed\r
+                        in, then it is assumed that any platform configuration language\r
+                        with the prefix of "x-UEFI-" are searched.\r
+                        \r
+  @param KeywordString  A null-terminated string in <MultiKeywordRequest> format. If a\r
+                        NULL is passed in the KeywordString field, all of the known \r
+                        keywords in the system for the NameSpaceId specified are \r
+                        returned in the Results field.\r
+  \r
+  @param Progress       On return, points to a character in the KeywordString. Points\r
+                        to the string's NULL terminator if the request was successful. \r
+                        Points to the most recent '&' before the first failing string\r
+                        element if the request was not successful.\r
+                        \r
+  @param ProgressErr    If during the processing of the KeywordString there was a\r
+                        failure, this parameter gives additional information about the \r
+                        possible source of the problem. See the definitions in SetData()\r
+                        for valid value definitions.\r
+  \r
+  @param Results        A null-terminated string in <MultiKeywordResp> format is returned\r
+                        which has all the values filled in for the keywords in the \r
+                        KeywordString. This is a callee-allocated field, and must be freed\r
+                        by the caller after being used. \r
+\r
+  @retval EFI_SUCCESS             The specified action was completed successfully.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:\r
+                                  1.Progress, ProgressErr, or Resuts is NULL.\r
+                                  2.Parsing of the KeywordString resulted in an error. See\r
+                                    Progress and ProgressErr for more data.\r
+  \r
+\r
+  @retval EFI_NOT_FOUND           An element of the KeywordString was not found. See\r
+                                  ProgressErr for more data.\r
+\r
+  @retval EFI_NOT_FOUND           The NamespaceId specified was not found.  See ProgressErr\r
+                                  for more data.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.  See\r
+                                  ProgressErr for more data.\r
+                                  \r
+  @retval EFI_ACCESS_DENIED       The action violated system policy.  See ProgressErr for\r
+                                  more data.\r
+\r
+  @retval EFI_DEVICE_ERROR        An unexpected system error occurred.  See ProgressErr\r
+                                  for more data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+EfiConfigKeywordHandlerGetData (\r
+  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL  *This,\r
+  IN CONST EFI_STRING                     NameSpaceId, OPTIONAL\r
+  IN CONST EFI_STRING                     KeywordString, OPTIONAL\r
+  OUT EFI_STRING                          *Progress, \r
+  OUT UINT32                              *ProgressErr,\r
+  OUT EFI_STRING                          *Results\r
+  )\r
+{\r
+  CHAR8                               *NameSpace;\r
+  EFI_STATUS                          Status;\r
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;\r
+  HII_DATABASE_RECORD                 *DataBaseRecord;\r
+  CHAR16                              *StringPtr;\r
+  CHAR16                              *NextStringPtr;  \r
+  CHAR16                              *KeywordData;\r
+  EFI_STRING_ID                       KeywordStringId;\r
+  UINT8                               *OpCode;\r
+  CHAR16                              *ConfigRequest;\r
+  CHAR16                              *ValueElement;\r
+  UINT32                              RetVal;\r
+  BOOLEAN                             ReadOnly;\r
+  CHAR16                              *KeywordResp;\r
+  CHAR16                              *MultiKeywordResp;\r
+\r
+  if (This == NULL || Progress == NULL || ProgressErr == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *ProgressErr = KEYWORD_HANDLER_UNDEFINED_PROCESSING_ERROR;\r
+  Status       = EFI_SUCCESS;\r
+  DevicePath   = NULL;\r
+  NameSpace    = NULL;\r
+  KeywordData  = NULL;\r
+  ConfigRequest= NULL;\r
+  StringPtr    = KeywordString;\r
+  ReadOnly     = FALSE;\r
+  MultiKeywordResp = NULL;\r
+  KeywordStringId  = 0;\r
+\r
+  //\r
+  // 1. Get NameSpace from NameSpaceId keyword.\r
+  //\r
+  Status = ExtractNameSpace (NameSpaceId, &NameSpace, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    *ProgressErr = KEYWORD_HANDLER_NAMESPACE_ID_NOT_FOUND;\r
+    return Status;\r
+  }\r
+\r
+  if (KeywordString != NULL) {\r
+    StringPtr = KeywordString;\r
+\r
+    while (*StringPtr != L'\0') {\r
+      //\r
+      // 2. Get possible Device Path info from KeywordString.\r
+      //\r
+      Status = ExtractDevicePath (StringPtr, (UINT8 **)&DevicePath, &NextStringPtr);\r
+      if (EFI_ERROR (Status)) {\r
+        *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+        goto Done;\r
+      }\r
+      StringPtr = NextStringPtr;\r
+\r
+     \r
+      //\r
+      // 3. Process Keyword section from the input keywordRequest string.\r
+      //\r
+      // 3.1 Extract keyword from the KeywordRequest string.\r
+      //\r
+      Status = ExtractKeyword(StringPtr, &KeywordData, &NextStringPtr);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Can't find Keyword base on the input device path info.\r
+        //\r
+        *ProgressErr = KEYWORD_HANDLER_MALFORMED_STRING;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // 3.2 Get EFI_STRING_ID for the input keyword.\r
+      //\r
+      Status = GetStringIdFromDatabase (&DevicePath, &NameSpace, KeywordData, &RetVal, &KeywordStringId, &DataBaseRecord);\r
+      if (EFI_ERROR (Status)) {\r
+        *ProgressErr = RetVal;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // 3.3 Construct the ConfigRequest string.\r
+      //\r
+      Status = ExtractConfigRequest (DataBaseRecord, KeywordStringId, &OpCode, &ConfigRequest);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+      \r
+      //\r
+      // 3.4 Extract Value for the input keyword.\r
+      //\r
+      Status = ExtractValueFromDriver(ConfigRequest, &ValueElement);\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status != EFI_OUT_OF_RESOURCES) {\r
+          Status = EFI_DEVICE_ERROR;\r
+        }\r
+        goto Done;\r
+      }\r
+      StringPtr = NextStringPtr;\r
+\r
+      //\r
+      // 4. Process the possible filter section.\r
+      //\r
+      RetVal = ValidateFilter (OpCode, StringPtr, &NextStringPtr, &ReadOnly);\r
+      if (RetVal != KEYWORD_HANDLER_NO_ERROR) {\r
+        *ProgressErr = RetVal;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+      StringPtr = NextStringPtr;\r
+\r
+\r
+      //\r
+      // 5. Generate KeywordResp string.\r
+      //\r
+      Status = GenerateKeywordResp(NameSpace, DevicePath, KeywordData, ValueElement, ReadOnly, &KeywordResp);\r
+      if (Status != EFI_SUCCESS) {\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // 6. Merge to the MultiKeywordResp string.\r
+      //\r
+      Status = MergeToMultiKeywordResp(&MultiKeywordResp, &KeywordResp);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // 7. Update return value.\r
+      //\r
+      *Results = MultiKeywordResp;\r
+\r
+      //\r
+      // 8. Clean the temp buffer.\r
+      //\r
+      FreePool (DevicePath);\r
+      FreePool (KeywordData);\r
+      FreePool (ValueElement);\r
+      FreePool (ConfigRequest);\r
+      DevicePath = NULL; \r
+      KeywordData = NULL;\r
+      ValueElement = NULL;\r
+      ConfigRequest = NULL;\r
+      if (KeywordResp != NULL) {\r
+        FreePool (KeywordResp);\r
+        KeywordResp = NULL;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // Enumerate all keyword in the system.\r
+    //\r
+    Status = EnumerateAllKeywords(NameSpace, &MultiKeywordResp);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+    *Results = MultiKeywordResp;\r
+  }\r
+\r
+  *ProgressErr = KEYWORD_HANDLER_NO_ERROR;\r
+\r
+Done:\r
+  if (NameSpace != NULL) {\r
+    FreePool (NameSpace);\r
+  }\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
+  if (KeywordData != NULL) {\r
+    FreePool (KeywordData);\r
+  }\r
+  *Progress = StringPtr;\r
+  return Status;\r
+}\r
index 32e48275b037612c8cabc392d5a480d685361190..bb0090aaa6246637ea21ece7cd38d93b57a923f1 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Private structures definitions in HiiDatabase.\r
 \r
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/HiiDatabase.h>\r
 #include <Protocol/HiiConfigRouting.h>\r
 #include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigKeyword.h>\r
 #include <Protocol/SimpleTextOut.h>\r
 \r
 #include <Guid/HiiKeyBoardLayout.h>\r
@@ -108,6 +109,19 @@ typedef struct {
 #define EFI_HII_VARSTORE_EFI_VARIABLE        2\r
 #define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3\r
 \r
+//\r
+// Keyword handler protocol filter type.\r
+//\r
+#define EFI_KEYWORD_FILTER_READONY           0x01\r
+#define EFI_KEYWORD_FILTER_REAWRITE          0x02\r
+#define EFI_KEYWORD_FILTER_BUFFER            0x10\r
+#define EFI_KEYWORD_FILTER_NUMERIC           0x20\r
+#define EFI_KEYWORD_FILTER_NUMERIC_1         0x30\r
+#define EFI_KEYWORD_FILTER_NUMERIC_2         0x40\r
+#define EFI_KEYWORD_FILTER_NUMERIC_4         0x50\r
+#define EFI_KEYWORD_FILTER_NUMERIC_8         0x60\r
+\r
+\r
 #define HII_FORMSET_STORAGE_SIGNATURE           SIGNATURE_32 ('H', 'S', 'T', 'G')\r
 typedef struct {\r
   UINTN               Signature;\r
@@ -288,6 +302,7 @@ typedef struct _HII_DATABASE_PRIVATE_DATA {
   EFI_HII_STRING_PROTOCOL               HiiString;\r
   EFI_HII_DATABASE_PROTOCOL             HiiDatabase;\r
   EFI_HII_CONFIG_ROUTING_PROTOCOL       ConfigRouting;\r
+  EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL   ConfigKeywordHandler;\r
   LIST_ENTRY                            HiiHandleList;\r
   INTN                                  HiiHandleCount;\r
   LIST_ENTRY                            FontInfoList;  // global font info list\r
@@ -331,10 +346,48 @@ typedef struct _HII_DATABASE_PRIVATE_DATA {
       HII_DATABASE_PRIVATE_DATA_SIGNATURE \\r
       )\r
 \r
+#define CONFIG_KEYWORD_HANDLER_DATABASE_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      HII_DATABASE_PRIVATE_DATA, \\r
+      ConfigKeywordHandler, \\r
+      HII_DATABASE_PRIVATE_DATA_SIGNATURE \\r
+      )\r
+\r
 //\r
 // Internal function prototypes.\r
 //\r
 \r
+/**\r
+  Generate a sub string then output it.\r
+\r
+  This is a internal function.\r
+\r
+  @param  String                 A constant string which is the prefix of the to be\r
+                                 generated string, e.g. GUID=\r
+\r
+  @param  BufferLen              The length of the Buffer in bytes.\r
+\r
+  @param  Buffer                 Points to a buffer which will be converted to be the \r
+                                 content of the generated string.\r
+\r
+  @param  Flag                   If 1, the buffer contains data for the value of GUID or PATH stored in \r
+                                 UINT8 *; if 2, the buffer contains unicode string for the value of NAME;\r
+                                 if 3, the buffer contains other data.\r
+\r
+  @param  SubStr                 Points to the output string. It's caller's\r
+                                 responsibility to free this buffer.\r
+\r
+\r
+**/\r
+VOID\r
+GenerateSubStr (\r
+  IN CONST EFI_STRING              String,\r
+  IN  UINTN                        BufferLen,\r
+  IN  VOID                         *Buffer,\r
+  IN  UINT8                        Flag,\r
+  OUT EFI_STRING                   *SubStr\r
+  );\r
+\r
 /**\r
   This function checks whether a handle is a valid EFI_HII_HANDLE.\r
 \r
@@ -1776,6 +1829,151 @@ HiiGetAltCfg (
   OUT EFI_STRING                               *AltCfgResp\r
   );\r
 \r
+/**\r
+\r
+  This function accepts a <MultiKeywordResp> formatted string, finds the associated\r
+  keyword owners, creates a <MultiConfigResp> string from it and forwards it to the\r
+  EFI_HII_ROUTING_PROTOCOL.RouteConfig function.\r
+  \r
+  If there is an issue in resolving the contents of the KeywordString, then the \r
+  function returns an error and also sets the Progress and ProgressErr with the \r
+  appropriate information about where the issue occurred and additional data about\r
+  the nature of the issue. \r
+  \r
+  In the case when KeywordString containing multiple keywords, when an EFI_NOT_FOUND\r
+  error is generated during processing the second or later keyword element, the system\r
+  storage associated with earlier keywords is not modified. All elements of the \r
+  KeywordString must successfully pass all tests for format and access prior to making\r
+  any modifications to storage.\r
+  \r
+  In the case when EFI_DEVICE_ERROR is returned from the processing of a KeywordString\r
+  containing multiple keywords, the state of storage associated with earlier keywords\r
+  is undefined.\r
+\r
+\r
+  @param This             Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
+\r
+  @param KeywordString    A null-terminated string in <MultiKeywordResp> format. \r
+\r
+  @param Progress         On return, points to a character in the KeywordString. \r
+                          Points to the string's NULL terminator if the request \r
+                          was successful. Points to the most recent '&' before \r
+                          the first failing string element if the request was \r
+                          not successful.\r
+\r
+  @param ProgressErr      If during the processing of the KeywordString there was\r
+                          a failure, this parameter gives additional information \r
+                          about the possible source of the problem. The various \r
+                          errors are defined in "Related Definitions" below.\r
+\r
+\r
+  @retval EFI_SUCCESS             The specified action was completed successfully.\r
+\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:\r
+                                  1. KeywordString is NULL.\r
+                                  2. Parsing of the KeywordString resulted in an \r
+                                     error. See Progress and ProgressErr for more data.\r
+\r
+  @retval EFI_NOT_FOUND           An element of the KeywordString was not found. \r
+                                  See ProgressErr for more data.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.  \r
+                                  See ProgressErr for more data.\r
+                                  \r
+  @retval EFI_ACCESS_DENIED       The action violated system policy. See ProgressErr \r
+                                  for more data.\r
+\r
+  @retval EFI_DEVICE_ERROR        An unexpected system error occurred. See ProgressErr\r
+                                  for more data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+EfiConfigKeywordHandlerSetData (\r
+  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *This,\r
+  IN CONST EFI_STRING                    KeywordString,\r
+  OUT EFI_STRING                         *Progress,\r
+  OUT UINT32                             *ProgressErr\r
+  );\r
+\r
+/**\r
+\r
+  This function accepts a <MultiKeywordRequest> formatted string, finds the underlying \r
+  keyword owners, creates a <MultiConfigRequest> string from it and forwards it to the\r
+  EFI_HII_ROUTING_PROTOCOL.ExtractConfig function.\r
+  \r
+  If there is an issue in resolving the contents of the KeywordString, then the function\r
+  returns an EFI_INVALID_PARAMETER and also set the Progress and ProgressErr with the\r
+  appropriate information about where the issue occurred and additional data about the\r
+  nature of the issue.\r
+  \r
+  In the case when KeywordString is NULL, or contains multiple keywords, or when\r
+  EFI_NOT_FOUND is generated while processing the keyword elements, the Results string\r
+  contains values returned for all keywords processed prior to the keyword generating the \r
+  error but no values for the keyword with error or any following keywords.\r
+\r
+  \r
+  @param This           Pointer to the EFI_KEYWORD_HANDLER _PROTOCOL instance.\r
+  \r
+  @param NameSpaceId    A null-terminated string containing the platform configuration\r
+                        language to search through in the system. If a NULL is passed\r
+                        in, then it is assumed that any platform configuration language\r
+                        with the prefix of "x-UEFI-" are searched.\r
+                        \r
+  @param KeywordString  A null-terminated string in <MultiKeywordRequest> format. If a\r
+                        NULL is passed in the KeywordString field, all of the known \r
+                        keywords in the system for the NameSpaceId specified are \r
+                        returned in the Results field.\r
+  \r
+  @param Progress       On return, points to a character in the KeywordString. Points\r
+                        to the string's NULL terminator if the request was successful. \r
+                        Points to the most recent '&' before the first failing string\r
+                        element if the request was not successful.\r
+                        \r
+  @param ProgressErr    If during the processing of the KeywordString there was a\r
+                        failure, this parameter gives additional information about the \r
+                        possible source of the problem. See the definitions in SetData()\r
+                        for valid value definitions.\r
+  \r
+  @param Results        A null-terminated string in <MultiKeywordResp> format is returned\r
+                        which has all the values filled in for the keywords in the \r
+                        KeywordString. This is a callee-allocated field, and must be freed\r
+                        by the caller after being used. \r
+\r
+  @retval EFI_SUCCESS             The specified action was completed successfully.\r
+  \r
+  @retval EFI_INVALID_PARAMETER   One or more of the following are TRUE:\r
+                                  1.Progress, ProgressErr, or Resuts is NULL.\r
+                                  2.Parsing of the KeywordString resulted in an error. See\r
+                                    Progress and ProgressErr for more data.\r
+  \r
+\r
+  @retval EFI_NOT_FOUND           An element of the KeywordString was not found. See\r
+                                  ProgressErr for more data.\r
+\r
+  @retval EFI_NOT_FOUND           The NamespaceId specified was not found.  See ProgressErr\r
+                                  for more data.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.  See\r
+                                  ProgressErr for more data.\r
+                                  \r
+  @retval EFI_ACCESS_DENIED       The action violated system policy.  See ProgressErr for\r
+                                  more data.\r
+\r
+  @retval EFI_DEVICE_ERROR        An unexpected system error occurred.  See ProgressErr\r
+                                  for more data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+EfiConfigKeywordHandlerGetData (\r
+  IN EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL  *This,\r
+  IN CONST EFI_STRING                     NameSpaceId, OPTIONAL\r
+  IN CONST EFI_STRING                     KeywordString, OPTIONAL\r
+  OUT EFI_STRING                          *Progress, \r
+  OUT UINT32                              *ProgressErr,\r
+  OUT EFI_STRING                          *Results\r
+  );\r
 \r
 /**\r
   Compare whether two names of languages are identical.\r
@@ -1794,6 +1992,29 @@ HiiCompareLanguage (
   )\r
 ;\r
 \r
+/**\r
+  Retrieves a pointer to the a Null-terminated ASCII string containing the list \r
+  of languages that an HII handle in the HII Database supports.  The returned \r
+  string is allocated using AllocatePool().  The caller is responsible for freeing\r
+  the returned string using FreePool().  The format of the returned string follows\r
+  the language format assumed the HII Database.\r
+  \r
+  If HiiHandle is NULL, then ASSERT().\r
+\r
+  @param[in]  HiiHandle  A handle that was previously registered in the HII Database.\r
+\r
+  @retval NULL   HiiHandle is not registered in the HII database\r
+  @retval NULL   There are not enough resources available to retrieve the suported \r
+                 languages.\r
+  @retval NULL   The list of suported languages could not be retrieved.\r
+  @retval Other  A pointer to the Null-terminated ASCII string of supported languages.\r
+\r
+**/\r
+CHAR8 *\r
+GetSupportedLanguages (\r
+  IN EFI_HII_HANDLE           HiiHandle\r
+  );\r
+\r
 //\r
 // Global variables\r
 //\r
index d5dbdcae5a2d14a2156f366599d76f3da8906fa3..7892503b47963c26676d7bd2c817a9555c56888f 100644 (file)
@@ -4,7 +4,7 @@
 # This driver produces all required HII serivces that includes HiiDataBase, HiiString,\r
 # HiiFont, HiiConfigRouting. To support UEFI HII, this driver is required.\r
 #\r
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 #\r
 #  This program and the accompanying materials       \r
 #  are licensed and made available under the terms and conditions of the BSD License   \r
@@ -40,6 +40,7 @@
   String.c\r
   Database.c\r
   Font.c\r
+  ConfigKeywordHandler.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -67,6 +68,7 @@
   gEfiHiiDatabaseProtocolGuid                                           ## PRODUCES\r
   gEfiHiiFontProtocolGuid                                               ## PRODUCES\r
   gEfiHiiConfigAccessProtocolGuid                                       ## SOMETIMES_CONSUMES\r
+  gEfiConfigKeywordHandlerProtocolGuid                                  ## PRODUCES\r
 \r
 [FeaturePcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol   ## CONSUMES\r
index ae75f8ccbf92dc6248b9190060845b03d73ae7a2..6448c97256fc764d812b141870a097ec4c98af8c 100644 (file)
@@ -2,7 +2,7 @@
 This file contains the entry code to the HII database, which is defined by\r
 UEFI 2.1 specification.\r
 \r
-Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -72,6 +72,10 @@ HII_DATABASE_PRIVATE_DATA mPrivate = {
     HiiConfigToBlock,\r
     HiiGetAltCfg\r
   },\r
+  {\r
+    EfiConfigKeywordHandlerSetData,\r
+    EfiConfigKeywordHandlerGetData\r
+  },\r
   {\r
     (LIST_ENTRY *) NULL,\r
     (LIST_ENTRY *) NULL\r
@@ -153,6 +157,7 @@ InitializeHiiDatabase (
   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiImageProtocolGuid);\r
   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiStringProtocolGuid);\r
   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiConfigRoutingProtocolGuid);\r
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiConfigKeywordHandlerProtocolGuid);\r
   \r
   InitializeListHead (&mPrivate.DatabaseList);\r
   InitializeListHead (&mPrivate.DatabaseNotifyList);\r
@@ -185,6 +190,8 @@ InitializeHiiDatabase (
                   &mPrivate.HiiDatabase,\r
                   &gEfiHiiConfigRoutingProtocolGuid,\r
                   &mPrivate.ConfigRouting,\r
+                  &gEfiConfigKeywordHandlerProtocolGuid,\r
+                  &mPrivate.ConfigKeywordHandler,\r
                   NULL\r
                   );\r
 \r