RedfishPkg/RedfishPlatformConfigDxe: Config language searching optimization

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>
Reviewed-by: Nickle Wang <nicklew@nvidia.com>
Reviewed-by: Igor Kulchytskyy <igork@ami.com>
This commit is contained in:
abnchang 2024-03-14 22:18:51 +08:00 committed by mergify[bot]
parent b387114113
commit 29114fc574
3 changed files with 877 additions and 72 deletions

View File

@ -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,15 +2062,12 @@ 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;
ASSERT (StatementRef->Statement->XuefiRedfishStr != NULL);
TmpConfigureLangList[Index] = AllocateCopyPool (HiiStrSize (StatementRef->Statement->XuefiRedfishStr), (VOID *)StatementRef->Statement->XuefiRedfishStr);
++Index;
}
}
}
}
*Count = StatementList.Count;
*ConfigureLangList = TmpConfigureLangList;

View File

@ -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->XuefiRedfishStr;
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->XuefiRedfishStr 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->XuefiRedfishStr;
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,606 @@ NewFormsetPrivate (
// Initial newly created formset private data.
//
InitializeListHead (&NewFormsetPrivate->HiiFormList);
InitializeListHead (&NewFormsetPrivate->XuefiRedfishStringDatabase);
return NewFormsetPrivate;
}
/**
Create new x-uefi-redfish string array.
@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_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 (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 (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__));
ReleaseXuefiStringDatabase (FormsetPrivate);
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 +1583,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 +1591,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 +1601,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 +1620,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 +1634,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 +1660,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 +1698,18 @@ LoadFormset (
}
}
// Get x-uefi-redfish string using String ID.
Status = GetXuefiStringAndLangByStringId (FormsetPrivate, HiiStatementPrivate->Description, &String, NULL, NULL);
if (!EFI_ERROR (Status)) {
HiiStatementPrivate->XuefiRedfishStr = String;
//
// Attach to statement list.
//
InsertTailList (&HiiFormPrivate->StatementList, &HiiStatementPrivate->Link);
} else {
FreePool (HiiStatementPrivate);
}
HiiStatementLink = GetNextNode (&HiiForm->StatementListHead, HiiStatementLink);
}
@ -1052,7 +1777,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 +2050,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));
}
}
}

View File

@ -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,6 +51,36 @@ 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
//
@ -54,9 +89,11 @@ typedef struct {
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.
CHAR16 *XuefiRedfishStr; // x-uefi-redfish string 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;
};
#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