public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nickle Wang via groups.io" <nicklew=nvidia.com@groups.io>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	Nickle Wang <nicklew@nvidia.com>,
	"abner.chang@amd.com" <abner.chang@amd.com>
Cc: Igor Kulchytskyy <igork@ami.com>
Subject: Re: [edk2-devel] [PATCH V2 1/6] RedfishPkg/RedfishPlatformConfigDxe: Config language searching optimization
Date: Wed, 27 Mar 2024 07:37:53 +0000	[thread overview]
Message-ID: <MW4PR12MB70312C50907F93880D7C3ADCD9342@MW4PR12MB7031.namprd12.prod.outlook.com> (raw)
In-Reply-To: <17C07EC03FCD57FF.6405@groups.io>

Per offline discussion with Abner, this will be addressed by separated patch since there is no function impact to performance improvements.

Reviewed-by: Nickle Wang <nicklew@nvidia.com>

Regards,
Nickle

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Nickle Wang
> via groups.io
> Sent: Wednesday, March 27, 2024 10:40 AM
> To: abner.chang@amd.com; devel@edk2.groups.io
> Cc: Igor Kulchytskyy <igork@ami.com>
> Subject: Re: [edk2-devel] [PATCH V2 1/6] RedfishPkg/RedfishPlatformConfigDxe:
> Config language searching optimization
> 
> External email: Use caution opening links or attachments
> 
> 
> Hi Abner,
> 
> Could we change "DescriptionStr" below to something like "XuefiString", so
> people don't think it is a regular English string of HII 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.
> 
> 
> Thanks,
> Nickle
> 
> > -----Original Message-----
> > From: abner.chang@amd.com <abner.chang@amd.com>
> > Sent: Tuesday, March 26, 2024 11:15 PM
> > To: devel@edk2.groups.io
> > Cc: Nickle Wang <nicklew@nvidia.com>; Igor Kulchytskyy <igork@ami.com>
> > Subject: [PATCH V2 1/6] RedfishPkg/RedfishPlatformConfigDxe: Config language
> > searching optimization
> >
> > External email: Use caution opening links or attachments
> >
> >
> > From: abnchang <abnchang@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.chang@amd.com>
> > Co-authored-by: Nickle Wang <nicklew@nvidia.com>
> > Cc: Igor Kulchytskyy <igork@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 (#117151): https://edk2.groups.io/g/devel/message/117151
Mute This Topic: https://groups.io/mt/105159783/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-03-27  7:38 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-26 15:14 [edk2-devel] [PATCH V2 0/6] [PATCH V2 0/5] Config language searching algorithm enhancement and the bug fixes Chang, Abner via groups.io
2024-03-26 15:14 ` [edk2-devel] [PATCH V2 1/6] RedfishPkg/RedfishPlatformConfigDxe: Config language searching optimization Chang, Abner via groups.io
2024-03-27  2:40   ` Nickle Wang via groups.io
2024-04-04  3:02     ` Chang, Abner via groups.io
     [not found]   ` <17C07EC03FCD57FF.6405@groups.io>
2024-03-27  7:37     ` Nickle Wang via groups.io [this message]
2024-04-04  0:44   ` Igor Kulchytskyy via groups.io
2024-04-04  3:00     ` Chang, Abner via groups.io
2024-03-26 15:14 ` [edk2-devel] [PATCH V2 2/6] RedfishPkg/RedfishDebugLib: Introduce Redfish DEBUG macro Chang, Abner via groups.io
2024-03-27  7:38   ` Nickle Wang via groups.io
2024-03-26 15:14 ` [edk2-devel] [PATCH V2 3/6] RedfishPkg/RedfishPlatformConfigDxe:Add RefishDebugLib support Chang, Abner via groups.io
2024-03-27  7:38   ` Nickle Wang via groups.io
2024-03-26 15:15 ` [edk2-devel] [PATCH V2 4/6] RedfishPkg/RedfishPlatformConfigDxe: HII string is deleted unexpectedly Chang, Abner via groups.io
2024-03-27  7:39   ` Nickle Wang via groups.io
2024-03-26 15:15 ` [edk2-devel] [PATCH V2 5/6] EmulatorPkg/Redfish: Use edk2 Redfish debug PCDs Chang, Abner via groups.io
2024-03-27  7:39   ` Nickle Wang via groups.io
2024-03-26 15:15 ` [edk2-devel] [PATCH V2 6/6] RedfishPkg/RedfishPlatformConfigDxe: support menu path report Chang, Abner via groups.io
2024-03-27  7:39   ` Nickle Wang via groups.io
2024-03-27  7:41 ` [edk2-devel] [PATCH V2 0/6] [PATCH V2 0/5] Config language searching algorithm enhancement and the bug fixes Nickle Wang via groups.io
2024-03-27  7:43   ` Chang, Abner via groups.io
2024-03-29 11:11     ` Igor Kulchytskyy via groups.io

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=MW4PR12MB70312C50907F93880D7C3ADCD9342@MW4PR12MB7031.namprd12.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox