strings.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,275 行 · 第 1/3 页
C
1,275 行
/*++
Copyright (c) 2004 - 2005, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Strings.c
Abstract:
This file contains the string processing code to the HII database.
--*/
#include "HiiDatabase.h"
VOID
AsciiToUnicode (
IN UINT8 *Lang,
IN UINT16 *Language
)
{
UINT8 Count;
//
// Convert the ASCII Lang variable to a Unicode Language variable
//
for (Count = 0; Count < 3; Count++) {
Language[Count] = (CHAR16) Lang[Count];
}
}
EFI_STATUS
EFIAPI
HiiTestString (
IN EFI_HII_PROTOCOL *This,
IN CHAR16 *StringToTest,
IN OUT UINT32 *FirstMissing,
OUT UINT32 *GlyphBufferSize
)
/*++
Routine Description:
Test if all of the characters in a string have corresponding font characters.
Arguments:
Returns:
--*/
{
EFI_HII_GLOBAL_DATA *GlobalData;
EFI_HII_DATA *HiiData;
UINTN Count;
BOOLEAN Narrow;
UINTN Location;
UINT8 GlyphCol1[19];
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
HiiData = EFI_HII_DATA_FROM_THIS (This);
GlobalData = HiiData->GlobalData;
Count = 0;
Narrow = TRUE;
EfiZeroMem (GlyphCol1, sizeof (GlyphCol1));
//
// Walk through the string until you hit the null terminator
//
for (; StringToTest[*FirstMissing] != 0x00; (*FirstMissing)++) {
Location = *FirstMissing;
//
// Rewind through the string looking for a glyph width identifier
//
for (; Location != 0; Location--) {
if (StringToTest[Location] == NARROW_CHAR || StringToTest[Location] == WIDE_CHAR) {
//
// We found something that identifies what glyph database to look in
//
if (StringToTest[Location] == WIDE_CHAR) {
Narrow = FALSE;
} else {
Narrow = TRUE;
}
}
}
if (Narrow) {
if (EfiCompareMem (
GlobalData->NarrowGlyphs[StringToTest[*FirstMissing]].GlyphCol1,
&mUnknownGlyph,
NARROW_GLYPH_ARRAY_SIZE
) == 0
) {
//
// Break since this glyph isn't defined
//
return EFI_NOT_FOUND;
}
} else {
//
// Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size
//
if (EfiCompareMem (
GlobalData->WideGlyphs[StringToTest[*FirstMissing]].GlyphCol1,
&mUnknownGlyph,
WIDE_GLYPH_ARRAY_SIZE
) == 0
) {
//
// Break since this glyph isn't defined
//
return EFI_NOT_FOUND;
}
}
Count++;
}
if (Narrow) {
*GlyphBufferSize = (UINT32) (Count * sizeof (EFI_NARROW_GLYPH));
} else {
*GlyphBufferSize = (UINT32) (Count * sizeof (EFI_WIDE_GLYPH));
}
return EFI_SUCCESS;
}
EFI_STATUS
HiiNewString2 (
IN EFI_HII_PROTOCOL *This,
IN CHAR16 *Language,
IN EFI_HII_HANDLE Handle,
IN OUT STRING_REF *Reference,
IN CHAR16 *NewString,
IN BOOLEAN ResetStrings
)
/*++
Routine Description:
This function allows a new String to be added to an already existing String Package.
We will make a buffer the size of the package + EfiStrSize of the new string. We will
copy the string package that first gets changed and the following language packages until
we encounter the NULL string package. All this time we will ensure that the offsets have
been adjusted.
Arguments:
This - Pointer to the HII protocol.
Language - Pointer to buffer which contains the language code of this NewString.
Handle - Handle of the package instance to be processed.
Reference - The token number for the string. If 0, new string token to be returned through this parameter.
NewString - Buffer pointer for the new string.
ResetStrings - Indicate if we are resetting a string.
Returns:
EFI_SUCCESS - The string has been added or reset to Hii database.
EFI_INVALID_PARAMETER - Some parameter passed in is invalid.
--*/
{
EFI_HII_PACKAGE_INSTANCE *PackageInstance;
EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;
EFI_HII_DATA *HiiData;
EFI_HII_STRING_PACK *StringPack;
EFI_HII_STRING_PACK *NewStringPack;
EFI_HII_HANDLE_DATABASE *HandleDatabase;
EFI_HII_PACKAGE_INSTANCE *NewBuffer;
UINT8 *Location;
UINT8 *StringLocation;
RELOFST *StringPointer;
UINTN Count;
UINTN Size;
UINTN Index;
UINTN SecondIndex;
BOOLEAN AddString;
EFI_STATUS Status;
UINTN Increment;
UINTN StringCount;
UINT32 TotalStringCount;
UINT32 OriginalStringCount;
RELOFST StringSize;
UINT32 Length;
RELOFST Offset;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
HiiData = EFI_HII_DATA_FROM_THIS (This);
HandleDatabase = HiiData->DatabaseHead;
PackageInstance = NULL;
AddString = FALSE;
Increment = 0;
StringCount = 0;
TotalStringCount = 0;
OriginalStringCount = 0;
//
// Check numeric value against the head of the database
//
for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
//
// Match the numeric value with the database entry - if matched, extract PackageInstance
//
if (Handle == HandleDatabase->Handle) {
PackageInstance = HandleDatabase->Buffer;
if (ResetStrings) {
TotalStringCount = HandleDatabase->NumberOfTokens;
}
break;
}
}
//
// No handle was found - error condition
//
if (PackageInstance == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = ValidatePack (This, PackageInstance, &StringPackageInstance, &TotalStringCount);
//
// This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value
//
Count = StringPackageInstance->IfrSize;
//
// This is the size of the complete series of string packs
//
Size = StringPackageInstance->StringSize;
//
// Based on if there is IFR data in this package instance, determine
// what the location is of the beginning of the string data.
//
if (StringPackageInstance->IfrSize > 0) {
Location = (CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize;
} else {
Location = (CHAR8 *) (&StringPackageInstance->IfrData);
}
//
// We allocate a buffer which is big enough for both adding and resetting string.
// The size is slightly larger than the real size of the packages when we are resetting a string.
//
NewBuffer = EfiLibAllocateZeroPool (
sizeof (EFI_HII_PACKAGE_INSTANCE) -
2 * sizeof (VOID *) +
StringPackageInstance->IfrSize +
StringPackageInstance->StringSize +
sizeof (RELOFST) +
EfiStrSize (NewString)
);
ASSERT (NewBuffer);
//
// Copy data to new buffer
//
NewBuffer->Handle = StringPackageInstance->Handle;
NewBuffer->IfrSize = StringPackageInstance->IfrSize;
//
// The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string
// package to begin with.
//
NewBuffer->StringSize = StringPackageInstance->StringSize + EfiStrSize (NewString) + sizeof (EFI_HII_STRING_PACK);
if (StringPackageInstance->IfrSize > 0) {
EfiCopyMem (&NewBuffer->IfrData, &StringPackageInstance->IfrData, StringPackageInstance->IfrSize);
}
StringPack = (EFI_HII_STRING_PACK *) Location;
//
// There may be multiple instances packed together of strings
// so we must walk the self describing structures until we encounter
// what we are looking for. In the meantime, copy everything we encounter
// to the new buffer.
//
EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
for (; Length != 0;) {
//
// If passed in Language ISO value is in this string pack's language string
// then we are dealing with the strings we want.
//
EfiCopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST));
Status = CompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language);
if (!EFI_ERROR (Status)) {
break;
}
EfiCopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length);
Count = Count + Length;
StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);
EfiCopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));
}
//
// Found the language pack to update on a particular handle
// We need to Copy the Contents of this pack and adjust the offset values associated
// with adding/changing a string. This is a particular piece of code that screams for
// it being prone to programming error.
//
//
// Copy the string package up to the string data
//
StringPointer = (RELOFST *) (StringPack + 1);
EfiCopyMem (
((CHAR8 *) (&NewBuffer->IfrData) + Count),
StringPack,
(UINTN) ((UINTN) (StringPointer) - (UINTN) (StringPack))
);
//
// Determine the number of StringPointers
//
if (!ResetStrings) {
EfiCopyMem (&TotalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));
} else {
//
// If we are resetting the strings, use the original value when exported
//
EfiCopyMem (&OriginalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST));
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString -=
(
(RELOFST) (OriginalStringCount - TotalStringCount) *
sizeof (RELOFST)
);
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName -=
(
(RELOFST) (OriginalStringCount - TotalStringCount) *
sizeof (RELOFST)
);
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers = TotalStringCount;
*Reference = (STRING_REF) (TotalStringCount);
}
//
// If the token value is not valid, error out
//
if ((*Reference >= TotalStringCount) && !ResetStrings) {
gBS->FreePool (NewBuffer);
return EFI_INVALID_PARAMETER;
}
//
// If Reference is 0, update it with what the new token reference will be and turn the AddString flag on
//
if (*Reference == 0) {
*Reference = (STRING_REF) (TotalStringCount);
AddString = TRUE;
}
if (AddString) {
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString += sizeof (RELOFST);
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName += sizeof (RELOFST);
((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers++;
}
//
// Increment offset by amount of copied data
//
Count = Count + ((UINTN) (StringPointer) - (UINTN) StringPack);
for (Index = 0; Index < TotalStringCount; Index++) {
//
// If we are pointing to the size of the changing string value
// then cache the old string value so you know what the difference is
//
if (Index == *Reference) {
EfiCopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
StringLocation = ((CHAR8 *) (StringPack) + Offset);
for (SecondIndex = 0;
(StringLocation[SecondIndex] != 0) || (StringLocation[SecondIndex + 1] != 0);
SecondIndex = SecondIndex + 2
)
;
SecondIndex = SecondIndex + 2;
Size = SecondIndex;
//
// NewString is a passed in local string which is assumed to be aligned
//
Size = EfiStrSize (NewString) - Size;
}
//
// If we are about to copy the offset of the string that follows the changed string make
// sure that the offsets are adjusted accordingly
//
if ((Index > *Reference) && !ResetStrings) {
EfiCopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
Offset = (RELOFST) (Offset + Size);
EfiCopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));
}
//
// If we are adding a string that means we will have an extra string pointer that will affect all string offsets
//
if (AddString) {
EfiCopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST));
Offset = (UINT32) (Offset + sizeof (RELOFST));
EfiCopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST));
}
//
// If resetting the strings, we need to reduce the offset by the difference in the strings
//
if (ResetStrings) {
EfiCopyMem (&Length, &StringPointer[Index], sizeof (RELOFST));
Length = Length - ((RELOFST) (OriginalStringCount - TotalStringCount) * sizeof (RELOFST));
EfiCopyMem (&StringPointer[Index], &Length, sizeof (RELOFST));
}
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?