diff options
Diffstat (limited to 'Core/CORE_DXE/UefiHii/HiiString.c')
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiString.c | 1609 |
1 files changed, 1609 insertions, 0 deletions
diff --git a/Core/CORE_DXE/UefiHii/HiiString.c b/Core/CORE_DXE/UefiHii/HiiString.c new file mode 100644 index 0000000..91f2708 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiString.c @@ -0,0 +1,1609 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiString.c 7 8/15/12 3:45p Artems $ +// +// $Revision: 7 $ +// +// $Date: 8/15/12 3:45p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiString.c $ +// +// 7 8/15/12 3:45p Artems +// [TAG] EIP96755 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Strings in new language added at runtime lost during export +// [RootCause] Every language represented by its own string package. +// When +// strings of new language added at runtime, they're added to database, +// but not to the list of packages. Export function is working with +// list of packages, so new language strings will be missed +// [Solution] Added code to create new string package at runtime when +// new string +// of new language is added to database +// [Files] HiiPrivate.h HiiString.c +// +// 6 5/22/12 4:34p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio +// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c +// UefiHii.h +// +// +// 5 10/24/11 5:40p Artems +// EIP 70530: Bug reported by SCT 2.3.1. Languages shold be compared +// ignoring case +// +// 4 5/13/11 6:15p Artems +// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and +// AmiHiiSetString +// to avoid collusion with EdkII native library functions +// +// 3 12/03/09 12:02p Aaronp +// Fix for SCT GetSecondLanguages failures. +// +// 2 11/23/09 7:38p Felixp +// HiiGetLanguages is updated to accept NULL language buffer when +// *LanguagesSize is zero. +// +// 1 10/09/09 6:12p Felixp +// +// 1 2/27/09 3:55p Artems +// Initial check-in +// +// 1 3/18/07 5:23p Felixp +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: HiiString.c +// +// Description: Hii string protocol functions implementation +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#pragma warning (disable : 4090) + +#include <AmiDxeLib.h> +#include "HiiPrivate.h" + +#define DEFAULT_FONT 0x100 +#define INVALID_FONT_ID 0xFEFE + +extern HII_DATABASE_PRIVATE_DATA PrivateData; + +DBE_OFFSET_KEY_CONTEXT StringDbKeyContext = {EFI_FIELD_OFFSET(STRING_RECORD ,StringId), 4 }; +DBE_KEY_FIELD StringDbKeyField = OFFSET_KEY(StringDbKeyContext); + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AmiHiiGetString +// +// Description: +// This function is HII String protocol function GetString implementation +// +// Input: +// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure +// IN CHAR8 *Language - Language definition +// IN EFI_HII_HANDLE PackageList - Handle of package list +// IN EFI_STRING_ID StringId - String Id +// OUT EFI_STRING String - Pointer to output string +// IN OUT UINTN *StringSize - Pointer to string size value +// OUT EFI_FONT_INFO *StringFontInfo - Pointer to returned string font info +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - String or StringSize or Language is NULL +// EFI_NOT_FOUND - String not found +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AmiHiiGetString( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN CONST CHAR8 *Language, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + OUT EFI_STRING String, + IN OUT UINTN *StringSize, + OUT EFI_FONT_INFO **StringFontInfo OPTIONAL) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList; + STRING_RECORD DbKey; + INT8 Vicinity; + STRING_RECORD *Found; + UINTN *FindRecord; + UINT32 Size; + EFI_STATUS Status; + LANGUAGE_LINK *Ptr; + UINT32 i; + UINT16 SaveLanguage; + + if (Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) + return EFI_INVALID_PARAMETER; + + if (String == NULL && *StringSize != 0) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + DbKey.StringId = StringId; + Status = GetLanguageId(Record, Language, &(DbKey.LanguageId), &Ptr); + if(EFI_ERROR(Status)) + return EFI_INVALID_LANGUAGE; + + Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + if(EFI_ERROR(Status)) + { + //string not found in database, try different languages + SaveLanguage = DbKey.LanguageId; + for(i = 0; i < Record->LanguageList.Size; i++) + { + if (i == SaveLanguage) + continue; + DbKey.LanguageId = (UINT16)i; + Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + if(!EFI_ERROR(Status)) + return EFI_INVALID_LANGUAGE; //string exists but with different language + } + + return EFI_NOT_FOUND; + } + + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + + Size = StrSize16(Found->String); + + if(Size > *StringSize) + { + *StringSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + StrCpy16(String, Found->String); + *StringSize = Size; + + if(StringFontInfo != NULL) + Status = FindStingFontInfoById(Record, Found->FontId, StringFontInfo); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AmiHiiSetString +// +// Description: +// This function is HII String protocol function SetString implementation +// +// Input: +// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure +// IN EFI_HII_HANDLE PackageList - Handle of package list +// IN EFI_STRING_ID StringId - String Id +// IN CHAR8 *Language - Language definition +// IN EFI_STRING String - String to set +// IN EFI_FONT_INFO *StringFontInfo - Pointer to string font info +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - String or Language is NULL +// EFI_NOT_FOUND - String not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AmiHiiSetString ( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST CHAR8 *Language, + IN CONST EFI_STRING String, + IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList; + STRING_RECORD DbKey; + INT8 Vicinity; + STRING_RECORD *Found; + UINTN *FindRecord; + UINT32 i; + UINT16 SaveLanguage; + LANGUAGE_LINK *Ptr; + EFI_STATUS Status; + + if(String == NULL || Language == NULL || PackageList == NULL) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + DbKey.StringId = StringId; + Status = GetLanguageId(Record, Language, &(DbKey.LanguageId), &Ptr); + + if(EFI_ERROR(Status)) + return Status; + + Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + if(!EFI_ERROR(Status)) + { //updated string found in database - retreive font info + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + DbKey.FontId = Found->FontId; + DbeDelete(&(Record->StringDb), Found, TRUE); + } + else //try same StringId with different languages + { + SaveLanguage = DbKey.LanguageId; + for(i = 0; i < Record->LanguageList.Size; i++) + { + if (i == SaveLanguage) + continue; + DbKey.LanguageId = i; + Status = DbeLocateKey(&(Record->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + if(!EFI_ERROR(Status)) + break; + } + if(i == Record->LanguageList.Size) + return EFI_NOT_FOUND; + + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + DbKey.FontId = Found->FontId; + DbKey.LanguageId = SaveLanguage; + } + + if(StringFontInfo != NULL) { + Status = FindStringFontInfoByTemplate(Record, StringFontInfo, &DbKey.FontId); + if(EFI_ERROR(Status)) { + Status = AddStringFont(Record, INVALID_FONT_ID, StringFontInfo->FontSize, + StringFontInfo->FontStyle, StringFontInfo->FontName, &DbKey.FontId); + if(EFI_ERROR(Status)) + return Status; + } + + } + + Status = AddString(Record, DbKey.LanguageId, DbKey.StringId, DbKey.FontId, String); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiNewString +// +// Description: +// This function is HII String protocol function NewString implementation +// +// Input: +// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure +// IN EFI_HII_HANDLE PackageList - Handle of package list +// OUT EFI_STRING_ID *StringId - Pointer to returned string Id +// IN CHAR8 *Language - Language definition +// IN CHAR16 *LanguageName - Language human readable name +// IN EFI_STRING String - String to set +// IN EFI_FONT_INFO *StringFontInfo - Pointer to string font info +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - String or Language or StringId is NULL +// EFI_NOT_FOUND - Package list handle is invalid +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiNewString ( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + OUT EFI_STRING_ID *StringId, + IN CONST CHAR8 *Language, + IN CONST CHAR16 *LanguageName OPTIONAL, + IN CONST EFI_STRING String, + IN CONST EFI_FONT_INFO *StringFontInfo) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList; + EFI_STATUS Status; + UINT16 LanguageId; + LANGUAGE_LINK *Link; + UINT16 FontId; + CHAR16 DefaultName[80]; + + if(String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + Status = GetLanguageId(Record, Language, &LanguageId, &Link); + if(EFI_ERROR(Status)) + { + Status = AddLanguage(Record, Language, LanguageName, 0); + if(EFI_ERROR(Status)) + return Status; + Status = GetLanguageId(Record, Language, &LanguageId, &Link); + //language added, now add language name string to database + if(LanguageName == NULL) { + CreateLanguageName(Language, DefaultName, 80 * sizeof(CHAR16)); + LanguageName = DefaultName; + } + //at this point LastStringId has value LanguageName + 1 + Status = AmiHiiSetString(This, PackageList, Link->LastStringId - 1, Language, LanguageName, NULL); + } + + if(StringFontInfo != NULL) { + Status = FindStringFontInfoByTemplate(Record, StringFontInfo, &FontId); + if(EFI_ERROR(Status)) { + Status = AddStringFont(Record, INVALID_FONT_ID, StringFontInfo->FontSize, + StringFontInfo->FontStyle, StringFontInfo->FontName, &FontId); + if(EFI_ERROR(Status)) + return Status; + } + + } else { + FontId = DEFAULT_FONT; + } + + Status = AddString(Record, LanguageId, Link->LastStringId, FontId, String); + if(EFI_ERROR(Status)) + return Status; + + *StringId = Link->LastStringId; + + Link->LastStringId++; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetLanguages +// +// Description: +// This function is HII String protocol function GetLanguages implementation +// +// Input: +// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure +// IN EFI_HII_HANDLE PackageList - Handle of package list +// IN OUT CHAR8 *Languages - Pointer to returned language buffer +// IN OUT UINTN *LanguagesSize - Pointer to language buffer size +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - LanguagesSize or Languages is NULL +// EFI_NOT_FOUND - Package list handle is invalid or NULL +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetLanguages ( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN OUT CHAR8 *Languages, + IN OUT UINTN *LanguagesSize +) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *)PackageList; +// EFI_STATUS Status; + LANGUAGE_LINK *Link; + UINTN Size = 0; + + if(PackageList == NULL) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + if(LanguagesSize == NULL || Languages == NULL && *LanguagesSize != 0) + return EFI_INVALID_PARAMETER; + + if(Record->LanguageList.Size == 0) + { + *LanguagesSize = 0; + *Languages = 0; + return EFI_SUCCESS; + } + + Link = (LANGUAGE_LINK *)Record->LanguageList.pHead; + while(Link != NULL) + { + Size += StrSize8(Link->Language); + Link = (LANGUAGE_LINK *)Link->Link.pNext; + } + + if(Size > *LanguagesSize) + { + *LanguagesSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + *LanguagesSize = Size; + + Link = (LANGUAGE_LINK *)Record->LanguageList.pHead; + while(Link != NULL) + { + Size = StrSize8(Link->Language); + Size--; //skip NULL-terminator + MemCpy(Languages, Link->Language, Size); + Languages += Size; //shift pointer + *Languages = ';'; //add delimiter + Languages++; + Link = (LANGUAGE_LINK *)Link->Link.pNext; + } + + Languages--; //change delimiter to NULL-terminator + *Languages = 0; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetSecondLanguages +// +// Description: +// This function is HII String protocol function GetSecondaryLanguages implementation +// +// Input: +// IN EFI_HII_STRING_PROTOCOL *This - Pointer to EFI_HII_STRING_PROTOCOL structure +// IN EFI_HII_HANDLE PackageList - Handle of package list +// IN CHAR8 *FirstLanguage - First language definition +// IN OUT CHAR8 *Languages - Pointer to returned language buffer +// IN OUT UINTN *LanguagesSize - Pointer to language buffer size +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - LanguagesSize or Languages is NULL +// EFI_NOT_FOUND - Package list handle is invalid or NULL +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetSecondLanguages( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN CONST CHAR8 *FirstLanguage, + IN OUT CHAR8 *SecondLanguages, + IN OUT UINTN *SecondLanguagesSize +) +{ + EFI_STATUS Status; + UINTN Size = 0; + UINTN i = 0; + + CHAR8 *Langs = NULL; + + if(FirstLanguage == NULL || SecondLanguages == NULL || SecondLanguagesSize == NULL) + return EFI_INVALID_PARAMETER; + + // Get the size of all the languages in the Hii Package + Status = HiiGetLanguages(This, PackageList, NULL, &Size); + + if(EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) + return Status; + + // Allocate space for the languages + Status = pBS->AllocatePool(EfiBootServicesData, Size, &Langs); + + if(!EFI_ERROR(Status)) + // Get the langues into the temp buffer + Status = HiiGetLanguages(This, PackageList, Langs, &Size); + + // find and remove the primary language from the string + if(!EFI_ERROR(Status)) + { + Status = EFI_INVALID_LANGUAGE; + + for(; i < Size; i++) + { + // check if the current offset matches the first language + if(MemCmp(Langs+i,FirstLanguage,StrSize8(FirstLanguage)-1) == 0) + { + Status = EFI_SUCCESS; + + // copy the rest of the string on top of the primary strings location + pBS->CopyMem(Langs+i,Langs+i+StrSize8(FirstLanguage),StrSize8(Langs)-i-StrSize8(FirstLanguage)); + break; + } + } + } + + if(!EFI_ERROR(Status)) + { + Status = EFI_BUFFER_TOO_SMALL; + + // Check if the buffer is large enough to fit the secondary langues + if(*SecondLanguagesSize >= StrSize8(Langs)) + { + Status = EFI_SUCCESS; + MemCpy(SecondLanguages, Langs, StrSize8(Langs)); + } + + // fill in the size of the secondary langauges + *SecondLanguagesSize = StrSize8(Langs); + } + + if(Langs != NULL) + pBS->FreePool(Langs); + + return Status; +} + +// *************************** Service functions (not for public use) ************************ + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CreateLanguageName +// +// Description: +// This function creates human-readable language name from RFC name +// +// Input: +// IN CHAR8 *RfcName - pointer to RFC name +// OUT CHAR16* OutName - pointer where to store human-readable name +// UINTN MaxSize - max size of output buffer in bytes +// +// Output: +// UINT16 - number of strings in package +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID CreateLanguageName( + IN CHAR8 *RfcName, + OUT CHAR16* OutName, + UINTN MaxSize) +{ + UINTN i; + + for(i = 0; (RfcName[i] != 0 && i < (MaxSize / 2 - 1)); i++) + OutName[i] = RfcName[i]; + OutName[i] = 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddStringPackage +// +// Description: +// This function creates string package for language not existed in package list +// at the time of submission to database +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs +// IN CHAR8 *Language - Language RFC name +// +// Output: +// UINT16 - number of strings in package +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 AddStringPackage( + PACKAGE_LIST_RECORD *PackageList, + CHAR8 *Language) +{ + UINT32 Size; + PACKAGE_LINK *Template; + PACKAGE_LINK *NewLink; + DLIST *PackList; + UINT16 LanguageStringId; + UINT32 i; + EFI_HII_STRING_PACKAGE_HDR *Hdr; + EFI_HII_STRING_PACKAGE_HDR *NewHdr; + + PackList = &(PackageList->PackageList); + Template = (PACKAGE_LINK *)PackList->pHead; + while(Template != NULL) { + if(Template->Package.Type == EFI_HII_PACKAGE_STRINGS) + break; + Template = (PACKAGE_LINK *)Template->Link.pNext; + } + + if(Template == NULL) {//no string packages in this package list + LanguageStringId = 1; + } else { + Hdr = (EFI_HII_STRING_PACKAGE_HDR *)&(Template->Package); + LanguageStringId = Hdr->LanguageName; + } + + Size = sizeof(EFI_HII_STRING_PACKAGE_HDR) - 1; + Size += StrSize8(Language); + + NewLink = (PACKAGE_LINK *) CreateNewLink(Size); + if(NewLink == NULL) + return 0; + + NewLink->Package.Type = EFI_HII_PACKAGE_STRINGS; + NewLink->Package.Length = Size; //this is technically incorrect, but it will be updated upon export + NewHdr = (EFI_HII_STRING_PACKAGE_HDR *)&(NewLink->Package); + NewHdr->HdrSize = Size; + NewHdr->StringInfoOffset = Size; + if(Template == NULL) { + for(i = 0; i < 16; i++) + NewHdr->LanguageWindow[i] = 0; + } else { + for(i = 0; i < 16; i++) + NewHdr->LanguageWindow[i] = Hdr->LanguageWindow[i]; + } + NewHdr->LanguageName = LanguageStringId; + StrCpy8(NewHdr->Language, Language); + DListAdd(PackList, (DLINK *)NewLink); + return LanguageStringId + 1; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddLanguage +// +// Description: +// This function adds language to private HII database +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs +// IN EFI_HII_HANDLE PackageList - Handle of package list +// IN CHAR8 *Language - Language Id +// IN CHAR16 *LanguageName - Pointer to human readable language name +// IN UINT16 LastStringId - Last string Id on this language +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddLanguage( + PACKAGE_LIST_RECORD *PackageList, + CHAR8 *Language, + CHAR16* LanguageName, + UINT16 LastStringId) +{ + UINT32 Size1, Size2 = 0; + LANGUAGE_LINK *Link; + CHAR16 DefaultName[80]; + UINT8 *Ptr; + + Size1 = StrSize8(Language); + + if(LanguageName == NULL) { + CreateLanguageName(Language, DefaultName, 80 * sizeof(CHAR16)); + LanguageName = DefaultName; + } + + Size2 = StrSize16(LanguageName); + + Link = (LANGUAGE_LINK *)CreateNewLink(Size1 + Size2 + sizeof(UINT32)); + if(Link == NULL) + return EFI_OUT_OF_RESOURCES; + + if(LastStringId != 0) { + Link->LastStringId = LastStringId; + } else { + //we're adding language, that wasn't in package list from the start + Link->LastStringId = AddStringPackage(PackageList, Language); + if(Link->LastStringId == 0) + return EFI_OUT_OF_RESOURCES; + } + StrCpy8(Link->Language, Language); + + Ptr = (UINT8 *)Link->Language; + Ptr += Size1; + StrCpy16((CHAR16 *)Ptr, LanguageName); + + DListAdd(&(PackageList->LanguageList), (DLINK *)Link); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetLanguageId +// +// Description: +// This function returns language private Id which corresponds with given language Id +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where language belongs +// IN CHAR8 *Language - Language Id +// OUT UINT16 *LanguageId - Pointer where to return private Id +// OUT LANGUAGE_LINK **Found - Pointer where to return found language private data +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_NOT_FOUND - language not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetLanguageId( + PACKAGE_LIST_RECORD *PackageList, + CHAR8 *Language, + UINT16 *LanguageId, + LANGUAGE_LINK **Found OPTIONAL) +{ + LANGUAGE_LINK *Link = (LANGUAGE_LINK *)PackageList->LanguageList.pHead; + UINT8 Id; + + Id = 0; + while(Link != NULL) + { + if(LanguageCodesEqual(Language, Link->Language)) + { + *LanguageId = Id; + + if(Found) + *Found = Link; + + return EFI_SUCCESS; + } + Link = (LANGUAGE_LINK *)Link->Link.pNext; + Id++; + } + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddString +// +// Description: +// This function adds string to private storage +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where string belongs +// IN UINT16 LanguageId - Private language Id of the string +// IN UINT16 StringId - Private string Id of the string +// IN UINT16 FontId - Private font Id of the string +// IN EFI_STRING String - String to add +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddString( + PACKAGE_LIST_RECORD *PackageList, + UINT16 LanguageId, + UINT16 StringId, + UINT16 FontId, + EFI_STRING String) +{ + STRING_RECORD *Record; + UINT32 Size; + EFI_STATUS Status; + + Size = StrSize16(String); + + Status = pBS->AllocatePool( + EfiBootServicesData, + Size + 6, + &Record); + if (EFI_ERROR(Status)) + return Status; + + Record->FontId = FontId; + Record->LanguageId = LanguageId; + Record->StringId = StringId; + StrCpy16(Record->String, String); + + DbeInsert(&(PackageList->StringDb), Record); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseStringsPackage +// +// Description: +// This function parses string package +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where string package belongs +// IN EFI_HII_STRING_PACKAGE_HDR *Package - Pointer to package to parse +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_ERROR - Some error occured during execution +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseStringsPackage( + PACKAGE_LIST_RECORD *PackageList, + IN EFI_HII_STRING_PACKAGE_HDR *Package) +{ + EFI_STATUS Status; + LANGUAGE_LINK *Link; + UINT16 LanguageId; + UINT16 StringId; + UINT16 FontId; + EFI_HII_STRING_BLOCK *ParsePointer; + UINT16 StringCount; + STRING_RECORD DbKey; + INT8 Vicinity; + STRING_RECORD *Found; + UINTN *FindRecord; + BOOLEAN NewLanguage = FALSE; + CHAR16 *FontName; + + ParsePointer = (EFI_HII_STRING_BLOCK *)Package; + (UINT8 *)ParsePointer += Package->StringInfoOffset; + + Status = GetLanguageId(PackageList, Package->Language, &LanguageId, &Link); + if(EFI_ERROR(Status)) + { + LanguageId = (UINT16)PackageList->LanguageList.Size; + StringId = 1; + NewLanguage = TRUE; + } + else + StringId = Link->LastStringId; + + while(ParsePointer->BlockType != EFI_HII_SIBT_END) + { + switch(ParsePointer->BlockType) + { + case EFI_HII_SIBT_SKIP1: + StringId += ((EFI_HII_SIBT_SKIP1_BLOCK *)ParsePointer)->SkipCount; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_SKIP1_BLOCK); + break; + case EFI_HII_SIBT_SKIP2: + StringId += ((EFI_HII_SIBT_SKIP2_BLOCK *)ParsePointer)->SkipCount; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK); + break; + case EFI_HII_SIBT_EXT1: + (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT1_BLOCK *)ParsePointer)->Length; + break; + case EFI_HII_SIBT_EXT2: + (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT2_BLOCK *)ParsePointer)->Length; + break; + case EFI_HII_SIBT_EXT4: + (UINT8 *)ParsePointer += ((EFI_HII_SIBT_EXT4_BLOCK *)ParsePointer)->Length; + break; + case EFI_HII_SIBT_FONT: + FontName = (CHAR16 *)((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer + 1); + Status = AddStringFont(PackageList, + ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontId, + ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontSize, + ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->FontStyle, + FontName, NULL); + if(EFI_ERROR(Status)) + return Status; + (UINT8 *)ParsePointer += ((EFI_HII_SIBT_FONT_BLOCK *)ParsePointer)->Header.Length; + break; + case EFI_HII_SIBT_STRING_SCSU: + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_SCSU_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT, + 1, TRUE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRING_SCSU_FONT: + FontId = ((EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK *)ParsePointer)->FontIdentifier; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId, + 1, TRUE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRINGS_SCSU: + StringCount = ((EFI_HII_SIBT_STRINGS_SCSU_BLOCK *)ParsePointer)->StringCount; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_SCSU_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT, + StringCount, TRUE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRINGS_SCSU_FONT: + StringCount = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ParsePointer)->StringCount; + FontId = ((EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK *)ParsePointer)->FontIdentifier; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId, + StringCount, TRUE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + case EFI_HII_SIBT_STRING_UCS2: + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT, + 1, FALSE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRING_UCS2_FONT: + FontId = ((EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK *)ParsePointer)->FontIdentifier; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId, + 1, FALSE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRINGS_UCS2: + StringCount = ((EFI_HII_SIBT_STRINGS_UCS2_BLOCK *)ParsePointer)->StringCount; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_UCS2_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, DEFAULT_FONT, + StringCount, FALSE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + break; + case EFI_HII_SIBT_STRINGS_UCS2_FONT: + StringCount = ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ParsePointer)->StringCount; + FontId = ((EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK *)ParsePointer)->FontIdentifier; + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK); + Status = ExtractStrings(PackageList, LanguageId, &StringId, FontId, + StringCount, TRUE, &ParsePointer); + if(EFI_ERROR(Status)) + return Status; + case EFI_HII_SIBT_DUPLICATE: + DbKey.LanguageId = LanguageId; + DbKey.StringId = ((EFI_HII_SIBT_DUPLICATE_BLOCK *)ParsePointer)->StringId; + Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + if(!EFI_ERROR(Status)) + { + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + Status = AddString(PackageList, Found->LanguageId, StringId, Found->FontId, Found->String); + if(EFI_ERROR(Status)) + return Status; + StringId++; + } + (UINT8 *)ParsePointer += sizeof(EFI_HII_SIBT_DUPLICATE_BLOCK); + break; + default: + break; + } + } + +//Reconstruct full language name + + if(NewLanguage) + { + DbKey.LanguageId = LanguageId; + DbKey.StringId = Package->LanguageName; + Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, NULL); + + if(!EFI_ERROR(Status)) + { + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + Status = AddLanguage(PackageList, Package->Language, Found->String, StringId); + } + else + Status = AddLanguage(PackageList, Package->Language, NULL, StringId); + + if(EFI_ERROR(Status)) + return Status; + } + else + Link->LastStringId = StringId; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ExtractStrings +// +// Description: +// This function extracts strings from given block of strings +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong +// IN UINT16 LanguageId - Private language Id +// IN OUT UINT16 *StringId - Pointer to string Id +// IN UINT16 FontId - Font Id +// IN UINT16 StringCount - Number of strings to extract +// IN BOOLEAN Compressed - Flag, that determines whether string is compressed or not +// IN OUT VOID **StringBlock - Pointer to block of strings to extract +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_ERROR - Some error occured during execution +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ExtractStrings( + PACKAGE_LIST_RECORD *PackageList, + UINT16 LanguageId, + UINT16 *StringId, + UINT16 FontId, + UINT16 StringCount, + BOOLEAN Compressed, + VOID **StringBlock +) +{ + UINT16 i; + EFI_STATUS Status; + UINT32 StringSize; + UINT32 MaxSize = 0x100; + CHAR16 *String = NULL; + VOID *Pointer = *StringBlock; + + if(Compressed) + { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * MaxSize, + &String); + if(EFI_ERROR(Status)) + return Status; + } + + for(i = 0; i < StringCount; i++) + { + if(Compressed) + { + StringSize = StrSize8((CHAR8 *)Pointer); + if(StringSize > MaxSize) + { + MaxSize = StringSize; + pBS->FreePool(String); + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * MaxSize, + &String); + if(EFI_ERROR(Status)) + return Status; + } +// UncompressString(String, (CHAR8 *)Pointer); + Status = AddString(PackageList, LanguageId, *StringId, FontId, String); + } + else + { + StringSize = StrSize16(Pointer); + Status = AddString(PackageList, LanguageId, *StringId, FontId, (EFI_STRING)Pointer); + } + + if(EFI_ERROR(Status)) + return Status; + (*StringId)++; + (UINT8 *)Pointer += StringSize; + } + *StringBlock = Pointer; + if(String != NULL) + pBS->FreePool(String); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetStringBlockSize +// +// Description: +// This function determines block size needed to pack strings into string package +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong +// IN CHAR8 *Language - Language Id +// +// Output: +// UINTN - String block size in bytes +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINTN GetStringBlockSize( + IN PACKAGE_LIST_RECORD *PackageList, + IN CHAR8 *Language) +{ + STRING_RECORD DbKey; + INT8 Vicinity; + STRING_RECORD *Found; + UINTN *FindRecord; + EFI_STATUS Status; + UINTN RecordIndex; + DBE_DATABASE *Database = &(PackageList->StringDb); + UINT16 StringCounter = 0; + UINT16 SkipBlock = 0; //number of skip blocks to add to string block + UINT16 CurrentStringId; + UINTN Size = 0; + UINTN i; + + Status = GetLanguageId(PackageList, Language, &(DbKey.LanguageId), NULL); + if(EFI_ERROR(Status)) + return 0; + + DbKey.StringId = 1; //find first string with given language + Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, &RecordIndex); + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + if(EFI_ERROR(Status)) + { //there isn't string with string id = 1 + if(Found->LanguageId != DbKey.LanguageId) //we got string from previous language + { + RecordIndex++; + Status = DbeGoToIndex(&(PackageList->StringDb), 0, RecordIndex, &Found); + } + SkipBlock++; //at least one skip block should be added as far as we don't have string with id=1 + } + CurrentStringId = Found->StringId; + Size += StrSize16(Found->String); + StringCounter++; + + for(i = RecordIndex + 1; + (i < PackageList->StringDb.RecordCount) && (Found->LanguageId == DbKey.LanguageId); + i++) + { + Status = DbeGoToIndex(&(PackageList->StringDb), 0, i, &Found); + Size += StrSize16(Found->String); + StringCounter++; + if(Found->StringId > (CurrentStringId + 1)) + SkipBlock++; + CurrentStringId = Found->StringId; + } + + Size += SkipBlock * sizeof(EFI_HII_SIBT_SKIP2_BLOCK); + Size += StringCounter * sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK); + Size += sizeof(EFI_HII_SIBT_END_BLOCK); + + return Size; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetStringBlock +// +// Description: +// This function packs strings from private storage into string package format +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - Pointer to package list where strings belong +// IN CHAR8 *Language - Language Id +// OUT UINT8 *Buffer - Pointer to output buffer +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID GetStringBlock( + IN PACKAGE_LIST_RECORD *PackageList, + IN CHAR8 *Language, + IN UINT8 *Buffer) +{ + STRING_RECORD DbKey; + INT8 Vicinity; + STRING_RECORD *Found; + UINTN *FindRecord; + EFI_STATUS Status; + UINTN RecordIndex; + DBE_DATABASE *Database = &(PackageList->StringDb); + UINT16 StringCounter = 0; + UINT16 SkipBlock = 0; //number of skip blocks to add to string block + UINT16 CurrentStringId = 1; + UINTN Size = 0; + UINTN i; + + Status = GetLanguageId(PackageList, Language, &(DbKey.LanguageId), NULL); + + DbKey.StringId = 1; //find first string with given language + Status = DbeLocateKey(&(PackageList->StringDb), 0, &DbKey, &FindRecord, &Vicinity, &RecordIndex); + Found = (STRING_RECORD *)(UINTN)(*FindRecord); + if(EFI_ERROR(Status)) + { //there isn't string with string id = 1 + if(Found->LanguageId != DbKey.LanguageId) //we got string from previous language + { + RecordIndex++; + Status = DbeGoToIndex(&(PackageList->StringDb), 0, RecordIndex, &Found); + } + + ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->SkipCount = Found->StringId - CurrentStringId - 1; + ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_SKIP2; + Buffer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK); + } + CurrentStringId = Found->StringId; + ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; + Buffer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK); + Size = StrSize16(Found->String); + StrCpy16((CHAR16 *)Buffer, Found->String); + Buffer += Size; + + for(i = RecordIndex + 1; + (i < PackageList->StringDb.RecordCount) && (Found->LanguageId == DbKey.LanguageId); + i++) + { + Status = DbeGoToIndex(&(PackageList->StringDb), 0, i, &Found); + + if(Found->StringId > (CurrentStringId + 1)) //add skip block + { + ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->SkipCount = Found->StringId - CurrentStringId - 1; + ((EFI_HII_SIBT_SKIP2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_SKIP2; + Buffer += sizeof(EFI_HII_SIBT_SKIP2_BLOCK); + } + + ((EFI_HII_SIBT_STRING_UCS2_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; + Buffer += sizeof(EFI_HII_SIBT_STRING_UCS2_BLOCK); + Size = StrSize16(Found->String); + StrCpy16((CHAR16 *)Buffer, Found->String); + Buffer += Size; + CurrentStringId = Found->StringId; + } + ((EFI_HII_SIBT_END_BLOCK *)Buffer)->Header.BlockType = EFI_HII_SIBT_END; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateStringPackages +// +// Description: +// This function updates string package with strings contained in private storage +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list to update +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS UpdateStringPackages(EFI_HII_HANDLE Handle) +{ + DLIST *PackageList; + PACKAGE_LINK *Link; + PACKAGE_LINK *NewLink; + EFI_HII_STRING_PACKAGE_HDR *StringPackage; + UINT8 *Buffer; + UINTN Size; + + PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList); + Link = (PACKAGE_LINK *)(PackageList->pHead); + + while(Link != NULL) + { + if(Link->Package.Type == EFI_HII_PACKAGE_STRINGS) + { + StringPackage = (EFI_HII_STRING_PACKAGE_HDR *) &(Link->Package); + Size = GetStringBlockSize((PACKAGE_LIST_RECORD *)Handle, StringPackage->Language); + + if(Size != 0) + { + Size += StringPackage->HdrSize; + NewLink = (PACKAGE_LINK *) CreateNewLink((UINT32)Size); + if(NewLink == NULL) + return EFI_OUT_OF_RESOURCES; + + MemCpy((VOID *) &(NewLink->Package), + (VOID *) &(Link->Package), + StringPackage->HdrSize); + NewLink->Package.Length = (UINT32)Size; + Buffer = (UINT8 *) &(NewLink->Package); + Buffer += StringPackage->HdrSize; + + GetStringBlock((PACKAGE_LIST_RECORD *)Handle, StringPackage->Language, Buffer); + + DListInsert(PackageList, (DLINK *)NewLink, (DLINK *)Link); + DListDelete(PackageList, (DLINK *)Link); + pBS->FreePool(Link); + Link = NewLink; + } + } + Link = (PACKAGE_LINK *)Link->Link.pNext; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrSize8 +// +// Description: +// This function returns ASCII string size in bytes +// +// Input: +// IN CHAR8 *String - Pointer to string +// +// Output: +// UINT32 - Size of string in bytes including nul-terminator +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 StrSize8(CHAR8 *String) +{ + UINT32 Size = 1; + while(*String++) + Size++; + return Size; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrSize16 +// +// Description: +// This function returns UNICODE string size in bytes +// +// Input: +// IN CHAR16 *String - Pointer to string +// +// Output: +// UINT32 - Size of string in bytes including nul-terminator +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT32 StrSize16(CHAR16 *String) +{ + UINT32 Size = 2; + while(*String++) + Size += 2; + return Size; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrCpy8 +// +// Description: +// This function copies one ASCII string into another +// +// Input: +// IN CHAR8 *Dest - Pointer to destination string +// IN CHAR8 *Src - Pointer to source string +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID StrCpy8(CHAR8 *Dest, CHAR8 *Src) +{ + MemCpy(Dest, Src, StrSize8(Src)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrCpy16 +// +// Description: +// This function copies one UNICODE string into another +// +// Input: +// IN CHAR16 *Dest - Pointer to destination string +// IN CHAR16 *Src - Pointer to source string +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID StrCpy16(CHAR16 *Dest, CHAR16 *Src) +{ + MemCpy(Dest, Src, StrSize16(Src)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrCmp8 +// +// Description: +// This function compares two ASCII strings +// +// Input: +// IN CHAR8 *Dest - Pointer to destination string +// IN CHAR8 *Src - Pointer to source string +// +// Output: +// INTN - Zero if strings are equal, non-zero otherwise +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +INTN StrCmp8(CHAR8 *Dest, CHAR8 *Src) +{ + return MemCmp(Dest, Src, StrSize8(Src)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: StrCmp16 +// +// Description: +// This function compares two UNICODE strings +// +// Input: +// IN CHAR16 *Dest - Pointer to destination string +// IN CHAR16 *Src - Pointer to source string +// +// Output: +// INTN - Zero if strings are equal, non-zero otherwise +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src) +{ + return MemCmp(Dest, Src, StrSize16(Src)); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetAvailableFontId +// +// Description: +// This function returns available font ID number +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs +// +// Output: +// UINT16 - font ID number +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +UINT16 GetAvailableFontId( + IN PACKAGE_LIST_RECORD *PackageList +) +{ + UINT16 Id = 0; + STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead; + while(Link != NULL) { + Id = (Link->FontId > Id) ? Link->FontId : Id; + Link = (STRING_FONT_LINK *)Link->Link.pNext; + } + return Id + 1; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindStringFontInfoByTemplate +// +// Description: +// This function searches available fonts and returns font ID if match found +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs +// IN EFI_FONT_INFO *Template - pointer to font description +// OUT UINT16 *FontId - pointer where to return font ID +// +// Output: +// EFI_SUCCESS - font found +// EFI_NOT_FOUND - font not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindStringFontInfoByTemplate( + IN PACKAGE_LIST_RECORD *PackageList, + IN EFI_FONT_INFO *Template, + OUT UINT16 *FontId +) +{ + STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead; + EFI_FONT_INFO *Info; + + while(Link != NULL) { + Info = (EFI_FONT_INFO *)(Link + 1); + if(!MemCmp(Info, Template, Link->FontInfoSize)) { + *FontId = Link->FontId; + return EFI_SUCCESS; + } + Link = (STRING_FONT_LINK *)Link->Link.pNext; + } + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindStingFontInfoById +// +// Description: +// This function searches available fonts and returns font description if match found +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs +// IN UINT16 FontId - font ID to find +// OUT EFI_FONT_INFO **Info - pointer where to store pointer to font description +// +// Output: +// EFI_SUCCESS - font found +// EFI_NOT_FOUND - font not found +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindStingFontInfoById( + IN PACKAGE_LIST_RECORD *PackageList, + IN UINT16 FontId, + OUT EFI_FONT_INFO **Info +) +{ + static CHAR16 DefaultFontName[] = L"System font"; + STRING_FONT_LINK *Link = (STRING_FONT_LINK *)PackageList->StringFontList.pHead; + UINTN StrSize; + EFI_STATUS Status; + + while(Link != NULL) { + if(Link->FontId == FontId) { + Status = pBS->AllocatePool(EfiBootServicesData, Link->FontInfoSize, Info); + if(EFI_ERROR(Status)) + return Status; + + MemCpy(*Info, (VOID *)(Link + 1), Link->FontInfoSize); + return EFI_SUCCESS; + } + Link = (STRING_FONT_LINK *)Link->Link.pNext; + } +//font not found, return default font + StrSize = Wcslen(DefaultFontName) * sizeof(CHAR16); + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_FONT_INFO) + StrSize, Info); + if(!EFI_ERROR(Status)) { + (*Info)->FontSize = EFI_GLYPH_HEIGHT; + (*Info)->FontStyle = EFI_HII_FONT_STYLE_NORMAL; + Wcscpy((*Info)->FontName, DefaultFontName); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddStringFont +// +// Description: +// This function adds font to font database and assigns font ID if latter was +// not supplied +// +// Input: +// IN PACKAGE_LIST_RECORD *PackageList - pointer to package list were font belongs +// IN UINT16 FontId - font ID +// IN UINT16 FontSize - font size +// IN EFI_HII_FONT_STYLE FontStyle - font style +// IN CHAR16 *FontName - pointer to font name +// OUT UINT16 *NewFontId OPTIONAL - pointer where to store assigned font ID +// +// Output: +// EFI_SUCCESS - font found +// EFI_NOT_FOUND - font not found +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddStringFont( + IN PACKAGE_LIST_RECORD *PackageList, + IN UINT16 FontId, + IN UINT16 FontSize, + IN EFI_HII_FONT_STYLE FontStyle, + IN CHAR16 *FontName, + OUT UINT16 *NewFontId OPTIONAL +) +{ + UINT16 Fid; + UINT32 FontNameSize; + STRING_FONT_LINK *AddLink; + EFI_FONT_INFO *FontInfo; + + Fid = (FontId == INVALID_FONT_ID) ? GetAvailableFontId(PackageList) : FontId; + + FontNameSize = (UINT32)((Wcslen(FontName)) * sizeof(CHAR16)); //null-terminator already accounted for in EFI_FONT_INFO structure + AddLink = CreateNewLink((UINT32)(sizeof(STRING_FONT_LINK) + sizeof(EFI_FONT_INFO)) + FontNameSize); + if(AddLink == NULL) + return EFI_OUT_OF_RESOURCES; + + AddLink->FontId = Fid; + AddLink->FontInfoSize = (UINT32)sizeof(EFI_FONT_INFO) + FontNameSize; + FontInfo = (EFI_FONT_INFO *)(AddLink + 1); + FontInfo->FontSize = FontSize; + FontInfo->FontStyle = FontStyle; + Wcscpy(FontInfo->FontName, FontName); + DListAdd(&(PackageList->StringFontList), (DLINK *)AddLink); + if(NewFontId) + *NewFontId = Fid; + return EFI_SUCCESS; +} + +#pragma warning (default : 4090) + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |