From: abnchang <abnch...@amd.com>

Build up the x-uefi-redfish string database for the Redfish confg
language searching, instead of using HII String protocol.
This can improve the time consumption lot on searching strings.

Signed-off-by: Abner Chang <abner.ch...@amd.com>
Co-authored-by: Nickle Wang <nick...@nvidia.com>
Cc: Igor Kulchytskyy <ig...@ami.com>
---
 .../RedfishPlatformConfigImpl.h               | 107 ++-
 .../RedfishPlatformConfigDxe.c                |  23 +-
 .../RedfishPlatformConfigImpl.c               | 820 +++++++++++++++++-
 3 files changed, 878 insertions(+), 72 deletions(-)

diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h 
b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
index 9f4312decf5..6e6c7fdb8a9 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
@@ -2,7 +2,8 @@
   This file defines the EDKII Redfish Platform Config Protocol private 
structure.
 
   (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
-  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights 
reserved.
+  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
 
@@ -30,6 +31,10 @@
 #define ENGLISH_LANGUAGE_CODE  "en-US"
 #define X_UEFI_SCHEMA_PREFIX   "x-uefi-redfish-"
 
+#define MAX_X_UEFI_REDFISH_STRING_SIZE  (128 * 2)// 128 character in UCS.
+
+typedef struct _REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE 
REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE;
+
 //
 // Definition of REDFISH_PLATFORM_CONFIG_PRIVATE.
 //
@@ -46,17 +51,49 @@ typedef struct {
   CHAR8    **SchemaList;                        // Schema list
 } REDFISH_PLATFORM_CONFIG_SCHEMA;
 
+// Defines the number of elements in array
+#define X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER  1024
+
+//
+// Definition of x-uefi-redfish string element.
+//
+typedef struct {
+  EFI_STRING_ID    StringId;
+  CHAR16           *UcsString;
+} REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT;
+
+//
+// Discrete string array buffer, each has X_UEFI_REDFISH_STRING_ARRAY_NUMBER 
element.
+//
+typedef struct {
+  LIST_ENTRY                              NextArray;
+  REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT    *ArrayEntryAddress;
+} REDFISH_X_UEFI_STRINGS_ARRAY;
+
+//
+// x-uefi-redfish string database, x-uefi-redfish language based.
+//
+typedef struct {
+  LIST_ENTRY    NextXuefiRedfishLanguage;                                     
// Link to the next suppoted x-uefi-Redfish language.
+  CHAR8         *XuefiRedfishLanguage;                                        
// x-uefi-redfish language.
+  UINTN         StringsArrayBlocks;                                           
// Number of the array blocks that accommodate 
X_UEFI_REDFISH_STRING_ARRAY_NUMBER
+                                                                              
// elements in each.
+  LIST_ENTRY    XuefiRedfishStringArrays;                                     
// Link entry of x-uefi-redfish string array.
+} REDFISH_X_UEFI_STRING_DATABASE;
+
 //
 // Definition of REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE
 //
 typedef struct {
   LIST_ENTRY                        Link;
-  HII_FORMSET                       *HiiFormSet;     // Pointer to HII formset 
data.
-  EFI_GUID                          Guid;            // Formset GUID.
-  EFI_HII_HANDLE                    HiiHandle;       // Hii Handle of this 
formset.
-  LIST_ENTRY                        HiiFormList;     // Form list that keep 
form data under this formset.
-  CHAR16                            *DevicePathStr;  // Device path of this 
formset.
-  REDFISH_PLATFORM_CONFIG_SCHEMA    SupportedSchema; // Schema that is 
supported in this formset.
+  HII_FORMSET                       *HiiFormSet;                // Pointer to 
HII formset data.
+  EFI_GUID                          Guid;                       // Formset 
GUID.
+  EFI_HII_HANDLE                    HiiHandle;                  // Hii Handle 
of this formset.
+  EFI_HII_PACKAGE_LIST_HEADER       *HiiPackageListHeader;      // Hii Package 
list header.
+  LIST_ENTRY                        HiiFormList;                // Form list 
that keep form data under this formset.
+  CHAR16                            *DevicePathStr;             // Device path 
of this formset.
+  REDFISH_PLATFORM_CONFIG_SCHEMA    SupportedSchema;            // Schema that 
is supported in this formset.
+  LIST_ENTRY                        XuefiRedfishStringDatabase; // 
x-uefi-redfish string/Id data base;
 } REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;
 
 #define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a)  BASE_CR (a, 
REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)
@@ -90,19 +127,19 @@ typedef struct {
 //
 // Definition of REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE
 //
-typedef struct {
+struct _REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE {
   LIST_ENTRY                                Link;
   REDFISH_PLATFORM_CONFIG_FORM_PRIVATE      *ParentForm;
-  HII_STATEMENT                             *HiiStatement;  // Pointer to HII 
statement data.
-  EFI_QUESTION_ID                           QuestionId;     // Question ID of 
this statement.
-  EFI_STRING_ID                             Description;    // String token of 
this question.
-  EFI_STRING_ID                             Help;           // String token of 
help message.
-  EFI_STRING                                DesStringCache; // The string 
cache for search function.
-  UINT8                                     Flags;          // The statement 
flag.
-  REDFISH_PLATFORM_CONFIG_STATEMENT_DATA    StatementData;  // The max/min for 
statement value.
-  BOOLEAN                                   Suppressed;     // Statement is 
suppressed.
-  BOOLEAN                                   GrayedOut;      // Statement is 
GrayedOut.
-} REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE;
+  HII_STATEMENT                             *HiiStatement;    // Pointer to 
HII statement data.
+  EFI_QUESTION_ID                           QuestionId;       // Question ID 
of this statement.
+  EFI_STRING_ID                             Description;      // String token 
of this question.
+  CHAR16                                    *DescriptionStr;  // String of 
this question.
+  EFI_STRING_ID                             Help;             // String token 
of help message.
+  UINT8                                     Flags;            // The statement 
flag.
+  REDFISH_PLATFORM_CONFIG_STATEMENT_DATA    StatementData;    // The max/min 
for statement value.
+  BOOLEAN                                   Suppressed;       // Statement is 
suppressed.
+  BOOLEAN                                   GrayedOut;        // Statement is 
GrayedOut.
+};
 
 #define REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK(a)  BASE_CR (a, 
REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE, Link)
 
@@ -347,4 +384,38 @@ ReleaseStatementList (
   IN  REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  *StatementList
   );
 
+/**
+  Return the HII string length. We don't check word alignment
+  of the input string as the same as the checking in StrLen
+  function. Because the HII string in the database is compact
+  at the byte alignment.
+
+  @param[in]  String  Input UCS format string.
+
+  @retval Length of
+
+**/
+UINTN
+EFIAPI
+HiiStrLen (
+  IN  CONST CHAR16  *String
+  );
+
+/**
+  Return the HII string size. We don't check word alignment
+  of the input string as the same as the checking in StrLen
+  function. Because the HII string in the database is compact
+  at the byte alignment.
+
+  @param[in]  String  Input UCS format string.
+
+  @retval Size of the string.
+
+**/
+UINTN
+EFIAPI
+HiiStrSize (
+  IN      CONST CHAR16  *String
+  );
+
 #endif
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c 
b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
index f970e317b3f..664b48eb50e 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
@@ -2,7 +2,8 @@
   The implementation of EDKII Redfish Platform Config Protocol.
 
   (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
-  Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights 
reserved.
+  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
 
@@ -928,6 +929,10 @@ HiiStringToOneOfOptionValue (
     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));
@@ -1227,6 +1232,10 @@ HiiStringToOrderedListOptionValue (
     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);
@@ -1491,7 +1500,7 @@ StrToAsciiStr (
     return NULL;
   }
 
-  StringLen = StrLen (UnicodeString) + 1;
+  StringLen = HiiStrLen (UnicodeString) + 1;
   Buffer    = AllocatePool (StringLen * sizeof (CHAR8));
   if (Buffer == NULL) {
     return NULL;
@@ -2000,7 +2009,6 @@ RedfishPlatformConfigProtocolGetConfigureLang (
   REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_LIST  StatementList;
   REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE_REF   *StatementRef;
   LIST_ENTRY                                      *NextLink;
-  EFI_STRING                                      TmpString;
   EFI_STRING                                      *TmpConfigureLangList;
   UINTN                                           Index;
   CHAR8                                           *FullSchema;
@@ -2054,12 +2062,9 @@ RedfishPlatformConfigProtocolGetConfigureLang (
 
       ASSERT (StatementRef->Statement->Description != 0);
       if (StatementRef->Statement->Description != 0) {
-        TmpString = HiiGetRedfishString 
(StatementRef->Statement->ParentForm->ParentFormset->HiiHandle, FullSchema, 
StatementRef->Statement->Description);
-        ASSERT (TmpString != NULL);
-        if (TmpString != NULL) {
-          TmpConfigureLangList[Index] = TmpString;
-          ++Index;
-        }
+        ASSERT (StatementRef->Statement->DescriptionStr != NULL);
+        TmpConfigureLangList[Index] = AllocateCopyPool (HiiStrSize 
(StatementRef->Statement->DescriptionStr), (VOID 
*)StatementRef->Statement->DescriptionStr);
+        ++Index;
       }
     }
   }
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c 
b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
index 47d35abc088..8b1ddf4360a 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
@@ -3,6 +3,7 @@
 
   (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
   Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights 
reserved.
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -143,6 +144,88 @@ DumpFormsetList (
   return EFI_SUCCESS;
 }
 
+/**
+  Return the HII string length. We don't check word alignment
+  of the input string as same as the checking in StrLen
+  function, because the HII string in the database is compact
+  at the byte alignment.
+
+  @param[in]  String  Input UCS format string.
+
+  @retval Length of the string.
+
+**/
+UINTN
+EFIAPI
+HiiStrLen (
+  IN  CONST CHAR16  *String
+  )
+{
+  UINTN  Length;
+
+  ASSERT (String != NULL);
+
+  for (Length = 0; *String != L'\0'; String++, Length++) {
+  }
+
+  return Length;
+}
+
+/**
+  Return the HII string size. We don't check word alignment
+  of the input string as same as the checking in StrLen
+  function, because the HII string in the database is compact
+  at the byte alignment.
+
+  @param[in]  String  Input UCS format string.
+
+  @retval Size of the string.
+
+**/
+UINTN
+EFIAPI
+HiiStrSize (
+  IN      CONST CHAR16  *String
+  )
+{
+  return (HiiStrLen (String) + 1) * sizeof (*String);
+}
+
+/**
+  Compare two HII strings. We don't check word alignment
+  of the input string as same as the checking in StrLen
+  function, because the HII string in the database is compact
+  at the byte alignment.
+
+  @param[in]  FirstString   Input UCS format of string to search.
+  @param[in]  SecondString  Input UCS format of string to look for in
+                            FirstString;
+
+  @retval 0   The strings are identical.
+          !0  The strings are not identical.
+
+**/
+INTN
+EFIAPI
+HiiStrCmp (
+  IN      CONST CHAR16  *FirstString,
+  IN      CONST CHAR16  *SecondString
+  )
+{
+  //
+  // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
+  //
+  ASSERT (HiiStrSize (FirstString) != 0);
+  ASSERT (HiiStrSize (SecondString) != 0);
+
+  while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+    FirstString++;
+    SecondString++;
+  }
+
+  return *FirstString - *SecondString;
+}
+
 /**
   Delete a string from HII Package List by given HiiHandle.
 
@@ -301,28 +384,6 @@ HiiGetRedfishAsciiString (
   return AsciiString;
 }
 
-/**
-  Get string from HII database in English language. The returned string is 
allocated
-  using AllocatePool(). The caller is responsible for freeing the allocated 
buffer using
-  FreePool().
-
-  @param[in]  HiiHandle         A handle that was previously registered in the 
HII Database.
-  @param[in]  StringId          The identifier of the string to retrieved from 
the string
-                                package associated with HiiHandle.
-
-  @retval NULL   The string specified by StringId is not present in the string 
package.
-  @retval Other  The string was returned.
-
-**/
-EFI_STRING
-HiiGetEnglishString (
-  IN EFI_HII_HANDLE  HiiHandle,
-  IN EFI_STRING_ID   StringId
-  )
-{
-  return HiiGetRedfishString (HiiHandle, ENGLISH_LANGUAGE_CODE, StringId);
-}
-
 /**
   Get ASCII string from HII database in English language. The returned string 
is allocated
   using AllocatePool(). The caller is responsible for freeing the allocated 
buffer using
@@ -562,7 +623,7 @@ GetStatementPrivateByConfigureLangRegex (
         HiiStatementPrivate  = REDFISH_PLATFORM_CONFIG_STATEMENT_FROM_LINK 
(HiiStatementLink);
 
         if ((HiiStatementPrivate->Description != 0) && 
!HiiStatementPrivate->Suppressed) {
-          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, 
Schema, HiiStatementPrivate->Description);
+          TmpString = HiiStatementPrivate->DescriptionStr;
           if (TmpString != NULL) {
             Status = RegularExpressionProtocol->MatchString (
                                                   RegularExpressionProtocol,
@@ -592,8 +653,9 @@ GetStatementPrivateByConfigureLangRegex (
               InsertTailList (&StatementList->StatementList, 
&StatementRef->Link);
               ++StatementList->Count;
             }
-
-            FreePool (TmpString);
+          } else {
+            DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->DescriptionStr is 
NULL, x-uefi-string has something wrong.\n", __func__));
+            ASSERT (FALSE);
           }
         }
 
@@ -676,14 +738,11 @@ GetStatementPrivateByConfigureLang (
           );
 
         if (HiiStatementPrivate->Description != 0) {
-          TmpString = HiiGetRedfishString (HiiFormsetPrivate->HiiHandle, 
Schema, HiiStatementPrivate->Description);
+          TmpString = HiiStatementPrivate->DescriptionStr;
           if (TmpString != NULL) {
-            if (StrCmp (TmpString, ConfigureLang) == 0) {
-              FreePool (TmpString);
+            if (HiiStrCmp (TmpString, ConfigureLang) == 0) {
               return HiiStatementPrivate;
             }
-
-            FreePool (TmpString);
           }
         }
 
@@ -741,10 +800,74 @@ GetFormsetPrivateByHiiHandle (
   return NULL;
 }
 
+/**
+  Release x-uefi-string related information.
+
+  @param[in]      FormsetPrivate Pointer to HII form-set private instance.
+
+  @retval         EFI_STATUS
+
+**/
+EFI_STATUS
+ReleaseXuefiStringDatabase (
+  IN REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate
+  )
+{
+  REDFISH_X_UEFI_STRING_DATABASE  *ThisDatabase;
+  REDFISH_X_UEFI_STRING_DATABASE  *PreDatabase;
+  REDFISH_X_UEFI_STRINGS_ARRAY    *ThisStringArray;
+  REDFISH_X_UEFI_STRINGS_ARRAY    *PreStringArray;
+  BOOLEAN                         EndDatabase;
+  BOOLEAN                         EndArray;
+
+  if (FormsetPrivate->HiiPackageListHeader != NULL) {
+    FreePool (FormsetPrivate->HiiPackageListHeader);
+  }
+
+  // Walk through x-uefi-redfish string database.
+  if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
+    EndDatabase  = FALSE;
+    ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode 
(&FormsetPrivate->XuefiRedfishStringDatabase);
+    while (!EndDatabase) {
+      // Walk through string arrays.
+      if (!IsListEmpty (&ThisDatabase->XuefiRedfishStringArrays)) {
+        EndArray        = FALSE;
+        ThisStringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode 
(&ThisDatabase->XuefiRedfishStringArrays);
+        while (!EndArray) {
+          // Remove this array
+          FreePool (ThisStringArray->ArrayEntryAddress);
+          EndArray       = IsNodeAtEnd 
(&ThisDatabase->XuefiRedfishStringArrays, &ThisStringArray->NextArray);
+          PreStringArray = ThisStringArray;
+          if (!EndArray) {
+            ThisStringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode 
(&ThisDatabase->XuefiRedfishStringArrays, &ThisStringArray->NextArray);
+          }
+
+          RemoveEntryList (&PreStringArray->NextArray);
+          FreePool (PreStringArray);
+        }
+      }
+
+      //
+      // Remove this database
+      //
+      EndDatabase = IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, 
&ThisDatabase->NextXuefiRedfishLanguage);
+      PreDatabase = ThisDatabase;
+      if (!EndDatabase) {
+        ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode 
(&FormsetPrivate->XuefiRedfishStringDatabase, 
&ThisDatabase->NextXuefiRedfishLanguage);
+      }
+
+      RemoveEntryList (&PreDatabase->NextXuefiRedfishLanguage);
+      FreePool (PreDatabase);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
 /**
   Release formset and all the forms and statements that belong to this formset.
 
-  @param[in]      FormsetPrivate Pointer to HP_HII_FORM_SET_PRIVATE
+  @param[in]      FormsetPrivate Pointer to HII form-set private instance.
 
   @retval         EFI_STATUS
 
@@ -779,12 +902,6 @@ ReleaseFormset (
       //
       // HiiStatementPrivate->HiiStatement will be released in 
DestroyFormSet().
       //
-
-      if (HiiStatementPrivate->DesStringCache != NULL) {
-        FreePool (HiiStatementPrivate->DesStringCache);
-        HiiStatementPrivate->DesStringCache = NULL;
-      }
-
       RemoveEntryList (&HiiStatementPrivate->Link);
       FreePool (HiiStatementPrivate);
       HiiStatementLink = HiiNextStatementLink;
@@ -821,6 +938,8 @@ ReleaseFormset (
     FormsetPrivate->SupportedSchema.Count      = 0;
   }
 
+  ReleaseXuefiStringDatabase (FormsetPrivate);
+
   return EFI_SUCCESS;
 }
 
@@ -846,17 +965,607 @@ NewFormsetPrivate (
   // Initial newly created formset private data.
   //
   InitializeListHead (&NewFormsetPrivate->HiiFormList);
+  InitializeListHead (&NewFormsetPrivate->XuefiRedfishStringDatabase);
 
   return NewFormsetPrivate;
 }
 
+/**
+  Create new x-uefi-redfish string array.
+
+  @param[in]      FormsetPrivate              Pointer to HII form-set private 
instance.
+  @param[in]      XuefiRedfishStringDatabase  The x-uefi-redfish string 
database.
+
+  @retval         EFI_OUT_OF_RESOURCES  Not enough memory for creating a new 
array.
+                  EFI_SUCCESS           New array is created successfully.
+
+**/
+EFI_STATUS
+NewRedfishXuefiStringArray (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN  REDFISH_X_UEFI_STRING_DATABASE            *XuefiRedfishStringDatabase
+  )
+{
+  REDFISH_X_UEFI_STRINGS_ARRAY  *ArrayAddress;
+
+  // Initial first REDFISH_X_UEFI_STRINGS_ARRAY memory.
+  ArrayAddress = (REDFISH_X_UEFI_STRINGS_ARRAY *)AllocateZeroPool (sizeof 
(REDFISH_X_UEFI_STRINGS_ARRAY));
+  if (ArrayAddress == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate 
REDFISH_X_UEFI_STRINGS_ARRAY.\n", __func__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InitializeListHead (&ArrayAddress->NextArray);
+
+  // Allocate memory buffer for REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT elements.
+  ArrayAddress->ArrayEntryAddress = \
+    (REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT *)AllocateZeroPool (sizeof 
(REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENT) * 
X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER);
+  if (ArrayAddress->ArrayEntryAddress == NULL) {
+    FreePool (ArrayAddress);
+    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate array for 
REDFISH_X_UEFI_STRINGS_ARRAY_ELEMENTs.\n", __func__));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  XuefiRedfishStringDatabase->StringsArrayBlocks++;
+  InsertTailList (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, 
&ArrayAddress->NextArray);
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the pointer of x-uefi-redfish database or create a new database.
+
+  @param[in]      FormsetPrivate          Pointer to HII form-set private 
instance.
+  @param[in]      HiiStringPackageHeader  HII string package header.
+
+  @retval         Pointer to REDFISH_X_UEFI_STRING_DATABASE.
+                  If NULL, it fails to obtain x-uefi-redfish database.
+
+**/
+REDFISH_X_UEFI_STRING_DATABASE *
+GetExitOrCreateXuefiStringDatabase (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN  EFI_HII_STRING_PACKAGE_HDR                *HiiStringPackageHeader
+  )
+{
+  EFI_STATUS                      Status;
+  BOOLEAN                         CreateNewOne;
+  REDFISH_X_UEFI_STRING_DATABASE  *XuefiRedfishStringDatabase;
+
+  DEBUG ((DEBUG_INFO, "%a: Entry\n", __func__));
+
+  CreateNewOne               = TRUE;
+  XuefiRedfishStringDatabase = NULL;
+  if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
+    XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE 
*)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
+
+    while (TRUE) {
+      if (AsciiStriCmp (XuefiRedfishStringDatabase->XuefiRedfishLanguage, 
HiiStringPackageHeader->Language) == 0) {
+        CreateNewOne = FALSE;
+        break;
+      }
+
+      if (IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, 
&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage)) {
+        break;
+      }
+
+      XuefiRedfishStringDatabase = \
+        (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode 
(&FormsetPrivate->XuefiRedfishStringDatabase, 
&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
+    }
+  }
+
+  if (CreateNewOne) {
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "  Creating x-uefi-redfish (%a) 
string database...\n", HiiStringPackageHeader->Language));
+    XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE 
*)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRING_DATABASE));
+    if (XuefiRedfishStringDatabase == NULL) {
+      DEBUG ((DEBUG_ERROR, "  Failed to allocate 
REDFISH_X_UEFI_STRING_DATABASE.\n"));
+      return NULL;
+    }
+
+    InitializeListHead (&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
+    InitializeListHead (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
+    XuefiRedfishStringDatabase->StringsArrayBlocks   = 0;
+    XuefiRedfishStringDatabase->XuefiRedfishLanguage = 
HiiStringPackageHeader->Language;
+
+    Status = NewRedfishXuefiStringArray (FormsetPrivate, 
XuefiRedfishStringDatabase);
+    if (EFI_ERROR (Status)) {
+      FreePool (XuefiRedfishStringDatabase);
+      return NULL;
+    }
+
+    DEBUG ((
+      REDFISH_PLATFORM_CONFIG_DEBUG,
+      "  x-uefi-redfish (%a):\n    String array is added to 
XuefiRedfishStringDatabase, total %d arrays now.\n",
+      XuefiRedfishStringDatabase->XuefiRedfishLanguage,
+      XuefiRedfishStringDatabase->StringsArrayBlocks
+      ));
+
+    // Link string database to FormsetPrivate.
+    InsertTailList (&FormsetPrivate->XuefiRedfishStringDatabase, 
&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage);
+  }
+
+  return XuefiRedfishStringDatabase;
+}
+
+/**
+  Check and allocate a new x-uefi-redfish array if it is insufficient for the
+  newly added x-uefi-redfish string.
+
+  @param[in]      FormsetPrivate              Pointer to HII form-set private 
instance.
+  @param[in]      XuefiRedfishStringDatabase  Pointer to the x-uefi-redfish 
database.
+  @param[in]      StringId                    String ID added to database.
+
+  @retval         EFI_SUCCESS                 The size of x-uefi-string array 
is adjusted or
+                                              is not required to be adjusted.
+                  Otherwise, refer to the error code returned from 
NewRedfishXuefiStringArray().
+
+**/
+EFI_STATUS
+RedfishXuefiStringAdjustArrays (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN  REDFISH_X_UEFI_STRING_DATABASE            *XuefiRedfishStringDatabase,
+  IN  EFI_STRING_ID                             StringId
+  )
+{
+  EFI_STATUS  Status;
+
+  while (((StringId + X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) / 
X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) > 
(UINT16)XuefiRedfishStringDatabase->StringsArrayBlocks) {
+    Status = NewRedfishXuefiStringArray (FormsetPrivate, 
XuefiRedfishStringDatabase);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-string array", 
__func__));
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Insert a x-uefi-redfish string to database.
+
+  @param[in]      FormsetPrivate          Pointer to HII form-set private 
instance.
+  @param[in]      HiiStringPackageHeader  Pointer to HII string package.
+  @param[in]      StringId                The HII string ID
+  @param[in]      StringTextPtr           Pointer to HII string text.
+
+  @retval         EFI_SUCCESS             The HII string is added to database.
+                  EFI_LOAD_ERROR          Something wrong when insert an HII 
string
+                                          to database.
+
+**/
+EFI_STATUS
+RedfishXuefiStringInsertDatabase (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN  EFI_HII_STRING_PACKAGE_HDR                *HiiStringPackageHeader,
+  IN  EFI_STRING_ID                             StringId,
+  IN  CHAR16                                    *StringTextPtr
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           StringIdOffset;
+  REDFISH_X_UEFI_STRING_DATABASE  *XuefiRedfishStringDatabase;
+  REDFISH_X_UEFI_STRINGS_ARRAY    *ThisArray;
+
+  XuefiRedfishStringDatabase = GetExitOrCreateXuefiStringDatabase 
(FormsetPrivate, HiiStringPackageHeader);
+  if (XuefiRedfishStringDatabase == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of 
x-uefi-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
+    ReleaseXuefiStringDatabase (FormsetPrivate);
+    return EFI_LOAD_ERROR;
+  }
+
+  Status = RedfishXuefiStringAdjustArrays (FormsetPrivate, 
XuefiRedfishStringDatabase, StringId);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-redfish string 
array.\n", __func__));
+    return EFI_LOAD_ERROR;
+  }
+
+  // Insert string to x-uefi-redfish string array.
+  StringIdOffset = (UINTN)StringId;
+  ThisArray      = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode 
(&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
+  while (StringIdOffset >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
+    ThisArray       = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode 
(&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, &ThisArray->NextArray);
+    StringIdOffset -= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER;
+  }
+
+  // Insert string
+  (ThisArray->ArrayEntryAddress + StringIdOffset)->StringId  = StringId;
+  (ThisArray->ArrayEntryAddress + StringIdOffset)->UcsString = StringTextPtr;
+
+  DEBUG ((
+    REDFISH_PLATFORM_CONFIG_DEBUG,
+    "  Insert string ID: (%d) to database\n    x-uefi-string: \"%s\"\n    
Language: %a.\n",
+    StringId,
+    StringTextPtr,
+    HiiStringPackageHeader->Language
+    ));
+  return EFI_SUCCESS;
+}
+
+/**
+  Get x-uefi-redfish string and language by string ID.
+
+  @param[in]      FormsetPrivate          Pointer to HII form-set private 
instance.
+  @param[in]      HiiStringPackageHeader  HII string package header.
+
+  @retval  TRUE   x-uefi-redfish string and ID map is inserted to database.
+           FALSE  Something is wrong when insert x-uefi-redfish string and ID 
map.
+
+**/
+BOOLEAN
+CreateXuefiLanguageStringIdMap (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN  EFI_HII_STRING_PACKAGE_HDR                *HiiStringPackageHeader
+  )
+{
+  EFI_STATUS               Status;
+  UINT8                    *BlockHdr;
+  EFI_STRING_ID            CurrentStringId;
+  UINTN                    BlockSize;
+  UINTN                    Index;
+  UINT8                    *StringTextPtr;
+  UINTN                    Offset;
+  UINT16                   StringCount;
+  UINT16                   SkipCount;
+  UINT8                    Length8;
+  EFI_HII_SIBT_EXT2_BLOCK  Ext2;
+  UINT32                   Length32;
+  UINT8                    *StringBlockInfo;
+
+  //
+  // Parse the string blocks to get the string text and font.
+  //
+  StringBlockInfo = (UINT8 *)((UINTN)HiiStringPackageHeader + 
HiiStringPackageHeader->StringInfoOffset);
+  BlockHdr        = StringBlockInfo;
+  BlockSize       = 0;
+  Offset          = 0;
+  CurrentStringId = 1;
+  while (*BlockHdr != EFI_HII_SIBT_END) {
+    switch (*BlockHdr) {
+      case EFI_HII_SIBT_STRING_SCSU:
+        Offset        = sizeof (EFI_HII_STRING_BLOCK);
+        StringTextPtr = BlockHdr + Offset;
+        BlockSize    += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+        CurrentStringId++;
+        break;
+
+      case EFI_HII_SIBT_STRING_SCSU_FONT:
+        Offset        = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof 
(UINT8);
+        StringTextPtr = BlockHdr + Offset;
+        BlockSize    += Offset + AsciiStrSize ((CHAR8 *)StringTextPtr);
+        CurrentStringId++;
+        break;
+
+      case EFI_HII_SIBT_STRINGS_SCSU:
+        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), 
sizeof (UINT16));
+        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof 
(EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8));
+        BlockSize    += StringTextPtr - BlockHdr;
+
+        for (Index = 0; Index < StringCount; Index++) {
+          BlockSize    += AsciiStrSize ((CHAR8 *)StringTextPtr);
+          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 
*)StringTextPtr);
+          CurrentStringId++;
+        }
+
+        break;
+
+      case EFI_HII_SIBT_STRINGS_SCSU_FONT:
+        CopyMem (
+          &StringCount,
+          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof 
(UINT8)),
+          sizeof (UINT16)
+          );
+        StringTextPtr = (UINT8 *)((UINTN)BlockHdr + sizeof 
(EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8));
+        BlockSize    += StringTextPtr - BlockHdr;
+
+        for (Index = 0; Index < StringCount; Index++) {
+          BlockSize    += AsciiStrSize ((CHAR8 *)StringTextPtr);
+          StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 
*)StringTextPtr);
+          CurrentStringId++;
+        }
+
+        break;
+
+      case EFI_HII_SIBT_STRING_UCS2:
+        Offset        = sizeof (EFI_HII_STRING_BLOCK);
+        StringTextPtr = BlockHdr + Offset;
+
+        // x-uefi-redfish string is always encoded as UCS and started with '/'.
+        if (*StringTextPtr == (UINT16)'/') {
+          Status = RedfishXuefiStringInsertDatabase (
+                     FormsetPrivate,
+                     HiiStringPackageHeader,
+                     CurrentStringId,
+                     (CHAR16 *)StringTextPtr
+                     );
+          if (EFI_ERROR (Status)) {
+            DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-uefi-redfish string 
%s.\n", __func__, StringTextPtr));
+            return FALSE;
+          }
+        }
+
+        BlockSize += (Offset + HiiStrSize ((CHAR16 *)StringTextPtr));
+        CurrentStringId++;
+        break;
+
+      case EFI_HII_SIBT_STRING_UCS2_FONT:
+        Offset        = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK)  - sizeof 
(CHAR16);
+        StringTextPtr = BlockHdr + Offset;
+        BlockSize    += (Offset + HiiStrSize ((CHAR16 *)StringTextPtr));
+        CurrentStringId++;
+        break;
+
+      case EFI_HII_SIBT_STRINGS_UCS2:
+        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof 
(CHAR16);
+        StringTextPtr = BlockHdr + Offset;
+        BlockSize    += Offset;
+        CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), 
sizeof (UINT16));
+        for (Index = 0; Index < StringCount; Index++) {
+          BlockSize    += HiiStrSize ((CHAR16 *)StringTextPtr);
+          StringTextPtr = StringTextPtr + HiiStrSize ((CHAR16 *)StringTextPtr);
+          CurrentStringId++;
+        }
+
+        break;
+
+      case EFI_HII_SIBT_STRINGS_UCS2_FONT:
+        Offset        = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof 
(CHAR16);
+        StringTextPtr = BlockHdr + Offset;
+        BlockSize    += Offset;
+        CopyMem (
+          &StringCount,
+          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof 
(UINT8)),
+          sizeof (UINT16)
+          );
+        for (Index = 0; Index < StringCount; Index++) {
+          BlockSize    += HiiStrSize ((CHAR16 *)StringTextPtr);
+          StringTextPtr = StringTextPtr + HiiStrSize ((CHAR16 *)StringTextPtr);
+          CurrentStringId++;
+        }
+
+        break;
+
+      case EFI_HII_SIBT_DUPLICATE:
+        BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
+        CurrentStringId++;
+        break;
+
+      case EFI_HII_SIBT_SKIP1:
+        SkipCount       = (UINT16)(*(UINT8 *)((UINTN)BlockHdr + sizeof 
(EFI_HII_STRING_BLOCK)));
+        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
+        break;
+
+      case EFI_HII_SIBT_SKIP2:
+        CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof 
(UINT16));
+        CurrentStringId = (UINT16)(CurrentStringId + SkipCount);
+        BlockSize      +=  sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
+        break;
+
+      case EFI_HII_SIBT_EXT1:
+        CopyMem (
+          &Length8,
+          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof 
(UINT8)),
+          sizeof (UINT8)
+          );
+        BlockSize += Length8;
+        break;
+
+      case EFI_HII_SIBT_EXT2:
+        CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
+        BlockSize += Ext2.Length;
+        break;
+
+      case EFI_HII_SIBT_EXT4:
+        CopyMem (
+          &Length32,
+          (UINT8 *)((UINTN)BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof 
(UINT8)),
+          sizeof (UINT32)
+          );
+
+        BlockSize += Length32;
+        break;
+
+      default:
+        break;
+    }
+
+    BlockHdr = (UINT8 *)(StringBlockInfo + BlockSize);
+  }
+
+  return TRUE;
+}
+
+/**
+  Get x-uefi-redfish string and language by string ID.
+
+  @param[in]      FormsetPrivate       Pointer to HII form-set private 
instance.
+  @param[in]      StringId             The HII string ID.
+  @param[out]     String               Optionally return USC string.
+  @param[out]     Language             Optionally return x-uefi-redfish 
language.
+  @param[out]     XuefiStringDatabase  Optionally return x-uefi-redfish 
database.
+
+  @retval  EFI_SUCCESS            String information is returned.
+           EFI_INVALID_PARAMETER  One of the given parameters to this function 
is
+                                  invalid.
+           EFI_NOT_FOUND          String is not found.
+
+**/
+EFI_STATUS
+GetXuefiStringAndLangByStringId (
+  IN   REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate,
+  IN   EFI_STRING_ID                             StringId,
+  OUT  CHAR16                                    **String OPTIONAL,
+  OUT  CHAR8                                     **Language OPTIONAL,
+  OUT  REDFISH_X_UEFI_STRING_DATABASE            **XuefiStringDatabase OPTIONAL
+  )
+{
+  REDFISH_X_UEFI_STRING_DATABASE  *XuefiRedfishStringDatabase;
+  REDFISH_X_UEFI_STRINGS_ARRAY    *StringArray;
+  UINT16                          StringIndex;
+
+  if ((String == NULL) && (Language == NULL) && (XuefiStringDatabase == NULL)) 
{
+    DEBUG ((DEBUG_ERROR, "%a: Invalid parameters for this function.\n", 
__func__));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
+    return EFI_NOT_FOUND;
+  }
+
+  XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode 
(&FormsetPrivate->XuefiRedfishStringDatabase);
+  while (TRUE) {
+    if (Language != NULL) {
+      *Language = XuefiRedfishStringDatabase->XuefiRedfishLanguage;
+    }
+
+    StringArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode 
(&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
+
+    // Loop to the correct string array.
+    StringIndex = StringId;
+    while (StringIndex >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
+      if (IsNodeAtEnd (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, 
&StringArray->NextArray)) {
+        goto ErrorEixt;
+      }
+
+      StringArray  = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetNextNode 
(&XuefiRedfishStringDatabase->XuefiRedfishStringArrays, 
&StringArray->NextArray);
+      StringIndex -= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER;
+    }
+
+    //
+    // NOTE: The string ID in the formset is a unique number.
+    //       If the string in the array is NULL, then the matched string ID
+    //       should be in another x-uefi-redfish database.
+    //
+    if ((StringArray->ArrayEntryAddress + StringIndex)->UcsString != NULL) {
+      //
+      // String ID is belong to this x-uef-redfish language database.
+      //
+      if (String != NULL) {
+        *String = (StringArray->ArrayEntryAddress + StringIndex)->UcsString;
+      }
+
+      if (XuefiStringDatabase != NULL) {
+        *XuefiStringDatabase = XuefiRedfishStringDatabase;
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    if (IsNodeAtEnd (&FormsetPrivate->XuefiRedfishStringDatabase, 
&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage)) {
+      return EFI_NOT_FOUND;
+    }
+
+    XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetNextNode 
(
+                                                                     
&FormsetPrivate->XuefiRedfishStringDatabase,
+                                                                     
&XuefiRedfishStringDatabase->NextXuefiRedfishLanguage
+                                                                     );
+  }
+
+ErrorEixt:;
+  DEBUG ((DEBUG_ERROR, "%a: String ID (%d) is not in any x-uef-redfish string 
databases.\n", __func__, StringId));
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Build a x-uefi-redfish database for the newly added x-uefi-redfish language.
+
+  @param[in]      FormsetPrivate          Pointer to HII form-set private 
instance.
+
+**/
+VOID
+BuildXUefiRedfishStringDatabase (
+  IN  REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE  *FormsetPrivate
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       BufferSize;
+  EFI_HII_PACKAGE_HEADER      *PackageHeader;
+  UINTN                       EndingPackageAddress;
+  EFI_HII_STRING_PACKAGE_HDR  *HiiStringPackageHeader;
+  UINTN                       SupportedSchemaLangCount;
+  CHAR8                       **SupportedSchemaLang;
+  BOOLEAN                     StringIdMapIsBuilt;
+
+  DEBUG ((DEBUG_INFO, "%a: Building x-uefi-redfish string database, HII 
Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
+
+  BufferSize = 0;
+  Status     = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
+                                                             
mRedfishPlatformConfigPrivate->HiiDatabase,
+                                                             
FormsetPrivate->HiiHandle,
+                                                             &BufferSize,
+                                                             
FormsetPrivate->HiiPackageListHeader
+                                                             );
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    DEBUG ((DEBUG_ERROR, "  Failed to export package list.\n"));
+    return;
+  }
+
+  FormsetPrivate->HiiPackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER 
*)AllocateZeroPool (BufferSize);
+  if (FormsetPrivate->HiiPackageListHeader == NULL) {
+    DEBUG ((DEBUG_ERROR, "  Failed to allocate memory for the exported package 
list.\n"));
+    return;
+  }
+
+  Status = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
+                                                         
mRedfishPlatformConfigPrivate->HiiDatabase,
+                                                         
FormsetPrivate->HiiHandle,
+                                                         &BufferSize,
+                                                         
FormsetPrivate->HiiPackageListHeader
+                                                         );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Finding the string package.
+  //
+  EndingPackageAddress = (UINTN)FormsetPrivate->HiiPackageListHeader + 
FormsetPrivate->HiiPackageListHeader->PackageLength;
+  PackageHeader        = (EFI_HII_PACKAGE_HEADER 
*)(FormsetPrivate->HiiPackageListHeader + 1);
+  SupportedSchemaLang  = FormsetPrivate->SupportedSchema.SchemaList;
+  while ((UINTN)PackageHeader < EndingPackageAddress) {
+    switch (PackageHeader->Type) {
+      case EFI_HII_PACKAGE_STRINGS:
+        StringIdMapIsBuilt     = FALSE;
+        HiiStringPackageHeader = (EFI_HII_STRING_PACKAGE_HDR *)PackageHeader;
+
+        // Check if this is the string package for x-uefi-redfish
+        for (SupportedSchemaLangCount = 0;
+             SupportedSchemaLangCount < FormsetPrivate->SupportedSchema.Count;
+             SupportedSchemaLangCount++
+             )
+        {
+          if (AsciiStrnCmp (
+                *(SupportedSchemaLang + SupportedSchemaLangCount),
+                HiiStringPackageHeader->Language,
+                AsciiStrLen (HiiStringPackageHeader->Language)
+                ) == 0)
+          {
+            StringIdMapIsBuilt = CreateXuefiLanguageStringIdMap 
(FormsetPrivate, HiiStringPackageHeader);
+            break;
+          }
+        }
+
+        if (StringIdMapIsBuilt == FALSE) {
+          if (AsciiStrStr (HiiStringPackageHeader->Language, 
X_UEFI_SCHEMA_PREFIX) == NULL) {
+            DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "  No need to build 
x-uefi-redfish string ID map for HII language %a\n", 
HiiStringPackageHeader->Language));
+          } else {
+            DEBUG ((DEBUG_ERROR, "  Failed to build x-uefi-redfish string ID 
map of HII language %a\n", HiiStringPackageHeader->Language));
+          }
+        }
+
+      default:
+        PackageHeader = (EFI_HII_PACKAGE_HEADER *)((UINTN)PackageHeader + 
PackageHeader->Length);
+    }
+  }
+}
+
 /**
   Load the HII formset from the given HII handle.
 
   @param[in]  HiiHandle       Target HII handle to load.
   @param[out] FormsetPrivate  The formset private data.
 
-  @retval EFI_STATUS
+  @retval EFI_STATUS          The formset is loaded successfully.
+  @retval EFI_UNSUPPORTED     This formset doesn't have any x-uefi-redfish 
configuration.
 
 **/
 EFI_STATUS
@@ -875,6 +1584,7 @@ LoadFormset (
   REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE  *HiiStatementPrivate;
   EFI_GUID                                   ZeroGuid;
   EXPRESS_RESULT                             ExpressionResult;
+  CHAR16                                     *String;
 
   if ((HiiHandle == NULL) || (FormsetPrivate == NULL)) {
     return EFI_INVALID_PARAMETER;
@@ -882,6 +1592,7 @@ LoadFormset (
 
   HiiFormSet = AllocateZeroPool (sizeof (HII_FORMSET));
   if (HiiFormSet == NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: No memory resource for HII_FORMSET - %g\n", 
__func__, FormsetPrivate->Guid));
     return EFI_OUT_OF_RESOURCES;
   }
 
@@ -891,6 +1602,7 @@ LoadFormset (
   ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
   Status = CreateFormSetFromHiiHandle (HiiHandle, &ZeroGuid, HiiFormSet);
   if (EFI_ERROR (Status) || IsListEmpty (&HiiFormSet->FormListHead)) {
+    DEBUG ((DEBUG_ERROR, "%a: Formset not found by HII handle - %g\n", 
__func__, FormsetPrivate->Guid));
     Status = EFI_NOT_FOUND;
     goto ErrorExit;
   }
@@ -909,7 +1621,11 @@ LoadFormset (
   FormsetPrivate->DevicePathStr = ConvertDevicePathToText 
(HiiFormSet->DevicePath, FALSE, FALSE);
   Status                        = GetSupportedSchema 
(FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);
   if (EFI_ERROR (Status)) {
-    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: No schema from HII handle: 
0x%x found: %r\n", __func__, FormsetPrivate->HiiHandle, Status));
+    DEBUG ((REDFISH_PLATFORM_CONFIG_DEBUG, "%a: No x-uefi-redfish 
configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
+    return EFI_UNSUPPORTED; // Can't build AttributeRegistry Meni path with 
returning EFI_UNSUPPORTED.
+  } else {
+    // Building x-uefi-redfish string database
+    BuildXUefiRedfishStringDatabase (FormsetPrivate);
   }
 
   HiiFormLink = GetFirstNode (&HiiFormSet->FormListHead);
@@ -919,6 +1635,7 @@ LoadFormset (
     HiiFormPrivate = AllocateZeroPool (sizeof 
(REDFISH_PLATFORM_CONFIG_FORM_PRIVATE));
     if (HiiFormPrivate == NULL) {
       Status = EFI_OUT_OF_RESOURCES;
+      DEBUG ((DEBUG_ERROR, "%a: No memory resource for 
REDFISH_PLATFORM_CONFIG_FORM_PRIVATE.\n", __func__));
       goto ErrorExit;
     }
 
@@ -944,6 +1661,7 @@ LoadFormset (
 
       HiiStatementPrivate = AllocateZeroPool (sizeof 
(REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE));
       if (HiiStatementPrivate == NULL) {
+        DEBUG ((DEBUG_ERROR, "%a: No memory resource for 
REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE.\n", __func__));
         Status = EFI_OUT_OF_RESOURCES;
         goto ErrorExit;
       }
@@ -981,10 +1699,18 @@ LoadFormset (
         }
       }
 
-      //
-      // Attach to statement list.
-      //
-      InsertTailList (&HiiFormPrivate->StatementList, 
&HiiStatementPrivate->Link);
+      // Get x-uefi-redfish string using String ID.
+      Status = GetXuefiStringAndLangByStringId (FormsetPrivate, 
HiiStatementPrivate->Description, &String, NULL, NULL);
+      if (!EFI_ERROR (Status)) {
+        HiiStatementPrivate->DescriptionStr = String;
+        //
+        // Attach to statement list.
+        //
+        InsertTailList (&HiiFormPrivate->StatementList, 
&HiiStatementPrivate->Link);
+      } else {
+        FreePool (HiiStatementPrivate);
+      }
+
       HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, 
HiiStatementLink);
     }
 
@@ -1052,7 +1778,7 @@ LoadFormsetList (
   //
   Status = LoadFormset (HiiHandle, FormsetPrivate);
   if (EFI_ERROR (Status)) {
-    DEBUG ((DEBUG_ERROR, "%a: failed to load formset: %r\n", __func__, 
Status));
+    DEBUG ((DEBUG_ERROR, "%a: Formset is not loaded for edk2 redfish: %r\n", 
__func__, Status));
     FreePool (FormsetPrivate);
     return Status;
   }
@@ -1325,7 +2051,11 @@ ProcessPendingList (
 
       Status = LoadFormsetList (Target->HiiHandle, FormsetList);
       if (EFI_ERROR (Status)) {
-        DEBUG ((DEBUG_ERROR, "%a: load formset from HII handle: 0x%x failed: 
%r\n", __func__, Target->HiiHandle, Status));
+        if (Status == EFI_UNSUPPORTED) {
+          DEBUG ((DEBUG_ERROR, "  The formset has no x-uefi-redfish 
configurations.\n"));
+        } else {
+          DEBUG ((DEBUG_ERROR, "  load formset from HII handle: 0x%x failed: 
%r\n", Target->HiiHandle, Status));
+        }
       }
     }
 
-- 
2.37.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#117123): https://edk2.groups.io/g/devel/message/117123
Mute This Topic: https://groups.io/mt/105159783/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to