[edk2-devel] [PATCH 3/5] RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL

Chang, Abner via groups.io abner.chang=amd.com at groups.io
Sun Apr 16 04:08:57 UTC 2023


[AMD Official Use Only - General]



> -----Original Message-----
> From: Nickle Wang <nicklew at nvidia.com>
> Sent: Thursday, April 13, 2023 2:21 PM
> To: devel at edk2.groups.io
> Cc: Chang, Abner <Abner.Chang at amd.com>; Igor Kulchytskyy
> <igork at ami.com>; Nick Ramirez <nramirez at nvidia.com>
> Subject: [PATCH 3/5] RedfishPkg: Implementation of
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> 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 at nvidia.com>
> Cc: Abner Chang <abner.chang at amd.com>
> Cc: Igor Kulchytskyy <igork at ami.com>
> Cc: Nick Ramirez <nramirez at nvidia.com>
> ---
>  .../RedfishPlatformConfigDxe.inf              |   53 +
>  .../RedfishPlatformConfigDxe.h                |   77 +
>  .../RedfishPlatformConfigImpl.h               |  334 +++
>  .../RedfishPlatformConfigDxe.c                | 2495 +++++++++++++++++
>  .../RedfishPlatformConfigImpl.c               | 1364 +++++++++
>  5 files changed, 4323 insertions(+)
>  create mode 100644
> RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
>  create mode 100644
> RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
>  create mode 100644
> RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
>  create mode 100644
> RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
>  create mode 100644
> RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
> 
> diff --git
> a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
> b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
> new file mode 100644
> index 000000000000..eb5872a4f29b
> --- /dev/null
> +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.inf
> @@ -0,0 +1,53 @@
> +## @file
> +#  Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
> interfaces.
> +#
> +#  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
You can add Nvidia copyright if you ever updated this file, otherwise we just keep it as it.

