[edk2-devel] [edk2-staging][PATCH 1/3] edk2-staging/RedfishPkg: Add interface to get question default value

Nickle Wang via groups.io nicklew=nvidia.com at groups.io
Wed Dec 7 14:09:10 UTC 2022


Implement GetQuestionDefault() in HiiUtilityLib. Caller can get question
default value from this interface. GetQuestionDefault() is created and
modifed from SetupBrowserDxe\Setup.c under MdeModulePkg.

Signed-off-by: Nickle Wang <nicklew at nvidia.com>
Cc: Abner Chang <abner.chang at amd.com>
Cc: Igor Kulchytskyy <igork at ami.com>
Cc: Nick Ramirez <nramirez at nvidia.com>
---
 RedfishPkg/Include/Library/HiiUtilityLib.h    |  31 +-
 .../Library/HiiUtilityLib/HiiExpression.c     |  77 +++
 .../Library/HiiUtilityLib/HiiExpression.h     |  23 +
 .../HiiUtilityLib/HiiUtilityInternal.c        | 614 ++++++++++++++++++
 4 files changed, 728 insertions(+), 17 deletions(-)

diff --git a/RedfishPkg/Include/Library/HiiUtilityLib.h b/RedfishPkg/Include/Library/HiiUtilityLib.h
index 1f164ba49c..f4be485423 100644
--- a/RedfishPkg/Include/Library/HiiUtilityLib.h
+++ b/RedfishPkg/Include/Library/HiiUtilityLib.h
@@ -3,6 +3,7 @@
 
   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -1168,28 +1169,24 @@ GetHiiExpressionDependency (
   );
 
 /**
-  Evaluate the result of a HII expression.
-
-  If Expression is NULL, then ASSERT.
+  Get default value of question.
 
-  @param  FormSet                FormSet associated with this expression.
-  @param  Form                   Form associated with this expression.
-  @param  Expression             Expression to be evaluated.
+  @param  FormSet                The form set.
+  @param  Form                   The form.
+  @param  Question               The question.
+  @param  DefaultId              The Class of the default.
+  @param  DefaultValue           The default value of given question.
 
-  @retval EFI_SUCCESS            The expression evaluated successfuly
-  @retval EFI_NOT_FOUND          The Question which referenced by a QuestionId
-                                 could not be found.
-  @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
-                                 stack.
-  @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
-  @retval EFI_INVALID_PARAMETER  Syntax error with the Expression
+  @retval EFI_SUCCESS            Question is reset to default value.
 
 **/
 EFI_STATUS
-HpEvaluateHiiExpression (
-  IN     HII_FORMSET       *FormSet,
-  IN     HII_FORM          *Form,
-  IN OUT HII_EXPRESSION    *Expression
+GetQuestionDefault (
+  IN HII_FORMSET           *FormSet,
+  IN HII_FORM              *Form,
+  IN HII_STATEMENT         *Question,
+  IN UINT16                DefaultId,
+  OUT HII_STATEMENT_VALUE  *DefaultValue
   );
 
 #endif // _HII_UTILITY_LIB_
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
index 7111b40acf..c6954587f5 100644
--- a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.c
@@ -3,6 +3,7 @@
 
   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -1365,3 +1366,79 @@ GetHiiExpressionDependency (
 Done:
   return Status;
 }
+
+/**
+  Return the result of the expression list. Check the expression list and
+  return the highest priority express result.
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
+
+  @param  ExpList             The input expression list.
+  @param  Evaluate            Whether need to evaluate the expression first.
+  @param  FormSet             FormSet associated with this expression.
+  @param  Form                Form associated with this expression.
+
+  @retval EXPRESS_RESULT      Return the higher priority express result.
+                              DisableIf > SuppressIf > GrayOutIf > FALSE
+
+**/
+EXPRESS_RESULT
+EvaluateExpressionList (
+  IN HII_EXPRESSION_LIST *ExpList,
+  IN BOOLEAN Evaluate,
+  IN HII_FORMSET *FormSet, OPTIONAL
+  IN HII_FORM    *Form OPTIONAL
+  )
+{
+  UINTN           Index;
+  EXPRESS_RESULT  ReturnVal;
+  EXPRESS_RESULT  CompareOne;
+  EFI_STATUS      Status;
+
+  if (ExpList == NULL) {
+    return ExpressFalse;
+  }
+
+  ASSERT (ExpList->Signature == HII_EXPRESSION_LIST_SIGNATURE);
+  Index = 0;
+
+  //
+  // Check whether need to evaluate the expression first.
+  //
+  if (Evaluate) {
+    while (ExpList->Count > Index) {
+      Status = EvaluateHiiExpression (FormSet, Form, ExpList->Expression[Index++]);
+      if (EFI_ERROR (Status)) {
+        return ExpressFalse;
+      }
+    }
+  }
+
+  //
+  // Run the list of expressions.
+  //
+  ReturnVal = ExpressFalse;
+  for (Index = 0; Index < ExpList->Count; Index++) {
+    if (IsTrue (&ExpList->Expression[Index]->Result)) {
+      switch (ExpList->Expression[Index]->Type) {
+        case EFI_HII_EXPRESSION_SUPPRESS_IF:
+          CompareOne = ExpressSuppress;
+          break;
+
+        case EFI_HII_EXPRESSION_GRAY_OUT_IF:
+          CompareOne = ExpressGrayOut;
+          break;
+
+        case EFI_HII_EXPRESSION_DISABLE_IF:
+          CompareOne = ExpressDisable;
+          break;
+
+        default:
+          return ExpressFalse;
+      }
+
+      ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;
+    }
+  }
+
+  return ReturnVal;
+}
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
index e96c07b4de..25a3a44b48 100644
--- a/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiExpression.h
@@ -3,6 +3,7 @@
 
   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -187,4 +188,26 @@ PopScope (
   OUT UINT8    *Operand
   );
 
+/**
+  Return the result of the expression list. Check the expression list and
+  return the highest priority express result.
+  Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
+
+  @param  ExpList             The input expression list.
+  @param  Evaluate            Whether need to evaluate the expression first.
+  @param  FormSet             FormSet associated with this expression.
+  @param  Form                Form associated with this expression.
+
+  @retval EXPRESS_RESULT      Return the higher priority express result.
+                              DisableIf > SuppressIf > GrayOutIf > FALSE
+
+**/
+EXPRESS_RESULT
+EvaluateExpressionList (
+  IN HII_EXPRESSION_LIST *ExpList,
+  IN BOOLEAN Evaluate,
+  IN HII_FORMSET *FormSet, OPTIONAL
+  IN HII_FORM    *Form OPTIONAL
+  );
+
 #endif
diff --git a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
index 55b78315d1..b4dd61f360 100644
--- a/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
+++ b/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c
@@ -3,6 +3,7 @@
 
   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
   (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -5043,3 +5044,616 @@ Done:
 
   return Status;
 }
+
+/**
+  Set value of a data element in an Array by its Index.
+
+  @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
+SetArrayData (
+  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;
+  }
+}
+
+/**
+  Search an Option of a Question by its value.
+
+  @param  Question               The Question
+  @param  OptionValue            Value for Option to be searched.
+
+  @retval Pointer                Pointer to the found Option.
+  @retval NULL                   Option not found.
+
+**/
+HII_QUESTION_OPTION *
+ValueToOption (
+  IN HII_STATEMENT        *Question,
+  IN HII_STATEMENT_VALUE  *OptionValue
+  )
+{
+  LIST_ENTRY           *Link;
+  HII_QUESTION_OPTION  *Option;
+  EFI_HII_VALUE        Data1;
+  EFI_HII_VALUE        Data2;
+  INTN                 Result;
+  EFI_STATUS           Status;
+
+  Status = HiiStatementValueToHiiValue (OptionValue, &Data1);
+  ASSERT_EFI_ERROR (Status);
+
+  Link = GetFirstNode (&Question->OptionListHead);
+  while (!IsNull (&Question->OptionListHead, Link)) {
+    Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+
+    Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);
+    ASSERT_EFI_ERROR (Status);
+
+    if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+      //
+      // Check the suppressif condition, only a valid option can be return.
+      //
+      if ((Option->SuppressExpression == NULL) ||
+          ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))
+      {
+        return Option;
+      }
+    }
+
+    Link = GetNextNode (&Question->OptionListHead, Link);
+  }
+
+  return NULL;
+}
+
+/**
+  Find the point in the ConfigResp string for this question.
+
+  @param  Question               The question.
+  @param  ConfigResp             Get ConfigResp string.
+
+  @retval  point to the offset where is for this question.
+
+**/
+CHAR16 *
+GetOffsetFromConfigResp (
+  IN HII_STATEMENT  *Question,
+  IN CHAR16         *ConfigResp
+  )
+{
+  CHAR16  *RequestElement;
+  CHAR16  *BlockData;
+
+  //
+  // Type is EFI_HII_VARSTORE_NAME_VALUE.
+  //
+  if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+    RequestElement = StrStr (ConfigResp, Question->VariableName);
+    if (RequestElement != NULL) {
+      //
+      // Skip the "VariableName=" field.
+      //
+      RequestElement += StrLen (Question->VariableName) + 1;
+    }
+
+    return RequestElement;
+  }
+
+  //
+  // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
+  //
+
+  //
+  // Convert all hex digits in ConfigResp to lower case before searching.
+  //
+  HiiToLower (ConfigResp);
+
+  //
+  // 1. Directly use Question->BlockName to find.
+  //
+  RequestElement = StrStr (ConfigResp, Question->BlockName);
+  if (RequestElement != NULL) {
+    //
+    // Skip the "Question->BlockName&VALUE=" field.
+    //
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
+    return RequestElement;
+  }
+
+  //
+  // 2. Change all hex digits in Question->BlockName to lower and compare again.
+  //
+  BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);
+  ASSERT (BlockData != NULL);
+  HiiToLower (BlockData);
+  RequestElement = StrStr (ConfigResp, BlockData);
+  FreePool (BlockData);
+
+  if (RequestElement != NULL) {
+    //
+    // Skip the "Question->BlockName&VALUE=" field.
+    //
+    RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
+  }
+
+  return RequestElement;
+}
+
+/**
+  Get Question default value from AltCfg string.
+
+  @param  FormSet                The form set.
+  @param  Form                   The form
+  @param  Question               The question.
+  @param  DefaultValue           Default value.
+
+  @retval EFI_SUCCESS            Question is reset to default value.
+
+**/
+EFI_STATUS
+GetDefaultValueFromAltCfg (
+  IN     HII_FORMSET          *FormSet,
+  IN     HII_FORM             *Form,
+  IN     HII_STATEMENT        *Question,
+  OUT    HII_STATEMENT_VALUE  *DefaultValue
+  )
+{
+  HII_FORMSET_STORAGE      *Storage;
+  CHAR16                   *ConfigResp;
+  CHAR16                   *Value;
+  LIST_ENTRY               *Link;
+  HII_FORM_CONFIG_REQUEST  *ConfigInfo;
+
+  Storage = Question->Storage;
+  if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Try to get AltCfg string from form. If not found it, then
+  // try to get it from formset.
+  //
+  ConfigResp = NULL;
+  Link       = GetFirstNode (&Form->ConfigRequestHead);
+  while (!IsNull (&Form->ConfigRequestHead, Link)) {
+    ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
+    Link       = GetNextNode (&Form->ConfigRequestHead, Link);
+
+    if (Storage == ConfigInfo->Storage) {
+      ConfigResp = ConfigInfo->ConfigAltResp;
+      break;
+    }
+  }
+
+  if (ConfigResp == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  Value = GetOffsetFromConfigResp (Question, ConfigResp);
+  if (Value == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  return BufferToValue (Question, Value, DefaultValue);
+}
+
+/**
+  Get default Id value used for browser.
+
+  @param  DefaultId              The default id value used by hii.
+
+  @retval Browser used default value.
+
+**/
+INTN
+GetDefaultIdForCallBack (
+  UINTN  DefaultId
+  )
+{
+  if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {
+    return EFI_BROWSER_ACTION_DEFAULT_STANDARD;
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+    return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;
+  } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {
+    return EFI_BROWSER_ACTION_DEFAULT_SAFE;
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {
+    return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {
+    return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;
+  } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {
+    return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;
+  } else {
+    return -1;
+  }
+}
+
+/**
+  Get default value of question.
+
+  @param  FormSet                The form set.
+  @param  Form                   The form.
+  @param  Question               The question.
+  @param  DefaultId              The Class of the default.
+  @param  DefaultValue           The default value of given question.
+
+  @retval EFI_SUCCESS            Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+  IN HII_FORMSET           *FormSet,
+  IN HII_FORM              *Form,
+  IN HII_STATEMENT         *Question,
+  IN UINT16                DefaultId,
+  OUT HII_STATEMENT_VALUE  *DefaultValue
+  )
+{
+  EFI_STATUS                      Status;
+  LIST_ENTRY                      *Link;
+  HII_QUESTION_DEFAULT            *Default;
+  HII_QUESTION_OPTION             *Option;
+  HII_STATEMENT_VALUE             *HiiValue;
+  UINT8                           Index;
+  EFI_STRING                      StrValue;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+  EFI_BROWSER_ACTION_REQUEST      ActionRequest;
+  INTN                            Action;
+  EFI_IFR_TYPE_VALUE              *TypeValue;
+  UINT16                          OriginalDefaultId;
+  HII_FORMSET_DEFAULTSTORE        *DefaultStore;
+  LIST_ENTRY                      *DefaultLink;
+
+  if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (DefaultValue == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status            = EFI_NOT_FOUND;
+  StrValue          = NULL;
+  OriginalDefaultId = DefaultId;
+  DefaultLink       = GetFirstNode (&FormSet->DefaultStoreListHead);
+
+  //
+  // Statement don't have storage, skip them
+  //
+  if (Question->QuestionId == 0) {
+    return Status;
+  }
+
+  //
+  // There are Five ways to specify default value for a Question:
+  //  1, use call back function (highest priority)
+  //  2, use ExtractConfig function
+  //  3, use nested EFI_IFR_DEFAULT
+  //  4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+  //  5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+  //
+  CopyMem (DefaultValue, &Question->Value, sizeof (HII_STATEMENT_VALUE));
+ReGetDefault:
+  HiiValue  = DefaultValue;
+  TypeValue = &HiiValue->Value;
+  if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
+    //
+    // For orderedlist, need to pass the BufferValue to Callback function.
+    //
+    DefaultValue->BufferLen = Question->Value.BufferLen;
+    DefaultValue->Buffer    = AllocateZeroPool (DefaultValue->BufferLen);
+    ASSERT (DefaultValue->Buffer != NULL);
+    if (DefaultValue->Buffer == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;
+  }
+
+  //
+  // Get Question defaut value from call back function.
+  // The string type of question cause HII driver to set string to its default value.
+  // So, we don't do this otherwise it will actually set question to default value.
+  // We only want to get default value of question.
+  //
+  if (HiiValue->Type != EFI_IFR_TYPE_STRING) {
+    ConfigAccess = FormSet->ConfigAccess;
+    Action       = GetDefaultIdForCallBack (DefaultId);
+    if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {
+      ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+      Status        = ConfigAccess->Callback (
+                                      ConfigAccess,
+                                      Action,
+                                      Question->QuestionId,
+                                      HiiValue->Type,
+                                      TypeValue,
+                                      &ActionRequest
+                                      );
+      if (!EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  //
+  // Get default value from altcfg string.
+  //
+  if (ConfigAccess != NULL) {
+    Status = GetDefaultValueFromAltCfg (FormSet, Form, Question, DefaultValue);
+    if (!EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // EFI_IFR_DEFAULT has highest priority
+  //
+  if (!IsListEmpty (&Question->DefaultListHead)) {
+    Link = GetFirstNode (&Question->DefaultListHead);
+    while (!IsNull (&Question->DefaultListHead, Link)) {
+      Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
+
+      if (Default->DefaultId == DefaultId) {
+        if (Default->ValueExpression != NULL) {
+          //
+          // Default is provided by an Expression, evaluate it
+          //
+          Status = EvaluateHiiExpression (FormSet, Form, Default->ValueExpression);
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+
+          if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
+            ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue->Buffer != NULL);
+            if (DefaultValue->BufferLen > Default->ValueExpression->Result.BufferLen) {
+              CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
+              DefaultValue->BufferLen = Default->ValueExpression->Result.BufferLen;
+            } else {
+              CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, DefaultValue->BufferLen);
+            }
+
+            FreePool (Default->ValueExpression->Result.Buffer);
+          }
+
+          HiiValue->Type = Default->ValueExpression->Result.Type;
+          CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
+        } else {
+          //
+          // Default value is embedded in EFI_IFR_DEFAULT
+          //
+          if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
+            ASSERT (HiiValue->Buffer != NULL);
+            CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);
+          } else {
+            CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+          }
+        }
+
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
+          StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);
+          if (StrValue == NULL) {
+            return EFI_NOT_FOUND;
+          }
+
+          if (DefaultValue->BufferLen > StrSize (StrValue)) {
+            ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);
+            CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));
+          } else {
+            CopyMem (DefaultValue->Buffer, StrValue, DefaultValue->BufferLen);
+          }
+        }
+
+        return EFI_SUCCESS;
+      }
+
+      Link = GetNextNode (&Question->DefaultListHead, Link);
+    }
+  }
+
+  //
+  // EFI_ONE_OF_OPTION
+  //
+  if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+      //
+      // OneOfOption could only provide Standard and Manufacturing default
+      //
+      Link = GetFirstNode (&Question->OptionListHead);
+      while (!IsNull (&Question->OptionListHead, Link)) {
+        Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+        Link   = GetNextNode (&Question->OptionListHead, Link);
+
+        if ((Option->SuppressExpression != NULL) &&
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+        {
+          continue;
+        }
+
+        if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
+            ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
+            )
+        {
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+          return EFI_SUCCESS;
+        }
+      }
+    }
+  }
+
+  //
+  // EFI_IFR_CHECKBOX - lowest priority
+  //
+  if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+    if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+      //
+      // Checkbox could only provide Standard and Manufacturing default
+      //
+      if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
+          ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
+          )
+      {
+        HiiValue->Value.b = TRUE;
+      }
+
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
+  // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
+  // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
+  //
+  while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
+    DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);
+    DefaultLink  = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
+    DefaultId    = DefaultStore->DefaultId;
+    if (DefaultId == OriginalDefaultId) {
+      continue;
+    }
+
+    goto ReGetDefault;
+  }
+
+  //
+  // For Questions without default value for all the default id in the DefaultStoreList.
+  //
+  Status = EFI_NOT_FOUND;
+  switch (Question->Operand) {
+    case EFI_IFR_CHECKBOX_OP:
+      HiiValue->Value.b = FALSE;
+      Status            = EFI_SUCCESS;
+      break;
+
+    case EFI_IFR_NUMERIC_OP:
+      //
+      // Take minimum value as numeric default value
+      //
+      if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {
+        //
+        // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
+        //
+        switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {
+          case EFI_IFR_NUMERIC_SIZE_1:
+            if (((INT8)HiiValue->Value.u8 < (INT8)Question->ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->ExtraData.NumData.Maximum)) {
+              HiiValue->Value.u8 = (UINT8)Question->ExtraData.NumData.Minimum;
+              Status             = EFI_SUCCESS;
+            }
+
+            break;
+          case EFI_IFR_NUMERIC_SIZE_2:
+            if (((INT16)HiiValue->Value.u16 < (INT16)Question->ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->ExtraData.NumData.Maximum)) {
+              HiiValue->Value.u16 = (UINT16)Question->ExtraData.NumData.Minimum;
+              Status              = EFI_SUCCESS;
+            }
+
+            break;
+          case EFI_IFR_NUMERIC_SIZE_4:
+            if (((INT32)HiiValue->Value.u32 < (INT32)Question->ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->ExtraData.NumData.Maximum)) {
+              HiiValue->Value.u32 = (UINT32)Question->ExtraData.NumData.Minimum;
+              Status              = EFI_SUCCESS;
+            }
+
+            break;
+          case EFI_IFR_NUMERIC_SIZE_8:
+            if (((INT64)HiiValue->Value.u64 < (INT64)Question->ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->ExtraData.NumData.Maximum)) {
+              HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
+              Status              = EFI_SUCCESS;
+            }
+
+            break;
+          default:
+            break;
+        }
+      } else {
+        if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) || (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {
+          HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
+          Status              = EFI_SUCCESS;
+        }
+      }
+
+      break;
+
+    case EFI_IFR_ONE_OF_OP:
+      //
+      // Take first oneof option as oneof's default value
+      //
+      if (ValueToOption (Question, HiiValue) == NULL) {
+        Link = GetFirstNode (&Question->OptionListHead);
+        while (!IsNull (&Question->OptionListHead, Link)) {
+          Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+          Link   = GetNextNode (&Question->OptionListHead, Link);
+
+          if ((Option->SuppressExpression != NULL) &&
+              (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+          {
+            continue;
+          }
+
+          CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+          Status = EFI_SUCCESS;
+          break;
+        }
+      }
+
+      break;
+
+    case EFI_IFR_ORDERED_LIST_OP:
+      //
+      // Take option sequence in IFR as ordered list's default value
+      //
+      Index = 0;
+      Link  = GetFirstNode (&Question->OptionListHead);
+      while (!IsNull (&Question->OptionListHead, Link)) {
+        Status = EFI_SUCCESS;
+        Option = HII_QUESTION_OPTION_FROM_LINK (Link);
+        Link   = GetNextNode (&Question->OptionListHead, Link);
+
+        if ((Option->SuppressExpression != NULL) &&
+            (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
+        {
+          continue;
+        }
+
+        SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index, Option->Value.Value.u64);
+
+        Index++;
+        if (Index >= Question->ExtraData.OrderListData.MaxContainers) {
+          break;
+        }
+      }
+
+      break;
+
+    default:
+      break;
+  }
+
+  return Status;
+}
-- 
2.38.1.windows.1



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




More information about the edk2-devel-archive mailing list