From: "Chang, Abner" <abner.chang@amd.com>
To: Nickle Wang <nicklew@nvidia.com>,
"devel@edk2.groups.io" <devel@edk2.groups.io>
Cc: Igor Kulchytskyy <igork@ami.com>, Nick Ramirez <nramirez@nvidia.com>
Subject: Re: [PATCH 3/5] RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL
Date: Sun, 16 Apr 2023 04:08:57 +0000 [thread overview]
Message-ID: <MN2PR12MB3966D775E9D879D019346263EA9F9@MN2PR12MB3966.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20230413062052.1700-1-nicklew@nvidia.com>
[AMD Official Use Only - General]
> -----Original Message-----
> From: Nickle Wang <nicklew@nvidia.com>
> Sent: Thursday, April 13, 2023 2:21 PM
> To: devel@edk2.groups.io
> Cc: Chang, Abner <Abner.Chang@amd.com>; Igor Kulchytskyy
> <igork@ami.com>; Nick Ramirez <nramirez@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@nvidia.com>
> Cc: Abner Chang <abner.chang@amd.com>
> Cc: Igor Kulchytskyy <igork@ami.com>
> Cc: Nick Ramirez <nramirez@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
prev parent reply other threads:[~2023-04-16 4:09 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-13 6:20 [PATCH 3/5] RedfishPkg: Implementation of EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL Nickle Wang
2023-04-16 4:08 ` Chang, Abner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN2PR12MB3966D775E9D879D019346263EA9F9@MN2PR12MB3966.namprd12.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox