mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-01 12:53:27 +01:00
2724 lines
86 KiB
C
2724 lines
86 KiB
C
/** @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;
|
|
}
|
|
|
|
/**
|
|
Debug dump HII statement value.
|
|
|
|
@param[in] ErrorLevel DEBUG macro error level
|
|
@param[in] Value HII statement value to dump
|
|
@param[in] Message Debug message
|
|
|
|
@retval EFI_SUCCESS Dump HII statement value successfully
|
|
@retval Others Errors occur
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DumpHiiStatementValue (
|
|
IN UINTN ErrorLevel,
|
|
IN HII_STATEMENT_VALUE *Value,
|
|
IN CHAR8 *Message OPTIONAL
|
|
)
|
|
{
|
|
UINT64 Data;
|
|
|
|
if (Value == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (Value->Type) {
|
|
case EFI_IFR_TYPE_NUM_SIZE_8:
|
|
Data = Value->Value.u8;
|
|
break;
|
|
case EFI_IFR_TYPE_NUM_SIZE_16:
|
|
Data = Value->Value.u16;
|
|
break;
|
|
case EFI_IFR_TYPE_NUM_SIZE_32:
|
|
Data = Value->Value.u32;
|
|
break;
|
|
case EFI_IFR_TYPE_NUM_SIZE_64:
|
|
Data = Value->Value.u64;
|
|
break;
|
|
case EFI_IFR_TYPE_BOOLEAN:
|
|
Data = (Value->Value.b ? 1 : 0);
|
|
break;
|
|
default:
|
|
DEBUG ((ErrorLevel, "%a: unsupported type: 0x%x\n", __func__, Value->Type));
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (IS_EMPTY_STRING (Message)) {
|
|
DEBUG ((ErrorLevel, "0x%lx\n", Data));
|
|
} else {
|
|
DEBUG ((ErrorLevel, "%a: 0x%lx\n", Message, Data));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Debug dump HII statement prompt string.
|
|
|
|
@param[in] ErrorLevel DEBUG macro error level
|
|
@param[in] HiiHandle HII handle instance
|
|
@param[in] HiiStatement HII statement
|
|
@param[in] Message Debug message
|
|
|
|
@retval EFI_SUCCESS Dump HII statement string successfully
|
|
@retval Others Errors occur
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DumpHiiStatementPrompt (
|
|
IN UINTN ErrorLevel,
|
|
IN EFI_HII_HANDLE HiiHandle,
|
|
IN HII_STATEMENT *HiiStatement,
|
|
IN CHAR8 *Message OPTIONAL
|
|
)
|
|
{
|
|
EFI_STRING String;
|
|
|
|
if ((HiiHandle == NULL) || (HiiStatement == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (HiiStatement->Prompt == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
String = HiiGetString (HiiHandle, HiiStatement->Prompt, NULL);
|
|
if (String == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (IS_EMPTY_STRING (Message)) {
|
|
DEBUG ((ErrorLevel, "%s\n", String));
|
|
} else {
|
|
DEBUG ((ErrorLevel, "%a: %s\n", Message, String));
|
|
}
|
|
|
|
FreePool (String);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
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", __func__, 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", __func__, 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;
|
|
DEBUG ((DEBUG_ERROR, "%a: Unsupported value type: 0x%x\n", __func__, Value->Type));
|
|
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;
|
|
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 ((REDFISH_PLATFORM_CONFIG_DEBUG, "Value.Type= 0x%x\n", OrderedListStatement->Value.Type));
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "Value.BufferValueType= 0x%x\n", OrderedListStatement->Value.BufferValueType));
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "Value.BufferLen= 0x%x\n", OrderedListStatement->Value.BufferLen));
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "Value.Buffer= 0x%x\n", OrderedListStatement->Value.Buffer));
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "Value.MaxContainers= 0x%x\n", OrderedListStatement->ExtraData.OrderListData.MaxContainers));
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "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 ((REDFISH_PLATFORM_CONFIG_DEBUG, "%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 ((REDFISH_PLATFORM_CONFIG_DEBUG, "%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 ((REDFISH_PLATFORM_CONFIG_DEBUG, "%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 ((REDFISH_PLATFORM_CONFIG_DEBUG, "%d ", Value64[Index]));
|
|
}
|
|
|
|
break;
|
|
default:
|
|
Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
|
|
Count = OrderedListStatement->StorageWidth / sizeof (UINT8);
|
|
for (Index = 0; Index < Count; Index++) {
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%d ", Value8[Index]));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "\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", __func__));
|
|
*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;
|
|
CHAR8 NullChar;
|
|
|
|
if ((HiiHandle == NULL) || (HiiStatement == NULL) || (Value == NULL) || (RedfishValue == NULL) || IS_EMPTY_STRING (FullSchema)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
StringIdArray = NULL;
|
|
Count = 0;
|
|
Status = EFI_SUCCESS;
|
|
NullChar = '\0';
|
|
|
|
switch (HiiStatement->Operand) {
|
|
case EFI_IFR_ONE_OF_OP:
|
|
StringId = HiiValueToOneOfOptionStringId (HiiStatement, Value);
|
|
if (StringId == 0) {
|
|
//
|
|
// Print prompt string of HII statement for ease of debugging
|
|
//
|
|
DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not find string ID");
|
|
DumpHiiStatementValue (DEBUG_ERROR, Value, "Current value");
|
|
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;
|
|
}
|
|
|
|
if (Value->Buffer == NULL) {
|
|
RedfishValue->Value.Buffer = AllocateCopyPool (sizeof (NullChar), &NullChar);
|
|
} else {
|
|
RedfishValue->Value.Buffer = StrToAsciiStr ((EFI_STRING)Value->Buffer);
|
|
}
|
|
|
|
if (RedfishValue->Value.Buffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
RedfishValue->Type = RedfishValueTypeString;
|
|
break;
|
|
case EFI_IFR_CHECKBOX_OP:
|
|
//
|
|
// There is case where HII driver defines UINT8 for checked-box opcode storage.
|
|
// IFR compiler will assign EFI_IFR_TYPE_NUM_SIZE_8 to its value type instead of
|
|
// EFI_IFR_TYPE_BOOLEAN. We do a patch here and use boolean value type for this
|
|
// case.
|
|
//
|
|
if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
|
|
Value->Type = EFI_IFR_TYPE_BOOLEAN;
|
|
}
|
|
|
|
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", __func__, 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) {
|
|
//
|
|
// Print prompt string of HII statement for ease of debugging
|
|
//
|
|
DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not get string ID array");
|
|
ASSERT (FALSE);
|
|
Status = EFI_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
|
|
RedfishValue->Value.StringArray = AllocatePool (sizeof (CHAR8 *) * Count);
|
|
if (RedfishValue->Value.StringArray == NULL) {
|
|
//
|
|
// Print prompt string of HII statement for ease of debugging
|
|
//
|
|
DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "Can not allocate memory");
|
|
ASSERT (FALSE);
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
for (Index = 0; Index < Count; Index++) {
|
|
if (StringIdArray[Index] == 0) {
|
|
//
|
|
// Print prompt string of HII statement for ease of debugging
|
|
//
|
|
DumpHiiStatementPrompt (DEBUG_ERROR, HiiHandle, HiiStatement, "String ID in array is 0");
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
RedfishValue->Value.StringArray[Index] = HiiGetRedfishAsciiString (HiiHandle, FullSchema, StringIdArray[Index]);
|
|
ASSERT (RedfishValue->Value.StringArray[Index] != NULL);
|
|
}
|
|
|
|
RedfishValue->ArrayCount = Count;
|
|
RedfishValue->Type = RedfishValueTypeStringArray;
|
|
|
|
FreePool (StringIdArray);
|
|
break;
|
|
case EFI_IFR_TEXT_OP:
|
|
//
|
|
// Use text two as the value
|
|
//
|
|
if (HiiStatement->ExtraData.TextTwo == 0x00) {
|
|
Status = EFI_NOT_FOUND;
|
|
break;
|
|
}
|
|
|
|
RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, HiiStatement->ExtraData.TextTwo);
|
|
if (RedfishValue->Value.Buffer == NULL) {
|
|
//
|
|
// No x-uefi-redfish string defined. Try to get string in English.
|
|
//
|
|
RedfishValue->Value.Buffer = HiiGetEnglishAsciiString (HiiHandle, HiiStatement->ExtraData.TextTwo);
|
|
}
|
|
|
|
if (RedfishValue->Value.Buffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
RedfishValue->Type = RedfishValueTypeString;
|
|
break;
|
|
default:
|
|
DEBUG ((DEBUG_ERROR, "%a: catch unsupported type: 0x%x! Please contact with author if we need to support this type.\n", __func__, 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) {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
Convert input unicode string to ascii string. It's caller's
|
|
responsibility to free returned buffer using FreePool().
|
|
|
|
@param[in] UnicodeString Unicode string to be converted.
|
|
|
|
@retval CHAR8 * Ascii string on return.
|
|
|
|
**/
|
|
CHAR8 *
|
|
StrToAsciiStr (
|
|
IN EFI_STRING UnicodeString
|
|
)
|
|
{
|
|
UINTN StringLen;
|
|
CHAR8 *Buffer;
|
|
EFI_STATUS Status;
|
|
|
|
if (UnicodeString == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
StringLen = StrLen (UnicodeString) + 1;
|
|
Buffer = AllocatePool (StringLen * sizeof (CHAR8));
|
|
if (Buffer == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = UnicodeStrToAsciiStrS (UnicodeString, 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", __func__));
|
|
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", __func__, 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", __func__, ConfigureLang, Schema));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Find current HII question value.
|
|
//
|
|
Status = GetQuestionValue (
|
|
TargetStatement->ParentForm->ParentFormset->HiiFormSet,
|
|
TargetStatement->ParentForm->HiiForm,
|
|
TargetStatement->HiiStatement,
|
|
GetSetValueWithBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "%a: failed to get question current value: %r\n", __func__, 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", __func__, 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", __func__, Status));
|
|
return Status;
|
|
}
|
|
|
|
Status = SubmitForm (HiiFormset, HiiForm);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "%a: failed to submit form: %r\n", __func__, 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", __func__, 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", __func__, 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)) {
|
|
//
|
|
// Keep input buffer to TempBuffer because StatementValue will be
|
|
// assigned in HiiStringToOneOfOptionValue().
|
|
//
|
|
TempBuffer = (EFI_STRING)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", __func__, 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", __func__, StatementValue->Type, TargetStatement->HiiStatement->Value.Type));
|
|
ASSERT (FALSE);
|
|
}
|
|
}
|
|
|
|
if ((TargetStatement->HiiStatement->Operand == EFI_IFR_STRING_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
|
|
//
|
|
// Create string ID for new string.
|
|
//
|
|
StatementValue->Value.string = HiiSetString (TargetStatement->ParentForm->ParentFormset->HiiHandle, 0x00, (EFI_STRING)StatementValue->Buffer, NULL);
|
|
if (StatementValue->Value.string == 0) {
|
|
DEBUG ((DEBUG_ERROR, "%a: can not create string id\n", __func__));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
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", __func__, Status));
|
|
}
|
|
|
|
if (StatementValue->Value.string != 0) {
|
|
HiiDeleteString (StatementValue->Value.string, TargetStatement->ParentForm->ParentFormset->HiiHandle);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
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", __func__, Status));
|
|
goto RELEASE_RESOURCE;
|
|
}
|
|
|
|
break;
|
|
case RedfishValueTypeString:
|
|
if (Value.Value.Buffer == NULL) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto RELEASE_RESOURCE;
|
|
}
|
|
|
|
NewValue.Type = EFI_IFR_TYPE_STRING;
|
|
NewValue.BufferLen = (UINT16)(AsciiStrSize (Value.Value.Buffer) * sizeof (CHAR16));
|
|
NewValue.Buffer = (UINT8 *)StrToUnicodeStr (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", __func__, Status));
|
|
}
|
|
|
|
RELEASE_RESOURCE:
|
|
|
|
if (FullSchema != NULL) {
|
|
FreePool (FullSchema);
|
|
}
|
|
|
|
if ((Value.Type == RedfishValueTypeString) && (NewValue.Buffer != NULL)) {
|
|
FreePool (NewValue.Buffer);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
ZeroMem (&StatementList, sizeof (StatementList));
|
|
*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", __func__, 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", __func__, 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);
|
|
}
|
|
|
|
if (StatementList.Count > 0) {
|
|
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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__, 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", __func__));
|
|
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", __func__, 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", __func__));
|
|
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", __func__));
|
|
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", __func__));
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|