]> xenbits.xensource.com Git - ovmf.git/commitdiff
RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
authorNickle Wang <nicklew@nvidia.com>
Mon, 10 Apr 2023 13:14:41 +0000 (21:14 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Fri, 28 Apr 2023 12:21:38 +0000 (12:21 +0000)
This is the Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL,
which is the EDKII Redfish Platform Config driver instance that accesses
EDK2 HII configuration format and storage.

Signed-off-by: Nickle Wang <nicklew@nvidia.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Nick Ramirez <nramirez@nvidia.com>
Reviewed-by: Abner Chang <abner.chang@amd.com>
Reviewed-by: Igor Kulchytskyy <igork @ami.com>
RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c [new file with mode: 0644]
RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h [new file with mode: 0644]
RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf [new file with mode: 0644]
RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c [new file with mode: 0644]
RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h [new file with mode: 0644]

diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
new file mode 100644 (file)
index 0000000..d3902f4
--- /dev/null
@@ -0,0 +1,2495 @@
+/** @file\r
+  The implementation of EDKII Redfish Platform Config Protocol.\r
+\r
+  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "RedfishPlatformConfigDxe.h"\r
+#include "RedfishPlatformConfigImpl.h"\r
+\r
+REDFISH_PLATFORM_CONFIG_PRIVATE  *mRedfishPlatformConfigPrivate = NULL;\r
+\r
+/**\r
+  Create a new stack instance with given stack size.\r
+\r
+  @param[in]  StackSize  The size of stack.\r
+\r
+  @retval REDFISH_STACK * Pointer to created stack.\r
+  @retval NULL            Out of resource.\r
+\r
+**/\r
+REDFISH_STACK *\r
+NewRedfishStack (\r
+  IN UINTN  StackSize\r
+  )\r
+{\r
+  REDFISH_STACK  *Buffer;\r
+\r
+  if (StackSize == 0) {\r
+    return NULL;\r
+  }\r
+\r
+  Buffer = AllocateZeroPool (sizeof (REDFISH_STACK));\r
+  if (Buffer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Buffer->Pool = AllocateZeroPool (sizeof (VOID *) * StackSize);\r
+  if (Buffer->Pool == NULL) {\r
+    FreePool (Buffer);\r
+    return NULL;\r
+  }\r
+\r
+  Buffer->Size  = StackSize;\r
+  Buffer->Index = 0;\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Release stack buffer.\r
+\r
+  @param[in]  Stack     Pointer to stack instance.\r
+\r
+**/\r
+VOID\r
+ReleaseRedfishStack (\r
+  IN REDFISH_STACK  *Stack\r
+  )\r
+{\r
+  if (Stack == NULL) {\r
+    return;\r
+  }\r
+\r
+  FreePool (Stack->Pool);\r
+  FreePool (Stack);\r
+}\r
+\r
+/**\r
+  Check and see if stack is empty or not.\r
+\r
+  @param[in]  Stack     Pointer to stack instance.\r
+\r
+  @retval TRUE          Stack is empty.\r
+  @retval FALSE         Stack is not empty.\r
+\r
+**/\r
+BOOLEAN\r
+IsEmptyRedfishStack (\r
+  IN REDFISH_STACK  *Stack\r
+  )\r
+{\r
+  return (Stack->Index == 0);\r
+}\r
+\r
+/**\r
+  Push an item to stack.\r
+\r
+  @param[in]  Stack     Pointer to stack instance.\r
+  @param[in]  Data      Pointer to data.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Stack is full.\r
+  @retval EFI_SUCCESS            Item is pushed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+PushRedfishStack (\r
+  IN REDFISH_STACK  *Stack,\r
+  IN VOID           *Data\r
+  )\r
+{\r
+  if (Stack->Index == Stack->Size) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Stack->Pool[Stack->Index] = Data;\r
+  Stack->Index             += 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Pop an item from stack.\r
+\r
+  @param[in]  Stack     Pointer to stack instance.\r
+\r
+  @retval VOID *        Pointer to popped item.\r
+  @retval NULL          Stack is empty.\r
+\r
+**/\r
+VOID *\r
+PopRedfishStack (\r
+  IN REDFISH_STACK  *Stack\r
+  )\r
+{\r
+  if (IsEmptyRedfishStack (Stack)) {\r
+    return NULL;\r
+  }\r
+\r
+  Stack->Index -= 1;\r
+  return Stack->Pool[Stack->Index];\r
+}\r
+\r
+/**\r
+  Seach forms in this HII package and find which form links to give form.\r
+\r
+  @param[in]  FormPrivate   Pointer to form private instance.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_FORM_PRIVATE Pointer to target form\r
+  @retval NULL                                 No form links to give form.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *\r
+FindFormLinkToThis (\r
+  IN REDFISH_PLATFORM_CONFIG_FORM_PRIVATE  *FormPrivate\r
+  )\r
+{\r
+  LIST_ENTRY                                 *HiiFormLink;\r
+  LIST_ENTRY                                 *HiiNextFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;\r
+  LIST_ENTRY                                 *HiiStatementLink;\r
+  LIST_ENTRY                                 *HiiNextStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE   *HiiFormsetPrivate;\r
+\r
+  if (FormPrivate == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  HiiFormsetPrivate = FormPrivate->ParentFormset;\r
+\r
+  if (IsListEmpty (&HiiFormsetPrivate->HiiFormList)) {\r
+    return NULL;\r
+  }\r
+\r
+  HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);\r
+  while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {\r
+    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);\r
+    HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);\r
+\r
+    //\r
+    // Skip myself\r
+    //\r
+    if (HiiFormPrivate == FormPrivate) {\r
+      HiiFormLink = HiiNextFormLink;\r
+      continue;\r
+    }\r
+\r
+    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);\r
+    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {\r
+      HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);\r
+      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);\r
+\r
+      //\r
+      // Check go-to opcode and find form ID. If form ID is the same ID as given form,\r
+      // this go-to opcode links to given form.\r
+      //\r
+      if ((HiiStatementPrivate->HiiStatement->Operand == EFI_IFR_REF_OP) &&\r
+          (HiiStatementPrivate->HiiStatement->Value.Value.ref.FormId == FormPrivate->HiiForm->FormId))\r
+      {\r
+        return HiiFormPrivate;\r
+      }\r
+\r
+      HiiStatementLink = HiiNextStatementLink;\r
+    }\r
+\r
+    HiiFormLink = HiiNextFormLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Build the menu path to given statement instance. It is caller's\r
+  responsibility to free returned string buffer.\r
+\r
+  @param[in]  StatementPrivate   Pointer to statement private instance.\r
+\r
+  @retval CHAR8 *                Menu path to given statement.\r
+  @retval NULL                   Can not find menu path.\r
+\r
+**/\r
+CHAR8 *\r
+BuildMenPath (\r
+  IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *StatementPrivate\r
+  )\r
+{\r
+  REDFISH_STACK                         *FormStack;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE  *FormPrivate;\r
+  UINTN                                 OldBufferSize;\r
+  UINTN                                 NewBufferSize;\r
+  CHAR8                                 *Buffer;\r
+  CHAR8                                 *FormTitle;\r
+  EFI_STATUS                            Status;\r
+\r
+  Buffer        = NULL;\r
+  OldBufferSize = 0;\r
+  NewBufferSize = 0;\r
+  FormStack     = NewRedfishStack (REDFISH_MENU_PATH_SIZE);\r
+  if (FormStack == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Build form link stack\r
+  //\r
+  FormPrivate = StatementPrivate->ParentForm;\r
+  Status      = PushRedfishStack (FormStack, (VOID *)FormPrivate);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RELEASE;\r
+  }\r
+\r
+  do {\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "F(%d) <-", FormPrivate->Id));\r
+    FormPrivate = FindFormLinkToThis (FormPrivate);\r
+    if (FormPrivate == NULL) {\r
+      break;\r
+    }\r
+\r
+    PushRedfishStack (FormStack, (VOID *)FormPrivate);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  } while (TRUE);\r
+\r
+  if (IsEmptyRedfishStack (FormStack)) {\r
+    goto RELEASE;\r
+  }\r
+\r
+  //\r
+  // Initial Buffer to empty string for error case.\r
+  //\r
+  OldBufferSize = AsciiStrSize ("");\r
+  Buffer        = AllocateCopyPool (OldBufferSize, "");\r
+  if (Buffer == NULL) {\r
+    goto RELEASE;\r
+  }\r
+\r
+  //\r
+  // Build menu path in string format\r
+  //\r
+  FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *)PopRedfishStack (FormStack);\r
+  while (FormPrivate != NULL) {\r
+    FormTitle = HiiGetEnglishAsciiString (FormPrivate->ParentFormset->HiiHandle, FormPrivate->Title);\r
+    if (FormTitle != NULL) {\r
+      NewBufferSize = AsciiStrSize (FormTitle) + OldBufferSize;\r
+      Buffer        = ReallocatePool (OldBufferSize, NewBufferSize, Buffer);\r
+      if (Buffer == NULL) {\r
+        goto RELEASE;\r
+      }\r
+\r
+      OldBufferSize = NewBufferSize;\r
+      AsciiStrCatS (Buffer, OldBufferSize, "/");\r
+      AsciiStrCatS (Buffer, OldBufferSize, FormTitle);\r
+      FreePool (FormTitle);\r
+      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, " %a\n", Buffer));\r
+    }\r
+\r
+    FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *)PopRedfishStack (FormStack);\r
+  }\r
+\r
+RELEASE:\r
+\r
+  ReleaseRedfishStack (FormStack);\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Get the attribute name from config language.\r
+\r
+  For example:  /Bios/Attributes/BiosOption1 is config language\r
+  and attribute name is BiosOption1.\r
+\r
+  @param[in]  ConfigLanguage     Config language string.\r
+\r
+  @retval CHAR8 *                Attribute name string.\r
+  @retval NULL                   Can not find attribute name.\r
+\r
+**/\r
+CHAR8 *\r
+GetAttributeNameFromConfigLanguage (\r
+  IN  CHAR8  *ConfigLanguage\r
+  )\r
+{\r
+  CHAR8  *attributeName;\r
+  CHAR8  *Pointer;\r
+  UINTN  StrLen;\r
+  UINTN  Index;\r
+  UINTN  AttrStrLen;\r
+\r
+  if (IS_EMPTY_STRING (ConfigLanguage)) {\r
+    return NULL;\r
+  }\r
+\r
+  attributeName = NULL;\r
+  Pointer       = NULL;\r
+  AttrStrLen    = 0;\r
+  StrLen        = AsciiStrLen (ConfigLanguage);\r
+\r
+  if (ConfigLanguage[StrLen - 1] == '/') {\r
+    //\r
+    // wrong format\r
+    //\r
+    DEBUG ((DEBUG_ERROR, "%a: invalid format: %a\n", __func__, ConfigLanguage));\r
+    ASSERT (FALSE);\r
+    return NULL;\r
+  }\r
+\r
+  Index = StrLen;\r
+  while (TRUE) {\r
+    Index -= 1;\r
+\r
+    if (ConfigLanguage[Index] == '/') {\r
+      Pointer = &ConfigLanguage[Index + 1];\r
+      break;\r
+    }\r
+\r
+    if (Index == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Not found. There is no '/' in input string.\r
+  //\r
+  if (Pointer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  AttrStrLen    = StrLen - Index;\r
+  attributeName = AllocateCopyPool (AttrStrLen, Pointer);\r
+\r
+  return attributeName;\r
+}\r
+\r
+/**\r
+  Convert one-of options to string array in Redfish attribute.\r
+\r
+  @param[in]  HiiHandle          HII handle.\r
+  @param[in]  SchemaName         Schema string.\r
+  @param[in]  StatementPrivate   Pointer to statement instance.\r
+  @param[out] Values             Attribute value array.\r
+\r
+  @retval EFI_SUCCESS            Options are converted successfully.\r
+  @retval Other                  Error occurs.\r
+\r
+**/\r
+EFI_STATUS\r
+OneOfStatementToAttributeValues (\r
+  IN  EFI_HII_HANDLE                             HiiHandle,\r
+  IN  CHAR8                                      *SchemaName,\r
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *StatementPrivate,\r
+  OUT EDKII_REDFISH_POSSIBLE_VALUES              *Values\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+  UINTN                Index;\r
+  HII_STATEMENT        *HiiStatement;\r
+\r
+  if ((HiiHandle == NULL) || (StatementPrivate == NULL) || (Values == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HiiStatement = StatementPrivate->HiiStatement;\r
+  ASSERT (HiiStatement != NULL);\r
+\r
+  if (IsListEmpty (&HiiStatement->OptionListHead)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Loop through the option to get count\r
+  //\r
+  Values->ValueCount = 0;\r
+  Link               = GetFirstNode (&HiiStatement->OptionListHead);\r
+  while (!IsNull (&HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    if ((Option->SuppressExpression != NULL) &&\r
+        (EvaluateExpressionList (Option->SuppressExpression, TRUE, StatementPrivate->ParentForm->ParentFormset->HiiFormSet, StatementPrivate->ParentForm->HiiForm) != ExpressFalse))\r
+    {\r
+      Link = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+      continue;\r
+    }\r
+\r
+    Values->ValueCount += 1;\r
+    Link                = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  Values->ValueArray = AllocateZeroPool (sizeof (EDKII_REDFISH_ATTRIBUTE_VALUE) * Values->ValueCount);\r
+  if (Values->ValueArray == NULL) {\r
+    Values->ValueCount = 0;\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Index = 0;\r
+  Link  = GetFirstNode (&HiiStatement->OptionListHead);\r
+  while (!IsNull (&HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    if ((Option->SuppressExpression != NULL) &&\r
+        (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))\r
+    {\r
+      Link = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+      continue;\r
+    }\r
+\r
+    if (Option->Text != 0) {\r
+      Values->ValueArray[Index].ValueName        = HiiGetRedfishAsciiString (HiiHandle, SchemaName, Option->Text);\r
+      Values->ValueArray[Index].ValueDisplayName = HiiGetEnglishAsciiString (HiiHandle, Option->Text);\r
+    }\r
+\r
+    Index += 1;\r
+    Link   = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Return Redfish attribute type from given HII statement operand.\r
+\r
+  @param[in]  HiiStatement       Target HII statement.\r
+\r
+  @retval EDKII_REDFISH_ATTRIBUTE_TYPES    Attribute type.\r
+\r
+**/\r
+EDKII_REDFISH_ATTRIBUTE_TYPES\r
+HiiStatementToAttributeType (\r
+  IN  HII_STATEMENT  *HiiStatement\r
+  )\r
+{\r
+  EDKII_REDFISH_ATTRIBUTE_TYPES  type;\r
+\r
+  if (HiiStatement == NULL) {\r
+    return RedfishAttributeTypeUnknown;\r
+  }\r
+\r
+  type = RedfishAttributeTypeUnknown;\r
+  switch (HiiStatement->Operand) {\r
+    case EFI_IFR_ONE_OF_OP:\r
+    case EFI_IFR_ORDERED_LIST_OP:\r
+      type = RedfishAttributeTypeEnumeration;\r
+      break;\r
+    case EFI_IFR_STRING_OP:\r
+      type = RedfishAttributeTypeString;\r
+      break;\r
+    case EFI_IFR_NUMERIC_OP:\r
+      type = RedfishAttributeTypeInteger;\r
+      break;\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      type = RedfishAttributeTypeBoolean;\r
+      break;\r
+    case EFI_IFR_DATE_OP:\r
+    case EFI_IFR_TIME_OP:\r
+    default:\r
+      DEBUG ((DEBUG_ERROR, "%a: unsupported operand: 0x%x\n", __func__, HiiStatement->Operand));\r
+      break;\r
+  }\r
+\r
+  return type;\r
+}\r
+\r
+/**\r
+  Zero extend integer/boolean to UINT64 for comparing.\r
+\r
+  @param  Value                  HII Value to be converted.\r
+\r
+**/\r
+UINT64\r
+ExtendHiiValueToU64 (\r
+  IN HII_STATEMENT_VALUE  *Value\r
+  )\r
+{\r
+  UINT64  Temp;\r
+\r
+  Temp = 0;\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Temp = Value->Value.u8;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Temp = Value->Value.u16;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Temp = Value->Value.u32;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      Temp = Value->Value.b;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_TIME:\r
+    case EFI_IFR_TYPE_DATE:\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return Temp;\r
+}\r
+\r
+/**\r
+  Set value of a data element in an Array by its Index in ordered list buffer.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+  @param  Value                  The value to be set.\r
+\r
+**/\r
+VOID\r
+OrderedListSetArrayData (\r
+  IN VOID    *Array,\r
+  IN UINT8   Type,\r
+  IN UINTN   Index,\r
+  IN UINT64  Value\r
+  )\r
+{\r
+  ASSERT (Array != NULL);\r
+\r
+  switch (Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      *(((UINT8 *)Array) + Index) = (UINT8)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      *(((UINT16 *)Array) + Index) = (UINT16)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      *(((UINT32 *)Array) + Index) = (UINT32)Value;\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      *(((UINT64 *)Array) + Index) = (UINT64)Value;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+}\r
+\r
+/**\r
+  Return data element in an Array by its Index in ordered list array buffer.\r
+\r
+  @param  Array                  The data array.\r
+  @param  Type                   Type of the data in this array.\r
+  @param  Index                  Zero based index for data in this array.\r
+\r
+  @retval Value                  The data to be returned\r
+\r
+**/\r
+UINT64\r
+OrderedListGetArrayData (\r
+  IN VOID   *Array,\r
+  IN UINT8  Type,\r
+  IN UINTN  Index\r
+  )\r
+{\r
+  UINT64  Data;\r
+\r
+  ASSERT (Array != NULL);\r
+\r
+  Data = 0;\r
+  switch (Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Data = (UINT64)*(((UINT8 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Data = (UINT64)*(((UINT16 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Data = (UINT64)*(((UINT32 *)Array) + Index);\r
+      break;\r
+\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      Data = (UINT64)*(((UINT64 *)Array) + Index);\r
+      break;\r
+\r
+    default:\r
+      break;\r
+  }\r
+\r
+  return Data;\r
+}\r
+\r
+/**\r
+  Find string ID of option if its value equals to given value.\r
+\r
+  @param[in]  HiiStatement  Statement to search.\r
+  @param[in]  Value         Target value.\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STRING_ID\r
+OrderedListOptionValueToStringId (\r
+  IN  HII_STATEMENT  *HiiStatement,\r
+  IN  UINT64         Value\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+  UINT64               CurrentValue;\r
+\r
+  if (HiiStatement == NULL) {\r
+    return 0;\r
+  }\r
+\r
+  if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+    return 0;\r
+  }\r
+\r
+  if (IsListEmpty (&HiiStatement->OptionListHead)) {\r
+    return 0;\r
+  }\r
+\r
+  Link = GetFirstNode (&HiiStatement->OptionListHead);\r
+  while (!IsNull (&HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    CurrentValue = ExtendHiiValueToU64 (&Option->Value);\r
+    if (Value == CurrentValue) {\r
+      return Option->Text;\r
+    }\r
+\r
+    Link = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Compare two value in HII statement format.\r
+\r
+  @param[in]  Value1        First value to compare.\r
+  @param[in]  Value2        Second value to be compared.\r
+\r
+  @retval INTN          0 is returned when two values are equal.\r
+                        1 is returned when first value is greater than second value.\r
+                        -1 is returned when second value is greater than first value.\r
+\r
+**/\r
+INTN\r
+CompareHiiStatementValue (\r
+  IN HII_STATEMENT_VALUE  *Value1,\r
+  IN HII_STATEMENT_VALUE  *Value2\r
+  )\r
+{\r
+  INTN    Result;\r
+  UINT64  Data1;\r
+  UINT64  Data2;\r
+\r
+  if ((Value1 == NULL) || (Value2 == NULL)) {\r
+    return -1;\r
+  }\r
+\r
+  switch (Value1->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Data1 = Value1->Value.u8;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Data1 = Value1->Value.u16;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Data1 = Value1->Value.u32;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      Data1 = Value1->Value.u64;\r
+      break;\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      Data1 = (Value1->Value.b ? 1 : 0);\r
+      break;\r
+    default:\r
+      return -1;\r
+  }\r
+\r
+  switch (Value2->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Data2 = Value2->Value.u8;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Data2 = Value2->Value.u16;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Data2 = Value2->Value.u32;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      Data2 = Value2->Value.u64;\r
+      break;\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      Data2 = (Value2->Value.b ? 1 : 0);\r
+      break;\r
+    default:\r
+      return -1;\r
+  }\r
+\r
+  Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1));\r
+\r
+  return Result;\r
+}\r
+\r
+/**\r
+  Convert HII value to the string in HII one-of opcode.\r
+\r
+  @param[in]  HiiStatement  HII Statement private instance\r
+  @param[in]  Value         HII Statement value\r
+\r
+  @retval EFI_STRING_ID     The string ID in HII database.\r
+                            0 is returned when something goes wrong.\r
+\r
+**/\r
+EFI_STRING_ID\r
+HiiValueToOneOfOptionStringId (\r
+  IN HII_STATEMENT        *HiiStatement,\r
+  IN HII_STATEMENT_VALUE  *Value\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+\r
+  if ((HiiStatement == NULL) || (Value == NULL)) {\r
+    return 0;\r
+  }\r
+\r
+  if (HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {\r
+    return 0;\r
+  }\r
+\r
+  if (IsListEmpty (&HiiStatement->OptionListHead)) {\r
+    return 0;\r
+  }\r
+\r
+  Link = GetFirstNode (&HiiStatement->OptionListHead);\r
+  while (!IsNull (&HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    if (CompareHiiStatementValue (Value, &Option->Value) == 0) {\r
+      return Option->Text;\r
+    }\r
+\r
+    Link = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+/**\r
+  Convert HII string to the value in HII one-of opcode.\r
+\r
+  @param[in]  Statement     Statement private instance\r
+  @param[in]  Schema        Schema string\r
+  @param[in]  HiiString     Input string\r
+  @param[out] Value         Value returned\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+HiiStringToOneOfOptionValue (\r
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *Statement,\r
+  IN  CHAR8                                      *Schema,\r
+  IN  EFI_STRING                                 HiiString,\r
+  OUT HII_STATEMENT_VALUE                        *Value\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+  EFI_STRING           TmpString;\r
+  BOOLEAN              Found;\r
+\r
+  if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Found = FALSE;\r
+  Link  = GetFirstNode (&Statement->HiiStatement->OptionListHead);\r
+  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text);\r
+    if (TmpString != NULL) {\r
+      if (StrCmp (TmpString, HiiString) == 0) {\r
+        CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE));\r
+        Found = TRUE;\r
+      }\r
+\r
+      FreePool (TmpString);\r
+    }\r
+\r
+    if (Found) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Convert HII value to numeric value in Redfish format.\r
+\r
+  @param[in]  Value         Value to be converted.\r
+  @param[out] RedfishValue  Value in Redfish format.\r
+\r
+  @retval EFI_SUCCESS       Redfish value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+HiiValueToRedfishNumeric (\r
+  IN  HII_STATEMENT_VALUE  *Value,\r
+  OUT EDKII_REDFISH_VALUE  *RedfishValue\r
+  )\r
+{\r
+  if ((Value == NULL) || (RedfishValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  switch (Value->Type) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      RedfishValue->Type          = RedfishValueTypeInteger;\r
+      RedfishValue->Value.Integer = (INT64)Value->Value.u8;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      RedfishValue->Type          = RedfishValueTypeInteger;\r
+      RedfishValue->Value.Integer = (INT64)Value->Value.u16;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      RedfishValue->Type          = RedfishValueTypeInteger;\r
+      RedfishValue->Value.Integer = (INT64)Value->Value.u32;\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      RedfishValue->Type          = RedfishValueTypeInteger;\r
+      RedfishValue->Value.Integer = (INT64)Value->Value.u64;\r
+      break;\r
+    case EFI_IFR_TYPE_BOOLEAN:\r
+      RedfishValue->Type          = RedfishValueTypeBoolean;\r
+      RedfishValue->Value.Boolean = Value->Value.b;\r
+      break;\r
+    default:\r
+      RedfishValue->Type = RedfishValueTypeUnknown;\r
+      break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert numeric value in Redfish format to HII value.\r
+\r
+  @param[in]   RedfishValue  Value in Redfish format to be converted.\r
+  @param[out]  Value         HII value returned.\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+RedfishNumericToHiiValue (\r
+  IN  EDKII_REDFISH_VALUE  *RedfishValue,\r
+  OUT HII_STATEMENT_VALUE  *Value\r
+  )\r
+{\r
+  if ((Value == NULL) || (RedfishValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  switch (RedfishValue->Type) {\r
+    case RedfishValueTypeInteger:\r
+      Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;\r
+      Value->Value.u64 = (UINT64)RedfishValue->Value.Integer;\r
+      break;\r
+    case RedfishValueTypeBoolean:\r
+      Value->Type    = EFI_IFR_TYPE_BOOLEAN;\r
+      Value->Value.b = RedfishValue->Value.Boolean;\r
+      break;\r
+    default:\r
+      Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
+      break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Dump the value in ordered list buffer.\r
+\r
+  @param[in]   OrderedListStatement Ordered list statement.\r
+\r
+**/\r
+VOID\r
+DumpOrderedListValue (\r
+  IN  HII_STATEMENT  *OrderedListStatement\r
+  )\r
+{\r
+  UINT8   *Value8;\r
+  UINT16  *Value16;\r
+  UINT32  *Value32;\r
+  UINT64  *Value64;\r
+  UINTN   Count;\r
+  UINTN   Index;\r
+\r
+  if ((OrderedListStatement == NULL) || (OrderedListStatement->Operand != EFI_IFR_ORDERED_LIST_OP)) {\r
+    return;\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "Value.Type= 0x%x\n", OrderedListStatement->Value.Type));\r
+  DEBUG ((DEBUG_ERROR, "Value.BufferValueType= 0x%x\n", OrderedListStatement->Value.BufferValueType));\r
+  DEBUG ((DEBUG_ERROR, "Value.BufferLen= 0x%x\n", OrderedListStatement->Value.BufferLen));\r
+  DEBUG ((DEBUG_ERROR, "Value.Buffer= 0x%x\n", OrderedListStatement->Value.Buffer));\r
+  DEBUG ((DEBUG_ERROR, "Value.MaxContainers= 0x%x\n", OrderedListStatement->ExtraData.OrderListData.MaxContainers));\r
+  DEBUG ((DEBUG_ERROR, "StorageWidth= 0x%x\n", OrderedListStatement->StorageWidth));\r
+\r
+  if (OrderedListStatement->Value.Buffer == NULL) {\r
+    return;\r
+  }\r
+\r
+  Value8  = NULL;\r
+  Value16 = NULL;\r
+  Value32 = NULL;\r
+  Value64 = NULL;\r
+  Count   = 0;\r
+\r
+  switch (OrderedListStatement->Value.BufferValueType) {\r
+    case EFI_IFR_TYPE_NUM_SIZE_8:\r
+      Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;\r
+      Count  = OrderedListStatement->StorageWidth / sizeof (UINT8);\r
+      for (Index = 0; Index < Count; Index++) {\r
+        DEBUG ((DEBUG_ERROR, "%d ", Value8[Index]));\r
+      }\r
+\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_16:\r
+      Value16 = (UINT16 *)OrderedListStatement->Value.Buffer;\r
+      Count   = OrderedListStatement->StorageWidth / sizeof (UINT16);\r
+      for (Index = 0; Index < Count; Index++) {\r
+        DEBUG ((DEBUG_ERROR, "%d ", Value16[Index]));\r
+      }\r
+\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_32:\r
+      Value32 = (UINT32 *)OrderedListStatement->Value.Buffer;\r
+      Count   = OrderedListStatement->StorageWidth / sizeof (UINT32);\r
+      for (Index = 0; Index < Count; Index++) {\r
+        DEBUG ((DEBUG_ERROR, "%d ", Value32[Index]));\r
+      }\r
+\r
+      break;\r
+    case EFI_IFR_TYPE_NUM_SIZE_64:\r
+      Value64 = (UINT64 *)OrderedListStatement->Value.Buffer;\r
+      Count   = OrderedListStatement->StorageWidth / sizeof (UINT64);\r
+      for (Index = 0; Index < Count; Index++) {\r
+        DEBUG ((DEBUG_ERROR, "%d ", Value64[Index]));\r
+      }\r
+\r
+      break;\r
+    default:\r
+      Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;\r
+      Count  = OrderedListStatement->StorageWidth / sizeof (UINT8);\r
+      for (Index = 0; Index < Count; Index++) {\r
+        DEBUG ((DEBUG_ERROR, "%d ", Value8[Index]));\r
+      }\r
+\r
+      break;\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "\n"));\r
+}\r
+\r
+/**\r
+  Convert HII value to the string in HII ordered list opcode. It's caller's\r
+  responsibility to free returned buffer using FreePool().\r
+\r
+  @param[in]  HiiStatement  HII Statement private instance\r
+  @param[out] ReturnSize    The size of returned array\r
+\r
+  @retval EFI_STRING_ID     The string ID array for options in ordered list.\r
+\r
+**/\r
+EFI_STRING_ID *\r
+HiiValueToOrderedListOptionStringId (\r
+  IN  HII_STATEMENT  *HiiStatement,\r
+  OUT UINTN          *ReturnSize\r
+  )\r
+{\r
+  LIST_ENTRY     *Link;\r
+  UINTN          OptionCount;\r
+  EFI_STRING_ID  *ReturnedArray;\r
+  UINTN          Index;\r
+  UINT64         Value;\r
+\r
+  if ((HiiStatement == NULL) || (ReturnSize == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  *ReturnSize = 0;\r
+\r
+  if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+    return NULL;\r
+  }\r
+\r
+  if (IsListEmpty (&HiiStatement->OptionListHead)) {\r
+    return NULL;\r
+  }\r
+\r
+  DEBUG_CODE (\r
+    DumpOrderedListValue (HiiStatement);\r
+    );\r
+\r
+  OptionCount = 0;\r
+  Link        = GetFirstNode (&HiiStatement->OptionListHead);\r
+  while (!IsNull (&HiiStatement->OptionListHead, Link)) {\r
+    ++OptionCount;\r
+    Link = GetNextNode (&HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  *ReturnSize   = OptionCount;\r
+  ReturnedArray = AllocatePool (sizeof (EFI_STRING_ID) * OptionCount);\r
+  if (ReturnedArray == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__));\r
+    *ReturnSize = 0;\r
+    return NULL;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    Value                = OrderedListGetArrayData (HiiStatement->Value.Buffer, HiiStatement->Value.BufferValueType, Index);\r
+    ReturnedArray[Index] = OrderedListOptionValueToStringId (HiiStatement, Value);\r
+  }\r
+\r
+  return ReturnedArray;\r
+}\r
+\r
+/**\r
+  Convert HII string to the value in HII ordered list opcode.\r
+\r
+  @param[in]  Statement     Statement private instance\r
+  @param[in]  Schema        Schema string\r
+  @param[in]  HiiString     Input string\r
+  @param[out] Value         Value returned\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+HiiStringToOrderedListOptionValue (\r
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *Statement,\r
+  IN  CHAR8                                      *Schema,\r
+  IN  EFI_STRING                                 HiiString,\r
+  OUT UINT64                                     *Value\r
+  )\r
+{\r
+  LIST_ENTRY           *Link;\r
+  HII_QUESTION_OPTION  *Option;\r
+  EFI_STRING           TmpString;\r
+  BOOLEAN              Found;\r
+\r
+  if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Value = 0;\r
+\r
+  if (Statement->HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Found = FALSE;\r
+  Link  = GetFirstNode (&Statement->HiiStatement->OptionListHead);\r
+  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {\r
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+    TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, Schema, Option->Text);\r
+    if (TmpString != NULL) {\r
+      if (StrCmp (TmpString, HiiString) == 0) {\r
+        *Value = ExtendHiiValueToU64 (&Option->Value);\r
+        Found  = TRUE;\r
+      }\r
+\r
+      FreePool (TmpString);\r
+    }\r
+\r
+    if (Found) {\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Convert HII value to Redfish value.\r
+\r
+  @param[in]  HiiHandle     HII handle.\r
+  @param[in]  FullSchema    Schema string.\r
+  @param[in]  HiiStatement  HII statement.\r
+  @param[in]  Value         Value to be converted.\r
+  @param[out] RedfishValue  Value in Redfish format.\r
+\r
+  @retval EFI_SUCCESS       Redfish value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+HiiValueToRedfishValue (\r
+  IN  EFI_HII_HANDLE       HiiHandle,\r
+  IN  CHAR8                *FullSchema,\r
+  IN  HII_STATEMENT        *HiiStatement,\r
+  IN  HII_STATEMENT_VALUE  *Value,\r
+  OUT EDKII_REDFISH_VALUE  *RedfishValue\r
+  )\r
+{\r
+  EFI_STATUS     Status;\r
+  EFI_STRING_ID  StringId;\r
+  UINTN          Index;\r
+  UINTN          Count;\r
+  EFI_STRING_ID  *StringIdArray;\r
+\r
+  if ((HiiHandle == NULL) || (HiiStatement == NULL) || (Value == NULL) || (RedfishValue == NULL) || IS_EMPTY_STRING (FullSchema)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  StringIdArray = NULL;\r
+  Count         = 0;\r
+  Status        = EFI_SUCCESS;\r
+\r
+  switch (HiiStatement->Operand) {\r
+    case EFI_IFR_ONE_OF_OP:\r
+      StringId = HiiValueToOneOfOptionStringId (HiiStatement, Value);\r
+      if (StringId == 0) {\r
+        ASSERT (FALSE);\r
+        Status = EFI_DEVICE_ERROR;\r
+        break;\r
+      }\r
+\r
+      RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, StringId);\r
+      if (RedfishValue->Value.Buffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        break;\r
+      }\r
+\r
+      RedfishValue->Type = RedfishValueTypeString;\r
+      break;\r
+    case EFI_IFR_STRING_OP:\r
+      if (Value->Type != EFI_IFR_TYPE_STRING) {\r
+        ASSERT (FALSE);\r
+        Status = EFI_DEVICE_ERROR;\r
+        break;\r
+      }\r
+\r
+      RedfishValue->Type         = RedfishValueTypeString;\r
+      RedfishValue->Value.Buffer = AllocatePool (StrLen ((CHAR16 *)Value->Buffer) + 1);\r
+      UnicodeStrToAsciiStrS ((CHAR16 *)Value->Buffer, RedfishValue->Value.Buffer, StrLen ((CHAR16 *)Value->Buffer) + 1);\r
+      break;\r
+    case EFI_IFR_CHECKBOX_OP:\r
+    case EFI_IFR_NUMERIC_OP:\r
+      Status = HiiValueToRedfishNumeric (Value, RedfishValue);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_ERROR, "%a: failed to convert HII value to Redfish value: %r\n", __func__, Status));\r
+        break;\r
+      }\r
+\r
+      break;\r
+    case EFI_IFR_ACTION_OP:\r
+      if (Value->Type != EFI_IFR_TYPE_ACTION) {\r
+        ASSERT (FALSE);\r
+        Status = EFI_DEVICE_ERROR;\r
+        break;\r
+      }\r
+\r
+      //\r
+      // Action has no value. Just return unknown type.\r
+      //\r
+      RedfishValue->Type = RedfishValueTypeUnknown;\r
+      break;\r
+    case EFI_IFR_ORDERED_LIST_OP:\r
+      StringIdArray = HiiValueToOrderedListOptionStringId (HiiStatement, &Count);\r
+      if (StringIdArray == NULL) {\r
+        ASSERT (FALSE);\r
+        Status = EFI_DEVICE_ERROR;\r
+        break;\r
+      }\r
+\r
+      RedfishValue->Value.StringArray = AllocatePool (sizeof (CHAR8 *) * Count);\r
+      if (RedfishValue->Value.StringArray == NULL) {\r
+        ASSERT (FALSE);\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        break;\r
+      }\r
+\r
+      for (Index = 0; Index < Count; Index++) {\r
+        ASSERT (StringIdArray[Index] != 0);\r
+        RedfishValue->Value.StringArray[Index] = HiiGetRedfishAsciiString (HiiHandle, FullSchema, StringIdArray[Index]);\r
+        ASSERT (RedfishValue->Value.StringArray[Index] != NULL);\r
+      }\r
+\r
+      RedfishValue->ArrayCount = Count;\r
+      RedfishValue->Type       = RedfishValueTypeStringArray;\r
+\r
+      FreePool (StringIdArray);\r
+      break;\r
+    default:\r
+      DEBUG ((DEBUG_ERROR, "%a: catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __func__, HiiStatement->Operand));\r
+      ASSERT (FALSE);\r
+      Status = EFI_UNSUPPORTED;\r
+      break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Convert input ascii string to unicode string. It's caller's\r
+  responsibility to free returned buffer using FreePool().\r
+\r
+  @param[in]  AsciiString     Ascii string to be converted.\r
+\r
+  @retval CHAR16 *            Unicode string on return.\r
+\r
+**/\r
+EFI_STRING\r
+StrToUnicodeStr (\r
+  IN  CHAR8  *AsciiString\r
+  )\r
+{\r
+  UINTN       StringLen;\r
+  EFI_STRING  Buffer;\r
+  EFI_STATUS  Status;\r
+\r
+  if ((AsciiString == NULL) || (AsciiString[0] == '\0')) {\r
+    return NULL;\r
+  }\r
+\r
+  StringLen = AsciiStrLen (AsciiString) + 1;\r
+  Buffer    = AllocatePool (StringLen * sizeof (CHAR16));\r
+  if (Buffer == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = AsciiStrToUnicodeStrS (AsciiString, Buffer, StringLen);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Buffer);\r
+    return NULL;\r
+  }\r
+\r
+  return Buffer;\r
+}\r
+\r
+/**\r
+  Return the full Redfish schema string from the given Schema and Version.\r
+\r
+  Returned schema string is: Schema + '.' + Version\r
+\r
+  @param[in]  Schema      Schema string\r
+  @param[in]  Version     Schema version string\r
+\r
+  @retval CHAR8 *         Schema string. NULL when errors occur.\r
+\r
+**/\r
+CHAR8 *\r
+GetFullSchemaString (\r
+  IN CHAR8  *Schema,\r
+  IN CHAR8  *Version\r
+  )\r
+{\r
+  UINTN  Size;\r
+  CHAR8  *FullName;\r
+\r
+  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) {\r
+    return NULL;\r
+  }\r
+\r
+  Size = AsciiStrSize (CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize (Schema) + AsciiStrSize (Version);\r
+\r
+  FullName = AllocatePool (Size);\r
+  if (FullName == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: out-of-resource\n", __func__));\r
+    return NULL;\r
+  }\r
+\r
+  AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX, Schema, Version);\r
+\r
+  return FullName;\r
+}\r
+\r
+/**\r
+  Common implementation to get statement private instance.\r
+\r
+  @param[in]   RedfishPlatformConfigPrivate   Private instance.\r
+  @param[in]   Schema                         Redfish schema string.\r
+  @param[in]   ConfigureLang                  Configure language that refers to this statement.\r
+  @param[out]  Statement                      Statement instance\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+RedfishPlatformConfigGetStatementCommon (\r
+  IN     REDFISH_PLATFORM_CONFIG_PRIVATE            *RedfishPlatformConfigPrivate,\r
+  IN     CHAR8                                      *Schema,\r
+  IN     EFI_STRING                                 ConfigureLang,\r
+  OUT    REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  **Statement\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;\r
+\r
+  if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || (Statement == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Statement = NULL;\r
+\r
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);\r
+  if (TargetStatement == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: No match HII statement is found by the given %s in schema %a\n", __func__, ConfigureLang, Schema));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Find current HII question value.\r
+  //\r
+  Status = GetQuestionValue (\r
+             TargetStatement->ParentForm->ParentFormset->HiiFormSet,\r
+             TargetStatement->ParentForm->HiiForm,\r
+             TargetStatement->HiiStatement,\r
+             GetSetValueWithBuffer\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to get question current value: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  if (TargetStatement->HiiStatement->Value.Type == EFI_IFR_TYPE_UNDEFINED) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Return Value.\r
+  //\r
+  *Statement = TargetStatement;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get Redfish value with the given Schema and Configure Language.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[in]   Schema              The Redfish schema to query.\r
+  @param[in]   Version             The Redfish version to query.\r
+  @param[in]   ConfigureLang       The target value which match this configure Language.\r
+  @param[out]  Value               The returned value.\r
+\r
+  @retval EFI_SUCCESS              Value is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolGetValue (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  IN     CHAR8                                   *Schema,\r
+  IN     CHAR8                                   *Version,\r
+  IN     EFI_STRING                              ConfigureLang,\r
+  OUT    EDKII_REDFISH_VALUE                     *Value\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE            *RedfishPlatformConfigPrivate;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;\r
+  CHAR8                                      *FullSchema;\r
+\r
+  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+  Value->Type                  = RedfishValueTypeUnknown;\r
+  Value->ArrayCount            = 0;\r
+  FullSchema                   = NULL;\r
+\r
+  FullSchema = GetFullSchemaString (Schema, Version);\r
+  if (FullSchema == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  if (TargetStatement->Suppressed) {\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  Status = HiiValueToRedfishValue (\r
+             TargetStatement->ParentForm->ParentFormset->HiiHandle,\r
+             FullSchema,\r
+             TargetStatement->HiiStatement,\r
+             &TargetStatement->HiiStatement->Value,\r
+             Value\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: HiiValueToRedfishValue failed: %r\n", __func__, Status));\r
+  }\r
+\r
+RELEASE_RESOURCE:\r
+\r
+  if (FullSchema != NULL) {\r
+    FreePool (FullSchema);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Function to save question value into HII database.\r
+\r
+  @param[in]   HiiFormset       HII form-set instance\r
+  @param[in]   HiiForm          HII form instance\r
+  @param[in]   HiiStatement     HII statement that keeps new value.\r
+  @param[in]   Value            New value to apply.\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+RedfishPlatformConfigSaveQuestionValue (\r
+  IN  HII_FORMSET          *HiiFormset,\r
+  IN  HII_FORM             *HiiForm,\r
+  IN  HII_STATEMENT        *HiiStatement,\r
+  IN  HII_STATEMENT_VALUE  *Value\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if ((HiiFormset == NULL) || (HiiForm == NULL) || (HiiStatement == NULL) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = SetQuestionValue (\r
+             HiiFormset,\r
+             HiiForm,\r
+             HiiStatement,\r
+             Value\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to set question value: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  Status = SubmitForm (HiiFormset, HiiForm);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to submit form: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Common implementation to set statement private instance.\r
+\r
+  @param[in]   RedfishPlatformConfigPrivate   Private instance.\r
+  @param[in]   Schema                         Redfish schema string.\r
+  @param[in]   ConfigureLang                  Configure language that refers to this statement.\r
+  @param[in]   StatementValue                 Statement value.\r
+\r
+  @retval EFI_SUCCESS       HII value is returned successfully.\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+RedfishPlatformConfigSetStatementCommon (\r
+  IN     REDFISH_PLATFORM_CONFIG_PRIVATE  *RedfishPlatformConfigPrivate,\r
+  IN     CHAR8                            *Schema,\r
+  IN     EFI_STRING                       ConfigureLang,\r
+  IN     HII_STATEMENT_VALUE              *StatementValue\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;\r
+  EFI_STRING                                 TempBuffer;\r
+  UINT8                                      *StringArray;\r
+  UINTN                                      Index;\r
+  UINT64                                     Value;\r
+  CHAR8                                      **CharArray;\r
+\r
+  if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang) || (StatementValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  TempBuffer  = NULL;\r
+  StringArray = NULL;\r
+\r
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  TargetStatement = GetStatementPrivateByConfigureLang (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);\r
+  if (TargetStatement == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: No match HII statement is found by the given %s in schema %a\n", __func__, ConfigureLang, Schema));\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (StatementValue->Type != TargetStatement->HiiStatement->Value.Type) {\r
+    //\r
+    // We treat one-of type as string in Redfish. But one-of statement is not\r
+    // in string format from HII point of view. Do a patch here.\r
+    //\r
+    if ((TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {\r
+      TempBuffer = StrToUnicodeStr ((CHAR8 *)StatementValue->Buffer);\r
+      if (TempBuffer == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      FreePool (StatementValue->Buffer);\r
+      StatementValue->Buffer    = NULL;\r
+      StatementValue->BufferLen = 0;\r
+\r
+      Status = HiiStringToOneOfOptionValue (TargetStatement, Schema, TempBuffer, StatementValue);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_ERROR, "%a: failed to find option value by the given %s\n", __func__, TempBuffer));\r
+        FreePool (TempBuffer);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      FreePool (TempBuffer);\r
+    } else if ((TargetStatement->HiiStatement->Operand == EFI_IFR_ORDERED_LIST_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {\r
+      //\r
+      // We treat ordered list type as string in Redfish. But ordered list statement is not\r
+      // in string format from HII point of view. Do a patch here.\r
+      //\r
+      StringArray = AllocateZeroPool (TargetStatement->HiiStatement->StorageWidth);\r
+      if (StringArray == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      //\r
+      // Arrange new option order from input string array\r
+      //\r
+      CharArray = (CHAR8 **)StatementValue->Buffer;\r
+      for (Index = 0; Index < StatementValue->BufferLen; Index++) {\r
+        TempBuffer = StrToUnicodeStr (CharArray[Index]);\r
+        if (TempBuffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+\r
+        Status = HiiStringToOrderedListOptionValue (TargetStatement, Schema, TempBuffer, &Value);\r
+        if (EFI_ERROR (Status)) {\r
+          ASSERT (FALSE);\r
+          continue;\r
+        }\r
+\r
+        FreePool (TempBuffer);\r
+        OrderedListSetArrayData (StringArray, TargetStatement->HiiStatement->Value.BufferValueType, Index, Value);\r
+      }\r
+\r
+      StatementValue->Type            = EFI_IFR_TYPE_BUFFER;\r
+      StatementValue->Buffer          = StringArray;\r
+      StatementValue->BufferLen       = TargetStatement->HiiStatement->StorageWidth;\r
+      StatementValue->BufferValueType = TargetStatement->HiiStatement->Value.BufferValueType;\r
+    } else if ((TargetStatement->HiiStatement->Operand == EFI_IFR_NUMERIC_OP) && (StatementValue->Type == EFI_IFR_TYPE_NUM_SIZE_64)) {\r
+      //\r
+      // Redfish only has numeric value type and it does not care about the value size.\r
+      // Do a patch here so we have proper value size applied.\r
+      //\r
+      StatementValue->Type = TargetStatement->HiiStatement->Value.Type;\r
+    } else {\r
+      DEBUG ((DEBUG_ERROR, "%a: catch value type mismatch! input type: 0x%x but target value type: 0x%x\n", __func__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type));\r
+      ASSERT (FALSE);\r
+    }\r
+  }\r
+\r
+  Status = RedfishPlatformConfigSaveQuestionValue (\r
+             TargetStatement->ParentForm->ParentFormset->HiiFormSet,\r
+             TargetStatement->ParentForm->HiiForm,\r
+             TargetStatement->HiiStatement,\r
+             StatementValue\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to save question value: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Set Redfish value with the given Schema and Configure Language.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[in]   Schema              The Redfish schema to query.\r
+  @param[in]   Version             The Redfish version to query.\r
+  @param[in]   ConfigureLang       The target value which match this configure Language.\r
+  @param[in]   Value               The value to set.\r
+\r
+  @retval EFI_SUCCESS              Value is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolSetValue (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  IN     CHAR8                                   *Schema,\r
+  IN     CHAR8                                   *Version,\r
+  IN     EFI_STRING                              ConfigureLang,\r
+  IN     EDKII_REDFISH_VALUE                     Value\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE  *RedfishPlatformConfigPrivate;\r
+  CHAR8                            *FullSchema;\r
+  HII_STATEMENT_VALUE              NewValue;\r
+\r
+  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((Value.Type == RedfishValueTypeUnknown) || (Value.Type >= RedfishValueTypeMax)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+  FullSchema                   = NULL;\r
+\r
+  FullSchema = GetFullSchemaString (Schema, Version);\r
+  if (FullSchema == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE));\r
+\r
+  switch (Value.Type) {\r
+    case RedfishValueTypeInteger:\r
+    case RedfishValueTypeBoolean:\r
+      Status = RedfishNumericToHiiValue (&Value, &NewValue);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_ERROR, "%a: failed to convert Redfish value to Hii value: %r\n", __func__, Status));\r
+        goto RELEASE_RESOURCE;\r
+      }\r
+\r
+      break;\r
+    case RedfishValueTypeString:\r
+      NewValue.Type      = EFI_IFR_TYPE_STRING;\r
+      NewValue.BufferLen = (UINT16)AsciiStrSize (Value.Value.Buffer);\r
+      NewValue.Buffer    = AllocateCopyPool (NewValue.BufferLen, Value.Value.Buffer);\r
+      if (NewValue.Buffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto RELEASE_RESOURCE;\r
+      }\r
+\r
+      break;\r
+    case RedfishValueTypeStringArray:\r
+      NewValue.Type      = EFI_IFR_TYPE_STRING;\r
+      NewValue.BufferLen = (UINT16)Value.ArrayCount;\r
+      NewValue.Buffer    = (UINT8 *)Value.Value.StringArray;\r
+      break;\r
+    default:\r
+      ASSERT (FALSE);\r
+      break;\r
+  }\r
+\r
+  Status = RedfishPlatformConfigSetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to set value to statement: %r\n", __func__, Status));\r
+  }\r
+\r
+RELEASE_RESOURCE:\r
+\r
+  if (FullSchema != NULL) {\r
+    FreePool (FullSchema);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get the list of Configure Language from platform configuration by the given Schema and RegexPattern.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[in]   Schema              The Redfish schema to query.\r
+  @param[in]   Version             The Redfish version to query.\r
+  @param[in]   RegexPattern        The target Configure Language pattern. This is used for regular expression matching.\r
+  @param[out]  ConfigureLangList   The list of Configure Language.\r
+  @param[out]  Count               The number of Configure Language in ConfigureLangList.\r
+\r
+  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolGetConfigureLang (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  IN     CHAR8                                   *Schema,\r
+  IN     CHAR8                                   *Version,\r
+  IN     EFI_STRING                              RegexPattern,\r
+  OUT    EFI_STRING                              **ConfigureLangList,\r
+  OUT    UINTN                                   *Count\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE                 *RedfishPlatformConfigPrivate;\r
+  EFI_STATUS                                      Status;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  StatementList;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF   *StatementRef;\r
+  LIST_ENTRY                                      *NextLink;\r
+  EFI_STRING                                      TmpString;\r
+  EFI_STRING                                      *TmpConfigureLangList;\r
+  UINTN                                           Index;\r
+  CHAR8                                           *FullSchema;\r
+\r
+  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || (Count == NULL) || (ConfigureLangList == NULL) || IS_EMPTY_STRING (RegexPattern)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Count                       = 0;\r
+  *ConfigureLangList           = NULL;\r
+  FullSchema                   = NULL;\r
+  TmpConfigureLangList         = NULL;\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  FullSchema = GetFullSchemaString (Schema, Version);\r
+  if (FullSchema == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = GetStatementPrivateByConfigureLangRegex (\r
+             RedfishPlatformConfigPrivate->RegularExpressionProtocol,\r
+             &RedfishPlatformConfigPrivate->FormsetList,\r
+             FullSchema,\r
+             RegexPattern,\r
+             &StatementList\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: GetStatementPrivateByConfigureLangRegex failure: %r\n", __func__, Status));\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  if (!IsListEmpty (&StatementList.StatementList)) {\r
+    TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) * StatementList.Count);\r
+    if (TmpConfigureLangList == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto RELEASE_RESOURCE;\r
+    }\r
+\r
+    Index    = 0;\r
+    NextLink = GetFirstNode (&StatementList.StatementList);\r
+    while (!IsNull (&StatementList.StatementList, NextLink)) {\r
+      StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);\r
+      NextLink     = GetNextNode (&StatementList.StatementList, NextLink);\r
+\r
+      ASSERT (StatementRef->Statement->Description != 0);\r
+      if (StatementRef->Statement->Description != 0) {\r
+        TmpString = HiiGetRedfishString (StatementRef->Statement->ParentForm->ParentFormset->HiiHandle, FullSchema, StatementRef->Statement->Description);\r
+        ASSERT (TmpString != NULL);\r
+        if (TmpString != NULL) {\r
+          TmpConfigureLangList[Index] = AllocateCopyPool (StrSize (TmpString), TmpString);\r
+          ASSERT (TmpConfigureLangList[Index] != NULL);\r
+          FreePool (TmpString);\r
+          ++Index;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  *Count             = StatementList.Count;\r
+  *ConfigureLangList = TmpConfigureLangList;\r
+\r
+RELEASE_RESOURCE:\r
+\r
+  if (FullSchema != NULL) {\r
+    FreePool (FullSchema);\r
+  }\r
+\r
+  ReleaseStatementList (&StatementList);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get the list of supported Redfish schema from platform configuration.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[out]  SupportedSchema     The supported schema list which is separated by ';'.\r
+                                   For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"\r
+                                   The SupportedSchema is allocated by the callee. It's caller's\r
+                                   responsibility to free this buffer using FreePool().\r
+\r
+  @retval EFI_SUCCESS              Schema is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolGetSupportedSchema (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  OUT    CHAR8                                   **SupportedSchema\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE           *RedfishPlatformConfigPrivate;\r
+  EFI_STATUS                                Status;\r
+  LIST_ENTRY                                *HiiFormsetLink;\r
+  LIST_ENTRY                                *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;\r
+  UINTN                                     Index;\r
+  UINTN                                     StringSize;\r
+  CHAR8                                     *StringBuffer;\r
+  UINTN                                     StringIndex;\r
+\r
+  if ((This == NULL) || (SupportedSchema == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *SupportedSchema = NULL;\r
+\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+\r
+  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList, &RedfishPlatformConfigPrivate->PendingList);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: ProcessPendingList failure: %r\n", __func__, Status));\r
+    return Status;\r
+  }\r
+\r
+  if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Calculate for string buffer size.\r
+  //\r
+  StringSize     = 0;\r
+  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);\r
+  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {\r
+      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {\r
+        StringSize += AsciiStrSize (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);\r
+      }\r
+    }\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  if (StringSize == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  StringBuffer = AllocatePool (StringSize);\r
+  if (StringBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  StringIndex    = 0;\r
+  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate->FormsetList);\r
+  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate->FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {\r
+      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count; Index++) {\r
+        AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex), HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);\r
+        StringIndex              += AsciiStrLen (HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);\r
+        StringBuffer[StringIndex] = ';';\r
+        ++StringIndex;\r
+      }\r
+    }\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  StringBuffer[--StringIndex] = '\0';\r
+\r
+  *SupportedSchema = StringBuffer;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get Redfish default value with the given Schema and Configure Language.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[in]   Schema              The Redfish schema to query.\r
+  @param[in]   Version             The Redfish version to query.\r
+  @param[in]   ConfigureLang       The target value which match this configure Language.\r
+  @param[in]   DefaultClass        The UEFI defined default class.\r
+                                   Please refer to UEFI spec. 33.2.5.8 "defaults" for details.\r
+  @param[out]  Value               The returned value.\r
+\r
+  @retval EFI_SUCCESS              Value is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolGetDefaultValue (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  IN     CHAR8                                   *Schema,\r
+  IN     CHAR8                                   *Version,\r
+  IN     EFI_STRING                              ConfigureLang,\r
+  IN     UINT16                                  DefaultClass,\r
+  OUT    EDKII_REDFISH_VALUE                     *Value\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE            *RedfishPlatformConfigPrivate;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;\r
+  CHAR8                                      *FullSchema;\r
+  HII_STATEMENT_VALUE                        DefaultValue;\r
+\r
+  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+  ZeroMem (&DefaultValue, sizeof (HII_STATEMENT_VALUE));\r
+  ZeroMem (Value, sizeof (EDKII_REDFISH_VALUE));\r
+\r
+  FullSchema = NULL;\r
+  FullSchema = GetFullSchemaString (Schema, Version);\r
+  if (FullSchema == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  if (TargetStatement->Suppressed) {\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  Status = GetQuestionDefault (TargetStatement->ParentForm->ParentFormset->HiiFormSet, TargetStatement->ParentForm->HiiForm, TargetStatement->HiiStatement, DefaultClass, &DefaultValue);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: GetQuestionDefault failed: %r\n", __func__, Status));\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  Status = HiiValueToRedfishValue (\r
+             TargetStatement->ParentForm->ParentFormset->HiiHandle,\r
+             FullSchema,\r
+             TargetStatement->HiiStatement,\r
+             &DefaultValue,\r
+             Value\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: HiiValueToRedfishValue failed: %r\n", __func__, Status));\r
+  }\r
+\r
+RELEASE_RESOURCE:\r
+\r
+  if (FullSchema != NULL) {\r
+    FreePool (FullSchema);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get Redfish attribute value with the given Schema and Configure Language.\r
+\r
+  @param[in]   This                Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.\r
+  @param[in]   Schema              The Redfish schema to query.\r
+  @param[in]   Version             The Redfish version to query.\r
+  @param[in]   ConfigureLang       The target value which match this configure Language.\r
+  @param[out]  AttributeValue      The attribute value.\r
+\r
+  @retval EFI_SUCCESS              Value is returned successfully.\r
+  @retval Others                   Some error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigProtocolGetAttribute (\r
+  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,\r
+  IN     CHAR8                                   *Schema,\r
+  IN     CHAR8                                   *Version,\r
+  IN     EFI_STRING                              ConfigureLang,\r
+  OUT    EDKII_REDFISH_ATTRIBUTE                 *AttributeValue\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  REDFISH_PLATFORM_CONFIG_PRIVATE            *RedfishPlatformConfigPrivate;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;\r
+  CHAR8                                      *FullSchema;\r
+  CHAR8                                      *Buffer;\r
+\r
+  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) || IS_EMPTY_STRING (ConfigureLang) || (AttributeValue == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  RedfishPlatformConfigPrivate = REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);\r
+  ZeroMem (AttributeValue, sizeof (EDKII_REDFISH_ATTRIBUTE));\r
+  FullSchema = NULL;\r
+  FullSchema = GetFullSchemaString (Schema, Version);\r
+  if (FullSchema == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = RedfishPlatformConfigGetStatementCommon (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &TargetStatement);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RELEASE_RESOURCE;\r
+  }\r
+\r
+  if (TargetStatement->Description != 0) {\r
+    AttributeValue->AttributeName = HiiGetRedfishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, TargetStatement->Description);\r
+    Buffer                        = GetAttributeNameFromConfigLanguage (AttributeValue->AttributeName);\r
+    if (Buffer != NULL) {\r
+      FreePool (AttributeValue->AttributeName);\r
+      AttributeValue->AttributeName = Buffer;\r
+    }\r
+\r
+    AttributeValue->DisplayName = HiiGetEnglishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, TargetStatement->Description);\r
+  }\r
+\r
+  if (TargetStatement->Help != 0) {\r
+    AttributeValue->HelpText = HiiGetEnglishAsciiString (TargetStatement->ParentForm->ParentFormset->HiiHandle, TargetStatement->Help);\r
+  }\r
+\r
+  AttributeValue->ReadOnly      = ((TargetStatement->Flags & EFI_IFR_FLAG_READ_ONLY) == 0 ? FALSE : TRUE);\r
+  AttributeValue->ResetRequired = ((TargetStatement->Flags & EFI_IFR_FLAG_RESET_REQUIRED) == 0 ? FALSE : TRUE);\r
+  AttributeValue->Type          = HiiStatementToAttributeType (TargetStatement->HiiStatement);\r
+  AttributeValue->Suppress      = TargetStatement->Suppressed;\r
+  AttributeValue->GrayedOut     = TargetStatement->GrayedOut;\r
+\r
+  //\r
+  // Build up menu path\r
+  //\r
+  AttributeValue->MenuPath = BuildMenPath (TargetStatement);\r
+  if (AttributeValue->MenuPath == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to build menu path for \"%a\"\n", __func__, AttributeValue->AttributeName));\r
+  }\r
+\r
+  //\r
+  // Deal with maximum and minimum\r
+  //\r
+  if (AttributeValue->Type == RedfishAttributeTypeString) {\r
+    AttributeValue->StrMaxSize = TargetStatement->StatementData.StrMaxSize;\r
+    AttributeValue->StrMinSize = TargetStatement->StatementData.StrMinSize;\r
+  } else if (AttributeValue->Type == RedfishAttributeTypeInteger) {\r
+    AttributeValue->NumMaximum = TargetStatement->StatementData.NumMaximum;\r
+    AttributeValue->NumMinimum = TargetStatement->StatementData.NumMinimum;\r
+    AttributeValue->NumStep    = TargetStatement->StatementData.NumStep;\r
+  }\r
+\r
+  //\r
+  // Provide value array if this is enumeration type.\r
+  //\r
+  if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP) {\r
+    Status = OneOfStatementToAttributeValues (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema, TargetStatement, &AttributeValue->Values);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "%a: failed to convert one-of options to attribute values: %r\n", __func__, Status));\r
+    }\r
+  }\r
+\r
+RELEASE_RESOURCE:\r
+\r
+  if (FullSchema != NULL) {\r
+    FreePool (FullSchema);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Functions which are registered to receive notification of\r
+  database events have this prototype. The actual event is encoded\r
+  in NotifyType. The following table describes how PackageType,\r
+  PackageGuid, Handle, and Package are used for each of the\r
+  notification types.\r
+\r
+  @param[in] PackageType  Package type of the notification.\r
+  @param[in] PackageGuid  If PackageType is\r
+                          EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+                          the pointer to the GUID from the Guid\r
+                          field of EFI_HII_PACKAGE_GUID_HEADER.\r
+                          Otherwise, it must be NULL.\r
+  @param[in] Package      Points to the package referred to by the\r
+                          notification Handle The handle of the package\r
+                          list which contains the specified package.\r
+  @param[in] Handle       The HII handle.\r
+  @param[in] NotifyType   The type of change concerning the\r
+                          database. See\r
+                          EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigFormUpdateNotify (\r
+  IN UINT8                         PackageType,\r
+  IN CONST EFI_GUID                *PackageGuid,\r
+  IN CONST EFI_HII_PACKAGE_HEADER  *Package,\r
+  IN EFI_HII_HANDLE                Handle,\r
+  IN EFI_HII_DATABASE_NOTIFY_TYPE  NotifyType\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if ((NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK) || (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK)) {\r
+    //\r
+    // HII formset on this handle is updated by driver during run-time. The formset needs to be reloaded.\r
+    //\r
+    Status = NotifyFormsetUpdate (Handle, &mRedfishPlatformConfigPrivate->PendingList);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "%a: failed to notify updated formset of HII handle: 0x%x\n", __func__, Handle));\r
+      return Status;\r
+    }\r
+  } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) {\r
+    //\r
+    // HII resource is removed. The formset is no longer exist.\r
+    //\r
+    Status = NotifyFormsetDeleted (Handle, &mRedfishPlatformConfigPrivate->PendingList);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "%a: failed to notify deleted formset of HII handle: 0x%x\n", __func__, Handle));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This is a EFI_HII_STRING_PROTOCOL notification event handler.\r
+\r
+  Install HII package notification.\r
+\r
+  @param[in] Event    Event whose notification function is being invoked.\r
+  @param[in] Context  Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiStringProtocolInstalled (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Locate HII database protocol.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiStringProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&mRedfishPlatformConfigPrivate->HiiString\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: locate EFI_HII_STRING_PROTOCOL failure: %r\n", __func__, Status));\r
+    return;\r
+  }\r
+\r
+  gBS->CloseEvent (Event);\r
+  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL;\r
+}\r
+\r
+/**\r
+  This is a EFI_HII_DATABASE_PROTOCOL notification event handler.\r
+\r
+  Install HII package notification.\r
+\r
+  @param[in] Event    Event whose notification function is being invoked.\r
+  @param[in] Context  Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HiiDatabaseProtocolInstalled (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Locate HII database protocol.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiDatabaseProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: locate EFI_HII_DATABASE_PROTOCOL failure: %r\n", __func__, Status));\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Register package notification when new form package is installed.\r
+  //\r
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (\r
+                                                         mRedfishPlatformConfigPrivate->HiiDatabase,\r
+                                                         EFI_HII_PACKAGE_FORMS,\r
+                                                         NULL,\r
+                                                         RedfishPlatformConfigFormUpdateNotify,\r
+                                                         EFI_HII_DATABASE_NOTIFY_NEW_PACK,\r
+                                                         &mRedfishPlatformConfigPrivate->NotifyHandle\r
+                                                         );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __func__, Status));\r
+  }\r
+\r
+  //\r
+  // Register package notification when new form package is updated.\r
+  //\r
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->RegisterPackageNotify (\r
+                                                         mRedfishPlatformConfigPrivate->HiiDatabase,\r
+                                                         EFI_HII_PACKAGE_FORMS,\r
+                                                         NULL,\r
+                                                         RedfishPlatformConfigFormUpdateNotify,\r
+                                                         EFI_HII_DATABASE_NOTIFY_ADD_PACK,\r
+                                                         &mRedfishPlatformConfigPrivate->NotifyHandle\r
+                                                         );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: RegisterPackageNotify for EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __func__, Status));\r
+  }\r
+\r
+  gBS->CloseEvent (Event);\r
+  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL;\r
+}\r
+\r
+/**\r
+  This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler.\r
+\r
+  @param[in] Event    Event whose notification function is being invoked.\r
+  @param[in] Context  Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RegexProtocolInstalled (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Locate regular expression protocol.\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiRegularExpressionProtocolGuid,\r
+                  NULL,\r
+                  (VOID **)&mRedfishPlatformConfigPrivate->RegularExpressionProtocol\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: locate EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __func__, Status));\r
+    return;\r
+  }\r
+\r
+  gBS->CloseEvent (Event);\r
+  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL;\r
+}\r
+\r
+/**\r
+  Unloads an image.\r
+\r
+  @param  ImageHandle           Handle that identifies the image to be unloaded.\r
+\r
+  @retval EFI_SUCCESS           The image has been unloaded.\r
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigDxeUnload (\r
+  IN EFI_HANDLE  ImageHandle\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  if (mRedfishPlatformConfigPrivate != NULL) {\r
+    Status = gBS->UninstallProtocolInterface (\r
+                    mRedfishPlatformConfigPrivate->ImageHandle,\r
+                    &gEdkIIRedfishPlatformConfigProtocolGuid,\r
+                    (VOID *)&mRedfishPlatformConfigPrivate->Protocol\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "%a: can not uninstall gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __func__, Status));\r
+      ASSERT (FALSE);\r
+    }\r
+\r
+    //\r
+    // Close events\r
+    //\r
+    if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) {\r
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent);\r
+    }\r
+\r
+    if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent != NULL) {\r
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent);\r
+    }\r
+\r
+    if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL) {\r
+      gBS->CloseEvent (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent);\r
+    }\r
+\r
+    //\r
+    // Unregister package notification.\r
+    //\r
+    if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) {\r
+      mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify (\r
+                                                    mRedfishPlatformConfigPrivate->HiiDatabase,\r
+                                                    mRedfishPlatformConfigPrivate->NotifyHandle\r
+                                                    );\r
+    }\r
+\r
+    ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList);\r
+    FreePool (mRedfishPlatformConfigPrivate);\r
+    mRedfishPlatformConfigPrivate = NULL;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This is the declaration of an EFI image entry point. This entry point is\r
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
+  both device drivers and bus drivers.\r
+\r
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.\r
+  @param  SystemTable           A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval Others                An unexpected error occurred.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RedfishPlatformConfigDxeEntryPoint (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE));\r
+  if (mRedfishPlatformConfigPrivate == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: can not allocate pool for REDFISH_PLATFORM_CONFIG_PRIVATE\n", __func__));\r
+    ASSERT (FALSE);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Protocol initialization\r
+  //\r
+  mRedfishPlatformConfigPrivate->ImageHandle                 = ImageHandle;\r
+  mRedfishPlatformConfigPrivate->Protocol.Revision           = REDFISH_PLATFORM_CONFIG_VERSION;\r
+  mRedfishPlatformConfigPrivate->Protocol.GetValue           = RedfishPlatformConfigProtocolGetValue;\r
+  mRedfishPlatformConfigPrivate->Protocol.SetValue           = RedfishPlatformConfigProtocolSetValue;\r
+  mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang   = RedfishPlatformConfigProtocolGetConfigureLang;\r
+  mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema = RedfishPlatformConfigProtocolGetSupportedSchema;\r
+  mRedfishPlatformConfigPrivate->Protocol.GetAttribute       = RedfishPlatformConfigProtocolGetAttribute;\r
+  mRedfishPlatformConfigPrivate->Protocol.GetDefaultValue    = RedfishPlatformConfigProtocolGetDefaultValue;\r
+\r
+  InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList);\r
+  InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList);\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &ImageHandle,\r
+                  &gEdkIIRedfishPlatformConfigProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  (VOID *)&mRedfishPlatformConfigPrivate->Protocol\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: can not install gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __func__, Status));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  //\r
+  // Install protocol notification if HII database protocol is installed.\r
+  //\r
+  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (\r
+                                                               &gEfiHiiDatabaseProtocolGuid,\r
+                                                               TPL_CALLBACK,\r
+                                                               HiiDatabaseProtocolInstalled,\r
+                                                               NULL,\r
+                                                               &mRedfishPlatformConfigPrivate->HiiDbNotify.Registration\r
+                                                               );\r
+  if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiHiiDatabaseProtocolGuid\n", __func__));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  //\r
+  // Install protocol notification if HII string protocol is installed.\r
+  //\r
+  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (\r
+                                                                   &gEfiHiiStringProtocolGuid,\r
+                                                                   TPL_CALLBACK,\r
+                                                                   HiiStringProtocolInstalled,\r
+                                                                   NULL,\r
+                                                                   &mRedfishPlatformConfigPrivate->HiiStringNotify.Registration\r
+                                                                   );\r
+  if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiHiiStringProtocolGuid\n", __func__));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  //\r
+  // Install protocol notification if regular expression protocol is installed.\r
+  //\r
+  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = EfiCreateProtocolNotifyEvent (\r
+                                                               &gEfiRegularExpressionProtocolGuid,\r
+                                                               TPL_CALLBACK,\r
+                                                               RegexProtocolInstalled,\r
+                                                               NULL,\r
+                                                               &mRedfishPlatformConfigPrivate->RegexNotify.Registration\r
+                                                               );\r
+  if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to create protocol notification for gEfiRegularExpressionProtocolGuid\n", __func__));\r
+    ASSERT (FALSE);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
new file mode 100644 (file)
index 0000000..67697ec
--- /dev/null
@@ -0,0 +1,81 @@
+/** @file\r
+  This file defines the EDKII Redfish Platform Config Protocol interface.\r
+\r
+  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_\r
+#define EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_\r
+\r
+#include <Uefi.h>\r
+\r
+//\r
+// Libraries\r
+//\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+\r
+//\r
+// Protocols\r
+//\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/RegularExpressionProtocol.h>\r
+\r
+//\r
+// Produced Protocol\r
+//\r
+#include <Protocol/EdkIIRedfishPlatformConfig.h>\r
+\r
+///\r
+/// Definition of EDKII_REDFISH_PLATFORM_CONFIG_NOTIFY.\r
+///\r
+typedef struct {\r
+  EFI_EVENT    ProtocolEvent;                  ///< Protocol notification event.\r
+  VOID         *Registration;                  ///< Protocol notification registration.\r
+} REDFISH_PLATFORM_CONFIG_NOTIFY;\r
+\r
+///\r
+/// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.\r
+///\r
+typedef struct {\r
+  EFI_HANDLE                                ImageHandle;                ///< Driver image handle.\r
+  EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL    Protocol;\r
+  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiDbNotify;\r
+  EFI_HII_DATABASE_PROTOCOL                 *HiiDatabase;               ///< The HII database protocol.\r
+  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiStringNotify;\r
+  EFI_HII_STRING_PROTOCOL                   *HiiString;                 ///< HII String Protocol.\r
+  REDFISH_PLATFORM_CONFIG_NOTIFY            RegexNotify;\r
+  EFI_REGULAR_EXPRESSION_PROTOCOL           *RegularExpressionProtocol; ///< Regular Expression Protocol.\r
+  EFI_HANDLE                                NotifyHandle;               ///< The notify handle.\r
+  LIST_ENTRY                                FormsetList;                ///< The list to keep cached HII formset.\r
+  LIST_ENTRY                                PendingList;                ///< The list to keep updated HII handle.\r
+} REDFISH_PLATFORM_CONFIG_PRIVATE;\r
+\r
+///\r
+/// Definition of REDFISH_STACK.\r
+///\r
+typedef struct {\r
+  VOID     **Pool;\r
+  UINTN    Size;\r
+  UINTN    Index;\r
+} REDFISH_STACK;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol)\r
+#define REGULAR_EXPRESSION_INCLUDE_ALL   L".*"\r
+#define CONFIGURE_LANGUAGE_PREFIX        "x-uefi-redfish-"\r
+#define REDFISH_PLATFORM_CONFIG_VERSION  0x00010000\r
+#define REDFISH_PLATFORM_CONFIG_DEBUG    DEBUG_VERBOSE\r
+#define REDFISH_MENU_PATH_SIZE           8\r
+\r
+#endif\r
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
new file mode 100644 (file)
index 0000000..5a249c8
--- /dev/null
@@ -0,0 +1,55 @@
+## @file\r
+#  Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interfaces.\r
+#\r
+#  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>\r
+#  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION               = 0x00010005\r
+  BASE_NAME                 = RedfishPlatformConfigDxe\r
+  FILE_GUID                 = BEAEFFE1-0633-41B5-913C-9389339C2927\r
+  MODULE_TYPE               = DXE_DRIVER\r
+  VERSION_STRING            = 1.0\r
+  ENTRY_POINT               = RedfishPlatformConfigDxeEntryPoint\r
+  UNLOAD_IMAGE              = RedfishPlatformConfigDxeUnload\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  RedfishPkg/RedfishPkg.dec\r
+\r
+[Sources]\r
+  RedfishPlatformConfigDxe.h\r
+  RedfishPlatformConfigDxe.c\r
+  RedfishPlatformConfigImpl.h\r
+  RedfishPlatformConfigImpl.c\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  DevicePathLib\r
+  HiiLib\r
+  HiiUtilityLib\r
+  MemoryAllocationLib\r
+  PrintLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiDriverEntryPoint\r
+\r
+[Protocols]\r
+  gEdkIIRedfishPlatformConfigProtocolGuid ## PRODUCED\r
+  gEfiHiiDatabaseProtocolGuid             ## CONSUMED\r
+  gEfiHiiStringProtocolGuid               ## CONSUMED\r
+  gEfiRegularExpressionProtocolGuid       ## CONSUMED\r
+\r
+[Guids]\r
+  gEfiRegexSyntaxTypePerlGuid             ## CONSUMED\r
+\r
+[Depex]\r
+  TRUE\r
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
new file mode 100644 (file)
index 0000000..889448f
--- /dev/null
@@ -0,0 +1,1364 @@
+/** @file\r
+  The implementation of EDKII Redfish Platform Config Protocol.\r
+\r
+  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "RedfishPlatformConfigDxe.h"\r
+#include "RedfishPlatformConfigImpl.h"\r
+\r
+extern REDFISH_PLATFORM_CONFIG_PRIVATE  *mRedfishPlatformConfigPrivate;\r
+\r
+/**\r
+  Debug dump HII string.\r
+\r
+  @param[in]  HiiHandle   HII handle instance\r
+  @param[in]  StringId    HII string to dump\r
+\r
+  @retval EFI_SUCCESS       Dump HII string successfully\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+DumpHiiString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_STRING_ID   StringId\r
+  )\r
+{\r
+  EFI_STRING  String;\r
+\r
+  if ((HiiHandle == NULL) || (StringId == 0)) {\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "???"));\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  String = HiiGetString (HiiHandle, StringId, NULL);\r
+  if (String == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%s", String));\r
+  FreePool (String);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Debug dump HII form-set data.\r
+\r
+  @param[in]  FormsetPrivate    HII form-set private instance.\r
+\r
+  @retval EFI_SUCCESS       Dump form-set successfully\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+DumpFormset (\r
+  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate\r
+  )\r
+{\r
+  LIST_ENTRY                                 *HiiFormLink;\r
+  LIST_ENTRY                                 *HiiNextFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;\r
+  LIST_ENTRY                                 *HiiStatementLink;\r
+  LIST_ENTRY                                 *HiiNextStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;\r
+  UINTN                                      Index;\r
+\r
+  if (FormsetPrivate == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Index       = 0;\r
+  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);\r
+  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {\r
+    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);\r
+    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);\r
+\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "  [%d] form: %d title: ", ++Index, HiiFormPrivate->Id));\r
+    DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title);\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "\n"));\r
+\r
+    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);\r
+    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {\r
+      HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);\r
+      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);\r
+\r
+      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "    QID: 0x%x Prompt: ", HiiStatementPrivate->QuestionId));\r
+      DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate->Description);\r
+      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "\n"));\r
+\r
+      HiiStatementLink = HiiNextStatementLink;\r
+    }\r
+\r
+    HiiFormLink = HiiNextFormLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Debug dump HII form-set list.\r
+\r
+  @param[in]  FormsetList   Form-set list instance\r
+\r
+  @retval EFI_SUCCESS       Dump list successfully\r
+  @retval Others            Errors occur\r
+\r
+**/\r
+EFI_STATUS\r
+DumpFormsetList (\r
+  IN  LIST_ENTRY  *FormsetList\r
+  )\r
+{\r
+  LIST_ENTRY                                *HiiFormsetLink;\r
+  LIST_ENTRY                                *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;\r
+  UINTN                                     Index;\r
+\r
+  if (FormsetList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IsListEmpty (FormsetList)) {\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: Empty formset list\n", __func__));\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Index          = 0;\r
+  HiiFormsetLink = GetFirstNode (FormsetList);\r
+  while (!IsNull (FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "[%d] HII Handle: 0x%x formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle, &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr));\r
+    DumpFormset (HiiFormsetPrivate);\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Retrieves a unicode string from a string package in a given language. The\r
+  returned string is allocated using AllocatePool().  The caller is responsible\r
+  for freeing the allocated buffer using FreePool().\r
+\r
+  If HiiHandle is NULL, then ASSERT().\r
+  If StringId is 0, then ASSET.\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  Language          The specified configure language to get string.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+EFI_STRING\r
+HiiGetRedfishString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN CHAR8           *Language,\r
+  IN EFI_STRING_ID   StringId\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       StringSize;\r
+  CHAR16      TempString;\r
+  EFI_STRING  String;\r
+\r
+  if ((mRedfishPlatformConfigPrivate->HiiString == NULL) || (HiiHandle == NULL) || (StringId == 0) || IS_EMPTY_STRING (Language)) {\r
+    ASSERT (FALSE);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Retrieve the size of the string in the string package for the BestLanguage\r
+  //\r
+  StringSize = 0;\r
+  Status     = mRedfishPlatformConfigPrivate->HiiString->GetString (\r
+                                                           mRedfishPlatformConfigPrivate->HiiString,\r
+                                                           Language,\r
+                                                           HiiHandle,\r
+                                                           StringId,\r
+                                                           &TempString,\r
+                                                           &StringSize,\r
+                                                           NULL\r
+                                                           );\r
+  //\r
+  // If GetString() returns EFI_SUCCESS for a zero size,\r
+  // then there are no supported languages registered for HiiHandle.  If GetString()\r
+  // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present\r
+  // in the HII Database\r
+  //\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Allocate a buffer for the return string\r
+  //\r
+  String = AllocateZeroPool (StringSize);\r
+  if (String == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Retrieve the string from the string package\r
+  //\r
+  Status = mRedfishPlatformConfigPrivate->HiiString->GetString (\r
+                                                       mRedfishPlatformConfigPrivate->HiiString,\r
+                                                       Language,\r
+                                                       HiiHandle,\r
+                                                       StringId,\r
+                                                       String,\r
+                                                       &StringSize,\r
+                                                       NULL\r
+                                                       );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Free the buffer and return NULL if the supported languages can not be retrieved.\r
+    //\r
+    FreePool (String);\r
+    String = NULL;\r
+  }\r
+\r
+  //\r
+  // Return the Null-terminated Unicode string\r
+  //\r
+  return String;\r
+}\r
+\r
+/**\r
+  Retrieves a ASCII string from a string package in a given language. The\r
+  returned string is allocated using AllocatePool().  The caller is responsible\r
+  for freeing the allocated buffer using FreePool().\r
+\r
+  If HiiHandle is NULL, then ASSERT().\r
+  If StringId is 0, then ASSET.\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  Language          The specified configure language to get string.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+CHAR8 *\r
+HiiGetRedfishAsciiString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN CHAR8           *Language,\r
+  IN EFI_STRING_ID   StringId\r
+  )\r
+{\r
+  EFI_STRING  HiiString;\r
+  UINTN       StringSize;\r
+  CHAR8       *AsciiString;\r
+\r
+  HiiString = HiiGetRedfishString (HiiHandle, Language, StringId);\r
+  if (HiiString == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: Can not find string ID: 0x%x with %a\n", __func__, StringId, Language));\r
+    return NULL;\r
+  }\r
+\r
+  StringSize  = (StrLen (HiiString) + 1) * sizeof (CHAR8);\r
+  AsciiString = AllocatePool (StringSize);\r
+  if (AsciiString == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  UnicodeStrToAsciiStrS (HiiString, AsciiString, StringSize);\r
+\r
+  FreePool (HiiString);\r
+  return AsciiString;\r
+}\r
+\r
+/**\r
+  Get string from HII database in English language. The returned string is allocated\r
+  using AllocatePool(). The caller is responsible for freeing the allocated buffer using\r
+  FreePool().\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+EFI_STRING\r
+HiiGetEnglishString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_STRING_ID   StringId\r
+  )\r
+{\r
+  return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId);\r
+}\r
+\r
+/**\r
+  Get ASCII string from HII database in English language. The returned string is allocated\r
+  using AllocatePool(). The caller is responsible for freeing the allocated buffer using\r
+  FreePool().\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+CHAR8 *\r
+HiiGetEnglishAsciiString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_STRING_ID   StringId\r
+  )\r
+{\r
+  EFI_STRING  HiiString;\r
+  UINTN       StringSize;\r
+  CHAR8       *AsciiString;\r
+\r
+  HiiString = HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId);\r
+  if (HiiString == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: Can not find string ID: 0x%x with %a\n", __func__, StringId, ENGLISH_LANGUAGE_CODE));\r
+    return NULL;\r
+  }\r
+\r
+  StringSize  = (StrLen (HiiString) + 1) * sizeof (CHAR8);\r
+  AsciiString = AllocatePool (StringSize);\r
+  if (AsciiString == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  UnicodeStrToAsciiStrS (HiiString, AsciiString, StringSize);\r
+\r
+  FreePool (HiiString);\r
+  return AsciiString;\r
+}\r
+\r
+/**\r
+  Check and see if this is supported schema or not.\r
+\r
+  @param[in]  SupportedSchema   The list of supported schema.\r
+  @param[in]  Schema            Schema string to be checked.\r
+\r
+  @retval BOOLEAN               TRUE if this is supported schema. FALSE otherwise.\r
+\r
+**/\r
+BOOLEAN\r
+CheckSupportedSchema (\r
+  IN REDFISH_PLATFORM_CONFIG_SCHEMA  *SupportedSchema,\r
+  IN CHAR8                           *Schema\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  if ((SupportedSchema == NULL) || IS_EMPTY_STRING (Schema)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (SupportedSchema->Count == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  for (Index = 0; Index < SupportedSchema->Count; Index++) {\r
+    if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Get the list of supported schema from the given HII handle.\r
+\r
+  @param[in]  HiiHandle         HII handle instance.\r
+  @param[out] SupportedSchema   Supported schema on this HII handle.\r
+\r
+  @retval EFI_SUCCESS           Schema list is returned.\r
+  @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema is NULL.\r
+  @retval EFI_NOT_FOUND         No supported schema found.\r
+  @retval EFI_OUT_OF_RESOURCES  System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetSupportedSchema (\r
+  IN  EFI_HII_HANDLE                  HiiHandle,\r
+  OUT REDFISH_PLATFORM_CONFIG_SCHEMA  *SupportedSchema\r
+  )\r
+{\r
+  CHAR8  *SupportedLanguages;\r
+  UINTN  Index;\r
+  UINTN  LangIndex;\r
+  UINTN  Count;\r
+  UINTN  StrSize;\r
+  UINTN  ListIndex;\r
+\r
+  if ((HiiHandle == NULL) || (SupportedSchema == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SupportedSchema->Count = 0;\r
+\r
+  SupportedLanguages = HiiGetSupportedLanguages (HiiHandle);\r
+  if (SupportedLanguages == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Index     = 0;\r
+  LangIndex = 0;\r
+  Count     = 0;\r
+  while (TRUE) {\r
+    if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] == '\0')) {\r
+      if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {\r
+        ++Count;\r
+      }\r
+\r
+      LangIndex = Index + 1;\r
+    }\r
+\r
+    if (SupportedLanguages[Index] == '\0') {\r
+      break;\r
+    }\r
+\r
+    ++Index;\r
+  }\r
+\r
+  if (Count == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  SupportedSchema->Count      = Count;\r
+  SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count);\r
+  if (SupportedSchema->SchemaList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Index     = 0;\r
+  LangIndex = 0;\r
+  ListIndex = 0;\r
+  while (TRUE) {\r
+    if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] == '\0')) {\r
+      if (AsciiStrnCmp (&SupportedLanguages[LangIndex], X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {\r
+        StrSize                                         = Index - LangIndex;\r
+        SupportedSchema->SchemaList[ListIndex]          = AllocateCopyPool ((StrSize + 1), &SupportedLanguages[LangIndex]);\r
+        SupportedSchema->SchemaList[ListIndex][StrSize] = '\0';\r
+        ++ListIndex;\r
+      }\r
+\r
+      LangIndex = Index + 1;\r
+    }\r
+\r
+    if (SupportedLanguages[Index] == '\0') {\r
+      break;\r
+    }\r
+\r
+    ++Index;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Search and find statement private instance by given regular expression pattern\r
+  which describes the Configure Language.\r
+\r
+  @param[in]  RegularExpressionProtocol   Regular express protocol.\r
+  @param[in]  FormsetList                 Form-set list to search.\r
+  @param[in]  Schema                      Schema to be matched.\r
+  @param[in]  Pattern                     Regular expression pattern.\r
+  @param[out] StatementList               Statement list that match above pattern.\r
+\r
+  @retval EFI_SUCCESS             Statement list is returned.\r
+  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.\r
+  @retval EFI_NOT_READY           Regular express protocol is NULL.\r
+  @retval EFI_NOT_FOUND           No statement is found.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetStatementPrivateByConfigureLangRegex (\r
+  IN  EFI_REGULAR_EXPRESSION_PROTOCOL                 *RegularExpressionProtocol,\r
+  IN  LIST_ENTRY                                      *FormsetList,\r
+  IN  CHAR8                                           *Schema,\r
+  IN  EFI_STRING                                      Pattern,\r
+  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList\r
+  )\r
+{\r
+  LIST_ENTRY                                     *HiiFormsetLink;\r
+  LIST_ENTRY                                     *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE       *HiiFormsetPrivate;\r
+  LIST_ENTRY                                     *HiiFormLink;\r
+  LIST_ENTRY                                     *HiiNextFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE           *HiiFormPrivate;\r
+  LIST_ENTRY                                     *HiiStatementLink;\r
+  LIST_ENTRY                                     *HiiNextStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE      *HiiStatementPrivate;\r
+  EFI_STRING                                     TmpString;\r
+  UINTN                                          CaptureCount;\r
+  BOOLEAN                                        IsMatch;\r
+  EFI_STATUS                                     Status;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF  *StatementRef;\r
+\r
+  if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Pattern) || (StatementList == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (RegularExpressionProtocol == NULL) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  StatementList->Count = 0;\r
+  InitializeListHead (&StatementList->StatementList);\r
+\r
+  if (IsListEmpty (FormsetList)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  HiiFormsetLink = GetFirstNode (FormsetList);\r
+  while (!IsNull (FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    //\r
+    // Performance check.\r
+    // If there is no desired Redfish schema found, skip this formset.\r
+    //\r
+    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {\r
+      HiiFormsetLink = HiiFormsetNextLink;\r
+      continue;\r
+    }\r
+\r
+    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);\r
+    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {\r
+      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);\r
+      HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);\r
+\r
+      HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);\r
+      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {\r
+        HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);\r
+        HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);\r
+\r
+        if ((HiiStatementPrivate->Description != 0) && !HiiStatementPrivate->Suppressed) {\r
+          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description);\r
+          if (TmpString != NULL) {\r
+            Status = RegularExpressionProtocol->MatchString (\r
+                                                  RegularExpressionProtocol,\r
+                                                  TmpString,\r
+                                                  Pattern,\r
+                                                  &gEfiRegexSyntaxTypePerlGuid,\r
+                                                  &IsMatch,\r
+                                                  NULL,\r
+                                                  &CaptureCount\r
+                                                  );\r
+            if (EFI_ERROR (Status)) {\r
+              DEBUG ((DEBUG_ERROR, "%a: MatchString \"%s\" failed: %r\n", __func__, Pattern, Status));\r
+              ASSERT (FALSE);\r
+              return Status;\r
+            }\r
+\r
+            //\r
+            // Found\r
+            //\r
+            if (IsMatch) {\r
+              StatementRef = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF));\r
+              if (StatementRef == NULL) {\r
+                return EFI_OUT_OF_RESOURCES;\r
+              }\r
+\r
+              StatementRef->Statement = HiiStatementPrivate;\r
+              InsertTailList (&StatementList->StatementList, &StatementRef->Link);\r
+              ++StatementList->Count;\r
+            }\r
+\r
+            FreePool (TmpString);\r
+          }\r
+        }\r
+\r
+        HiiStatementLink = HiiNextStatementLink;\r
+      }\r
+\r
+      HiiFormLink = HiiNextFormLink;\r
+    }\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get statement private instance by the given configure language.\r
+\r
+  @param[in]  FormsetList                 Form-set list to search.\r
+  @param[in]  Schema                      Schema to be matched.\r
+  @param[in]  ConfigureLang               Configure language.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer to statement private instance.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *\r
+GetStatementPrivateByConfigureLang (\r
+  IN  LIST_ENTRY  *FormsetList,\r
+  IN  CHAR8       *Schema,\r
+  IN  EFI_STRING  ConfigureLang\r
+  )\r
+{\r
+  LIST_ENTRY                                 *HiiFormsetLink;\r
+  LIST_ENTRY                                 *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE   *HiiFormsetPrivate;\r
+  LIST_ENTRY                                 *HiiFormLink;\r
+  LIST_ENTRY                                 *HiiNextFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;\r
+  LIST_ENTRY                                 *HiiStatementLink;\r
+  LIST_ENTRY                                 *HiiNextStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;\r
+  EFI_STRING                                 TmpString;\r
+\r
+  if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (ConfigureLang)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (IsListEmpty (FormsetList)) {\r
+    return NULL;\r
+  }\r
+\r
+  HiiFormsetLink = GetFirstNode (FormsetList);\r
+  while (!IsNull (FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    //\r
+    // Performance check.\r
+    // If there is no desired Redfish schema found, skip this formset.\r
+    //\r
+    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema, Schema)) {\r
+      HiiFormsetLink = HiiFormsetNextLink;\r
+      continue;\r
+    }\r
+\r
+    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);\r
+    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {\r
+      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList, HiiFormLink);\r
+      HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);\r
+\r
+      HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);\r
+      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {\r
+        HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);\r
+        HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);\r
+\r
+        DEBUG_CODE (\r
+          STATIC UINTN Index = 0;\r
+          DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: [%d] search %s in QID: 0x%x form: 0x%x formset: %g\n", __func__, ++Index, ConfigureLang, HiiStatementPrivate->QuestionId, HiiFormPrivate->Id, &HiiFormsetPrivate->Guid));\r
+          );\r
+\r
+        if (HiiStatementPrivate->Description != 0) {\r
+          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, Schema, HiiStatementPrivate->Description);\r
+          if (TmpString != NULL) {\r
+            if (StrCmp (TmpString, ConfigureLang) == 0) {\r
+              FreePool (TmpString);\r
+              return HiiStatementPrivate;\r
+            }\r
+\r
+            FreePool (TmpString);\r
+          }\r
+        }\r
+\r
+        HiiStatementLink = HiiNextStatementLink;\r
+      }\r
+\r
+      HiiFormLink = HiiNextFormLink;\r
+    }\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get form-set private instance by the given HII handle.\r
+\r
+  @param[in]  HiiHandle       HII handle instance.\r
+  @param[in]  FormsetList     Form-set list to search.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to form-set private instance.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *\r
+GetFormsetPrivateByHiiHandle (\r
+  IN  EFI_HII_HANDLE  HiiHandle,\r
+  IN  LIST_ENTRY      *FormsetList\r
+  )\r
+{\r
+  LIST_ENTRY                                *HiiFormsetLink;\r
+  LIST_ENTRY                                *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;\r
+\r
+  if ((HiiHandle == NULL) || (FormsetList == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (IsListEmpty (FormsetList)) {\r
+    return NULL;\r
+  }\r
+\r
+  HiiFormsetLink = GetFirstNode (FormsetList);\r
+  while (!IsNull (FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    if (HiiFormsetPrivate->HiiHandle == HiiHandle) {\r
+      return HiiFormsetPrivate;\r
+    }\r
+\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Release formset and all the forms and statements that belong to this formset.\r
+\r
+  @param[in]      FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE\r
+\r
+  @retval         EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseFormset (\r
+  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate\r
+  )\r
+{\r
+  LIST_ENTRY                                 *HiiFormLink;\r
+  LIST_ENTRY                                 *HiiNextFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;\r
+  LIST_ENTRY                                 *HiiStatementLink;\r
+  LIST_ENTRY                                 *HiiNextStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;\r
+  UINTN                                      Index;\r
+\r
+  if (FormsetPrivate == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);\r
+  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {\r
+    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK (HiiFormLink);\r
+    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList, HiiFormLink);\r
+\r
+    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);\r
+    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {\r
+      HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);\r
+      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList, HiiStatementLink);\r
+\r
+      //\r
+      // HiiStatementPrivate->HiiStatement will be released in DestroyFormSet().\r
+      //\r
+\r
+      if (HiiStatementPrivate->DesStringCache != NULL) {\r
+        FreePool (HiiStatementPrivate->DesStringCache);\r
+        HiiStatementPrivate->DesStringCache = NULL;\r
+      }\r
+\r
+      RemoveEntryList (&HiiStatementPrivate->Link);\r
+      FreePool (HiiStatementPrivate);\r
+      HiiStatementLink = HiiNextStatementLink;\r
+    }\r
+\r
+    //\r
+    // HiiStatementPrivate->HiiForm will be released in DestroyFormSet().\r
+    //\r
+\r
+    RemoveEntryList (&HiiFormPrivate->Link);\r
+    FreePool (HiiFormPrivate);\r
+    HiiFormLink = HiiNextFormLink;\r
+  }\r
+\r
+  if (FormsetPrivate->HiiFormSet != NULL) {\r
+    DestroyFormSet (FormsetPrivate->HiiFormSet);\r
+    FormsetPrivate->HiiFormSet = NULL;\r
+  }\r
+\r
+  if (FormsetPrivate->DevicePathStr != NULL) {\r
+    FreePool (FormsetPrivate->DevicePathStr);\r
+  }\r
+\r
+  //\r
+  // Release schema list\r
+  //\r
+  if (FormsetPrivate->SupportedSchema.SchemaList != NULL) {\r
+    for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count; Index++) {\r
+      FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]);\r
+    }\r
+\r
+    FreePool (FormsetPrivate->SupportedSchema.SchemaList);\r
+    FormsetPrivate->SupportedSchema.SchemaList = NULL;\r
+    FormsetPrivate->SupportedSchema.Count      = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create new form-set instance.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to newly created form-set private instance.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *\r
+NewFormsetPrivate (\r
+  VOID\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *NewFormsetPrivate;\r
+\r
+  NewFormsetPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE));\r
+  if (NewFormsetPrivate == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Initial newly created formset private data.\r
+  //\r
+  InitializeListHead (&NewFormsetPrivate->HiiFormList);\r
+\r
+  return NewFormsetPrivate;\r
+}\r
+\r
+/**\r
+  Load the HII formset from the given HII handle.\r
+\r
+  @param[in]  HiiHandle       Target HII handle to load.\r
+  @param[out] FormsetPrivate  The formset private data.\r
+\r
+  @retval EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormset (\r
+  IN  EFI_HII_HANDLE                            HiiHandle,\r
+  OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate\r
+  )\r
+{\r
+  EFI_STATUS                                 Status;\r
+  HII_FORMSET                                *HiiFormSet;\r
+  HII_FORM                                   *HiiForm;\r
+  LIST_ENTRY                                 *HiiFormLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;\r
+  HII_STATEMENT                              *HiiStatement;\r
+  LIST_ENTRY                                 *HiiStatementLink;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;\r
+  EFI_GUID                                   ZeroGuid;\r
+  EXPRESS_RESULT                             ExpressionResult;\r
+\r
+  if ((HiiHandle == NULL) || (FormsetPrivate == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET));\r
+  if (HiiFormSet == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Find HII formset by the given HII handle.\r
+  //\r
+  ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
+  Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet);\r
+  if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto ErrorExit;\r
+  }\r
+\r
+  //\r
+  // Initialize formset\r
+  //\r
+  InitializeFormSet (HiiFormSet);\r
+\r
+  //\r
+  // Initialize formset private data.\r
+  //\r
+  FormsetPrivate->HiiFormSet = HiiFormSet;\r
+  FormsetPrivate->HiiHandle  = HiiHandle;\r
+  CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid);\r
+  FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet->DevicePath, FALSE, FALSE);\r
+  Status                        = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: No schema from HII handle: 0x%x found: %r\n", __func__, FormsetPrivate->HiiHandle, Status));\r
+  }\r
+\r
+  HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead);\r
+  while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) {\r
+    HiiForm = HII_FORM_FROM_LINK (HiiFormLink);\r
+\r
+    HiiFormPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE));\r
+    if (HiiFormPrivate == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ErrorExit;\r
+    }\r
+\r
+    //\r
+    // Initialize form private data.\r
+    //\r
+    HiiFormPrivate->HiiForm       = HiiForm;\r
+    HiiFormPrivate->Id            = HiiForm->FormId;\r
+    HiiFormPrivate->Title         = HiiForm->FormTitle;\r
+    HiiFormPrivate->ParentFormset = FormsetPrivate;\r
+    HiiFormPrivate->Suppressed    = FALSE;\r
+    InitializeListHead (&HiiFormPrivate->StatementList);\r
+\r
+    if ((HiiForm->SuppressExpression != NULL) &&\r
+        (EvaluateExpressionList (HiiForm->SuppressExpression, TRUE, HiiFormSet, HiiForm) == ExpressSuppress))\r
+    {\r
+      HiiFormPrivate->Suppressed = TRUE;\r
+    }\r
+\r
+    HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead);\r
+    while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) {\r
+      HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink);\r
+\r
+      HiiStatementPrivate = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE));\r
+      if (HiiStatementPrivate == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto ErrorExit;\r
+      }\r
+\r
+      //\r
+      // Initialize statement private data.\r
+      //\r
+      HiiStatementPrivate->HiiStatement             = HiiStatement;\r
+      HiiStatementPrivate->QuestionId               = HiiStatement->QuestionId;\r
+      HiiStatementPrivate->Description              = HiiStatement->Prompt;\r
+      HiiStatementPrivate->Help                     = HiiStatement->Help;\r
+      HiiStatementPrivate->ParentForm               = HiiFormPrivate;\r
+      HiiStatementPrivate->Flags                    = HiiStatement->QuestionFlags;\r
+      HiiStatementPrivate->StatementData.NumMaximum = HiiStatement->ExtraData.NumData.Maximum;\r
+      HiiStatementPrivate->StatementData.NumMinimum = HiiStatement->ExtraData.NumData.Minimum;\r
+      HiiStatementPrivate->StatementData.NumStep    = HiiStatement->ExtraData.NumData.Step;\r
+      HiiStatementPrivate->StatementData.StrMaxSize = HiiStatement->ExtraData.StrData.MaxSize;\r
+      HiiStatementPrivate->StatementData.StrMinSize = HiiStatement->ExtraData.StrData.MinSize;\r
+      HiiStatementPrivate->Suppressed               = FALSE;\r
+      HiiStatementPrivate->GrayedOut                = FALSE;\r
+\r
+      //\r
+      // Expression\r
+      //\r
+      if (HiiFormPrivate->Suppressed) {\r
+        HiiStatementPrivate->Suppressed = TRUE;\r
+      } else {\r
+        if (HiiStatement->ExpressionList != NULL) {\r
+          ExpressionResult =  EvaluateExpressionList (HiiStatement->ExpressionList, TRUE, HiiFormSet, HiiForm);\r
+          if (ExpressionResult == ExpressGrayOut) {\r
+            HiiStatementPrivate->GrayedOut = TRUE;\r
+          } else if (ExpressionResult == ExpressSuppress) {\r
+            HiiStatementPrivate->Suppressed = TRUE;\r
+          }\r
+        }\r
+      }\r
+\r
+      //\r
+      // Attach to statement list.\r
+      //\r
+      InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link);\r
+      HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink);\r
+    }\r
+\r
+    //\r
+    // Attach to form list.\r
+    //\r
+    InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link);\r
+    HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ErrorExit:\r
+\r
+  //\r
+  // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet.\r
+  //\r
+  if ((HiiFormSet != NULL) && (FormsetPrivate->HiiFormSet != HiiFormSet)) {\r
+    DestroyFormSet (HiiFormSet);\r
+  }\r
+\r
+  //\r
+  // Release resource when error happens.\r
+  //\r
+  ReleaseFormset (FormsetPrivate);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Load formset list on given HII handle.\r
+\r
+  @param[in]  HiiHandle     HII handle to load formset list.\r
+  @param[out] FormsetList   Pointer to formset list returned on given handle.\r
+\r
+  @retval     EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormsetList (\r
+  IN   EFI_HII_HANDLE  *HiiHandle,\r
+  OUT  LIST_ENTRY      *FormsetList\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;\r
+\r
+  if ((HiiHandle == NULL) || (FormsetList == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList);\r
+  if (FormsetPrivate != NULL) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  FormsetPrivate =  NewFormsetPrivate ();\r
+  if (FormsetPrivate == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Load formset on the given HII handle.\r
+  //\r
+  Status = LoadFormset (HiiHandle, FormsetPrivate);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to load formset: %r\n", __func__, Status));\r
+    FreePool (FormsetPrivate);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Attach to cache list.\r
+  //\r
+  InsertTailList (FormsetList, &FormsetPrivate->Link);\r
+\r
+  DEBUG_CODE (\r
+    DumpFormsetList (FormsetList);\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Release formset list and all the forms that belong to this formset.\r
+\r
+  @param[in]      FormsetList   Pointer to formset list that needs to be\r
+                                released.\r
+\r
+  @retval         EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseFormsetList (\r
+  IN  LIST_ENTRY  *FormsetList\r
+  )\r
+{\r
+  LIST_ENTRY                                *HiiFormsetLink;\r
+  LIST_ENTRY                                *HiiFormsetNextLink;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;\r
+\r
+  if (FormsetList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IsListEmpty (FormsetList)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  HiiFormsetLink = GetFirstNode (FormsetList);\r
+  while (!IsNull (FormsetList, HiiFormsetLink)) {\r
+    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);\r
+    HiiFormsetPrivate  = REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);\r
+\r
+    //\r
+    // Detach from list.\r
+    //\r
+    RemoveEntryList (&HiiFormsetPrivate->Link);\r
+    ReleaseFormset (HiiFormsetPrivate);\r
+    FreePool (HiiFormsetPrivate);\r
+    HiiFormsetLink = HiiFormsetNextLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Get all pending list.\r
+\r
+  @param[in]  HiiHandle   HII handle instance.\r
+  @param[in]  PendingList Pending list to keep pending data.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST *   Pointer to pending list data.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_PENDING_LIST *\r
+GetPendingList (\r
+  IN  EFI_HII_HANDLE  *HiiHandle,\r
+  IN  LIST_ENTRY      *PendingList\r
+  )\r
+{\r
+  LIST_ENTRY                            *PendingListLink;\r
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *Target;\r
+\r
+  if ((HiiHandle == NULL) || (PendingList == NULL)) {\r
+    return NULL;\r
+  }\r
+\r
+  if (IsListEmpty (PendingList)) {\r
+    return NULL;\r
+  }\r
+\r
+  PendingListLink = GetFirstNode (PendingList);\r
+  while (!IsNull (PendingList, PendingListLink)) {\r
+    Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);\r
+\r
+    if (Target->HiiHandle == HiiHandle) {\r
+      return Target;\r
+    }\r
+\r
+    PendingListLink = GetNextNode (PendingList, PendingListLink);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  When HII database is updated. Keep updated HII handle into pending list so\r
+  we can process them later.\r
+\r
+  @param[in]  HiiHandle   HII handle instance.\r
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyFormsetUpdate (\r
+  IN  EFI_HII_HANDLE  *HiiHandle,\r
+  IN  LIST_ENTRY      *PendingList\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;\r
+\r
+  if ((HiiHandle == NULL) || (PendingList == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check and see if this HII handle is processed already.\r
+  //\r
+  TargetPendingList = GetPendingList (HiiHandle, PendingList);\r
+  if (TargetPendingList != NULL) {\r
+    TargetPendingList->IsDeleted = FALSE;\r
+    DEBUG_CODE (\r
+      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: HII handle: 0x%x is updated\n", __func__, HiiHandle));\r
+      );\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TargetPendingList = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));\r
+  if (TargetPendingList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TargetPendingList->HiiHandle = HiiHandle;\r
+  TargetPendingList->IsDeleted = FALSE;\r
+\r
+  InsertTailList (PendingList, &TargetPendingList->Link);\r
+\r
+  DEBUG_CODE (\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: HII handle: 0x%x is created\n", __func__, HiiHandle));\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so\r
+  we can process them later.\r
+\r
+  @param[in]  HiiHandle   HII handle instance.\r
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyFormsetDeleted (\r
+  IN  EFI_HII_HANDLE  *HiiHandle,\r
+  IN  LIST_ENTRY      *PendingList\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;\r
+\r
+  if ((HiiHandle == NULL) || (PendingList == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check and see if this HII handle is processed already.\r
+  //\r
+  TargetPendingList = GetPendingList (HiiHandle, PendingList);\r
+  if (TargetPendingList != NULL) {\r
+    TargetPendingList->IsDeleted = TRUE;\r
+    DEBUG_CODE (\r
+      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: HII handle: 0x%x is updated and deleted\n", __func__, HiiHandle));\r
+      );\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  TargetPendingList = AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PENDING_LIST));\r
+  if (TargetPendingList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TargetPendingList->HiiHandle = HiiHandle;\r
+  TargetPendingList->IsDeleted = TRUE;\r
+\r
+  InsertTailList (PendingList, &TargetPendingList->Link);\r
+\r
+  DEBUG_CODE (\r
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: HII handle: 0x%x is deleted\n", __func__, HiiHandle));\r
+    );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  There are HII database update and we need to process them accordingly so that we\r
+  won't use stale data. This function will parse updated HII handle again in order\r
+  to get updated data-set.\r
+\r
+  @param[in]  FormsetList   List to keep HII form-set.\r
+  @param[in]  PendingList   List to keep HII handle that is updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessPendingList (\r
+  IN  LIST_ENTRY  *FormsetList,\r
+  IN  LIST_ENTRY  *PendingList\r
+  )\r
+{\r
+  LIST_ENTRY                                *PendingListLink;\r
+  LIST_ENTRY                                *PendingListNextLink;\r
+  REDFISH_PLATFORM_CONFIG_PENDING_LIST      *Target;\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;\r
+  EFI_STATUS                                Status;\r
+\r
+  if ((FormsetList == NULL) || (PendingList == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IsListEmpty (PendingList)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  PendingListLink = GetFirstNode (PendingList);\r
+  while (!IsNull (PendingList, PendingListLink)) {\r
+    PendingListNextLink = GetNextNode (PendingList, PendingListLink);\r
+    Target              = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK (PendingListLink);\r
+\r
+    if (Target->IsDeleted) {\r
+      //\r
+      // The HII resource on this HII handle is removed. Release the formset.\r
+      //\r
+      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);\r
+      if (FormsetPrivate != NULL) {\r
+        DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: formset: %g is removed because driver release HII resource it already\n", __func__, FormsetPrivate->Guid));\r
+        RemoveEntryList (&FormsetPrivate->Link);\r
+        ReleaseFormset (FormsetPrivate);\r
+        FreePool (FormsetPrivate);\r
+      } else {\r
+        DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: formset on HII handle 0x%x was removed already\n", __func__, Target->HiiHandle));\r
+      }\r
+    } else {\r
+      //\r
+      // The HII resource on this HII handle is updated/removed.\r
+      //\r
+      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle, FormsetList);\r
+      if (FormsetPrivate != NULL) {\r
+        //\r
+        // HII formset already exist, release it and query again.\r
+        //\r
+        DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: formset: %g is updated. Release current formset\n", __func__, &FormsetPrivate->Guid));\r
+        RemoveEntryList (&FormsetPrivate->Link);\r
+        ReleaseFormset (FormsetPrivate);\r
+        FreePool (FormsetPrivate);\r
+      }\r
+\r
+      Status = LoadFormsetList (Target->HiiHandle, FormsetList);\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_ERROR, "%a: load formset from HII handle: 0x%x failed: %r\n", __func__, Target->HiiHandle, Status));\r
+      }\r
+    }\r
+\r
+    //\r
+    // Detach it from list first.\r
+    //\r
+    RemoveEntryList (&Target->Link);\r
+    FreePool (Target);\r
+\r
+    PendingListLink = PendingListNextLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Release all resource in statement list.\r
+\r
+  @param[in]  StatementList   Statement list to be released.\r
+\r
+  @retval EFI_SUCCESS             All resource are released.\r
+  @retval EFI_INVALID_PARAMETER   StatementList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseStatementList (\r
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList\r
+  )\r
+{\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF  *StatementRef;\r
+  LIST_ENTRY                                     *NextLink;\r
+\r
+  if (StatementList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IsListEmpty (&StatementList->StatementList)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  NextLink = GetFirstNode (&StatementList->StatementList);\r
+  while (!IsNull (&StatementList->StatementList, NextLink)) {\r
+    StatementRef = REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);\r
+    NextLink     = GetNextNode (&StatementList->StatementList, NextLink);\r
+\r
+    RemoveEntryList (&StatementRef->Link);\r
+    FreePool (StatementRef);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
new file mode 100644 (file)
index 0000000..9ef0327
--- /dev/null
@@ -0,0 +1,334 @@
+/** @file\r
+  This file defines the EDKII Redfish Platform Config Protocol private structure.\r
+\r
+  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#ifndef EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_\r
+#define EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_\r
+\r
+#include <Uefi.h>\r
+\r
+//\r
+// Libraries\r
+//\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/HiiUtilityLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#define IS_EMPTY_STRING(a)  (a == NULL || a[0] == L'\0')\r
+#define ENGLISH_LANGUAGE_CODE  "en-US"\r
+#define X_UEFI_SCHEMA_PREFIX   "x-uefi-redfish-"\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.\r
+//\r
+typedef struct {\r
+  LIST_ENTRY        Link;\r
+  EFI_HII_HANDLE    HiiHandle;\r
+  BOOLEAN           IsDeleted;\r
+} REDFISH_PLATFORM_CONFIG_PENDING_LIST;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_PENDING_LIST, Link)\r
+\r
+typedef struct {\r
+  UINTN    Count;                               // Number of schema in list\r
+  CHAR8    **SchemaList;                        // Schema list\r
+} REDFISH_PLATFORM_CONFIG_SCHEMA;\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE\r
+//\r
+typedef struct {\r
+  LIST_ENTRY                        Link;\r
+  HII_FORMSET                       *HiiFormSet;     // Pointer to HII formset data.\r
+  EFI_GUID                          Guid;            // Formset GUID.\r
+  EFI_HII_HANDLE                    HiiHandle;       // Hii Handle of this formset.\r
+  LIST_ENTRY                        HiiFormList;     // Form list that keep form data under this formset.\r
+  CHAR16                            *DevicePathStr;  // Device path of this formset.\r
+  REDFISH_PLATFORM_CONFIG_SCHEMA    SupportedSchema; // Schema that is supported in this formset.\r
+} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_FORM_PRIVATE\r
+//\r
+typedef struct {\r
+  LIST_ENTRY                                  Link;\r
+  UINT16                                      Id;           // Form ID.\r
+  EFI_STRING_ID                               Title;        // String token of form title.\r
+  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE    *ParentFormset;\r
+  HII_FORM                                    *HiiForm;      // Pointer to HII form data.\r
+  LIST_ENTRY                                  StatementList; // Statement list that keep statement under this form.\r
+  BOOLEAN                                     Suppressed;    // Form is suppressed\r
+} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_PRIVATE, Link)\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_DATA\r
+//\r
+typedef struct {\r
+  UINT64    NumMinimum;\r
+  UINT64    NumMaximum;\r
+  UINT64    NumStep;\r
+  UINT8     StrMinSize;\r
+  UINT8     StrMaxSize;\r
+} REDFISH_PLATFORM_CONFIG_STATEMENT_DATA;\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE\r
+//\r
+typedef struct {\r
+  LIST_ENTRY                                Link;\r
+  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *ParentForm;\r
+  HII_STATEMENT                             *HiiStatement;  // Pointer to HII statement data.\r
+  EFI_QUESTION_ID                           QuestionId;     // Question ID of this statement.\r
+  EFI_STRING_ID                             Description;    // String token of this question.\r
+  EFI_STRING_ID                             Help;           // String token of help message.\r
+  EFI_STRING                                DesStringCache; // The string cache for search function.\r
+  UINT8                                     Flags;          // The statement flag.\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_DATA    StatementData;  // The max/min for statement value.\r
+  BOOLEAN                                   Suppressed;     // Statement is suppressed.\r
+  BOOLEAN                                   GrayedOut;      // Statement is GrayedOut.\r
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link)\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF\r
+//\r
+typedef struct {\r
+  LIST_ENTRY                                   Link;\r
+  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE    *Statement;\r
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF;\r
+\r
+#define REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK(a)  BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link)\r
+\r
+//\r
+// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST\r
+//\r
+typedef struct {\r
+  LIST_ENTRY    StatementList;      // List of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF\r
+  UINTN         Count;\r
+} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST;\r
+\r
+/**\r
+  Release formset list and all the forms that belong to this formset.\r
+\r
+  @param[in]      FormsetList   Pointer to formset list that needs to be\r
+                                released.\r
+\r
+  @retval         EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseFormsetList (\r
+  IN  LIST_ENTRY  *FormsetList\r
+  );\r
+\r
+/**\r
+  Release formset list and all the forms that belong to this formset.\r
+\r
+  @param[in]      FormsetList   Pointer to formset list that needs to be\r
+                                released.\r
+\r
+  @retval         EFI_STATUS\r
+\r
+**/\r
+EFI_STATUS\r
+LoadFormsetList (\r
+  IN   EFI_HII_HANDLE  *HiiHandle,\r
+  OUT  LIST_ENTRY      *FormsetList\r
+  );\r
+\r
+/**\r
+  When HII database is updated. Keep updated HII handle into pending list so\r
+  we can process them later.\r
+\r
+  @param[in]  HiiHandle   HII handle instance.\r
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyFormsetUpdate (\r
+  IN  EFI_HII_HANDLE  *HiiHandle,\r
+  IN  LIST_ENTRY      *PendingList\r
+  );\r
+\r
+/**\r
+  When HII database is updated and form-set is deleted. Keep deleted HII handle into pending list so\r
+  we can process them later.\r
+\r
+  @param[in]  HiiHandle   HII handle instance.\r
+  @param[in]  PendingList Pending list to keep HII handle which is recently updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+NotifyFormsetDeleted (\r
+  IN  EFI_HII_HANDLE  *HiiHandle,\r
+  IN  LIST_ENTRY      *PendingList\r
+  );\r
+\r
+/**\r
+  Get statement private instance by the given configure language.\r
+\r
+  @param[in]  FormsetList                 Form-set list to search.\r
+  @param[in]  Schema                      Schema to be matched.\r
+  @param[in]  ConfigureLang               Configure language.\r
+\r
+  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer to statement private instance.\r
+\r
+**/\r
+REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *\r
+GetStatementPrivateByConfigureLang (\r
+  IN  LIST_ENTRY  *FormsetList,\r
+  IN  CHAR8       *Schema,\r
+  IN  EFI_STRING  ConfigureLang\r
+  );\r
+\r
+/**\r
+  Search and find statement private instance by given regular expression pattern\r
+  which describes the Configure Language.\r
+\r
+  @param[in]  RegularExpressionProtocol   Regular express protocol.\r
+  @param[in]  FormsetList                 Form-set list to search.\r
+  @param[in]  Schema                      Schema to be matched.\r
+  @param[in]  Pattern                     Regular expression pattern.\r
+  @param[out] StatementList               Statement list that match above pattern.\r
+\r
+  @retval EFI_SUCCESS             Statement list is returned.\r
+  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.\r
+  @retval EFI_NOT_READY           Regular express protocol is NULL.\r
+  @retval EFI_NOT_FOUND           No statement is found.\r
+  @retval EFI_OUT_OF_RESOURCES    System is out of memory.\r
+\r
+**/\r
+EFI_STATUS\r
+GetStatementPrivateByConfigureLangRegex (\r
+  IN  EFI_REGULAR_EXPRESSION_PROTOCOL                 *RegularExpressionProtocol,\r
+  IN  LIST_ENTRY                                      *FormsetList,\r
+  IN  CHAR8                                           *Schema,\r
+  IN  EFI_STRING                                      Pattern,\r
+  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList\r
+  );\r
+\r
+/**\r
+  There are HII database update and we need to process them accordingly so that we\r
+  won't use stale data. This function will parse updated HII handle again in order\r
+  to get updated data-set.\r
+\r
+  @param[in]  FormsetList   List to keep HII form-set.\r
+  @param[in]  PendingList   List to keep HII handle that is updated.\r
+\r
+  @retval EFI_SUCCESS             HII handle is saved in pending list.\r
+  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessPendingList (\r
+  IN  LIST_ENTRY  *FormsetList,\r
+  IN  LIST_ENTRY  *PendingList\r
+  );\r
+\r
+/**\r
+  Retrieves a unicode string from a string package in a given language. The\r
+  returned string is allocated using AllocatePool().  The caller is responsible\r
+  for freeing the allocated buffer using FreePool().\r
+\r
+  If HiiHandle is NULL, then ASSERT().\r
+  If StringId is 0, then ASSET.\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  Language          The specified configure language to get string.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+EFI_STRING\r
+HiiGetRedfishString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN CHAR8           *Language,\r
+  IN EFI_STRING_ID   StringId\r
+  );\r
+\r
+/**\r
+  Retrieves a ASCII string from a string package in a given language. The\r
+  returned string is allocated using AllocatePool().  The caller is responsible\r
+  for freeing the allocated buffer using FreePool().\r
+\r
+  If HiiHandle is NULL, then ASSERT().\r
+  If StringId is 0, then ASSET.\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  Language          The specified configure language to get string.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+CHAR8 *\r
+HiiGetRedfishAsciiString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN CHAR8           *Language,\r
+  IN EFI_STRING_ID   StringId\r
+  );\r
+\r
+/**\r
+  Get ASCII string from HII database in English language. The returned string is allocated\r
+  using AllocatePool(). The caller is responsible for freeing the allocated buffer using\r
+  FreePool().\r
+\r
+  @param[in]  HiiHandle         A handle that was previously registered in the HII Database.\r
+  @param[in]  StringId          The identifier of the string to retrieved from the string\r
+                                package associated with HiiHandle.\r
+\r
+  @retval NULL   The string specified by StringId is not present in the string package.\r
+  @retval Other  The string was returned.\r
+\r
+**/\r
+CHAR8 *\r
+HiiGetEnglishAsciiString (\r
+  IN EFI_HII_HANDLE  HiiHandle,\r
+  IN EFI_STRING_ID   StringId\r
+  );\r
+\r
+/**\r
+  Release all resource in statement list.\r
+\r
+  @param[in]  StatementList   Statement list to be released.\r
+\r
+  @retval EFI_SUCCESS             All resource are released.\r
+  @retval EFI_INVALID_PARAMETER   StatementList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+ReleaseStatementList (\r
+  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList\r
+  );\r
+\r
+#endif\r