Rename x-uefi-redfish to x-UEFI-redfish to match the format of UEFI configuration namespace prefix. RFC: https://edk2.groups.io/g/rfc/message/849 Signed-off-by: Jeff Brasen <jbrasen@nvidia.com> Co-authored-by: Nickle Wang <nicklew@nvidia.com> Cc: Abner Chang <abner.chang@amd.com> Cc: Igor Kulchytskyy <igork@ami.com> Cc: Nick Ramirez <nramirez@nvidia.com> Reviewed-by: Abner Chang <abner.chang@amd.com>
		
			
				
	
	
		
			2753 lines
		
	
	
		
			87 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2753 lines
		
	
	
		
			87 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The implementation of EDKII Redfish Platform Config Protocol.
 | 
						|
 | 
						|
  (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
 | 
						|
  Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 | 
						|
  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 | 
						|
 | 
						|
  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 *
 | 
						|
BuildMenuPath (
 | 
						|
  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 ((DEBUG_REDFISH_PLATFORM_CONFIG, "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 ((DEBUG_REDFISH_PLATFORM_CONFIG, " %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) {
 | 
						|
      TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, ENGLISH_LANGUAGE_CODE, 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 ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.Type= 0x%x\n", OrderedListStatement->Value.Type));
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.BufferValueType= 0x%x\n", OrderedListStatement->Value.BufferValueType));
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.BufferLen= 0x%x\n", OrderedListStatement->Value.BufferLen));
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.Buffer= 0x%x\n", OrderedListStatement->Value.Buffer));
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "Value.MaxContainers= 0x%x\n", OrderedListStatement->ExtraData.OrderListData.MaxContainers));
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "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_REDFISH_PLATFORM_CONFIG, "%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_REDFISH_PLATFORM_CONFIG, "%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_REDFISH_PLATFORM_CONFIG, "%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_REDFISH_PLATFORM_CONFIG, "%d ", Value64[Index]));
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      Value8 = (UINT8 *)OrderedListStatement->Value.Buffer;
 | 
						|
      Count  = OrderedListStatement->StorageWidth / sizeof (UINT8);
 | 
						|
      for (Index = 0; Index < Count; Index++) {
 | 
						|
        DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%d ", Value8[Index]));
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "\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) {
 | 
						|
      TmpString = HiiGetRedfishString (Statement->ParentForm->ParentFormset->HiiHandle, ENGLISH_LANGUAGE_CODE, 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 = HiiStrLen (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 ((TargetStatement->HiiStatement->Operand == EFI_IFR_STRING_OP) && (StatementValue->Type == EFI_IFR_TYPE_STRING)) {
 | 
						|
    if (StatementValue->Value.string != 0) {
 | 
						|
      // Delete HII string which was created for HII statement operand = EFI_IFR_STRING_OP and Type = EFI_IFR_TYPE_STRING.
 | 
						|
      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                                      *TmpConfigureLangList;
 | 
						|
  UINTN                                           Index;
 | 
						|
  CHAR8                                           *FullSchema;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Harvest config language of %a_%a (Regex: %s).\n", __func__, Schema, Version, RegexPattern));
 | 
						|
 | 
						|
  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) {
 | 
						|
        ASSERT (StatementRef->Statement->XuefiRedfishStr != NULL);
 | 
						|
        TmpConfigureLangList[Index] = AllocateCopyPool (HiiStrSize (StatementRef->Statement->XuefiRedfishStr), (VOID *)StatementRef->Statement->XuefiRedfishStr);
 | 
						|
        ++Index;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *Count             = StatementList.Count;
 | 
						|
  *ConfigureLangList = TmpConfigureLangList;
 | 
						|
 | 
						|
  DEBUG_REDFISH_THIS_MODULE (
 | 
						|
    REDFISH_PLATFORM_CONFIG_DEBUG_CONFIG_LANG_REGEX,
 | 
						|
    "%a: Number of configure language strings harvested: %d\n",
 | 
						|
    __func__,
 | 
						|
    StatementList.Count
 | 
						|
    );
 | 
						|
 | 
						|
  DEBUG_REDFISH_THIS_MODULE_CODE (
 | 
						|
    REDFISH_PLATFORM_CONFIG_DEBUG_CONFIG_LANG_REGEX,
 | 
						|
    DEBUG_REDFISH (DEBUG_REDFISH_COMPONENT_PLATFORM_CONFIG_DXE, "%a: Number of configure language strings harvested: %d\n", __func__, StatementList.Count);
 | 
						|
    for (Index = 0; Index < *Count; Index++) {
 | 
						|
    DEBUG_REDFISH (DEBUG_REDFISH_COMPONENT_PLATFORM_CONFIG_DXE, "   (%d) %s\n", Index, TmpConfigureLangList[Index]);
 | 
						|
  }
 | 
						|
 | 
						|
    );
 | 
						|
 | 
						|
RELEASE_RESOURCE:
 | 
						|
 | 
						|
  if (FullSchema != NULL) {
 | 
						|
    FreePool (FullSchema);
 | 
						|
  }
 | 
						|
 | 
						|
  if (StatementList.Count > 0) {
 | 
						|
    ReleaseStatementList (&StatementList);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: exit.\n", __func__));
 | 
						|
  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;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Entry\n", __func__));
 | 
						|
  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
 | 
						|
  //
 | 
						|
  if (RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
 | 
						|
    AttributeValue->MenuPath = BuildMenuPath (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);
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Exit\n", __func__));
 | 
						|
  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;
 | 
						|
}
 |