> +#
> +##
> +
> +[Defines]
> +  INF_VERSION               = 0x00010005
> +  BASE_NAME                 = RedfishPlatformConfigDxe
> +  FILE_GUID                 = BEAEFFE1-0633-41B5-913C-9389339C2927
> +  MODULE_TYPE               = DXE_DRIVER
> +  VERSION_STRING            = 1.0
> +  ENTRY_POINT               = RedfishPlatformConfigDxeEntryPoint
> +  UNLOAD_IMAGE              = RedfishPlatformConfigDxeUnload
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  RedfishPkg/RedfishPkg.dec
> +
> +[Sources]
> +  RedfishPlatformConfigDxe.h
> +  RedfishPlatformConfigDxe.c
> +  RedfishPlatformConfigImpl.h
> +  RedfishPlatformConfigImpl.c
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  HiiLib
> +  HiiUtilityLib
> +  MemoryAllocationLib
> +  PrintLib
> +  UefiLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEdkIIRedfishPlatformConfigProtocolGuid ## PRODUCED
> +  gEfiHiiDatabaseProtocolGuid             ## CONSUMED
> +  gEfiHiiStringProtocolGuid               ## CONSUMED
> +  gEfiRegularExpressionProtocolGuid       ## CONSUMED
> +
> +[Guids]
> +  gEfiRegexSyntaxTypePerlGuid             ## CONSUMED
> +
> +[Depex]
> +  TRUE
> diff --git
> a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
> b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
> new file mode 100644
> index 000000000000..b3787134d46e
> --- /dev/null
> +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
> @@ -0,0 +1,77 @@
> +/** @file
> +  This file defines the EDKII Redfish Platform Config Protocol interface.
> +
> +  (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
> +  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_
> +#define EDKII_REDFISH_PLATFORM_CONFIG_DXE_H_
> +
> +#include <Uefi.h>
> +
> +//
> +// Libraries
> +//
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiDriverEntryPoint.h>
> +
> +//
> +// Produced Protocols
> +//
This comment is confusing, it looks to me all of below protocol are produced by this driver. 😊

> +#include <Protocol/EdkIIRedfishPlatformConfig.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/HiiString.h>
> +#include <Protocol/RegularExpressionProtocol.h>
> +
Same for below, let's have a consistent comments for structures.




> +//
> +// Definition of EDKII_REDFISH_PLATFORM_CONFIG_NOTIFY.
> +//
> +typedef struct {
> +  EFI_EVENT    ProtocolEvent;                  // Protocol notification event.
> +  VOID         *Registration;                  // Protocol notification registration.
> +} REDFISH_PLATFORM_CONFIG_NOTIFY;
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.
> +//
> +typedef struct {
> +  EFI_HANDLE                                ImageHandle;                // Driver image handle.
> +  EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL    Protocol;
> +  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiDbNotify;
> +  EFI_HII_DATABASE_PROTOCOL                 *HiiDatabase;               // The HII
> database protocol.
> +  REDFISH_PLATFORM_CONFIG_NOTIFY            HiiStringNotify;
> +  EFI_HII_STRING_PROTOCOL                   *HiiString;                 // HII String
> Protocol.
> +  REDFISH_PLATFORM_CONFIG_NOTIFY            RegexNotify;
> +  EFI_REGULAR_EXPRESSION_PROTOCOL           *RegularExpressionProtocol;
> // Regular Expression Protocol.
> +  EFI_HANDLE                                NotifyHandle;               // The notify handle.
> +  LIST_ENTRY                                FormsetList;                // The list to keep cached
> HII formset.
> +  LIST_ENTRY                                PendingList;                // The list to keep updated
> HII handle.
> +} REDFISH_PLATFORM_CONFIG_PRIVATE;
> +
> +//
> +// Definition of REDFISH_STACK.
> +//
> +typedef struct {
> +  VOID     **Pool;
> +  UINTN    Size;
> +  UINTN    Index;
> +} REDFISH_STACK;
> +
> +#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a)  BASE_CR
> (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol)
> +#define REGULAR_EXPRESSION_INCLUDE_ALL   L".*"
> +#define CONFIGURE_LANGUAGE_PREFIX        "x-uefi-redfish-"
> +#define REDFISH_PLATFORM_CONFIG_VERSION  0x00010000
> +#define REDFISH_PLATFORM_CONFIG_DEBUG    DEBUG_VERBOSE
> +#define REDFISH_MENU_PATH_SIZE           8
> +
> +#endif
> diff --git
> a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
> b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
> new file mode 100644
> index 000000000000..9ef032748663
> --- /dev/null
> +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
> @@ -0,0 +1,334 @@
> +/** @file
> +  This file defines the EDKII Redfish Platform Config Protocol private
> structure.
> +
> +  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> +  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_
> +#define EDKII_REDFISH_PLATFORM_CONFIG_IMPL_H_
> +
> +#include <Uefi.h>
> +
> +//
> +// Libraries
> +//
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HiiUtilityLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#define IS_EMPTY_STRING(a)  (a == NULL || a[0] == L'\0')
> +#define ENGLISH_LANGUAGE_CODE  "en-US"
> +#define X_UEFI_SCHEMA_PREFIX   "x-uefi-redfish-"
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.
> +//
> +typedef struct {
> +  LIST_ENTRY        Link;
> +  EFI_HII_HANDLE    HiiHandle;
> +  BOOLEAN           IsDeleted;
> +} REDFISH_PLATFORM_CONFIG_PENDING_LIST;
> +
> +#define REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK(a)
> BASE_CR (a, REDFISH_PLATFORM_CONFIG_PENDING_LIST, Link)
> +
> +typedef struct {
> +  UINTN    Count;                               // Number of schema in list
> +  CHAR8    **SchemaList;                        // Schema list
> +} REDFISH_PLATFORM_CONFIG_SCHEMA;
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE
> +//
> +typedef struct {
> +  LIST_ENTRY                        Link;
> +  HII_FORMSET                       *HiiFormSet;     // Pointer to HII formset data.
> +  EFI_GUID                          Guid;            // Formset GUID.
> +  EFI_HII_HANDLE                    HiiHandle;       // Hii Handle of this formset.
> +  LIST_ENTRY                        HiiFormList;     // Form list that keep form data
> under this formset.
> +  CHAR16                            *DevicePathStr;  // Device path of this formset.
> +  REDFISH_PLATFORM_CONFIG_SCHEMA    SupportedSchema; // Schema
> that is supported in this formset.
> +} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;
> +
> +#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a)  BASE_CR
> (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_FORM_PRIVATE
> +//
> +typedef struct {
> +  LIST_ENTRY                                  Link;
> +  UINT16                                      Id;           // Form ID.
> +  EFI_STRING_ID                               Title;        // String token of form title.
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE    *ParentFormset;
> +  HII_FORM                                    *HiiForm;      // Pointer to HII form data.
> +  LIST_ENTRY                                  StatementList; // Statement list that keep
> statement under this form.
> +  BOOLEAN                                     Suppressed;    // Form is suppressed
> +} REDFISH_PLATFORM_CONFIG_FORM_PRIVATE;
> +
> +#define REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK(a)  BASE_CR (a,
> REDFISH_PLATFORM_CONFIG_FORM_PRIVATE, Link)
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_DATA
> +//
> +typedef struct {
> +  UINT64    NumMinimum;
> +  UINT64    NumMaximum;
> +  UINT64    NumStep;
> +  UINT8     StrMinSize;
> +  UINT8     StrMaxSize;
> +} REDFISH_PLATFORM_CONFIG_STATEMENT_DATA;
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> +//
> +typedef struct {
> +  LIST_ENTRY                                Link;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *ParentForm;
> +  HII_STATEMENT                             *HiiStatement;  // Pointer to HII statement
> data.
> +  EFI_QUESTION_ID                           QuestionId;     // Question ID of this
> statement.
> +  EFI_STRING_ID                             Description;    // String token of this question.
> +  EFI_STRING_ID                             Help;           // String token of help message.
> +  EFI_STRING                                DesStringCache; // The string cache for search
> function.
> +  UINT8                                     Flags;          // The statement flag.
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_DATA    StatementData;  //
> The max/min for statement value.
> +  BOOLEAN                                   Suppressed;     // Statement is suppressed.
> +  BOOLEAN                                   GrayedOut;      // Statement is GrayedOut.
> +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE;
> +
> +#define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a)
> BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link)
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF
> +//
> +typedef struct {
> +  LIST_ENTRY                                   Link;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE    *Statement;
> +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF;
> +
> +#define REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK(a)
> BASE_CR (a, REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF, Link)
> +
> +//
> +// Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
> +//
> +typedef struct {
> +  LIST_ENTRY    StatementList;      // List of
> REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF
> +  UINTN         Count;
> +} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST;
> +
> +/**
> +  Release formset list and all the forms that belong to this formset.
> +
> +  @param[in]      FormsetList   Pointer to formset list that needs to be
> +                                released.
> +
> +  @retval         EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +ReleaseFormsetList (
> +  IN  LIST_ENTRY  *FormsetList
> +  );
> +
> +/**
> +  Release formset list and all the forms that belong to this formset.
> +
> +  @param[in]      FormsetList   Pointer to formset list that needs to be
> +                                released.
> +
> +  @retval         EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +LoadFormsetList (
> +  IN   EFI_HII_HANDLE  *HiiHandle,
> +  OUT  LIST_ENTRY      *FormsetList
> +  );
> +
> +/**
> +  When HII database is updated. Keep updated HII handle into pending list
> so
> +  we can process them later.
> +
> +  @param[in]  HiiHandle   HII handle instance.
> +  @param[in]  PendingList Pending list to keep HII handle which is recently
> updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is
> NULL.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +NotifyFormsetUpdate (
> +  IN  EFI_HII_HANDLE  *HiiHandle,
> +  IN  LIST_ENTRY      *PendingList
> +  );
> +
> +/**
> +  When HII database is updated and form-set is deleted. Keep deleted HII
> handle into pending list so
> +  we can process them later.
> +
> +  @param[in]  HiiHandle   HII handle instance.
> +  @param[in]  PendingList Pending list to keep HII handle which is recently
> updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is
> NULL.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +NotifyFormsetDeleted (
> +  IN  EFI_HII_HANDLE  *HiiHandle,
> +  IN  LIST_ENTRY      *PendingList
> +  );
> +
> +/**
> +  Get statement private instance by the given configure language.
> +
> +  @param[in]  FormsetList                 Form-set list to search.
> +  @param[in]  Schema                      Schema to be matched.
> +  @param[in]  ConfigureLang               Configure language.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer
> to statement private instance.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *
> +GetStatementPrivateByConfigureLang (
> +  IN  LIST_ENTRY  *FormsetList,
> +  IN  CHAR8       *Schema,
> +  IN  EFI_STRING  ConfigureLang
> +  );
> +
> +/**
> +  Search and find statement private instance by given regular expression
> pattern
> +  which describes the Configure Language.
> +
> +  @param[in]  RegularExpressionProtocol   Regular express protocol.
> +  @param[in]  FormsetList                 Form-set list to search.
> +  @param[in]  Schema                      Schema to be matched.
> +  @param[in]  Pattern                     Regular expression pattern.
> +  @param[out] StatementList               Statement list that match above
> pattern.
> +
> +  @retval EFI_SUCCESS             Statement list is returned.
> +  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.
> +  @retval EFI_NOT_READY           Regular express protocol is NULL.
> +  @retval EFI_NOT_FOUND           No statement is found.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +GetStatementPrivateByConfigureLangRegex (
> +  IN  EFI_REGULAR_EXPRESSION_PROTOCOL
> *RegularExpressionProtocol,
> +  IN  LIST_ENTRY                                      *FormsetList,
> +  IN  CHAR8                                           *Schema,
> +  IN  EFI_STRING                                      Pattern,
> +  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
> *StatementList
> +  );
> +
> +/**
> +  There are HII database update and we need to process them accordingly
> so that we
> +  won't use stale data. This function will parse updated HII handle again in
> order
> +  to get updated data-set.
> +
> +  @param[in]  FormsetList   List to keep HII form-set.
> +  @param[in]  PendingList   List to keep HII handle that is updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is
> NULL.
> +
> +**/
> +EFI_STATUS
> +ProcessPendingList (
> +  IN  LIST_ENTRY  *FormsetList,
> +  IN  LIST_ENTRY  *PendingList
> +  );
> +
> +/**
> +  Retrieves a unicode string from a string package in a given language. The
> +  returned string is allocated using AllocatePool().  The caller is responsible
> +  for freeing the allocated buffer using FreePool().
> +
> +  If HiiHandle is NULL, then ASSERT().
> +  If StringId is 0, then ASSET.
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  Language          The specified configure language to get string.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +EFI_STRING
> +HiiGetRedfishString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN CHAR8           *Language,
> +  IN EFI_STRING_ID   StringId
> +  );
> +
> +/**
> +  Retrieves a ASCII string from a string package in a given language. The
> +  returned string is allocated using AllocatePool().  The caller is responsible
> +  for freeing the allocated buffer using FreePool().
> +
> +  If HiiHandle is NULL, then ASSERT().
> +  If StringId is 0, then ASSET.
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  Language          The specified configure language to get string.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +CHAR8 *
> +HiiGetRedfishAsciiString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN CHAR8           *Language,
> +  IN EFI_STRING_ID   StringId
> +  );
> +
> +/**
> +  Get ASCII string from HII database in English language. The returned string
> is allocated
> +  using AllocatePool(). The caller is responsible for freeing the allocated
> buffer using
> +  FreePool().
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +CHAR8 *
> +HiiGetEnglishAsciiString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN EFI_STRING_ID   StringId
> +  );
> +
> +/**
> +  Release all resource in statement list.
> +
> +  @param[in]  StatementList   Statement list to be released.
> +
> +  @retval EFI_SUCCESS             All resource are released.
> +  @retval EFI_INVALID_PARAMETER   StatementList is NULL.
> +
> +**/
> +EFI_STATUS
> +ReleaseStatementList (
> +  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
> *StatementList
> +  );
> +
> +#endif
> diff --git
> a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
> b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
> new file mode 100644
> index 000000000000..64f1d2e57cfb
> --- /dev/null
> +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
> @@ -0,0 +1,2495 @@
> +/** @file
> +  The implementation of EDKII Redfish Platform Config Protocol.
> +
> +  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> +  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "RedfishPlatformConfigDxe.h"
> +#include "RedfishPlatformConfigImpl.h"
> +
> +REDFISH_PLATFORM_CONFIG_PRIVATE  *mRedfishPlatformConfigPrivate =
> NULL;
> +
> +/**
> +  Create a new stack instance with given stack size.
> +
> +  @param[in]  StackSize  The size of stack.
> +
> +  @retval REDFISH_STACK * Pointer to created stack.
> +  @retval NULL            Out of resource.
> +
> +**/
> +REDFISH_STACK *
> +NewRedfishStack (
> +  IN UINTN  StackSize
> +  )
> +{
> +  REDFISH_STACK  *Buffer;
> +
> +  if (StackSize == 0) {
> +    return NULL;
> +  }
> +
> +  Buffer = AllocateZeroPool (sizeof (REDFISH_STACK));
> +  if (Buffer == NULL) {
> +    return NULL;
> +  }
> +
> +  Buffer->Pool = AllocateZeroPool (sizeof (VOID *) * StackSize);
> +  if (Buffer->Pool == NULL) {
> +    FreePool (Buffer);
> +    return NULL;
> +  }
> +
> +  Buffer->Size  = StackSize;
> +  Buffer->Index = 0;
> +
> +  return Buffer;
> +}
> +
> +/**
> +  Release stack buffer.
> +
> +  @param[in]  Stack     Pointer to stack instance.
> +
> +**/
> +VOID
> +ReleaseRedfishStack (
> +  IN REDFISH_STACK  *Stack
> +  )
> +{
> +  if (Stack == NULL) {
> +    return;
> +  }
> +
> +  FreePool (Stack->Pool);
> +  FreePool (Stack);
> +}
> +
> +/**
> +  Check and see if stack is empty or not.
> +
> +  @param[in]  Stack     Pointer to stack instance.
> +
> +  @retval TRUE          Stack is empty.
> +  @retval FALSE         Stack is not empty.
> +
> +**/
> +BOOLEAN
> +IsEmptyRedfishStack (
> +  IN REDFISH_STACK  *Stack
> +  )
> +{
> +  return (Stack->Index == 0);
> +}
> +
> +/**
> +  Push an item to stack.
> +
> +  @param[in]  Stack     Pointer to stack instance.
> +  @param[in]  Data      Pointer to data.
> +
> +  @retval EFI_OUT_OF_RESOURCES   Stack is full.
> +  @retval EFI_SUCCESS            Item is pushed successfully.
> +
> +**/
> +EFI_STATUS
> +PushRedfishStack (
> +  IN REDFISH_STACK  *Stack,
> +  IN VOID           *Data
> +  )
> +{
> +  if (Stack->Index == Stack->Size) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Stack->Pool[Stack->Index] = Data;
> +  Stack->Index             += 1;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Pop an item from stack.
> +
> +  @param[in]  Stack     Pointer to stack instance.
> +
> +  @retval VOID *        Pointer to popped item.
> +  @retval NULL          Stack is empty.
> +
> +**/
> +VOID *
> +PopRedfishStack (
> +  IN REDFISH_STACK  *Stack
> +  )
> +{
> +  if (IsEmptyRedfishStack (Stack)) {
> +    return NULL;
> +  }
> +
> +  Stack->Index -= 1;
> +  return Stack->Pool[Stack->Index];
> +}
> +
> +/**
> +  Seach forms in this HII package and find which form links to give form.
> +
> +  @param[in]  FormPrivate   Pointer to form private instance.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_FORM_PRIVATE Pointer to target
> form
> +  @retval NULL                                 No form links to give form.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_FORM_PRIVATE *
> +FindFormLinkToThis (
> +  IN REDFISH_PLATFORM_CONFIG_FORM_PRIVATE  *FormPrivate
> +  )
> +{
> +  LIST_ENTRY                                 *HiiFormLink;
> +  LIST_ENTRY                                 *HiiNextFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;
> +  LIST_ENTRY                                 *HiiStatementLink;
> +  LIST_ENTRY                                 *HiiNextStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE   *HiiFormsetPrivate;
> +
> +  if (FormPrivate == NULL) {
> +    return NULL;
> +  }
> +
> +  HiiFormsetPrivate = FormPrivate->ParentFormset;
> +
> +  if (IsListEmpty (&HiiFormsetPrivate->HiiFormList)) {
> +    return NULL;
> +  }
> +
> +  HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
> +  while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
> +    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK
> (HiiFormLink);
> +    HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList,
> HiiFormLink);
> +
> +    //
> +    // Skip myself
> +    //
> +    if (HiiFormPrivate == FormPrivate) {
> +      HiiFormLink = HiiNextFormLink;
> +      continue;
> +    }
> +
> +    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
> +    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
> +      HiiStatementPrivate  =
> REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
> +      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList,
> HiiStatementLink);
> +
> +      //
> +      // Check go-to opcode and find form ID. If form ID is the same ID as given
> form,
> +      // this go-to opcode links to given form.
> +      //
> +      if ((HiiStatementPrivate->HiiStatement->Operand == EFI_IFR_REF_OP)
> &&
> +          (HiiStatementPrivate->HiiStatement->Value.Value.ref.FormId ==
> FormPrivate->HiiForm->FormId))
> +      {
> +        return HiiFormPrivate;
> +      }
> +
> +      HiiStatementLink = HiiNextStatementLink;
> +    }
> +
> +    HiiFormLink = HiiNextFormLink;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Build the menu path to given statement instance. It is caller's
> +  responsibility to free returned string buffer.
> +
> +  @param[in]  StatementPrivate   Pointer to statement private instance.
> +
> +  @retval CHAR8 *                Menu path to given statement.
> +  @retval NULL                   Can not find menu path.
> +
> +**/
> +CHAR8 *
> +BuildMenPath (
> +  IN REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *StatementPrivate
> +  )
> +{
> +  REDFISH_STACK                         *FormStack;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE  *FormPrivate;
> +  UINTN                                 OldBufferSize;
> +  UINTN                                 NewBufferSize;
> +  CHAR8                                 *Buffer;
> +  CHAR8                                 *FormTitle;
> +  EFI_STATUS                            Status;
> +
> +  Buffer        = NULL;
> +  OldBufferSize = 0;
> +  NewBufferSize = 0;
> +  FormStack     = NewRedfishStack (REDFISH_MENU_PATH_SIZE);
> +  if (FormStack == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Build form link stack
> +  //
> +  FormPrivate = StatementPrivate->ParentForm;
> +  Status      = PushRedfishStack (FormStack, (VOID *)FormPrivate);
> +  if (EFI_ERROR (Status)) {
> +    goto RELEASE;
> +  }
> +
> +  do {
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "F(%d) <-",
> FormPrivate->Id));
> +    FormPrivate = FindFormLinkToThis (FormPrivate);
> +    if (FormPrivate == NULL) {
> +      break;
> +    }
> +
> +    PushRedfishStack (FormStack, (VOID *)FormPrivate);
> +    if (EFI_ERROR (Status)) {
> +      break;
> +    }
> +  } while (TRUE);
> +
> +  if (IsEmptyRedfishStack (FormStack)) {
> +    goto RELEASE;
> +  }
> +
> +  //
> +  // Initial Buffer to empty string for error case.
> +  //
> +  OldBufferSize = AsciiStrSize ("");
> +  Buffer        = AllocateCopyPool (OldBufferSize, "");
> +  if (Buffer == NULL) {
> +    goto RELEASE;
> +  }
> +
> +  //
> +  // Build menu path in string format
> +  //
> +  FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE
> *)PopRedfishStack (FormStack);
> +  while (FormPrivate != NULL) {
> +    FormTitle = HiiGetEnglishAsciiString (FormPrivate->ParentFormset-
> >HiiHandle, FormPrivate->Title);
> +    if (FormTitle != NULL) {
> +      NewBufferSize = AsciiStrSize (FormTitle) + OldBufferSize;
> +      Buffer        = ReallocatePool (OldBufferSize, NewBufferSize, Buffer);
> +      if (Buffer == NULL) {
> +        goto RELEASE;
> +      }
> +
> +      OldBufferSize = NewBufferSize;
> +      AsciiStrCatS (Buffer, OldBufferSize, "/");
> +      AsciiStrCatS (Buffer, OldBufferSize, FormTitle);
> +      FreePool (FormTitle);
> +      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, " %a\n", Buffer));
> +    }
> +
> +    FormPrivate = (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE
> *)PopRedfishStack (FormStack);
> +  }
> +
> +RELEASE:
> +
> +  ReleaseRedfishStack (FormStack);
> +
> +  return Buffer;
> +}
> +
> +/**
> +  Get the attribute name from config language.
> +
> +  For example:  /Bios/Attributes/BiosOption1 is config language
> +  and attribute name is BiosOption1.
> +
> +  @param[in]  ConfigLanguage     Config language string.
> +
> +  @retval CHAR8 *                Attribute name string.
> +  @retval NULL                   Can not find attribute name.
> +
> +**/
> +CHAR8 *
> +GetAttributeNameFromConfigLanguage (
> +  IN  CHAR8  *ConfigLanguage
> +  )
> +{
> +  CHAR8  *attributeName;
> +  CHAR8  *Pointer;
> +  UINTN  StrLen;
> +  UINTN  Index;
> +  UINTN  AttrStrLen;
> +
> +  if (IS_EMPTY_STRING (ConfigLanguage)) {
> +    return NULL;
> +  }
> +
> +  attributeName = NULL;
> +  Pointer       = NULL;
> +  AttrStrLen    = 0;
> +  StrLen        = AsciiStrLen (ConfigLanguage);
> +
> +  if (ConfigLanguage[StrLen - 1] == '/') {
> +    //
> +    // wrong format
> +    //
> +    DEBUG ((DEBUG_ERROR, "%a, invalid format: %a\n", __FUNCTION__,
> ConfigLanguage));
> +    ASSERT (FALSE);
> +    return NULL;
> +  }
> +
> +  Index = StrLen;
> +  while (TRUE) {
> +    Index -= 1;
> +
> +    if (ConfigLanguage[Index] == '/') {
> +      Pointer = &ConfigLanguage[Index + 1];
> +      break;
> +    }
> +
> +    if (Index == 0) {
> +      break;
> +    }
> +  }
> +
> +  //
> +  // Not found. There is no '/' in input string.
> +  //
> +  if (Pointer == NULL) {
> +    return NULL;
> +  }
> +
> +  AttrStrLen    = StrLen - Index;
> +  attributeName = AllocateCopyPool (AttrStrLen, Pointer);
> +
> +  return attributeName;
> +}
> +
> +/**
> +  Convert one-of options to string array in Redfish attribute.
> +
> +  @param[in]  HiiHandle          HII handle.
> +  @param[in]  SchemaName         Schema string.
> +  @param[in]  StatementPrivate   Pointer to statement instance.
> +  @param[out] Values             Attribute value array.
> +
> +  @retval EFI_SUCCESS            Options are converted successfully.
> +  @retval Other                  Error occurs.
> +
> +**/
> +EFI_STATUS
> +OneOfStatementToAttributeValues (
> +  IN  EFI_HII_HANDLE                             HiiHandle,
> +  IN  CHAR8                                      *SchemaName,
> +  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *StatementPrivate,
> +  OUT EDKII_REDFISH_POSSIBLE_VALUES              *Values
> +  )
> +{
> +  LIST_ENTRY           *Link;
> +  HII_QUESTION_OPTION  *Option;
> +  UINTN                Index;
> +  HII_STATEMENT        *HiiStatement;
> +
> +  if ((HiiHandle == NULL) || (StatementPrivate == NULL) || (Values == NULL))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  HiiStatement = StatementPrivate->HiiStatement;
> +  ASSERT (HiiStatement != NULL);
> +
> +  if (IsListEmpty (&HiiStatement->OptionListHead)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Loop through the option to get count
> +  //
> +  Values->ValueCount = 0;
> +  Link               = GetFirstNode (&HiiStatement->OptionListHead);
> +  while (!IsNull (&HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    if ((Option->SuppressExpression != NULL) &&
> +        (EvaluateExpressionList (Option->SuppressExpression, TRUE,
> StatementPrivate->ParentForm->ParentFormset->HiiFormSet,
> StatementPrivate->ParentForm->HiiForm) != ExpressFalse))
> +    {
> +      Link = GetNextNode (&HiiStatement->OptionListHead, Link);
> +      continue;
> +    }
> +
> +    Values->ValueCount += 1;
> +    Link                = GetNextNode (&HiiStatement->OptionListHead, Link);
> +  }
> +
> +  Values->ValueArray = AllocateZeroPool (sizeof
> (EDKII_REDFISH_ATTRIBUTE_VALUE) * Values->ValueCount);
> +  if (Values->ValueArray == NULL) {
> +    Values->ValueCount = 0;
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Index = 0;
> +  Link  = GetFirstNode (&HiiStatement->OptionListHead);
> +  while (!IsNull (&HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    if ((Option->SuppressExpression != NULL) &&
> +        (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL,
> NULL) != ExpressFalse))
> +    {
> +      Link = GetNextNode (&HiiStatement->OptionListHead, Link);
> +      continue;
> +    }
> +
> +    if (Option->Text != 0) {
> +      Values->ValueArray[Index].ValueName        = HiiGetRedfishAsciiString
> (HiiHandle, SchemaName, Option->Text);
> +      Values->ValueArray[Index].ValueDisplayName = HiiGetEnglishAsciiString
> (HiiHandle, Option->Text);
> +    }
> +
> +    Index += 1;
> +    Link   = GetNextNode (&HiiStatement->OptionListHead, Link);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Return Redfish attribute type from given HII statement operand.
> +
> +  @param[in]  HiiStatement       Target HII statement.
> +
> +  @retval EDKII_REDFISH_ATTRIBUTE_TYPES    Attribute type.
> +
> +**/
> +EDKII_REDFISH_ATTRIBUTE_TYPES
> +HiiStatementToAttributeType (
> +  IN  HII_STATEMENT  *HiiStatement
> +  )
> +{
> +  EDKII_REDFISH_ATTRIBUTE_TYPES  type;
> +
> +  if (HiiStatement == NULL) {
> +    return RedfishAttributeTypeUnknown;
> +  }
> +
> +  type = RedfishAttributeTypeUnknown;
> +  switch (HiiStatement->Operand) {
> +    case EFI_IFR_ONE_OF_OP:
> +    case EFI_IFR_ORDERED_LIST_OP:
> +      type = RedfishAttributeTypeEnumeration;
> +      break;
> +    case EFI_IFR_STRING_OP:
> +      type = RedfishAttributeTypeString;
> +      break;
> +    case EFI_IFR_NUMERIC_OP:
> +      type = RedfishAttributeTypeInteger;
> +      break;
> +    case EFI_IFR_CHECKBOX_OP:
> +      type = RedfishAttributeTypeBoolean;
> +      break;
> +    case EFI_IFR_DATE_OP:
> +    case EFI_IFR_TIME_OP:
> +    default:
> +      DEBUG ((DEBUG_ERROR, "%a, unsupported operand: 0x%x\n",
> __FUNCTION__, HiiStatement->Operand));
> +      break;
> +  }
> +
> +  return type;
> +}
> +
> +/**
> +  Zero extend integer/boolean to UINT64 for comparing.
> +
> +  @param  Value                  HII Value to be converted.
> +
> +**/
> +UINT64
> +ExtendHiiValueToU64 (
> +  IN HII_STATEMENT_VALUE  *Value
> +  )
> +{
> +  UINT64  Temp;
> +
> +  Temp = 0;
> +  switch (Value->Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      Temp = Value->Value.u8;
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      Temp = Value->Value.u16;
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      Temp = Value->Value.u32;
> +      break;
> +
> +    case EFI_IFR_TYPE_BOOLEAN:
> +      Temp = Value->Value.b;
> +      break;
> +
> +    case EFI_IFR_TYPE_TIME:
> +    case EFI_IFR_TYPE_DATE:
> +    default:
> +      break;
> +  }
> +
> +  return Temp;
> +}
> +
> +/**
> +  Set value of a data element in an Array by its Index in ordered list buffer.
> +
> +  @param  Array                  The data array.
> +  @param  Type                   Type of the data in this array.
> +  @param  Index                  Zero based index for data in this array.
> +  @param  Value                  The value to be set.
> +
> +**/
> +VOID
> +OrderedListSetArrayData (
> +  IN VOID    *Array,
> +  IN UINT8   Type,
> +  IN UINTN   Index,
> +  IN UINT64  Value
> +  )
> +{
> +  ASSERT (Array != NULL);
> +
> +  switch (Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      *(((UINT8 *)Array) + Index) = (UINT8)Value;
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      *(((UINT16 *)Array) + Index) = (UINT16)Value;
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      *(((UINT32 *)Array) + Index) = (UINT32)Value;
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      *(((UINT64 *)Array) + Index) = (UINT64)Value;
> +      break;
> +
> +    default:
> +      break;
> +  }
> +}
> +
> +/**
> +  Return data element in an Array by its Index in ordered list array buffer.
> +
> +  @param  Array                  The data array.
> +  @param  Type                   Type of the data in this array.
> +  @param  Index                  Zero based index for data in this array.
> +
> +  @retval Value                  The data to be returned
> +
> +**/
> +UINT64
> +OrderedListGetArrayData (
> +  IN VOID   *Array,
> +  IN UINT8  Type,
> +  IN UINTN  Index
> +  )
> +{
> +  UINT64  Data;
> +
> +  ASSERT (Array != NULL);
> +
> +  Data = 0;
> +  switch (Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      Data = (UINT64)*(((UINT8 *)Array) + Index);
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      Data = (UINT64)*(((UINT16 *)Array) + Index);
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      Data = (UINT64)*(((UINT32 *)Array) + Index);
> +      break;
> +
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      Data = (UINT64)*(((UINT64 *)Array) + Index);
> +      break;
> +
> +    default:
> +      break;
> +  }
> +
> +  return Data;
> +}
> +
> +/**
> +  Find string ID of option if its value equals to given value.
> +
> +  @param[in]  HiiStatement  Statement to search.
> +  @param[in]  Value         Target value.
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STRING_ID
> +OrderedListOptionValueToStringId (
> +  IN  HII_STATEMENT  *HiiStatement,
> +  IN  UINT64         Value
> +  )
> +{
> +  LIST_ENTRY           *Link;
> +  HII_QUESTION_OPTION  *Option;
> +  UINT64               CurrentValue;
> +
> +  if (HiiStatement == NULL) {
> +    return 0;
> +  }
> +
> +  if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
> +    return 0;
> +  }
> +
> +  if (IsListEmpty (&HiiStatement->OptionListHead)) {
> +    return 0;
> +  }
> +
> +  Link = GetFirstNode (&HiiStatement->OptionListHead);
> +  while (!IsNull (&HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    CurrentValue = ExtendHiiValueToU64 (&Option->Value);
> +    if (Value == CurrentValue) {
> +      return Option->Text;
> +    }
> +
> +    Link = GetNextNode (&HiiStatement->OptionListHead, Link);
> +  }
> +
> +  return 0;
> +}
> +
> +/**
> +  Compare two value in HII statement format.
> +
> +  @param[in]  Value1        First value to compare.
> +  @param[in]  Value2        Second value to be compared.
> +
> +  @retval INTN          0 is returned when two values are equal.
> +                        1 is returned when first value is greater than second value.
> +                        -1 is returned when second value is greater than first value.
> +
> +**/
> +INTN
> +CompareHiiStatementValue (
> +  IN HII_STATEMENT_VALUE  *Value1,
> +  IN HII_STATEMENT_VALUE  *Value2
> +  )
> +{
> +  INTN    Result;
> +  UINT64  Data1;
> +  UINT64  Data2;
> +
> +  if ((Value1 == NULL) || (Value2 == NULL)) {
> +    return -1;
> +  }
> +
> +  switch (Value1->Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      Data1 = Value1->Value.u8;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      Data1 = Value1->Value.u16;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      Data1 = Value1->Value.u32;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      Data1 = Value1->Value.u64;
> +      break;
> +    case EFI_IFR_TYPE_BOOLEAN:
> +      Data1 = (Value1->Value.b ? 1 : 0);
> +      break;
> +    default:
> +      return -1;
> +  }
> +
> +  switch (Value2->Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      Data2 = Value2->Value.u8;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      Data2 = Value2->Value.u16;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      Data2 = Value2->Value.u32;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      Data2 = Value2->Value.u64;
> +      break;
> +    case EFI_IFR_TYPE_BOOLEAN:
> +      Data2 = (Value2->Value.b ? 1 : 0);
> +      break;
> +    default:
> +      return -1;
> +  }
> +
> +  Result = (Data1 == Data2 ? 0 : (Data1 > Data2 ? 1 : -1));
> +
> +  return Result;
> +}
> +
> +/**
> +  Convert HII value to the string in HII one-of opcode.
> +
> +  @param[in]  HiiStatement  HII Statement private instance
> +  @param[in]  Value         HII Statement value
> +
> +  @retval EFI_STRING_ID     The string ID in HII database.
> +                            0 is returned when something goes wrong.
> +
> +**/
> +EFI_STRING_ID
> +HiiValueToOneOfOptionStringId (
> +  IN HII_STATEMENT        *HiiStatement,
> +  IN HII_STATEMENT_VALUE  *Value
> +  )
> +{
> +  LIST_ENTRY           *Link;
> +  HII_QUESTION_OPTION  *Option;
> +
> +  if ((HiiStatement == NULL) || (Value == NULL)) {
> +    return 0;
> +  }
> +
> +  if (HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
> +    return 0;
> +  }
> +
> +  if (IsListEmpty (&HiiStatement->OptionListHead)) {
> +    return 0;
> +  }
> +
> +  Link = GetFirstNode (&HiiStatement->OptionListHead);
> +  while (!IsNull (&HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    if (CompareHiiStatementValue (Value, &Option->Value) == 0) {
> +      return Option->Text;
> +    }
> +
> +    Link = GetNextNode (&HiiStatement->OptionListHead, Link);
> +  }
> +
> +  return 0;
> +}
> +
> +/**
> +  Convert HII string to the value in HII one-of opcode.
> +
> +  @param[in]  Statement     Statement private instance
> +  @param[in]  Schema        Schema string
> +  @param[in]  HiiString     Input string
> +  @param[out] Value         Value returned
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +HiiStringToOneOfOptionValue (
> +  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *Statement,
> +  IN  CHAR8                                      *Schema,
> +  IN  EFI_STRING                                 HiiString,
> +  OUT HII_STATEMENT_VALUE                        *Value
> +  )
> +{
> +  LIST_ENTRY           *Link;
> +  HII_QUESTION_OPTION  *Option;
> +  EFI_STRING           TmpString;
> +  BOOLEAN              Found;
> +
> +  if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value ==
> NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Statement->HiiStatement->Operand != EFI_IFR_ONE_OF_OP) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Found = FALSE;
> +  Link  = GetFirstNode (&Statement->HiiStatement->OptionListHead);
> +  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    TmpString = HiiGetRedfishString (Statement->ParentForm-
> >ParentFormset->HiiHandle, Schema, Option->Text);
> +    if (TmpString != NULL) {
> +      if (StrCmp (TmpString, HiiString) == 0) {
> +        CopyMem (Value, &Option->Value, sizeof (HII_STATEMENT_VALUE));
> +        Found = TRUE;
> +      }
> +
> +      FreePool (TmpString);
> +    }
> +
> +    if (Found) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +/**
> +  Convert HII value to numeric value in Redfish format.
> +
> +  @param[in]  Value         Value to be converted.
> +  @param[out] RedfishValue  Value in Redfish format.
> +
> +  @retval EFI_SUCCESS       Redfish value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +HiiValueToRedfishNumeric (
> +  IN  HII_STATEMENT_VALUE  *Value,
> +  OUT EDKII_REDFISH_VALUE  *RedfishValue
> +  )
> +{
> +  if ((Value == NULL) || (RedfishValue == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  switch (Value->Type) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      RedfishValue->Type          = RedfishValueTypeInteger;
> +      RedfishValue->Value.Integer = (INT64)Value->Value.u8;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      RedfishValue->Type          = RedfishValueTypeInteger;
> +      RedfishValue->Value.Integer = (INT64)Value->Value.u16;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      RedfishValue->Type          = RedfishValueTypeInteger;
> +      RedfishValue->Value.Integer = (INT64)Value->Value.u32;
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      RedfishValue->Type          = RedfishValueTypeInteger;
> +      RedfishValue->Value.Integer = (INT64)Value->Value.u64;
> +      break;
> +    case EFI_IFR_TYPE_BOOLEAN:
> +      RedfishValue->Type          = RedfishValueTypeBoolean;
> +      RedfishValue->Value.Boolean = Value->Value.b;
> +      break;
> +    default:
> +      RedfishValue->Type = RedfishValueTypeUnknown;
Do we have to return EFI_INVALID_PARAMETER here?


> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Convert numeric value in Redfish format to HII value.
> +
> +  @param[in]   RedfishValue  Value in Redfish format to be converted.
> +  @param[out]  Value         HII value returned.
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +RedfishNumericToHiiValue (
> +  IN  EDKII_REDFISH_VALUE  *RedfishValue,
> +  OUT HII_STATEMENT_VALUE  *Value
> +  )
> +{
> +  if ((Value == NULL) || (RedfishValue == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  switch (RedfishValue->Type) {
> +    case RedfishValueTypeInteger:
> +      Value->Type      = EFI_IFR_TYPE_NUM_SIZE_64;
> +      Value->Value.u64 = (UINT64)RedfishValue->Value.Integer;
> +      break;
> +    case RedfishValueTypeBoolean:
> +      Value->Type    = EFI_IFR_TYPE_BOOLEAN;
> +      Value->Value.b = RedfishValue->Value.Boolean;
> +      break;
> +    default:
> +      Value->Type = EFI_IFR_TYPE_UNDEFINED;
Do we have to return EFI_INVALID_PARAMETER here?

Abner


> +      break;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Dump the value in ordered list buffer.
> +
> +  @param[in]   OrderedListStatement Ordered list statement.
> +
> +**/
> +VOID
> +DumpOrderedListValue (
> +  IN  HII_STATEMENT  *OrderedListStatement
> +  )
> +{
> +  UINT8   *Value8;
> +  UINT16  *Value16;
> +  UINT32  *Value32;
> +  UINT64  *Value64;
> +  UINTN   Count;
> +  UINTN   Index;
> +
> +  if ((OrderedListStatement == NULL) || (OrderedListStatement-
> >Operand != EFI_IFR_ORDERED_LIST_OP)) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "Value.Type= 0x%x\n", OrderedListStatement-
> >Value.Type));
> +  DEBUG ((DEBUG_ERROR, "Value.BufferValueType= 0x%x\n",
> OrderedListStatement->Value.BufferValueType));
> +  DEBUG ((DEBUG_ERROR, "Value.BufferLen= 0x%x\n",
> OrderedListStatement->Value.BufferLen));
> +  DEBUG ((DEBUG_ERROR, "Value.Buffer= 0x%x\n", OrderedListStatement-
> >Value.Buffer));
> +  DEBUG ((DEBUG_ERROR, "Value.MaxContainers= 0x%x\n",
> OrderedListStatement->ExtraData.OrderListData.MaxContainers));
> +  DEBUG ((DEBUG_ERROR, "StorageWidth= 0x%x\n",
> OrderedListStatement->StorageWidth));
> +
> +  if (OrderedListStatement->Value.Buffer == NULL) {
> +    return;
> +  }
> +
> +  Value8  = NULL;
> +  Value16 = NULL;
> +  Value32 = NULL;
> +  Value64 = NULL;
> +  Count   = 0;
> +
> +  switch (OrderedListStatement->Value.BufferValueType) {
> +    case EFI_IFR_TYPE_NUM_SIZE_8:
> +      Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
> +      Count  = OrderedListStatement->StorageWidth / sizeof (UINT8);
> +      for (Index = 0; Index < Count; Index++) {
> +        DEBUG ((DEBUG_ERROR, "%d ", Value8[Index]));
> +      }
> +
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_16:
> +      Value16 = (UINT16 *)OrderedListStatement->Value.Buffer;
> +      Count   = OrderedListStatement->StorageWidth / sizeof (UINT16);
> +      for (Index = 0; Index < Count; Index++) {
> +        DEBUG ((DEBUG_ERROR, "%d ", Value16[Index]));
> +      }
> +
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_32:
> +      Value32 = (UINT32 *)OrderedListStatement->Value.Buffer;
> +      Count   = OrderedListStatement->StorageWidth / sizeof (UINT32);
> +      for (Index = 0; Index < Count; Index++) {
> +        DEBUG ((DEBUG_ERROR, "%d ", Value32[Index]));
> +      }
> +
> +      break;
> +    case EFI_IFR_TYPE_NUM_SIZE_64:
> +      Value64 = (UINT64 *)OrderedListStatement->Value.Buffer;
> +      Count   = OrderedListStatement->StorageWidth / sizeof (UINT64);
> +      for (Index = 0; Index < Count; Index++) {
> +        DEBUG ((DEBUG_ERROR, "%d ", Value64[Index]));
> +      }
> +
> +      break;
> +    default:
> +      Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
> +      Count  = OrderedListStatement->StorageWidth / sizeof (UINT8);
> +      for (Index = 0; Index < Count; Index++) {
> +        DEBUG ((DEBUG_ERROR, "%d ", Value8[Index]));
> +      }
> +
> +      break;
> +  }
> +
> +  DEBUG ((DEBUG_ERROR, "\n"));
> +}
> +
> +/**
> +  Convert HII value to the string in HII ordered list opcode. It's caller's
> +  responsibility to free returned buffer using FreePool().
> +
> +  @param[in]  HiiStatement  HII Statement private instance
> +  @param[out] ReturnSize    The size of returned array
> +
> +  @retval EFI_STRING_ID     The string ID array for options in ordered list.
> +
> +**/
> +EFI_STRING_ID *
> +HiiValueToOrderedListOptionStringId (
> +  IN  HII_STATEMENT  *HiiStatement,
> +  OUT UINTN          *ReturnSize
> +  )
> +{
> +  LIST_ENTRY     *Link;
> +  UINTN          OptionCount;
> +  EFI_STRING_ID  *ReturnedArray;
> +  UINTN          Index;
> +  UINT64         Value;
> +
> +  if ((HiiStatement == NULL) || (ReturnSize == NULL)) {
> +    return NULL;
> +  }
> +
> +  *ReturnSize = 0;
> +
> +  if (HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
> +    return NULL;
> +  }
> +
> +  if (IsListEmpty (&HiiStatement->OptionListHead)) {
> +    return NULL;
> +  }
> +
> +  DEBUG_CODE (
> +    DumpOrderedListValue (HiiStatement);
> +    );
> +
> +  OptionCount = 0;
> +  Link        = GetFirstNode (&HiiStatement->OptionListHead);
> +  while (!IsNull (&HiiStatement->OptionListHead, Link)) {
> +    ++OptionCount;
> +    Link = GetNextNode (&HiiStatement->OptionListHead, Link);
> +  }
> +
> +  *ReturnSize   = OptionCount;
> +  ReturnedArray = AllocatePool (sizeof (EFI_STRING_ID) * OptionCount);
> +  if (ReturnedArray == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    *ReturnSize = 0;
> +    return NULL;
> +  }
> +
> +  for (Index = 0; Index < OptionCount; Index++) {
> +    Value                = OrderedListGetArrayData (HiiStatement->Value.Buffer,
> HiiStatement->Value.BufferValueType, Index);
> +    ReturnedArray[Index] = OrderedListOptionValueToStringId (HiiStatement,
> Value);
> +  }
> +
> +  return ReturnedArray;
> +}
> +
> +/**
> +  Convert HII string to the value in HII ordered list opcode.
> +
> +  @param[in]  Statement     Statement private instance
> +  @param[in]  Schema        Schema string
> +  @param[in]  HiiString     Input string
> +  @param[out] Value         Value returned
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +HiiStringToOrderedListOptionValue (
> +  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *Statement,
> +  IN  CHAR8                                      *Schema,
> +  IN  EFI_STRING                                 HiiString,
> +  OUT UINT64                                     *Value
> +  )
> +{
> +  LIST_ENTRY           *Link;
> +  HII_QUESTION_OPTION  *Option;
> +  EFI_STRING           TmpString;
> +  BOOLEAN              Found;
> +
> +  if ((Statement == NULL) || IS_EMPTY_STRING (HiiString) || (Value ==
> NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Value = 0;
> +
> +  if (Statement->HiiStatement->Operand != EFI_IFR_ORDERED_LIST_OP) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  if (IsListEmpty (&Statement->HiiStatement->OptionListHead)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Found = FALSE;
> +  Link  = GetFirstNode (&Statement->HiiStatement->OptionListHead);
> +  while (!IsNull (&Statement->HiiStatement->OptionListHead, Link)) {
> +    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
> +
> +    TmpString = HiiGetRedfishString (Statement->ParentForm-
> >ParentFormset->HiiHandle, Schema, Option->Text);
> +    if (TmpString != NULL) {
> +      if (StrCmp (TmpString, HiiString) == 0) {
> +        *Value = ExtendHiiValueToU64 (&Option->Value);
> +        Found  = TRUE;
> +      }
> +
> +      FreePool (TmpString);
> +    }
> +
> +    if (Found) {
> +      return EFI_SUCCESS;
> +    }
> +
> +    Link = GetNextNode (&Statement->HiiStatement->OptionListHead, Link);
> +  }
> +
> +  return EFI_NOT_FOUND;
> +}
> +
> +/**
> +  Convert HII value to Redfish value.
> +
> +  @param[in]  HiiHandle     HII handle.
> +  @param[in]  FullSchema    Schema string.
> +  @param[in]  HiiStatement  HII statement.
> +  @param[in]  Value         Value to be converted.
> +  @param[out] RedfishValue  Value in Redfish format.
> +
> +  @retval EFI_SUCCESS       Redfish value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +HiiValueToRedfishValue (
> +  IN  EFI_HII_HANDLE       HiiHandle,
> +  IN  CHAR8                *FullSchema,
> +  IN  HII_STATEMENT        *HiiStatement,
> +  IN  HII_STATEMENT_VALUE  *Value,
> +  OUT EDKII_REDFISH_VALUE  *RedfishValue
> +  )
> +{
> +  EFI_STATUS     Status;
> +  EFI_STRING_ID  StringId;
> +  UINTN          Index;
> +  UINTN          Count;
> +  EFI_STRING_ID  *StringIdArray;
> +
> +  if ((HiiHandle == NULL) || (HiiStatement == NULL) || (Value == NULL) ||
> (RedfishValue == NULL) || IS_EMPTY_STRING (FullSchema)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  StringIdArray = NULL;
> +  Count         = 0;
> +  Status        = EFI_SUCCESS;
> +
> +  switch (HiiStatement->Operand) {
> +    case EFI_IFR_ONE_OF_OP:
> +      StringId = HiiValueToOneOfOptionStringId (HiiStatement, Value);
> +      if (StringId == 0) {
> +        ASSERT (FALSE);
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle,
> FullSchema, StringId);
> +      if (RedfishValue->Value.Buffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        break;
> +      }
> +
> +      RedfishValue->Type = RedfishValueTypeString;
> +      break;
> +    case EFI_IFR_STRING_OP:
> +      if (Value->Type != EFI_IFR_TYPE_STRING) {
> +        ASSERT (FALSE);
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      RedfishValue->Type         = RedfishValueTypeString;
> +      RedfishValue->Value.Buffer = AllocatePool (StrLen ((CHAR16 *)Value-
> >Buffer) + 1);
> +      UnicodeStrToAsciiStrS ((CHAR16 *)Value->Buffer, RedfishValue-
> >Value.Buffer, StrLen ((CHAR16 *)Value->Buffer) + 1);
> +      break;
> +    case EFI_IFR_CHECKBOX_OP:
> +    case EFI_IFR_NUMERIC_OP:
> +      Status = HiiValueToRedfishNumeric (Value, RedfishValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, failed to convert HII value to Redfish
> value: %r\n", __FUNCTION__, Status));
> +        break;
> +      }
> +
> +      break;
> +    case EFI_IFR_ACTION_OP:
> +      if (Value->Type != EFI_IFR_TYPE_ACTION) {
> +        ASSERT (FALSE);
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      //
> +      // Action has no value. Just return unknown type.
> +      //
> +      RedfishValue->Type = RedfishValueTypeUnknown;
> +      break;
> +    case EFI_IFR_ORDERED_LIST_OP:
> +      StringIdArray = HiiValueToOrderedListOptionStringId (HiiStatement,
> &Count);
> +      if (StringIdArray == NULL) {
> +        ASSERT (FALSE);
> +        Status = EFI_DEVICE_ERROR;
> +        break;
> +      }
> +
> +      RedfishValue->Value.StringArray = AllocatePool (sizeof (CHAR8 *) *
> Count);
> +      if (RedfishValue->Value.StringArray == NULL) {
> +        ASSERT (FALSE);
> +        Status = EFI_OUT_OF_RESOURCES;
> +        break;
> +      }
> +
> +      for (Index = 0; Index < Count; Index++) {
> +        ASSERT (StringIdArray[Index] != 0);
> +        RedfishValue->Value.StringArray[Index] = HiiGetRedfishAsciiString
> (HiiHandle, FullSchema, StringIdArray[Index]);
> +        ASSERT (RedfishValue->Value.StringArray[Index] != NULL);
> +      }
> +
> +      RedfishValue->ArrayCount = Count;
> +      RedfishValue->Type       = RedfishValueTypeStringArray;
> +
> +      FreePool (StringIdArray);
> +      break;
> +    default:
> +      DEBUG ((DEBUG_ERROR, "%a, catch unsupported type: 0x%x! Please
> contact with author if we need to support this type.\n", __FUNCTION__,
> HiiStatement->Operand));
> +      ASSERT (FALSE);
> +      Status = EFI_UNSUPPORTED;
> +      break;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Convert input ascii string to unicode string. It's caller's
> +  responsibility to free returned buffer using FreePool().
> +
> +  @param[in]  AsciiString     Ascii string to be converted.
> +
> +  @retval CHAR16 *            Unicode string on return.
> +
> +**/
> +EFI_STRING
> +StrToUnicodeStr (
> +  IN  CHAR8  *AsciiString
> +  )
> +{
> +  UINTN       StringLen;
> +  EFI_STRING  Buffer;
> +  EFI_STATUS  Status;
> +
> +  if ((AsciiString == NULL) || (AsciiString[0] == '\0')) {
> +    return NULL;
> +  }
> +
> +  StringLen = AsciiStrLen (AsciiString) + 1;
> +  Buffer    = AllocatePool (StringLen * sizeof (CHAR16));
> +  if (Buffer == NULL) {
> +    return NULL;
> +  }
> +
> +  Status = AsciiStrToUnicodeStrS (AsciiString, Buffer, StringLen);
> +  if (EFI_ERROR (Status)) {
> +    FreePool (Buffer);
> +    return NULL;
> +  }
> +
> +  return Buffer;
> +}
> +
> +/**
> +  Return the full Redfish schema string from the given Schema and Version.
> +
> +  Returned schema string is: Schema + '.' + Version
> +
> +  @param[in]  Schema      Schema string
> +  @param[in]  Version     Schema version string
> +
> +  @retval CHAR8 *         Schema string. NULL when errors occur.
> +
> +**/
> +CHAR8 *
> +GetFullSchemaString (
> +  IN CHAR8  *Schema,
> +  IN CHAR8  *Version
> +  )
> +{
> +  UINTN  Size;
> +  CHAR8  *FullName;
> +
> +  if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version)) {
> +    return NULL;
> +  }
> +
> +  Size = AsciiStrSize (CONFIGURE_LANGUAGE_PREFIX) + AsciiStrSize
> (Schema) + AsciiStrSize (Version);
> +
> +  FullName = AllocatePool (Size);
> +  if (FullName == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out-of-resource\n", __FUNCTION__));
> +    return NULL;
> +  }
> +
> +  AsciiSPrint (FullName, Size, "%a%a.%a", CONFIGURE_LANGUAGE_PREFIX,
> Schema, Version);
> +
> +  return FullName;
> +}
> +
> +/**
> +  Common implementation to get statement private instance.
> +
> +  @param[in]   RedfishPlatformConfigPrivate   Private instance.
> +  @param[in]   Schema                         Redfish schema string.
> +  @param[in]   ConfigureLang                  Configure language that refers to this
> statement.
> +  @param[out]  Statement                      Statement instance
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +RedfishPlatformConfigGetStatementCommon (
> +  IN     REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate,
> +  IN     CHAR8                                      *Schema,
> +  IN     EFI_STRING                                 ConfigureLang,
> +  OUT    REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  **Statement
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;
> +
> +  if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema)
> || IS_EMPTY_STRING (ConfigureLang) || (Statement == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Statement = NULL;
> +
> +  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList,
> &RedfishPlatformConfigPrivate->PendingList);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  TargetStatement = GetStatementPrivateByConfigureLang
> (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
> +  if (TargetStatement == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the
> given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Find current HII question value.
> +  //
> +  Status = GetQuestionValue (
> +             TargetStatement->ParentForm->ParentFormset->HiiFormSet,
> +             TargetStatement->ParentForm->HiiForm,
> +             TargetStatement->HiiStatement,
> +             GetSetValueWithHiiDriver
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to get question current value: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  if (TargetStatement->HiiStatement->Value.Type ==
> EFI_IFR_TYPE_UNDEFINED) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  //
> +  // Return Value.
> +  //
> +  *Statement = TargetStatement;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get Redfish value with the given Schema and Configure Language.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[in]   Schema              The Redfish schema to query.
> +  @param[in]   Version             The Redfish version to query.
> +  @param[in]   ConfigureLang       The target value which match this configure
> Language.
> +  @param[out]  Value               The returned value.
> +
> +  @retval EFI_SUCCESS              Value is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolGetValue (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  IN     CHAR8                                   *Schema,
> +  IN     CHAR8                                   *Version,
> +  IN     EFI_STRING                              ConfigureLang,
> +  OUT    EDKII_REDFISH_VALUE                     *Value
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;
> +  CHAR8                                      *FullSchema;
> +
> +  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING
> (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +  Value->Type                  = RedfishValueTypeUnknown;
> +  Value->ArrayCount            = 0;
> +  FullSchema                   = NULL;
> +
> +  FullSchema = GetFullSchemaString (Schema, Version);
> +  if (FullSchema == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = RedfishPlatformConfigGetStatementCommon
> (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang,
> &TargetStatement);
> +  if (EFI_ERROR (Status)) {
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  if (TargetStatement->Suppressed) {
> +    Status = EFI_ACCESS_DENIED;
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  Status = HiiValueToRedfishValue (
> +             TargetStatement->ParentForm->ParentFormset->HiiHandle,
> +             FullSchema,
> +             TargetStatement->HiiStatement,
> +             &TargetStatement->HiiStatement->Value,
> +             Value
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, HiiValueToRedfishValue failed: %r\n",
> __FUNCTION__, Status));
> +  }
> +
> +RELEASE_RESOURCE:
> +
> +  if (FullSchema != NULL) {
> +    FreePool (FullSchema);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Function to save question value into HII database.
> +
> +  @param[in]   HiiFormset       HII form-set instance
> +  @param[in]   HiiForm          HII form instance
> +  @param[in]   HiiStatement     HII statement that keeps new value.
> +  @param[in]   Value            New value to apply.
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +RedfishPlatformConfigSaveQuestionValue (
> +  IN  HII_FORMSET          *HiiFormset,
> +  IN  HII_FORM             *HiiForm,
> +  IN  HII_STATEMENT        *HiiStatement,
> +  IN  HII_STATEMENT_VALUE  *Value
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((HiiFormset == NULL) || (HiiForm == NULL) || (HiiStatement == NULL)
> || (Value == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = SetQuestionValue (
> +             HiiFormset,
> +             HiiForm,
> +             HiiStatement,
> +             Value
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to set question value: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  Status = SubmitForm (HiiFormset, HiiForm);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to submit form: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Common implementation to set statement private instance.
> +
> +  @param[in]   RedfishPlatformConfigPrivate   Private instance.
> +  @param[in]   Schema                         Redfish schema string.
> +  @param[in]   ConfigureLang                  Configure language that refers to this
> statement.
> +  @param[in]   StatementValue                 Statement value.
> +
> +  @retval EFI_SUCCESS       HII value is returned successfully.
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +RedfishPlatformConfigSetStatementCommon (
> +  IN     REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate,
> +  IN     CHAR8                            *Schema,
> +  IN     EFI_STRING                       ConfigureLang,
> +  IN     HII_STATEMENT_VALUE              *StatementValue
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;
> +  EFI_STRING                                 TempBuffer;
> +  UINT8                                      *StringArray;
> +  UINTN                                      Index;
> +  UINT64                                     Value;
> +  CHAR8                                      **CharArray;
> +
> +  if ((RedfishPlatformConfigPrivate == NULL) || IS_EMPTY_STRING (Schema)
> || IS_EMPTY_STRING (ConfigureLang) || (StatementValue == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TempBuffer  = NULL;
> +  StringArray = NULL;
> +
> +  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList,
> &RedfishPlatformConfigPrivate->PendingList);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  TargetStatement = GetStatementPrivateByConfigureLang
> (&RedfishPlatformConfigPrivate->FormsetList, Schema, ConfigureLang);
> +  if (TargetStatement == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, No match HII statement is found by the
> given %s in schema %a\n", __FUNCTION__, ConfigureLang, Schema));
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  if (StatementValue->Type != TargetStatement->HiiStatement-
> >Value.Type) {
> +    //
> +    // We treat one-of type as string in Redfish. But one-of statement is not
> +    // in string format from HII point of view. Do a patch here.
> +    //
> +    if ((TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP)
> && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
> +      TempBuffer = StrToUnicodeStr ((CHAR8 *)StatementValue->Buffer);
> +      if (TempBuffer == NULL) {
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +
> +      FreePool (StatementValue->Buffer);
> +      StatementValue->Buffer    = NULL;
> +      StatementValue->BufferLen = 0;
> +
> +      Status = HiiStringToOneOfOptionValue (TargetStatement, Schema,
> TempBuffer, StatementValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, failed to find option value by the given
> %s\n", __FUNCTION__, TempBuffer));
> +        FreePool (TempBuffer);
> +        return EFI_NOT_FOUND;
> +      }
> +
> +      FreePool (TempBuffer);
> +    } else if ((TargetStatement->HiiStatement->Operand ==
> EFI_IFR_ORDERED_LIST_OP) && (StatementValue->Type ==
> EFI_IFR_TYPE_STRING)) {
> +      //
> +      // We treat ordered list type as string in Redfish. But ordered list
> statement is not
> +      // in string format from HII point of view. Do a patch here.
> +      //
> +      StringArray = AllocateZeroPool (TargetStatement->HiiStatement-
> >StorageWidth);
> +      if (StringArray == NULL) {
> +        return EFI_OUT_OF_RESOURCES;
> +      }
> +
> +      //
> +      // Arrange new option order from input string array
> +      //
> +      CharArray = (CHAR8 **)StatementValue->Buffer;
> +      for (Index = 0; Index < StatementValue->BufferLen; Index++) {
> +        TempBuffer = StrToUnicodeStr (CharArray[Index]);
> +        if (TempBuffer == NULL) {
> +          return EFI_OUT_OF_RESOURCES;
> +        }
> +
> +        Status = HiiStringToOrderedListOptionValue (TargetStatement, Schema,
> TempBuffer, &Value);
> +        if (EFI_ERROR (Status)) {
> +          ASSERT (FALSE);
> +          continue;
> +        }
> +
> +        FreePool (TempBuffer);
> +        OrderedListSetArrayData (StringArray, TargetStatement->HiiStatement-
> >Value.BufferValueType, Index, Value);
> +      }
> +
> +      StatementValue->Type            = EFI_IFR_TYPE_BUFFER;
> +      StatementValue->Buffer          = StringArray;
> +      StatementValue->BufferLen       = TargetStatement->HiiStatement-
> >StorageWidth;
> +      StatementValue->BufferValueType = TargetStatement->HiiStatement-
> >Value.BufferValueType;
> +    } else if ((TargetStatement->HiiStatement->Operand ==
> EFI_IFR_NUMERIC_OP) && (StatementValue->Type ==
> EFI_IFR_TYPE_NUM_SIZE_64)) {
> +      //
> +      // Redfish only has numeric value type and it does not care about the
> value size.
> +      // Do a patch here so we have proper value size applied.
> +      //
> +      StatementValue->Type = TargetStatement->HiiStatement->Value.Type;
> +    } else {
> +      DEBUG ((DEBUG_ERROR, "%a, catch value type mismatch! input type:
> 0x%x but target value type: 0x%x\n", __FUNCTION__, StatementValue-
> >Type, TargetStatement->HiiStatement->Value.Type));
> +      ASSERT (FALSE);
> +    }
> +  }
> +
> +  Status = RedfishPlatformConfigSaveQuestionValue (
> +             TargetStatement->ParentForm->ParentFormset->HiiFormSet,
> +             TargetStatement->ParentForm->HiiForm,
> +             TargetStatement->HiiStatement,
> +             StatementValue
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to save question value: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set Redfish value with the given Schema and Configure Language.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[in]   Schema              The Redfish schema to query.
> +  @param[in]   Version             The Redfish version to query.
> +  @param[in]   ConfigureLang       The target value which match this configure
> Language.
> +  @param[in]   Value               The value to set.
> +
> +  @retval EFI_SUCCESS              Value is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolSetValue (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  IN     CHAR8                                   *Schema,
> +  IN     CHAR8                                   *Version,
> +  IN     EFI_STRING                              ConfigureLang,
> +  IN     EDKII_REDFISH_VALUE                     Value
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  REDFISH_PLATFORM_CONFIG_PRIVATE  *RedfishPlatformConfigPrivate;
> +  CHAR8                            *FullSchema;
> +  HII_STATEMENT_VALUE              NewValue;
> +
> +  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING
> (Version) || IS_EMPTY_STRING (ConfigureLang)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if ((Value.Type == RedfishValueTypeUnknown) || (Value.Type >=
> RedfishValueTypeMax)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +  FullSchema                   = NULL;
> +
> +  FullSchema = GetFullSchemaString (Schema, Version);
> +  if (FullSchema == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  ZeroMem (&NewValue, sizeof (HII_STATEMENT_VALUE));
> +
> +  switch (Value.Type) {
> +    case RedfishValueTypeInteger:
> +    case RedfishValueTypeBoolean:
> +      Status = RedfishNumericToHiiValue (&Value, &NewValue);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, failed to convert Redfish value to Hii
> value: %r\n", __FUNCTION__, Status));
> +        goto RELEASE_RESOURCE;
> +      }
> +
> +      break;
> +    case RedfishValueTypeString:
> +      NewValue.Type      = EFI_IFR_TYPE_STRING;
> +      NewValue.BufferLen = (UINT16)AsciiStrSize (Value.Value.Buffer);
> +      NewValue.Buffer    = AllocateCopyPool (NewValue.BufferLen,
> Value.Value.Buffer);
> +      if (NewValue.Buffer == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto RELEASE_RESOURCE;
> +      }
> +
> +      break;
> +    case RedfishValueTypeStringArray:
> +      NewValue.Type      = EFI_IFR_TYPE_STRING;
> +      NewValue.BufferLen = (UINT16)Value.ArrayCount;
> +      NewValue.Buffer    = (UINT8 *)Value.Value.StringArray;
> +      break;
> +    default:
> +      ASSERT (FALSE);
> +      break;
> +  }
> +
> +  Status = RedfishPlatformConfigSetStatementCommon
> (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang, &NewValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to set value to statement: %r\n",
> __FUNCTION__, Status));
> +  }
> +
> +RELEASE_RESOURCE:
> +
> +  if (FullSchema != NULL) {
> +    FreePool (FullSchema);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get the list of Configure Language from platform configuration by the
> given Schema and RegexPattern.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[in]   Schema              The Redfish schema to query.
> +  @param[in]   Version             The Redfish version to query.
> +  @param[in]   RegexPattern        The target Configure Language pattern.
> This is used for regular expression matching.
> +  @param[out]  ConfigureLangList   The list of Configure Language.
> +  @param[out]  Count               The number of Configure Language in
> ConfigureLangList.
> +
> +  @retval EFI_SUCCESS              ConfigureLangList is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolGetConfigureLang (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  IN     CHAR8                                   *Schema,
> +  IN     CHAR8                                   *Version,
> +  IN     EFI_STRING                              RegexPattern,
> +  OUT    EFI_STRING                              **ConfigureLangList,
> +  OUT    UINTN                                   *Count
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate;
> +  EFI_STATUS                                      Status;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  StatementList;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF
> *StatementRef;
> +  LIST_ENTRY                                      *NextLink;
> +  EFI_STRING                                      TmpString;
> +  EFI_STRING                                      *TmpConfigureLangList;
> +  UINTN                                           Index;
> +  CHAR8                                           *FullSchema;
> +
> +  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING
> (Version) || (Count == NULL) || (ConfigureLangList == NULL) ||
> IS_EMPTY_STRING (RegexPattern)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *Count                       = 0;
> +  *ConfigureLangList           = NULL;
> +  FullSchema                   = NULL;
> +  TmpConfigureLangList         = NULL;
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +
> +  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList,
> &RedfishPlatformConfigPrivate->PendingList);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  FullSchema = GetFullSchemaString (Schema, Version);
> +  if (FullSchema == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = GetStatementPrivateByConfigureLangRegex (
> +             RedfishPlatformConfigPrivate->RegularExpressionProtocol,
> +             &RedfishPlatformConfigPrivate->FormsetList,
> +             FullSchema,
> +             RegexPattern,
> +             &StatementList
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a,
> GetStatementPrivateByConfigureLangRegex failure: %r\n", __FUNCTION__,
> Status));
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  if (!IsListEmpty (&StatementList.StatementList)) {
> +    TmpConfigureLangList = AllocateZeroPool (sizeof (CHAR16 *) *
> StatementList.Count);
> +    if (TmpConfigureLangList == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto RELEASE_RESOURCE;
> +    }
> +
> +    Index    = 0;
> +    NextLink = GetFirstNode (&StatementList.StatementList);
> +    while (!IsNull (&StatementList.StatementList, NextLink)) {
> +      StatementRef =
> REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
> +      NextLink     = GetNextNode (&StatementList.StatementList, NextLink);
> +
> +      ASSERT (StatementRef->Statement->Description != 0);
> +      if (StatementRef->Statement->Description != 0) {
> +        TmpString = HiiGetRedfishString (StatementRef->Statement-
> >ParentForm->ParentFormset->HiiHandle, FullSchema, StatementRef-
> >Statement->Description);
> +        ASSERT (TmpString != NULL);
> +        if (TmpString != NULL) {
> +          TmpConfigureLangList[Index] = AllocateCopyPool (StrSize (TmpString),
> TmpString);
> +          ASSERT (TmpConfigureLangList[Index] != NULL);
> +          FreePool (TmpString);
> +          ++Index;
> +        }
> +      }
> +    }
> +  }
> +
> +  *Count             = StatementList.Count;
> +  *ConfigureLangList = TmpConfigureLangList;
> +
> +RELEASE_RESOURCE:
> +
> +  if (FullSchema != NULL) {
> +    FreePool (FullSchema);
> +  }
> +
> +  ReleaseStatementList (&StatementList);
> +
> +  return Status;
> +}
> +
> +/**
> +  Get the list of supported Redfish schema from platform configuration.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[out]  SupportedSchema     The supported schema list which is
> separated by ';'.
> +                                   For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-
> redfish-Boot.v1_0_1"
> +                                   The SupportedSchema is allocated by the callee. It's
> caller's
> +                                   responsibility to free this buffer using FreePool().
> +
> +  @retval EFI_SUCCESS              Schema is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolGetSupportedSchema (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  OUT    CHAR8                                   **SupportedSchema
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate;
> +  EFI_STATUS                                Status;
> +  LIST_ENTRY                                *HiiFormsetLink;
> +  LIST_ENTRY                                *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
> +  UINTN                                     Index;
> +  UINTN                                     StringSize;
> +  CHAR8                                     *StringBuffer;
> +  UINTN                                     StringIndex;
> +
> +  if ((This == NULL) || (SupportedSchema == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *SupportedSchema = NULL;
> +
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +
> +  Status = ProcessPendingList (&RedfishPlatformConfigPrivate->FormsetList,
> &RedfishPlatformConfigPrivate->PendingList);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, ProcessPendingList failure: %r\n",
> __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  if (IsListEmpty (&RedfishPlatformConfigPrivate->FormsetList)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Calculate for string buffer size.
> +  //
> +  StringSize     = 0;
> +  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate-
> >FormsetList);
> +  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList,
> HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate-
> >FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
> +      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count;
> Index++) {
> +        StringSize += AsciiStrSize (HiiFormsetPrivate-
> >SupportedSchema.SchemaList[Index]);
> +      }
> +    }
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  if (StringSize == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  StringBuffer = AllocatePool (StringSize);
> +  if (StringBuffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  StringIndex    = 0;
> +  HiiFormsetLink = GetFirstNode (&RedfishPlatformConfigPrivate-
> >FormsetList);
> +  while (!IsNull (&RedfishPlatformConfigPrivate->FormsetList,
> HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (&RedfishPlatformConfigPrivate-
> >FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    if (HiiFormsetPrivate->SupportedSchema.Count > 0) {
> +      for (Index = 0; Index < HiiFormsetPrivate->SupportedSchema.Count;
> Index++) {
> +        AsciiStrCpyS (&StringBuffer[StringIndex], (StringSize - StringIndex),
> HiiFormsetPrivate->SupportedSchema.SchemaList[Index]);
> +        StringIndex              += AsciiStrLen (HiiFormsetPrivate-
> >SupportedSchema.SchemaList[Index]);
> +        StringBuffer[StringIndex] = ';';
> +        ++StringIndex;
> +      }
> +    }
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  StringBuffer[--StringIndex] = '\0';
> +
> +  *SupportedSchema = StringBuffer;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get Redfish default value with the given Schema and Configure Language.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[in]   Schema              The Redfish schema to query.
> +  @param[in]   Version             The Redfish version to query.
> +  @param[in]   ConfigureLang       The target value which match this configure
> Language.
> +  @param[in]   DefaultClass        The UEFI defined default class.
> +                                   Please refer to UEFI spec. 33.2.5.8 "defaults" for details.
> +  @param[out]  Value               The returned value.
> +
> +  @retval EFI_SUCCESS              Value is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolGetDefaultValue (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  IN     CHAR8                                   *Schema,
> +  IN     CHAR8                                   *Version,
> +  IN     EFI_STRING                              ConfigureLang,
> +  IN     UINT16                                  DefaultClass,
> +  OUT    EDKII_REDFISH_VALUE                     *Value
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;
> +  CHAR8                                      *FullSchema;
> +  HII_STATEMENT_VALUE                        DefaultValue;
> +
> +  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING
> (Version) || IS_EMPTY_STRING (ConfigureLang) || (Value == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +  ZeroMem (&DefaultValue, sizeof (HII_STATEMENT_VALUE));
> +  ZeroMem (Value, sizeof (EDKII_REDFISH_VALUE));
> +
> +  FullSchema = NULL;
> +  FullSchema = GetFullSchemaString (Schema, Version);
> +  if (FullSchema == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = RedfishPlatformConfigGetStatementCommon
> (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang,
> &TargetStatement);
> +  if (EFI_ERROR (Status)) {
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  if (TargetStatement->Suppressed) {
> +    Status = EFI_ACCESS_DENIED;
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  Status = GetQuestionDefault (TargetStatement->ParentForm-
> >ParentFormset->HiiFormSet, TargetStatement->ParentForm->HiiForm,
> TargetStatement->HiiStatement, DefaultClass, &DefaultValue);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, GetQuestionDefault failed: %r\n",
> __FUNCTION__, Status));
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  Status = HiiValueToRedfishValue (
> +             TargetStatement->ParentForm->ParentFormset->HiiHandle,
> +             FullSchema,
> +             TargetStatement->HiiStatement,
> +             &DefaultValue,
> +             Value
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, HiiValueToRedfishValue failed: %r\n",
> __FUNCTION__, Status));
> +  }
> +
> +RELEASE_RESOURCE:
> +
> +  if (FullSchema != NULL) {
> +    FreePool (FullSchema);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Get Redfish attribute value with the given Schema and Configure Language.
> +
> +  @param[in]   This                Pointer to
> EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
> +  @param[in]   Schema              The Redfish schema to query.
> +  @param[in]   Version             The Redfish version to query.
> +  @param[in]   ConfigureLang       The target value which match this configure
> Language.
> +  @param[out]  AttributeValue      The attribute value.
> +
> +  @retval EFI_SUCCESS              Value is returned successfully.
> +  @retval Others                   Some error happened.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigProtocolGetAttribute (
> +  IN     EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL  *This,
> +  IN     CHAR8                                   *Schema,
> +  IN     CHAR8                                   *Version,
> +  IN     EFI_STRING                              ConfigureLang,
> +  OUT    EDKII_REDFISH_ATTRIBUTE                 *AttributeValue
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  REDFISH_PLATFORM_CONFIG_PRIVATE
> *RedfishPlatformConfigPrivate;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *TargetStatement;
> +  CHAR8                                      *FullSchema;
> +  CHAR8                                      *Buffer;
> +
> +  if ((This == NULL) || IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING
> (Version) || IS_EMPTY_STRING (ConfigureLang) || (AttributeValue == NULL))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  RedfishPlatformConfigPrivate =
> REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS (This);
> +  ZeroMem (AttributeValue, sizeof (EDKII_REDFISH_ATTRIBUTE));
> +  FullSchema = NULL;
> +  FullSchema = GetFullSchemaString (Schema, Version);
> +  if (FullSchema == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = RedfishPlatformConfigGetStatementCommon
> (RedfishPlatformConfigPrivate, FullSchema, ConfigureLang,
> &TargetStatement);
> +  if (EFI_ERROR (Status)) {
> +    goto RELEASE_RESOURCE;
> +  }
> +
> +  if (TargetStatement->Description != 0) {
> +    AttributeValue->AttributeName = HiiGetRedfishAsciiString
> (TargetStatement->ParentForm->ParentFormset->HiiHandle, FullSchema,
> TargetStatement->Description);
> +    Buffer                        = GetAttributeNameFromConfigLanguage
> (AttributeValue->AttributeName);
> +    if (Buffer != NULL) {
> +      FreePool (AttributeValue->AttributeName);
> +      AttributeValue->AttributeName = Buffer;
> +    }
> +
> +    AttributeValue->DisplayName = HiiGetEnglishAsciiString
> (TargetStatement->ParentForm->ParentFormset->HiiHandle,
> TargetStatement->Description);
> +  }
> +
> +  if (TargetStatement->Help != 0) {
> +    AttributeValue->HelpText = HiiGetEnglishAsciiString (TargetStatement-
> >ParentForm->ParentFormset->HiiHandle, TargetStatement->Help);
> +  }
> +
> +  AttributeValue->ReadOnly      = ((TargetStatement->Flags &
> EFI_IFR_FLAG_READ_ONLY) == 0 ? FALSE : TRUE);
> +  AttributeValue->ResetRequired = ((TargetStatement->Flags &
> EFI_IFR_FLAG_RESET_REQUIRED) == 0 ? FALSE : TRUE);
> +  AttributeValue->Type          = HiiStatementToAttributeType
> (TargetStatement->HiiStatement);
> +  AttributeValue->Suppress      = TargetStatement->Suppressed;
> +  AttributeValue->GrayedOut     = TargetStatement->GrayedOut;
> +
> +  //
> +  // Build up menu path
> +  //
> +  AttributeValue->MenuPath = BuildMenPath (TargetStatement);
> +  if (AttributeValue->MenuPath == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to build menu path for \"%a\"\n",
> __FUNCTION__, AttributeValue->AttributeName));
> +  }
> +
> +  //
> +  // Deal with maximum and minimum
> +  //
> +  if (AttributeValue->Type == RedfishAttributeTypeString) {
> +    AttributeValue->StrMaxSize = TargetStatement-
> >StatementData.StrMaxSize;
> +    AttributeValue->StrMinSize = TargetStatement-
> >StatementData.StrMinSize;
> +  } else if (AttributeValue->Type == RedfishAttributeTypeInteger) {
> +    AttributeValue->NumMaximum = TargetStatement-
> >StatementData.NumMaximum;
> +    AttributeValue->NumMinimum = TargetStatement-
> >StatementData.NumMinimum;
> +    AttributeValue->NumStep    = TargetStatement-
> >StatementData.NumStep;
> +  }
> +
> +  //
> +  // Provide value array if this is enumeration type.
> +  //
> +  if (TargetStatement->HiiStatement->Operand == EFI_IFR_ONE_OF_OP) {
> +    Status = OneOfStatementToAttributeValues (TargetStatement-
> >ParentForm->ParentFormset->HiiHandle, FullSchema, TargetStatement,
> &AttributeValue->Values);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, failed to convert one-of options to
> attribute values: %r\n", __FUNCTION__, Status));
> +    }
> +  }
> +
> +RELEASE_RESOURCE:
> +
> +  if (FullSchema != NULL) {
> +    FreePool (FullSchema);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Functions which are registered to receive notification of
> +  database events have this prototype. The actual event is encoded
> +  in NotifyType. The following table describes how PackageType,
> +  PackageGuid, Handle, and Package are used for each of the
> +  notification types.
> +
> +  @param[in] PackageType  Package type of the notification.
> +  @param[in] PackageGuid  If PackageType is
> +                          EFI_HII_PACKAGE_TYPE_GUID, then this is
> +                          the pointer to the GUID from the Guid
> +                          field of EFI_HII_PACKAGE_GUID_HEADER.
> +                          Otherwise, it must be NULL.
> +  @param[in] Package      Points to the package referred to by the
> +                          notification Handle The handle of the package
> +                          list which contains the specified package.
> +  @param[in] Handle       The HII handle.
> +  @param[in] NotifyType   The type of change concerning the
> +                          database. See
> +                          EFI_HII_DATABASE_NOTIFY_TYPE.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigFormUpdateNotify (
> +  IN UINT8                         PackageType,
> +  IN CONST EFI_GUID                *PackageGuid,
> +  IN CONST EFI_HII_PACKAGE_HEADER  *Package,
> +  IN EFI_HII_HANDLE                Handle,
> +  IN EFI_HII_DATABASE_NOTIFY_TYPE  NotifyType
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if ((NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK) ||
> (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK)) {
> +    //
> +    // HII formset on this handle is updated by driver during run-time. The
> formset needs to be reloaded.
> +    //
> +    Status = NotifyFormsetUpdate (Handle,
> &mRedfishPlatformConfigPrivate->PendingList);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, failed to notify updated formset of HII
> handle: 0x%x\n", __FUNCTION__, Handle));
> +      return Status;
> +    }
> +  } else if (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK) {
> +    //
> +    // HII resource is removed. The formset is no longer exist.
> +    //
> +    Status = NotifyFormsetDeleted (Handle,
> &mRedfishPlatformConfigPrivate->PendingList);
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, failed to notify deleted formset of HII
> handle: 0x%x\n", __FUNCTION__, Handle));
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This is a EFI_HII_STRING_PROTOCOL notification event handler.
> +
> +  Install HII package notification.
> +
> +  @param[in] Event    Event whose notification function is being invoked.
> +  @param[in] Context  Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +HiiStringProtocolInstalled (
> +  IN  EFI_EVENT  Event,
> +  IN  VOID       *Context
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Locate HII database protocol.
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiStringProtocolGuid,
> +                  NULL,
> +                  (VOID **)&mRedfishPlatformConfigPrivate->HiiString
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_STRING_PROTOCOL failure:
> %r\n", __FUNCTION__, Status));
> +    return;
> +  }
> +
> +  gBS->CloseEvent (Event);
> +  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent = NULL;
> +}
> +
> +/**
> +  This is a EFI_HII_DATABASE_PROTOCOL notification event handler.
> +
> +  Install HII package notification.
> +
> +  @param[in] Event    Event whose notification function is being invoked.
> +  @param[in] Context  Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +HiiDatabaseProtocolInstalled (
> +  IN  EFI_EVENT  Event,
> +  IN  VOID       *Context
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Locate HII database protocol.
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiDatabaseProtocolGuid,
> +                  NULL,
> +                  (VOID **)&mRedfishPlatformConfigPrivate->HiiDatabase
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, locate EFI_HII_DATABASE_PROTOCOL
> failure: %r\n", __FUNCTION__, Status));
> +    return;
> +  }
> +
> +  //
> +  // Register package notification when new form package is installed.
> +  //
> +  Status = mRedfishPlatformConfigPrivate->HiiDatabase-
> >RegisterPackageNotify (
> +                                                         mRedfishPlatformConfigPrivate->HiiDatabase,
> +                                                         EFI_HII_PACKAGE_FORMS,
> +                                                         NULL,
> +                                                         RedfishPlatformConfigFormUpdateNotify,
> +                                                         EFI_HII_DATABASE_NOTIFY_NEW_PACK,
> +                                                         &mRedfishPlatformConfigPrivate-
> >NotifyHandle
> +                                                         );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for
> EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__,
> Status));
> +  }
> +
> +  //
> +  // Register package notification when new form package is updated.
> +  //
> +  Status = mRedfishPlatformConfigPrivate->HiiDatabase-
> >RegisterPackageNotify (
> +                                                         mRedfishPlatformConfigPrivate->HiiDatabase,
> +                                                         EFI_HII_PACKAGE_FORMS,
> +                                                         NULL,
> +                                                         RedfishPlatformConfigFormUpdateNotify,
> +                                                         EFI_HII_DATABASE_NOTIFY_ADD_PACK,
> +                                                         &mRedfishPlatformConfigPrivate-
> >NotifyHandle
> +                                                         );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, RegisterPackageNotify for
> EFI_HII_DATABASE_NOTIFY_NEW_PACK failure: %r\n", __FUNCTION__,
> Status));
> +  }
> +
> +  gBS->CloseEvent (Event);
> +  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent = NULL;
> +}
> +
> +/**
> +  This is a EFI_REGULAR_EXPRESSION_PROTOCOL notification event handler.
> +
> +  @param[in] Event    Event whose notification function is being invoked.
> +  @param[in] Context  Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +RegexProtocolInstalled (
> +  IN  EFI_EVENT  Event,
> +  IN  VOID       *Context
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  //
> +  // Locate regular expression protocol.
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiRegularExpressionProtocolGuid,
> +                  NULL,
> +                  (VOID **)&mRedfishPlatformConfigPrivate-
> >RegularExpressionProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, locate
> EFI_REGULAR_EXPRESSION_PROTOCOL failure: %r\n", __FUNCTION__,
> Status));
> +    return;
> +  }
> +
> +  gBS->CloseEvent (Event);
> +  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent = NULL;
> +}
> +
> +/**
> +  Unloads an image.
> +
> +  @param  ImageHandle           Handle that identifies the image to be
> unloaded.
> +
> +  @retval EFI_SUCCESS           The image has been unloaded.
> +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> handle.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigDxeUnload (
> +  IN EFI_HANDLE  ImageHandle
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (mRedfishPlatformConfigPrivate != NULL) {
> +    Status = gBS->UninstallProtocolInterface (
> +                    mRedfishPlatformConfigPrivate->ImageHandle,
> +                    &gEdkIIRedfishPlatformConfigProtocolGuid,
> +                    (VOID *)&mRedfishPlatformConfigPrivate->Protocol
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "%a, can not uninstall
> gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status));
> +      ASSERT (FALSE);
> +    }
> +
> +    //
> +    // Close events
> +    //
> +    if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent != NULL) {
> +      gBS->CloseEvent (mRedfishPlatformConfigPrivate-
> >HiiDbNotify.ProtocolEvent);
> +    }
> +
> +    if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent !=
> NULL) {
> +      gBS->CloseEvent (mRedfishPlatformConfigPrivate-
> >HiiStringNotify.ProtocolEvent);
> +    }
> +
> +    if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent != NULL)
> {
> +      gBS->CloseEvent (mRedfishPlatformConfigPrivate-
> >RegexNotify.ProtocolEvent);
> +    }
> +
> +    //
> +    // Unregister package notification.
> +    //
> +    if (mRedfishPlatformConfigPrivate->NotifyHandle != NULL) {
> +      mRedfishPlatformConfigPrivate->HiiDatabase->UnregisterPackageNotify
> (
> +                                                    mRedfishPlatformConfigPrivate->HiiDatabase,
> +                                                    mRedfishPlatformConfigPrivate->NotifyHandle
> +                                                    );
> +    }
> +
> +    ReleaseFormsetList (&mRedfishPlatformConfigPrivate->FormsetList);
> +    FreePool (mRedfishPlatformConfigPrivate);
> +    mRedfishPlatformConfigPrivate = NULL;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This is the declaration of an EFI image entry point. This entry point is
> +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> +  both device drivers and bus drivers.
> +
> +  @param  ImageHandle           The firmware allocated handle for the UEFI
> image.
> +  @param  SystemTable           A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval Others                An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +RedfishPlatformConfigDxeEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  mRedfishPlatformConfigPrivate = (REDFISH_PLATFORM_CONFIG_PRIVATE
> *)AllocateZeroPool (sizeof (REDFISH_PLATFORM_CONFIG_PRIVATE));
> +  if (mRedfishPlatformConfigPrivate == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, can not allocate pool for
> REDFISH_PLATFORM_CONFIG_PRIVATE\n", __FUNCTION__));
> +    ASSERT (FALSE);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Protocol initialization
> +  //
> +  mRedfishPlatformConfigPrivate->ImageHandle                 = ImageHandle;
> +  mRedfishPlatformConfigPrivate->Protocol.Revision           =
> REDFISH_PLATFORM_CONFIG_VERSION;
> +  mRedfishPlatformConfigPrivate->Protocol.GetValue           =
> RedfishPlatformConfigProtocolGetValue;
> +  mRedfishPlatformConfigPrivate->Protocol.SetValue           =
> RedfishPlatformConfigProtocolSetValue;
> +  mRedfishPlatformConfigPrivate->Protocol.GetConfigureLang   =
> RedfishPlatformConfigProtocolGetConfigureLang;
> +  mRedfishPlatformConfigPrivate->Protocol.GetSupportedSchema =
> RedfishPlatformConfigProtocolGetSupportedSchema;
> +  mRedfishPlatformConfigPrivate->Protocol.GetAttribute       =
> RedfishPlatformConfigProtocolGetAttribute;
> +  mRedfishPlatformConfigPrivate->Protocol.GetDefaultValue    =
> RedfishPlatformConfigProtocolGetDefaultValue;
> +
> +  InitializeListHead (&mRedfishPlatformConfigPrivate->FormsetList);
> +  InitializeListHead (&mRedfishPlatformConfigPrivate->PendingList);
> +
> +  Status = gBS->InstallProtocolInterface (
> +                  &ImageHandle,
> +                  &gEdkIIRedfishPlatformConfigProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  (VOID *)&mRedfishPlatformConfigPrivate->Protocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, can not install
> gEdkIIRedfishPlatformConfigProtocolGuid: %r\n", __FUNCTION__, Status));
> +    ASSERT (FALSE);
> +  }
> +
> +  //
> +  // Install protocol notification if HII database protocol is installed.
> +  //
> +  mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent =
> EfiCreateProtocolNotifyEvent (
> +                                                               &gEfiHiiDatabaseProtocolGuid,
> +                                                               TPL_CALLBACK,
> +                                                               HiiDatabaseProtocolInstalled,
> +                                                               NULL,
> +                                                               &mRedfishPlatformConfigPrivate-
> >HiiDbNotify.Registration
> +                                                               );
> +  if (mRedfishPlatformConfigPrivate->HiiDbNotify.ProtocolEvent == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for
> gEfiHiiDatabaseProtocolGuid\n", __FUNCTION__));
> +    ASSERT (FALSE);
> +  }
> +
> +  //
> +  // Install protocol notification if HII string protocol is installed.
> +  //
> +  mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent =
> EfiCreateProtocolNotifyEvent (
> +                                                                   &gEfiHiiStringProtocolGuid,
> +                                                                   TPL_CALLBACK,
> +                                                                   HiiStringProtocolInstalled,
> +                                                                   NULL,
> +                                                                   &mRedfishPlatformConfigPrivate-
> >HiiStringNotify.Registration
> +                                                                   );
> +  if (mRedfishPlatformConfigPrivate->HiiStringNotify.ProtocolEvent == NULL)
> {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for
> gEfiHiiStringProtocolGuid\n", __FUNCTION__));
> +    ASSERT (FALSE);
> +  }
> +
> +  //
> +  // Install protocol notification if regular expression protocol is installed.
> +  //
> +  mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent =
> EfiCreateProtocolNotifyEvent (
> +                                                               &gEfiRegularExpressionProtocolGuid,
> +                                                               TPL_CALLBACK,
> +                                                               RegexProtocolInstalled,
> +                                                               NULL,
> +                                                               &mRedfishPlatformConfigPrivate-
> >RegexNotify.Registration
> +                                                               );
> +  if (mRedfishPlatformConfigPrivate->RegexNotify.ProtocolEvent == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to create protocol notification for
> gEfiRegularExpressionProtocolGuid\n", __FUNCTION__));
> +    ASSERT (FALSE);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
> b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
> new file mode 100644
> index 000000000000..8b8ff0ce4bda
> --- /dev/null
> +++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
> @@ -0,0 +1,1364 @@
> +/** @file
> +  The implementation of EDKII Redfish Platform Config Protocol.
> +
> +  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
> +  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights
> reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include "RedfishPlatformConfigDxe.h"
> +#include "RedfishPlatformConfigImpl.h"
> +
> +extern REDFISH_PLATFORM_CONFIG_PRIVATE
> *mRedfishPlatformConfigPrivate;
> +
> +/**
> +  Debug dump HII string.
> +
> +  @param[in]  HiiHandle   HII handle instance
> +  @param[in]  StringId    HII string to dump
> +
> +  @retval EFI_SUCCESS       Dump HII string successfully
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +DumpHiiString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN EFI_STRING_ID   StringId
> +  )
> +{
> +  EFI_STRING  String;
> +
> +  if ((HiiHandle == NULL) || (StringId == 0)) {
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "???"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  String = HiiGetString (HiiHandle, StringId, NULL);
> +  if (String == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%s", String));
> +  FreePool (String);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Debug dump HII form-set data.
> +
> +  @param[in]  FormsetPrivate    HII form-set private instance.
> +
> +  @retval EFI_SUCCESS       Dump form-set successfully
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +DumpFormset (
> +  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate
> +  )
> +{
> +  LIST_ENTRY                                 *HiiFormLink;
> +  LIST_ENTRY                                 *HiiNextFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;
> +  LIST_ENTRY                                 *HiiStatementLink;
> +  LIST_ENTRY                                 *HiiNextStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  UINTN                                      Index;
> +
> +  if (FormsetPrivate == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Index       = 0;
> +  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
> +  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
> +    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK
> (HiiFormLink);
> +    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList,
> HiiFormLink);
> +
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "  [%d] form: %d title: ",
> ++Index, HiiFormPrivate->Id));
> +    DumpHiiString (FormsetPrivate->HiiHandle, HiiFormPrivate->Title);
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "\n"));
> +
> +    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
> +    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
> +      HiiStatementPrivate  =
> REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
> +      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList,
> HiiStatementLink);
> +
> +      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "    QID: 0x%x Prompt: ",
> HiiStatementPrivate->QuestionId));
> +      DumpHiiString (FormsetPrivate->HiiHandle, HiiStatementPrivate-
> >Description);
> +      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "\n"));
> +
> +      HiiStatementLink = HiiNextStatementLink;
> +    }
> +
> +    HiiFormLink = HiiNextFormLink;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Debug dump HII form-set list.
> +
> +  @param[in]  FormsetList   Form-set list instance
> +
> +  @retval EFI_SUCCESS       Dump list successfully
> +  @retval Others            Errors occur
> +
> +**/
> +EFI_STATUS
> +DumpFormsetList (
> +  IN  LIST_ENTRY  *FormsetList
> +  )
> +{
> +  LIST_ENTRY                                *HiiFormsetLink;
> +  LIST_ENTRY                                *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
> +  UINTN                                     Index;
> +
> +  if (FormsetList == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (IsListEmpty (FormsetList)) {
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, Empty formset
> list\n", __FUNCTION__));
> +    return EFI_SUCCESS;
> +  }
> +
> +  Index          = 0;
> +  HiiFormsetLink = GetFirstNode (FormsetList);
> +  while (!IsNull (FormsetList, HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "[%d] HII Handle: 0x%x
> formset: %g at %s\n", ++Index, HiiFormsetPrivate->HiiHandle,
> &HiiFormsetPrivate->Guid, HiiFormsetPrivate->DevicePathStr));
> +    DumpFormset (HiiFormsetPrivate);
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Retrieves a unicode string from a string package in a given language. The
> +  returned string is allocated using AllocatePool().  The caller is responsible
> +  for freeing the allocated buffer using FreePool().
> +
> +  If HiiHandle is NULL, then ASSERT().
> +  If StringId is 0, then ASSET.
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  Language          The specified configure language to get string.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +EFI_STRING
> +HiiGetRedfishString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN CHAR8           *Language,
> +  IN EFI_STRING_ID   StringId
> +  )
> +{
> +  EFI_STATUS  Status;
> +  UINTN       StringSize;
> +  CHAR16      TempString;
> +  EFI_STRING  String;
> +
> +  if ((mRedfishPlatformConfigPrivate->HiiString == NULL) || (HiiHandle ==
> NULL) || (StringId == 0) || IS_EMPTY_STRING (Language)) {
> +    ASSERT (FALSE);
> +    return NULL;
> +  }
> +
> +  //
> +  // Retrieve the size of the string in the string package for the BestLanguage
> +  //
> +  StringSize = 0;
> +  Status     = mRedfishPlatformConfigPrivate->HiiString->GetString (
> +                                                           mRedfishPlatformConfigPrivate->HiiString,
> +                                                           Language,
> +                                                           HiiHandle,
> +                                                           StringId,
> +                                                           &TempString,
> +                                                           &StringSize,
> +                                                           NULL
> +                                                           );
> +  //
> +  // If GetString() returns EFI_SUCCESS for a zero size,
> +  // then there are no supported languages registered for HiiHandle.  If
> GetString()
> +  // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is
> not present
> +  // in the HII Database
> +  //
> +  if (Status != EFI_BUFFER_TOO_SMALL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Allocate a buffer for the return string
> +  //
> +  String = AllocateZeroPool (StringSize);
> +  if (String == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Retrieve the string from the string package
> +  //
> +  Status = mRedfishPlatformConfigPrivate->HiiString->GetString (
> +                                                       mRedfishPlatformConfigPrivate->HiiString,
> +                                                       Language,
> +                                                       HiiHandle,
> +                                                       StringId,
> +                                                       String,
> +                                                       &StringSize,
> +                                                       NULL
> +                                                       );
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // Free the buffer and return NULL if the supported languages can not be
> retrieved.
> +    //
> +    FreePool (String);
> +    String = NULL;
> +  }
> +
> +  //
> +  // Return the Null-terminated Unicode string
> +  //
> +  return String;
> +}
> +
> +/**
> +  Retrieves a ASCII string from a string package in a given language. The
> +  returned string is allocated using AllocatePool().  The caller is responsible
> +  for freeing the allocated buffer using FreePool().
> +
> +  If HiiHandle is NULL, then ASSERT().
> +  If StringId is 0, then ASSET.
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  Language          The specified configure language to get string.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +CHAR8 *
> +HiiGetRedfishAsciiString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN CHAR8           *Language,
> +  IN EFI_STRING_ID   StringId
> +  )
> +{
> +  EFI_STRING  HiiString;
> +  UINTN       StringSize;
> +  CHAR8       *AsciiString;
> +
> +  HiiString = HiiGetRedfishString (HiiHandle, Language, StringId);
> +  if (HiiString == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n",
> __FUNCTION__, StringId, Language));
> +    return NULL;
> +  }
> +
> +  StringSize  = (StrLen (HiiString) + 1) * sizeof (CHAR8);
> +  AsciiString = AllocatePool (StringSize);
> +  if (AsciiString == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (HiiString, AsciiString, StringSize);
> +
> +  FreePool (HiiString);
> +  return AsciiString;
> +}
> +
> +/**
> +  Get string from HII database in English language. The returned string is
> allocated
> +  using AllocatePool(). The caller is responsible for freeing the allocated
> buffer using
> +  FreePool().
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +EFI_STRING
> +HiiGetEnglishString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN EFI_STRING_ID   StringId
> +  )
> +{
> +  return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE,
> StringId);
> +}
> +
> +/**
> +  Get ASCII string from HII database in English language. The returned string
> is allocated
> +  using AllocatePool(). The caller is responsible for freeing the allocated
> buffer using
> +  FreePool().
> +
> +  @param[in]  HiiHandle         A handle that was previously registered in the
> HII Database.
> +  @param[in]  StringId          The identifier of the string to retrieved from the
> string
> +                                package associated with HiiHandle.
> +
> +  @retval NULL   The string specified by StringId is not present in the string
> package.
> +  @retval Other  The string was returned.
> +
> +**/
> +CHAR8 *
> +HiiGetEnglishAsciiString (
> +  IN EFI_HII_HANDLE  HiiHandle,
> +  IN EFI_STRING_ID   StringId
> +  )
> +{
> +  EFI_STRING  HiiString;
> +  UINTN       StringSize;
> +  CHAR8       *AsciiString;
> +
> +  HiiString = HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE,
> StringId);
> +  if (HiiString == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, Can not find string ID: 0x%x with %a\n",
> __FUNCTION__, StringId, ENGLISH_LANGUAGE_CODE));
> +    return NULL;
> +  }
> +
> +  StringSize  = (StrLen (HiiString) + 1) * sizeof (CHAR8);
> +  AsciiString = AllocatePool (StringSize);
> +  if (AsciiString == NULL) {
> +    return NULL;
> +  }
> +
> +  UnicodeStrToAsciiStrS (HiiString, AsciiString, StringSize);
> +
> +  FreePool (HiiString);
> +  return AsciiString;
> +}
> +
> +/**
> +  Check and see if this is supported schema or not.
> +
> +  @param[in]  SupportedSchema   The list of supported schema.
> +  @param[in]  Schema            Schema string to be checked.
> +
> +  @retval BOOLEAN               TRUE if this is supported schema. FALSE
> otherwise.
> +
> +**/
> +BOOLEAN
> +CheckSupportedSchema (
> +  IN REDFISH_PLATFORM_CONFIG_SCHEMA  *SupportedSchema,
> +  IN CHAR8                           *Schema
> +  )
> +{
> +  UINTN  Index;
> +
> +  if ((SupportedSchema == NULL) || IS_EMPTY_STRING (Schema)) {
> +    return FALSE;
> +  }
> +
> +  if (SupportedSchema->Count == 0) {
> +    return FALSE;
> +  }
> +
> +  for (Index = 0; Index < SupportedSchema->Count; Index++) {
> +    if (AsciiStrCmp (SupportedSchema->SchemaList[Index], Schema) == 0) {
> +      return TRUE;
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> +  Get the list of supported schema from the given HII handle.
> +
> +  @param[in]  HiiHandle         HII handle instance.
> +  @param[out] SupportedSchema   Supported schema on this HII handle.
> +
> +  @retval EFI_SUCCESS           Schema list is returned.
> +  @retval EFI_INVALID_PARAMETER HiiHandle is NULL or SupportedSchema
> is NULL.
> +  @retval EFI_NOT_FOUND         No supported schema found.
> +  @retval EFI_OUT_OF_RESOURCES  System is out of memory.
> +
> +**/
> +EFI_STATUS
> +GetSupportedSchema (
> +  IN  EFI_HII_HANDLE                  HiiHandle,
> +  OUT REDFISH_PLATFORM_CONFIG_SCHEMA  *SupportedSchema
> +  )
> +{
> +  CHAR8  *SupportedLanguages;
> +  UINTN  Index;
> +  UINTN  LangIndex;
> +  UINTN  Count;
> +  UINTN  StrSize;
> +  UINTN  ListIndex;
> +
> +  if ((HiiHandle == NULL) || (SupportedSchema == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  SupportedSchema->Count = 0;
> +
> +  SupportedLanguages = HiiGetSupportedLanguages (HiiHandle);
> +  if (SupportedLanguages == NULL) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Index     = 0;
> +  LangIndex = 0;
> +  Count     = 0;
> +  while (TRUE) {
> +    if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] ==
> '\0')) {
> +      if (AsciiStrnCmp (&SupportedLanguages[LangIndex],
> X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
> +        ++Count;
> +      }
> +
> +      LangIndex = Index + 1;
> +    }
> +
> +    if (SupportedLanguages[Index] == '\0') {
> +      break;
> +    }
> +
> +    ++Index;
> +  }
> +
> +  if (Count == 0) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  SupportedSchema->Count      = Count;
> +  SupportedSchema->SchemaList = AllocatePool (sizeof (CHAR8 *) * Count);
> +  if (SupportedSchema->SchemaList == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Index     = 0;
> +  LangIndex = 0;
> +  ListIndex = 0;
> +  while (TRUE) {
> +    if ((SupportedLanguages[Index] == ';') || (SupportedLanguages[Index] ==
> '\0')) {
> +      if (AsciiStrnCmp (&SupportedLanguages[LangIndex],
> X_UEFI_SCHEMA_PREFIX, AsciiStrLen (X_UEFI_SCHEMA_PREFIX)) == 0) {
> +        StrSize                                         = Index - LangIndex;
> +        SupportedSchema->SchemaList[ListIndex]          = AllocateCopyPool
> ((StrSize + 1), &SupportedLanguages[LangIndex]);
> +        SupportedSchema->SchemaList[ListIndex][StrSize] = '\0';
> +        ++ListIndex;
> +      }
> +
> +      LangIndex = Index + 1;
> +    }
> +
> +    if (SupportedLanguages[Index] == '\0') {
> +      break;
> +    }
> +
> +    ++Index;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Search and find statement private instance by given regular expression
> pattern
> +  which describes the Configure Language.
> +
> +  @param[in]  RegularExpressionProtocol   Regular express protocol.
> +  @param[in]  FormsetList                 Form-set list to search.
> +  @param[in]  Schema                      Schema to be matched.
> +  @param[in]  Pattern                     Regular expression pattern.
> +  @param[out] StatementList               Statement list that match above
> pattern.
> +
> +  @retval EFI_SUCCESS             Statement list is returned.
> +  @retval EFI_INVALID_PARAMETER   Input parameter is NULL.
> +  @retval EFI_NOT_READY           Regular express protocol is NULL.
> +  @retval EFI_NOT_FOUND           No statement is found.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +GetStatementPrivateByConfigureLangRegex (
> +  IN  EFI_REGULAR_EXPRESSION_PROTOCOL
> *RegularExpressionProtocol,
> +  IN  LIST_ENTRY                                      *FormsetList,
> +  IN  CHAR8                                           *Schema,
> +  IN  EFI_STRING                                      Pattern,
> +  OUT REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
> *StatementList
> +  )
> +{
> +  LIST_ENTRY                                     *HiiFormsetLink;
> +  LIST_ENTRY                                     *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE
> *HiiFormsetPrivate;
> +  LIST_ENTRY                                     *HiiFormLink;
> +  LIST_ENTRY                                     *HiiNextFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE           *HiiFormPrivate;
> +  LIST_ENTRY                                     *HiiStatementLink;
> +  LIST_ENTRY                                     *HiiNextStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  EFI_STRING                                     TmpString;
> +  UINTN                                          CaptureCount;
> +  BOOLEAN                                        IsMatch;
> +  EFI_STATUS                                     Status;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF  *StatementRef;
> +
> +  if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) ||
> IS_EMPTY_STRING (Pattern) || (StatementList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (RegularExpressionProtocol == NULL) {
> +    return EFI_NOT_READY;
> +  }
> +
> +  StatementList->Count = 0;
> +  InitializeListHead (&StatementList->StatementList);
> +
> +  if (IsListEmpty (FormsetList)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  HiiFormsetLink = GetFirstNode (FormsetList);
> +  while (!IsNull (FormsetList, HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    //
> +    // Performance check.
> +    // If there is no desired Redfish schema found, skip this formset.
> +    //
> +    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema,
> Schema)) {
> +      HiiFormsetLink = HiiFormsetNextLink;
> +      continue;
> +    }
> +
> +    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
> +    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
> +      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList,
> HiiFormLink);
> +      HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK
> (HiiFormLink);
> +
> +      HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
> +      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
> +        HiiNextStatementLink = GetNextNode (&HiiFormPrivate-
> >StatementList, HiiStatementLink);
> +        HiiStatementPrivate  =
> REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
> +
> +        if ((HiiStatementPrivate->Description != 0) && !HiiStatementPrivate-
> >Suppressed) {
> +          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle,
> Schema, HiiStatementPrivate->Description);
> +          if (TmpString != NULL) {
> +            Status = RegularExpressionProtocol->MatchString (
> +                                                  RegularExpressionProtocol,
> +                                                  TmpString,
> +                                                  Pattern,
> +                                                  &gEfiRegexSyntaxTypePerlGuid,
> +                                                  &IsMatch,
> +                                                  NULL,
> +                                                  &CaptureCount
> +                                                  );
> +            if (EFI_ERROR (Status)) {
> +              DEBUG ((DEBUG_ERROR, "%a, MatchString \"%s\" failed: %r\n",
> __FUNCTION__, Pattern, Status));
> +              ASSERT (FALSE);
> +              return Status;
> +            }
> +
> +            //
> +            // Found
> +            //
> +            if (IsMatch) {
> +              StatementRef = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF));
> +              if (StatementRef == NULL) {
> +                return EFI_OUT_OF_RESOURCES;
> +              }
> +
> +              StatementRef->Statement = HiiStatementPrivate;
> +              InsertTailList (&StatementList->StatementList, &StatementRef-
> >Link);
> +              ++StatementList->Count;
> +            }
> +
> +            FreePool (TmpString);
> +          }
> +        }
> +
> +        HiiStatementLink = HiiNextStatementLink;
> +      }
> +
> +      HiiFormLink = HiiNextFormLink;
> +    }
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get statement private instance by the given configure language.
> +
> +  @param[in]  FormsetList                 Form-set list to search.
> +  @param[in]  Schema                      Schema to be matched.
> +  @param[in]  ConfigureLang               Configure language.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *   Pointer
> to statement private instance.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE *
> +GetStatementPrivateByConfigureLang (
> +  IN  LIST_ENTRY  *FormsetList,
> +  IN  CHAR8       *Schema,
> +  IN  EFI_STRING  ConfigureLang
> +  )
> +{
> +  LIST_ENTRY                                 *HiiFormsetLink;
> +  LIST_ENTRY                                 *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE   *HiiFormsetPrivate;
> +  LIST_ENTRY                                 *HiiFormLink;
> +  LIST_ENTRY                                 *HiiNextFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;
> +  LIST_ENTRY                                 *HiiStatementLink;
> +  LIST_ENTRY                                 *HiiNextStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  EFI_STRING                                 TmpString;
> +
> +  if ((FormsetList == NULL) || IS_EMPTY_STRING (Schema) ||
> IS_EMPTY_STRING (ConfigureLang)) {
> +    return NULL;
> +  }
> +
> +  if (IsListEmpty (FormsetList)) {
> +    return NULL;
> +  }
> +
> +  HiiFormsetLink = GetFirstNode (FormsetList);
> +  while (!IsNull (FormsetList, HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    //
> +    // Performance check.
> +    // If there is no desired Redfish schema found, skip this formset.
> +    //
> +    if (!CheckSupportedSchema (&HiiFormsetPrivate->SupportedSchema,
> Schema)) {
> +      HiiFormsetLink = HiiFormsetNextLink;
> +      continue;
> +    }
> +
> +    HiiFormLink = GetFirstNode (&HiiFormsetPrivate->HiiFormList);
> +    while (!IsNull (&HiiFormsetPrivate->HiiFormList, HiiFormLink)) {
> +      HiiNextFormLink = GetNextNode (&HiiFormsetPrivate->HiiFormList,
> HiiFormLink);
> +      HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK
> (HiiFormLink);
> +
> +      HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
> +      while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
> +        HiiNextStatementLink = GetNextNode (&HiiFormPrivate-
> >StatementList, HiiStatementLink);
> +        HiiStatementPrivate  =
> REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
> +
> +        DEBUG_CODE (
> +          STATIC UINTN Index = 0;
> +          DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, [%d] search %s
> in QID: 0x%x form: 0x%x formset: %g\n", __FUNCTION__, ++Index,
> ConfigureLang, HiiStatementPrivate->QuestionId, HiiFormPrivate->Id,
> &HiiFormsetPrivate->Guid));
> +          );
> +
> +        if (HiiStatementPrivate->Description != 0) {
> +          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle,
> Schema, HiiStatementPrivate->Description);
> +          if (TmpString != NULL) {
> +            if (StrCmp (TmpString, ConfigureLang) == 0) {
> +              FreePool (TmpString);
> +              return HiiStatementPrivate;
> +            }
> +
> +            FreePool (TmpString);
> +          }
> +        }
> +
> +        HiiStatementLink = HiiNextStatementLink;
> +      }
> +
> +      HiiFormLink = HiiNextFormLink;
> +    }
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Get form-set private instance by the given HII handle.
> +
> +  @param[in]  HiiHandle       HII handle instance.
> +  @param[in]  FormsetList     Form-set list to search.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to
> form-set private instance.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *
> +GetFormsetPrivateByHiiHandle (
> +  IN  EFI_HII_HANDLE  HiiHandle,
> +  IN  LIST_ENTRY      *FormsetList
> +  )
> +{
> +  LIST_ENTRY                                *HiiFormsetLink;
> +  LIST_ENTRY                                *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
> +
> +  if ((HiiHandle == NULL) || (FormsetList == NULL)) {
> +    return NULL;
> +  }
> +
> +  if (IsListEmpty (FormsetList)) {
> +    return NULL;
> +  }
> +
> +  HiiFormsetLink = GetFirstNode (FormsetList);
> +  while (!IsNull (FormsetList, HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    if (HiiFormsetPrivate->HiiHandle == HiiHandle) {
> +      return HiiFormsetPrivate;
> +    }
> +
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Release formset and all the forms and statements that belong to this
> formset.
> +
> +  @param[in]      FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE
> +
> +  @retval         EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +ReleaseFormset (
> +  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate
> +  )
> +{
> +  LIST_ENTRY                                 *HiiFormLink;
> +  LIST_ENTRY                                 *HiiNextFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;
> +  LIST_ENTRY                                 *HiiStatementLink;
> +  LIST_ENTRY                                 *HiiNextStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  UINTN                                      Index;
> +
> +  if (FormsetPrivate == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  HiiFormLink = GetFirstNode (&FormsetPrivate->HiiFormList);
> +  while (!IsNull (&FormsetPrivate->HiiFormList, HiiFormLink)) {
> +    HiiFormPrivate  = REDFISH_PLATFORM_CONFIG_FORM_FROM_LINK
> (HiiFormLink);
> +    HiiNextFormLink = GetNextNode (&FormsetPrivate->HiiFormList,
> HiiFormLink);
> +
> +    HiiStatementLink = GetFirstNode (&HiiFormPrivate->StatementList);
> +    while (!IsNull (&HiiFormPrivate->StatementList, HiiStatementLink)) {
> +      HiiStatementPrivate  =
> REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK (HiiStatementLink);
> +      HiiNextStatementLink = GetNextNode (&HiiFormPrivate->StatementList,
> HiiStatementLink);
> +
> +      //
> +      // HiiStatementPrivate->HiiStatement will be released in
> DestroyFormSet().
> +      //
> +
> +      if (HiiStatementPrivate->DesStringCache != NULL) {
> +        FreePool (HiiStatementPrivate->DesStringCache);
> +        HiiStatementPrivate->DesStringCache = NULL;
> +      }
> +
> +      RemoveEntryList (&HiiStatementPrivate->Link);
> +      FreePool (HiiStatementPrivate);
> +      HiiStatementLink = HiiNextStatementLink;
> +    }
> +
> +    //
> +    // HiiStatementPrivate->HiiForm will be released in DestroyFormSet().
> +    //
> +
> +    RemoveEntryList (&HiiFormPrivate->Link);
> +    FreePool (HiiFormPrivate);
> +    HiiFormLink = HiiNextFormLink;
> +  }
> +
> +  if (FormsetPrivate->HiiFormSet != NULL) {
> +    DestroyFormSet (FormsetPrivate->HiiFormSet);
> +    FormsetPrivate->HiiFormSet = NULL;
> +  }
> +
> +  if (FormsetPrivate->DevicePathStr != NULL) {
> +    FreePool (FormsetPrivate->DevicePathStr);
> +  }
> +
> +  //
> +  // Release schema list
> +  //
> +  if (FormsetPrivate->SupportedSchema.SchemaList != NULL) {
> +    for (Index = 0; Index < FormsetPrivate->SupportedSchema.Count;
> Index++) {
> +      FreePool (FormsetPrivate->SupportedSchema.SchemaList[Index]);
> +    }
> +
> +    FreePool (FormsetPrivate->SupportedSchema.SchemaList);
> +    FormsetPrivate->SupportedSchema.SchemaList = NULL;
> +    FormsetPrivate->SupportedSchema.Count      = 0;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Create new form-set instance.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE *   Pointer to
> newly created form-set private instance.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *
> +NewFormsetPrivate (
> +  VOID
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *NewFormsetPrivate;
> +
> +  NewFormsetPrivate = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE));
> +  if (NewFormsetPrivate == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Initial newly created formset private data.
> +  //
> +  InitializeListHead (&NewFormsetPrivate->HiiFormList);
> +
> +  return NewFormsetPrivate;
> +}
> +
> +/**
> +  Load the HII formset from the given HII handle.
> +
> +  @param[in]  HiiHandle       Target HII handle to load.
> +  @param[out] FormsetPrivate  The formset private data.
> +
> +  @retval EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +LoadFormset (
> +  IN  EFI_HII_HANDLE                            HiiHandle,
> +  OUT REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE
> *FormsetPrivate
> +  )
> +{
> +  EFI_STATUS                                 Status;
> +  HII_FORMSET                                *HiiFormSet;
> +  HII_FORM                                   *HiiForm;
> +  LIST_ENTRY                                 *HiiFormLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_PRIVATE       *HiiFormPrivate;
> +  HII_STATEMENT                              *HiiStatement;
> +  LIST_ENTRY                                 *HiiStatementLink;
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
> *HiiStatementPrivate;
> +  EFI_GUID                                   ZeroGuid;
> +  EXPRESS_RESULT                             ExpressionResult;
> +
> +  if ((HiiHandle == NULL) || (FormsetPrivate == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET));
> +  if (HiiFormSet == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Find HII formset by the given HII handle.
> +  //
> +  ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
> +  Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet);
> +  if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) {
> +    Status = EFI_NOT_FOUND;
> +    goto ErrorExit;
> +  }
> +
> +  //
> +  // Initialize formset
> +  //
> +  InitializeFormSet (HiiFormSet);
> +
> +  //
> +  // Initialize formset private data.
> +  //
> +  FormsetPrivate->HiiFormSet = HiiFormSet;
> +  FormsetPrivate->HiiHandle  = HiiHandle;
> +  CopyGuid (&FormsetPrivate->Guid, &HiiFormSet->Guid);
> +  FormsetPrivate->DevicePathStr = ConvertDevicePathToText (HiiFormSet-
> >DevicePath, FALSE, FALSE);
> +  Status                        = GetSupportedSchema (FormsetPrivate->HiiHandle,
> &FormsetPrivate->SupportedSchema);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_WARN, "%a, No schema from HII handle: 0x%x found:
> %r\n", __FUNCTION__, FormsetPrivate->HiiHandle, Status));
> +  }
> +
> +  HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead);
> +  while (!IsNull (&HiiFormSet->FormListHead, HiiFormLink)) {
> +    HiiForm = HII_FORM_FROM_LINK (HiiFormLink);
> +
> +    HiiFormPrivate = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_FORM_PRIVATE));
> +    if (HiiFormPrivate == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ErrorExit;
> +    }
> +
> +    //
> +    // Initialize form private data.
> +    //
> +    HiiFormPrivate->HiiForm       = HiiForm;
> +    HiiFormPrivate->Id            = HiiForm->FormId;
> +    HiiFormPrivate->Title         = HiiForm->FormTitle;
> +    HiiFormPrivate->ParentFormset = FormsetPrivate;
> +    HiiFormPrivate->Suppressed    = FALSE;
> +    InitializeListHead (&HiiFormPrivate->StatementList);
> +
> +    if ((HiiForm->SuppressExpression != NULL) &&
> +        (EvaluateExpressionList (HiiForm->SuppressExpression, TRUE,
> HiiFormSet, HiiForm) == ExpressSuppress))
> +    {
> +      HiiFormPrivate->Suppressed = TRUE;
> +    }
> +
> +    HiiStatementLink = GetFirstNode (&HiiForm->StatementListHead);
> +    while (!IsNull (&HiiForm->StatementListHead, HiiStatementLink)) {
> +      HiiStatement = HII_STATEMENT_FROM_LINK (HiiStatementLink);
> +
> +      HiiStatementPrivate = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE));
> +      if (HiiStatementPrivate == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +        goto ErrorExit;
> +      }
> +
> +      //
> +      // Initialize statement private data.
> +      //
> +      HiiStatementPrivate->HiiStatement             = HiiStatement;
> +      HiiStatementPrivate->QuestionId               = HiiStatement->QuestionId;
> +      HiiStatementPrivate->Description              = HiiStatement->Prompt;
> +      HiiStatementPrivate->Help                     = HiiStatement->Help;
> +      HiiStatementPrivate->ParentForm               = HiiFormPrivate;
> +      HiiStatementPrivate->Flags                    = HiiStatement->QuestionFlags;
> +      HiiStatementPrivate->StatementData.NumMaximum = HiiStatement-
> >ExtraData.NumData.Maximum;
> +      HiiStatementPrivate->StatementData.NumMinimum = HiiStatement-
> >ExtraData.NumData.Minimum;
> +      HiiStatementPrivate->StatementData.NumStep    = HiiStatement-
> >ExtraData.NumData.Step;
> +      HiiStatementPrivate->StatementData.StrMaxSize = HiiStatement-
> >ExtraData.StrData.MaxSize;
> +      HiiStatementPrivate->StatementData.StrMinSize = HiiStatement-
> >ExtraData.StrData.MinSize;
> +      HiiStatementPrivate->Suppressed               = FALSE;
> +      HiiStatementPrivate->GrayedOut                = FALSE;
> +
> +      //
> +      // Expression
> +      //
> +      if (HiiFormPrivate->Suppressed) {
> +        HiiStatementPrivate->Suppressed = TRUE;
> +      } else {
> +        if (HiiStatement->ExpressionList != NULL) {
> +          ExpressionResult =  EvaluateExpressionList (HiiStatement-
> >ExpressionList, TRUE, HiiFormSet, HiiForm);
> +          if (ExpressionResult == ExpressGrayOut) {
> +            HiiStatementPrivate->GrayedOut = TRUE;
> +          } else if (ExpressionResult == ExpressSuppress) {
> +            HiiStatementPrivate->Suppressed = TRUE;
> +          }
> +        }
> +      }
> +
> +      //
> +      // Attach to statement list.
> +      //
> +      InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate-
> >Link);
> +      HiiStatementLink = GetNextNode (&HiiForm->StatementListHead,
> HiiStatementLink);
> +    }
> +
> +    //
> +    // Attach to form list.
> +    //
> +    InsertTailList (&FormsetPrivate->HiiFormList, &HiiFormPrivate->Link);
> +    HiiFormLink = GetNextNode (&HiiFormSet->FormListHead, HiiFormLink);
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ErrorExit:
> +
> +  //
> +  // Release HiiFormSet if HiiFormSet is not linked to FormsetPrivate yet.
> +  //
> +  if ((HiiFormSet != NULL) && (FormsetPrivate->HiiFormSet != HiiFormSet)) {
> +    DestroyFormSet (HiiFormSet);
> +  }
> +
> +  //
> +  // Release resource when error happens.
> +  //
> +  ReleaseFormset (FormsetPrivate);
> +
> +  return Status;
> +}
> +
> +/**
> +  Load formset list on given HII handle.
> +
> +  @param[in]  HiiHandle     HII handle to load formset list.
> +  @param[out] FormsetList   Pointer to formset list returned on given
> handle.
> +
> +  @retval     EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +LoadFormsetList (
> +  IN   EFI_HII_HANDLE  *HiiHandle,
> +  OUT  LIST_ENTRY      *FormsetList
> +  )
> +{
> +  EFI_STATUS                                Status;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;
> +
> +  if ((HiiHandle == NULL) || (FormsetList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  FormsetPrivate = GetFormsetPrivateByHiiHandle (HiiHandle, FormsetList);
> +  if (FormsetPrivate != NULL) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  FormsetPrivate =  NewFormsetPrivate ();
> +  if (FormsetPrivate == NULL) {
> +    DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Load formset on the given HII handle.
> +  //
> +  Status = LoadFormset (HiiHandle, FormsetPrivate);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a, failed to load formset: %r\n",
> __FUNCTION__, Status));
> +    FreePool (FormsetPrivate);
> +    return Status;
> +  }
> +
> +  //
> +  // Attach to cache list.
> +  //
> +  InsertTailList (FormsetList, &FormsetPrivate->Link);
> +
> +  DEBUG_CODE (
> +    DumpFormsetList (FormsetList);
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Release formset list and all the forms that belong to this formset.
> +
> +  @param[in]      FormsetList   Pointer to formset list that needs to be
> +                                released.
> +
> +  @retval         EFI_STATUS
> +
> +**/
> +EFI_STATUS
> +ReleaseFormsetList (
> +  IN  LIST_ENTRY  *FormsetList
> +  )
> +{
> +  LIST_ENTRY                                *HiiFormsetLink;
> +  LIST_ENTRY                                *HiiFormsetNextLink;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *HiiFormsetPrivate;
> +
> +  if (FormsetList == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (IsListEmpty (FormsetList)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  HiiFormsetLink = GetFirstNode (FormsetList);
> +  while (!IsNull (FormsetList, HiiFormsetLink)) {
> +    HiiFormsetNextLink = GetNextNode (FormsetList, HiiFormsetLink);
> +    HiiFormsetPrivate  =
> REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK (HiiFormsetLink);
> +
> +    //
> +    // Detach from list.
> +    //
> +    RemoveEntryList (&HiiFormsetPrivate->Link);
> +    ReleaseFormset (HiiFormsetPrivate);
> +    FreePool (HiiFormsetPrivate);
> +    HiiFormsetLink = HiiFormsetNextLink;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get all pending list.
> +
> +  @param[in]  HiiHandle   HII handle instance.
> +  @param[in]  PendingList Pending list to keep pending data.
> +
> +  @retval REDFISH_PLATFORM_CONFIG_PENDING_LIST *   Pointer to
> pending list data.
> +
> +**/
> +REDFISH_PLATFORM_CONFIG_PENDING_LIST *
> +GetPendingList (
> +  IN  EFI_HII_HANDLE  *HiiHandle,
> +  IN  LIST_ENTRY      *PendingList
> +  )
> +{
> +  LIST_ENTRY                            *PendingListLink;
> +  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *Target;
> +
> +  if ((HiiHandle == NULL) || (PendingList == NULL)) {
> +    return NULL;
> +  }
> +
> +  if (IsListEmpty (PendingList)) {
> +    return NULL;
> +  }
> +
> +  PendingListLink = GetFirstNode (PendingList);
> +  while (!IsNull (PendingList, PendingListLink)) {
> +    Target = REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK
> (PendingListLink);
> +
> +    if (Target->HiiHandle == HiiHandle) {
> +      return Target;
> +    }
> +
> +    PendingListLink = GetNextNode (PendingList, PendingListLink);
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  When HII database is updated. Keep updated HII handle into pending list
> so
> +  we can process them later.
> +
> +  @param[in]  HiiHandle   HII handle instance.
> +  @param[in]  PendingList Pending list to keep HII handle which is recently
> updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is
> NULL.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +NotifyFormsetUpdate (
> +  IN  EFI_HII_HANDLE  *HiiHandle,
> +  IN  LIST_ENTRY      *PendingList
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;
> +
> +  if ((HiiHandle == NULL) || (PendingList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check and see if this HII handle is processed already.
> +  //
> +  TargetPendingList = GetPendingList (HiiHandle, PendingList);
> +  if (TargetPendingList != NULL) {
> +    TargetPendingList->IsDeleted = FALSE;
> +    DEBUG_CODE (
> +      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, HII handle: 0x%x is
> updated\n", __FUNCTION__, HiiHandle));
> +      );
> +    return EFI_SUCCESS;
> +  }
> +
> +  TargetPendingList = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
> +  if (TargetPendingList == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  TargetPendingList->HiiHandle = HiiHandle;
> +  TargetPendingList->IsDeleted = FALSE;
> +
> +  InsertTailList (PendingList, &TargetPendingList->Link);
> +
> +  DEBUG_CODE (
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, HII handle: 0x%x is
> created\n", __FUNCTION__, HiiHandle));
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  When HII database is updated and form-set is deleted. Keep deleted HII
> handle into pending list so
> +  we can process them later.
> +
> +  @param[in]  HiiHandle   HII handle instance.
> +  @param[in]  PendingList Pending list to keep HII handle which is recently
> updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   HiiHandle is NULL or PendingList is
> NULL.
> +  @retval EFI_OUT_OF_RESOURCES    System is out of memory.
> +
> +**/
> +EFI_STATUS
> +NotifyFormsetDeleted (
> +  IN  EFI_HII_HANDLE  *HiiHandle,
> +  IN  LIST_ENTRY      *PendingList
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_PENDING_LIST  *TargetPendingList;
> +
> +  if ((HiiHandle == NULL) || (PendingList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check and see if this HII handle is processed already.
> +  //
> +  TargetPendingList = GetPendingList (HiiHandle, PendingList);
> +  if (TargetPendingList != NULL) {
> +    TargetPendingList->IsDeleted = TRUE;
> +    DEBUG_CODE (
> +      DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, HII handle: 0x%x is
> updated and deleted\n", __FUNCTION__, HiiHandle));
> +      );
> +    return EFI_SUCCESS;
> +  }
> +
> +  TargetPendingList = AllocateZeroPool (sizeof
> (REDFISH_PLATFORM_CONFIG_PENDING_LIST));
> +  if (TargetPendingList == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  TargetPendingList->HiiHandle = HiiHandle;
> +  TargetPendingList->IsDeleted = TRUE;
> +
> +  InsertTailList (PendingList, &TargetPendingList->Link);
> +
> +  DEBUG_CODE (
> +    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, HII handle: 0x%x is
> deleted\n", __FUNCTION__, HiiHandle));
> +    );
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  There are HII database update and we need to process them accordingly
> so that we
> +  won't use stale data. This function will parse updated HII handle again in
> order
> +  to get updated data-set.
> +
> +  @param[in]  FormsetList   List to keep HII form-set.
> +  @param[in]  PendingList   List to keep HII handle that is updated.
> +
> +  @retval EFI_SUCCESS             HII handle is saved in pending list.
> +  @retval EFI_INVALID_PARAMETER   FormsetList is NULL or PendingList is
> NULL.
> +
> +**/
> +EFI_STATUS
> +ProcessPendingList (
> +  IN  LIST_ENTRY  *FormsetList,
> +  IN  LIST_ENTRY  *PendingList
> +  )
> +{
> +  LIST_ENTRY                                *PendingListLink;
> +  LIST_ENTRY                                *PendingListNextLink;
> +  REDFISH_PLATFORM_CONFIG_PENDING_LIST      *Target;
> +  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate;
> +  EFI_STATUS                                Status;
> +
> +  if ((FormsetList == NULL) || (PendingList == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (IsListEmpty (PendingList)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  PendingListLink = GetFirstNode (PendingList);
> +  while (!IsNull (PendingList, PendingListLink)) {
> +    PendingListNextLink = GetNextNode (PendingList, PendingListLink);
> +    Target              =
> REDFISH_PLATFORM_CONFIG_PENDING_LIST_FROM_LINK
> (PendingListLink);
> +
> +    if (Target->IsDeleted) {
> +      //
> +      // The HII resource on this HII handle is removed. Release the formset.
> +      //
> +      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle,
> FormsetList);
> +      if (FormsetPrivate != NULL) {
> +        DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, formset: %g is
> removed because driver release HII resource it already\n", __FUNCTION__,
> FormsetPrivate->Guid));
> +        RemoveEntryList (&FormsetPrivate->Link);
> +        ReleaseFormset (FormsetPrivate);
> +        FreePool (FormsetPrivate);
> +      } else {
> +        DEBUG ((DEBUG_WARN, "%a, formset on HII handle 0x%x was
> removed already\n", __FUNCTION__, Target->HiiHandle));
> +      }
> +    } else {
> +      //
> +      // The HII resource on this HII handle is updated/removed.
> +      //
> +      FormsetPrivate = GetFormsetPrivateByHiiHandle (Target->HiiHandle,
> FormsetList);
> +      if (FormsetPrivate != NULL) {
> +        //
> +        // HII formset already exist, release it and query again.
> +        //
> +        DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a, formset: %g is
> updated. Release current formset\n", __FUNCTION__, &FormsetPrivate-
> >Guid));
> +        RemoveEntryList (&FormsetPrivate->Link);
> +        ReleaseFormset (FormsetPrivate);
> +        FreePool (FormsetPrivate);
> +      }
> +
> +      Status = LoadFormsetList (Target->HiiHandle, FormsetList);
> +      if (EFI_ERROR (Status)) {
> +        DEBUG ((DEBUG_ERROR, "%a, load formset from HII handle: 0x%x
> failed: %r\n", __FUNCTION__, Target->HiiHandle, Status));
> +      }
> +    }
> +
> +    //
> +    // Detach it from list first.
> +    //
> +    RemoveEntryList (&Target->Link);
> +    FreePool (Target);
> +
> +    PendingListLink = PendingListNextLink;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Release all resource in statement list.
> +
> +  @param[in]  StatementList   Statement list to be released.
> +
> +  @retval EFI_SUCCESS             All resource are released.
> +  @retval EFI_INVALID_PARAMETER   StatementList is NULL.
> +
> +**/
> +EFI_STATUS
> +ReleaseStatementList (
> +  IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST
> *StatementList
> +  )
> +{
> +  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF  *StatementRef;
> +  LIST_ENTRY                                     *NextLink;
> +
> +  if (StatementList == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (IsListEmpty (&StatementList->StatementList)) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  NextLink = GetFirstNode (&StatementList->StatementList);
> +  while (!IsNull (&StatementList->StatementList, NextLink)) {
> +    StatementRef =
> REDFISH_PLATFORM_CONFIG_STATEMENT_REF_FROM_LINK (NextLink);
> +    NextLink     = GetNextNode (&StatementList->StatementList, NextLink);
> +
> +    RemoveEntryList (&StatementRef->Link);
> +    FreePool (StatementRef);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> --
> 2.17.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#103042): https://edk2.groups.io/g/devel/message/103042
Mute This Topic: https://groups.io/mt/98235742/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list