diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_DXE/UefiHii | |
download | zprj-master.tar.xz |
Diffstat (limited to 'Core/CORE_DXE/UefiHii')
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiAccessConfig.c | 322 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/Hii.chm | bin | 0 -> 60152 bytes | |||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiConfig.c | 1263 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiDatabase.c | 1814 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiFont.c | 1035 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiFontEx.c | 1332 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiPrivate.h | 885 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiString.c | 1609 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/UefiHii.cif | 18 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/UefiHii.sdl | 15 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/UefiHiiUtils.c | 750 | ||||
-rw-r--r-- | Core/CORE_DXE/UefiHii/hii21ExportConfig.c | 1143 |
12 files changed, 10186 insertions, 0 deletions
diff --git a/Core/CORE_DXE/UefiHii/HiAccessConfig.c b/Core/CORE_DXE/UefiHii/HiAccessConfig.c new file mode 100644 index 0000000..d165a1e --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiAccessConfig.c @@ -0,0 +1,322 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c 7 5/04/11 12:08p Artems $ +// +// $Revision: 7 $ +// +// $Date: 5/04/11 12:08p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiAccessConfig.c $ +// +// 7 5/04/11 12:08p Artems +// Bug fix: when variable is absent attribute state was undefined +// +// 6 1/25/11 4:03p Artems +// EIP 51298: Fixed corruption in buffer size after passing it to +// ConfigToBlock function +// Added check for correct syntax of request string in ExtractConfig +// function +// +// 5 9/30/10 6:12p Artems +// Removed unnecessary service functions +// +// 3 2/19/10 4:01p Felixp +// Debug messages are removed. +// +// 2 11/25/09 11:25a Felixp +// Action parameter of the Callback function is updated based on UEFI +// errata +// +// 1 10/09/09 6:12p Felixp +// +// 1 3/18/07 5:23p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: HiiAccessConfig.c +// +// Description: Hii Config Access protocol implementation +// +//<AMI_FHDR_END> +//********************************************************************** + +#pragma warning (disable : 4090) + +#include <AmiDxeLib.h> +#include <Protocol/HiiConfigAccess.h> +#include <Protocol/HiiConfigRouting.h> + +#include "HiiPrivate.h" + +extern const NAME_PATTERN GuidPattern; +extern const NAME_PATTERN NamePattern; +extern const NAME_PATTERN PathPattern; +extern const NAME_PATTERN AltCfgPattern; +extern const NAME_PATTERN OffsetPattern; +extern const NAME_PATTERN WidthPattern; +extern const NAME_PATTERN ValuePattern; +extern const CHAR16 HexDigit[]; + +UINTN EfiStrLen (IN CHAR16 *String); +UINTN EfiStrSize (IN CHAR16 *String); +VOID EfiStrCat (IN CHAR16 *Destination, IN CHAR16 *Source); + +//**************************** Protocol functions implementation *************************** + + +EFI_STATUS HiiAccessExtractConfig( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + EFI_STATUS Status; + UINTN Length; + EFI_GUID Guid; + CHAR16 Name[80]; + CHAR16 *Pointer = Request; + UINT8 *Var = NULL; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + CHAR16 *ErrorMarker; + + if(Request == NULL) { + *Progress = NULL; + return EFI_INVALID_PARAMETER; + } + + Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting); + if(EFI_ERROR(Status)) + return Status; + +//check syntax for guid + if(!CheckPattern(Request, &GuidPattern)) { + *Progress = Request; + return EFI_INVALID_PARAMETER; + } +//extract guid + ErrorMarker = Pointer; + Pointer += 5; //skip "GUID=" pattern + Length = 32; //length of guid in symbols + StringToBlock(Pointer, Length, (UINT8 *)&Guid); + Pointer += Length; + if(*Pointer != L'&') { + TRACE((TRACE_DXE_CORE, "HII Extract Config: Guid extraction failed\n")); + *Progress = ErrorMarker; + return EFI_INVALID_PARAMETER; + } + +//check syntax for name + if(!CheckPattern(Pointer + 1, &NamePattern)) { + *Progress = Pointer; + return EFI_INVALID_PARAMETER; + } +//extract name + ErrorMarker = Pointer; + Pointer += 6; //skip '&NAME=' pattern + Length = 80; + StringToChar16(Pointer, &Length, Name); + Pointer += (Length * 4); + if(*Pointer != L'&') { + TRACE((TRACE_DXE_CORE, "HII Extract Config: Name extraction failed\n")); + *Progress = ErrorMarker; + return EFI_INVALID_PARAMETER; + } + +//get variable by name and guid from nvram + + Length = 0; + Status = GetEfiVariable(Name, &Guid, NULL, &Length, &Var); + if(EFI_ERROR(Status)) { + *Progress = Request; + return Status; + } + +//find start of OFFSET/WIDTH/VALUE block + Pointer++; //skip '&' + while((*Pointer != L'&') && (*Pointer != 0)) //skip PATH + Pointer++; + + if(*Pointer == 0) { //OFFSET/WIDTH blocks are missed + UINTN TempSize; + CHAR16 *TempString; + CHAR16 *TempString2; + + TempSize = (EfiStrLen(L"&OFFSET=0&WIDTH=") + sizeof(Length) + 1) * sizeof(CHAR16); + TempString = MallocZ(TempSize); + if(TempString == NULL) + return EFI_OUT_OF_RESOURCES; + + Swprintf_s(TempString, TempSize, L"&OFFSET=0&WIDTH=%x", Length); + + TempSize += EfiStrSize(Request); + TempString2 = MallocZ(TempSize); + if(TempString2 == NULL) + return EFI_OUT_OF_RESOURCES; + + EfiStrCat(TempString2, Request); + EfiStrCat(TempString2, TempString); + + Status = ConfigRouting->BlockToConfig(ConfigRouting, TempString2, Var, Length, Results, Progress); + *Progress = Request + EfiStrLen(Request); //set Progress to end of ConfigHdr + pBS->FreePool(TempString); + pBS->FreePool(TempString2); + } else { //OFFSET/WIDTH block found, let's check if it's correct + if(!CheckPattern(Pointer + 1, &OffsetPattern)) { + *Progress = Pointer; + return EFI_INVALID_PARAMETER; + } + Status = ConfigRouting->BlockToConfig(ConfigRouting, Request, Var, Length, Results, Progress); + } + + pBS->FreePool(Var); + + return Status; +} + +EFI_STATUS HiiAccessRouteConfig( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + EFI_STATUS Status; + UINTN Length; + UINTN VarSize; + EFI_GUID Guid; + CHAR16 Name[80]; + CHAR16 *Pointer = Configuration; + UINT8 *Var = NULL; + EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting; + EFI_HANDLE Handle; + UINT32 Attributes; + + if(Configuration == NULL) + { + *Progress = NULL; + return EFI_INVALID_PARAMETER; + } + + Status = pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &ConfigRouting); + if(EFI_ERROR(Status)) + return Status; + +//check syntax for guid + if(!CheckPattern(Configuration, &GuidPattern)) + { + *Progress = Configuration; + return EFI_INVALID_PARAMETER; + } + +//check proper device path + Status = FindDeviceHandle(Configuration, &Handle); + if(EFI_ERROR(Status)) + return EFI_NOT_FOUND; + +//extract guid + Pointer += 5; //skip "GUID=" pattern + Length = 32; //length of guid in bytes + StringToBlock(Pointer, Length, (UINT8 *)&Guid); + Pointer += Length; + if(*Pointer != L'&') + { + TRACE((TRACE_DXE_CORE, "HII Route Config: Guid extraction failed\n")); + *Progress = Pointer; + return EFI_INVALID_PARAMETER; + } + +//check syntax for name + if(!CheckPattern(Pointer + 1, &NamePattern)) + { + *Progress = Pointer; + return EFI_INVALID_PARAMETER; + } +//extract name + Pointer += 6; //skip '&NAME=' pattern + Length = 80; + StringToChar16(Pointer, &Length, Name); + Pointer += (Length * 4); + if(*Pointer != L'&') + { + TRACE((TRACE_DXE_CORE, "HII Route Config: Name extraction failed\n")); + *Progress = Pointer; + return EFI_INVALID_PARAMETER; + } + +//get variable by name and guid from nvram + + Length = 0; + Status = GetEfiVariable(Name, &Guid, &Attributes, &Length, &Var); + if(EFI_ERROR(Status)) //requested variable not found + { + Var = NULL; + Length = 0; + Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; + } + VarSize = Length; + + Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress); + while(Status == EFI_DEVICE_ERROR) //block not large enough + { + if(Var != NULL) + pBS->FreePool(Var); + + Status = pBS->AllocatePool(EfiBootServicesData, Length, &Var); + if(EFI_ERROR(Status)) + return Status; + + VarSize = Length; + Status = ConfigRouting->ConfigToBlock(ConfigRouting, Configuration, Var, &Length, Progress); + } + + if(EFI_ERROR(Status)) + return Status; + + pRS->SetVariable(Name, &Guid, Attributes, VarSize, Var); + + pBS->FreePool(Var); + + return EFI_SUCCESS; +} + +EFI_STATUS HiiAccessFormCallback( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest +) +{ + return EFI_UNSUPPORTED; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/UefiHii/Hii.chm b/Core/CORE_DXE/UefiHii/Hii.chm Binary files differnew file mode 100644 index 0000000..b2affb3 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/Hii.chm diff --git a/Core/CORE_DXE/UefiHii/HiiConfig.c b/Core/CORE_DXE/UefiHii/HiiConfig.c new file mode 100644 index 0000000..8a8b10a --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiConfig.c @@ -0,0 +1,1263 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiConfig.c 10 6/16/11 12:52p Artems $ +// +// $Revision: 10 $ +// +// $Date: 6/16/11 12:52p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiConfig.c $ +// +// 10 6/16/11 12:52p Artems +// Bugfix: Handle situation when string passed to BlockToConfig function +// doesn't have standard header +// +// 9 5/13/11 5:17p Artems +// Function CompareGuid (native EdkII) renamed to HiiCompareGuid to avoid +// collusion +// +// 8 5/09/11 6:40p Artems +// Bugfix: Handle situation when config string passed to ConfigToBlock +// function doesn't have standard header +// +// 7 1/25/11 3:26p Artems +// EIP 47960 : Added functionality for ExportConfig function +// +// 6 11/05/10 5:17p Artems +// EIP 46880: Fixed bug, where two functions referred to the same global +// pointer +// +// 4 10/01/10 4:36p Artems +// Added service function StripValuePattern +// +// 2 12/03/09 6:02p Artems +// SCT test bug fix +// +// 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: HiiConfig.c +// +// Description: Hii Config Routing protocol implementation +// +//<AMI_FHDR_END> +//********************************************************************** + +#pragma warning (disable : 4090) + +#include <AmiDxeLib.h> +#include "HiiPrivate.h" + + +extern HII_DATABASE_PRIVATE_DATA PrivateData; + +const NAME_PATTERN GuidPattern = { 10, L"GUID=" }; +const NAME_PATTERN NamePattern = { 10, L"NAME=" }; +const NAME_PATTERN PathPattern = { 10, L"PATH=" }; +const NAME_PATTERN AltCfgPattern = { 14, L"ALTCFG=" }; +const NAME_PATTERN OffsetPattern = { 14, L"OFFSET=" }; +const NAME_PATTERN WidthPattern = { 12, L"WIDTH=" }; +const NAME_PATTERN ValuePattern = { 12, L"VALUE=" }; + +const CHAR16 HexDigit[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', + L'8', L'9', L'a', L'b', L'c', L'd', L'e', L'f' }; + +EFI_GUID HiiConfigAccessProtocolGuid = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; + +#define INITIAL_RESULT_STRING_SIZE 0x1000 + + + +//**************************** Protocol functions implementation *************************** + +EFI_STATUS HiiExtractConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Request1, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +) +{ + EFI_STRING ConfigString; + EFI_STRING ErrorPointer; + EFI_STRING ResultPointer; + BOOLEAN LastString = FALSE; + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE Handle; + UINTN ProgressMarker = 0; + UINTN Gap; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_STRING Request = Request1; + RESULT_BLOCK Result; + + if(Progress == NULL || Results == NULL) + return EFI_INVALID_PARAMETER; + + if(Request == NULL) + { + *Progress = NULL; + return EFI_INVALID_PARAMETER; + } + + if(!CheckPattern(Request, &GuidPattern)) + { + *Progress = Request; + return EFI_INVALID_PARAMETER; + } + + Status = InitResultBlock(&Result); + if (EFI_ERROR(Status)) + return Status; + + do + { + Status = ExtractConfigString(Request, &Index, &ConfigString); + if(EFI_ERROR(Status)) + return Status; + + if(ConfigString != NULL) + { + Status = FindDeviceHandle(ConfigString, &Handle); + if(EFI_ERROR(Status)) //we failed to find corresponding driver handle + { + pBS->FreePool(ConfigString); + *Progress = &Request[ProgressMarker]; + *Results = Result.ResultString; + return Status; + } + + Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess); + if(EFI_ERROR(Status)) //we failed to find corresponding protocol + { + pBS->FreePool(ConfigString); + *Progress = &Request[ProgressMarker]; + *Results = Result.ResultString; + return Status; + } + + Status = ConfigAccess->ExtractConfig(ConfigAccess, ConfigString, + &ErrorPointer, &ResultPointer); + if(EFI_ERROR(Status)) + { + Gap = (UINTN)(ErrorPointer - ConfigString); //determine offset of error + pBS->FreePool(ConfigString); + *Progress = &Request[ProgressMarker + Gap]; + *Results = Result.ResultString; + return Status; + } + + ProgressMarker += Index; //shift to next config string + Request += Index; + pBS->FreePool(ConfigString); + Status = CollectResults(ResultPointer, 0, &Result); + if (EFI_ERROR(Status)) + return Status; + pBS->FreePool(ResultPointer); + } + else //now we process last request + { + LastString = TRUE; + Status = FindDeviceHandle(Request, &Handle); + if(EFI_ERROR(Status)) //we failed to find corresponding driver handle + { + *Progress = Request; + *Results = Result.ResultString; + return Status; + } + + Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess); + if(EFI_ERROR(Status)) //we failed to find corresponding protocol + { + *Progress = Request; + *Results = Result.ResultString; + return Status; + } + + Status = ConfigAccess->ExtractConfig(ConfigAccess, Request, + &ErrorPointer, &ResultPointer); + if(EFI_ERROR(Status)) + { + *Progress = ErrorPointer; + *Results = Result.ResultString; + return Status; + } + Status = CollectResults(ResultPointer, 0, &Result); + if (EFI_ERROR(Status)) + return Status; + pBS->FreePool(ResultPointer); + } + } while(!LastString); + + *Results = Result.ResultString; + +//set Progress to null-terminator + Index = StrSize16(Request) / 2; + *Progress = &Request[Index - 1]; + + return EFI_SUCCESS; +} + +EFI_STATUS Hii21ExportConfigHelper ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + OUT EFI_STRING *Results +); + +EFI_STATUS HiiExportConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + OUT EFI_STRING *Results +) +{ + if(Results == NULL) + return EFI_INVALID_PARAMETER; + + return Hii21ExportConfigHelper (This, Results); +} + +EFI_STATUS HiiRouteConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Configuration1, + OUT EFI_STRING *Progress +) +{ + EFI_STRING ConfigString; + EFI_STRING ErrorPointer; + BOOLEAN LastString = FALSE; + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE Handle; + UINTN ProgressMarker = 0; + UINTN Gap; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_STRING Configuration = Configuration1; + + if(Progress == NULL) + return EFI_INVALID_PARAMETER; + + if(Configuration == NULL) + { + *Progress = NULL; + return EFI_INVALID_PARAMETER; + } + + if(!CheckPattern(Configuration, &GuidPattern)) + { + *Progress = Configuration; + return EFI_INVALID_PARAMETER; + } + + do + { + Status = ExtractConfigString(Configuration, &Index, &ConfigString); + if(EFI_ERROR(Status)) + return Status; + + if(ConfigString != NULL) + { + Status = FindDeviceHandle(ConfigString, &Handle); + if(EFI_ERROR(Status)) //we failed to find corresponding driver handle + { + pBS->FreePool(ConfigString); + *Progress = &Configuration[ProgressMarker]; + return Status; + } + + Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess); + if(EFI_ERROR(Status)) //we failed to find corresponding protocol + { + pBS->FreePool(ConfigString); + *Progress = &Configuration[ProgressMarker]; + return Status; + } + + Status = ConfigAccess->RouteConfig(ConfigAccess, ConfigString, &ErrorPointer); + if(EFI_ERROR(Status)) + { + Gap = (UINTN)(ErrorPointer - ConfigString); //determine offset of error + pBS->FreePool(ConfigString); + *Progress = &Configuration[ProgressMarker + Gap]; + return Status; + } + + ProgressMarker += Index; //shift to next config string + Configuration += Index; + pBS->FreePool(ConfigString); + } + else //now we process last cofiguration + { + LastString = TRUE; + Status = FindDeviceHandle(Configuration, &Handle); + if(EFI_ERROR(Status)) //we failed to find corresponding driver handle + { + *Progress = Configuration; + return Status; + } + + Status = pBS->HandleProtocol(Handle, &HiiConfigAccessProtocolGuid, &ConfigAccess); + if(EFI_ERROR(Status)) //we failed to find corresponding protocol + { + *Progress = Configuration; + return Status; + } + + Status = ConfigAccess->RouteConfig(ConfigAccess, Configuration, &ErrorPointer); + if(EFI_ERROR(Status)) + { + *Progress = ErrorPointer; + return Status; + } + } + } while(!LastString); + +//set Progress to null-terminator + Index = StrSize16(Configuration) / 2; + *Progress = &Configuration[Index - 1]; + + return EFI_SUCCESS; +} + +EFI_STATUS HiiBlockToConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigRequest, + IN CONST UINT8 *Block, + IN CONST UINTN BlockSize, + OUT EFI_STRING *Config, + OUT EFI_STRING *Progress +) +{ + UINTN ProgressMarker; + UINTN i = 0; + UINTN Start; + UINT32 Offset; + UINT32 Width; + UINT32 ConfigStringSize; + EFI_STATUS Status; + RESULT_BLOCK Result; + + if(Progress == NULL) + return EFI_INVALID_PARAMETER; + + if(ConfigRequest == NULL || Block == NULL || Config == NULL ) + { + *Progress = ConfigRequest; + return EFI_INVALID_PARAMETER; + } + + ConfigStringSize = StrSize16(ConfigRequest) / 2; + +//Prepare result buffer for output + Status = InitResultBlock(&Result); + if (EFI_ERROR(Status)) + return Status; + +//find start of OFFSET/WIDTH/VALUE block + if(!CheckPattern(ConfigRequest, &OffsetPattern)) { //for BlockToConfig function ConfigResp is allowed not to have standard header GUID=...NAME=. + do + { + while((ConfigRequest[i] != L'&') && (ConfigRequest[i] != 0)) + i++; + + if(ConfigRequest[i] == 0) + { + *Progress = ConfigRequest; + pBS->FreePool(Result.ResultString); + return EFI_NOT_FOUND; + } + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigRequest[i], &OffsetPattern)) + break; + } while(1); + } + + Status = CollectResults(ConfigRequest, i, &Result); //copy header + if (EFI_ERROR(Status)) + { + pBS->FreePool(Result.ResultString); + return Status; + } + + do + { + ProgressMarker = i - 1; //set ProgressMarker to '&' + + Start = i; + Status = GetPatternValue(ConfigRequest, &i, &OffsetPattern, &Offset); + if(EFI_ERROR(Status)) + { + *Progress = &ConfigRequest[ProgressMarker]; + pBS->FreePool(Result.ResultString); + return Status; + } + else + { + Status = CollectResults(&ConfigRequest[Start], i - Start, &Result); //copy header + if (EFI_ERROR(Status)) + { + pBS->FreePool(Result.ResultString); + return Status; + } + } + + Start = i; + Status = GetPatternValue(ConfigRequest, &i, &WidthPattern, &Width); + if(EFI_ERROR(Status)) + { + *Progress = &ConfigRequest[ProgressMarker]; + pBS->FreePool(Result.ResultString); + return Status; + } + else + { + Status = CollectResults(&ConfigRequest[Start], i - Start, &Result); //copy header + if (EFI_ERROR(Status)) + { + pBS->FreePool(Result.ResultString); + return Status; + } + } + + if(BlockSize < (Offset + Width)) + { + pBS->FreePool(Result.ResultString); + return EFI_DEVICE_ERROR; + } + + Status = CollectValueResults(&Block[Offset], Width, &Result); + if (EFI_ERROR(Status)) + { + pBS->FreePool(Result.ResultString); + return Status; + } + + } while(i < ConfigStringSize); + + *Progress = &ConfigRequest[ConfigStringSize - 1]; //set Progress to null-terminator + *Config = Result.ResultString; + + return EFI_SUCCESS; +} + +EFI_STATUS HiiConfigToBlock ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN OUT CONST UINT8 *Block, + IN OUT UINTN *BlockSize, + OUT EFI_STRING *Progress +) +{ + UINTN ProgressMarker; + UINTN i = 0; + UINT32 Offset; + UINT32 Width; + UINT32 ConfigStringSize; + EFI_STATUS Status; + + if(Progress == NULL) + return EFI_INVALID_PARAMETER; + + if(ConfigResp == NULL || BlockSize == NULL ) + { + *Progress = ConfigResp; + return EFI_INVALID_PARAMETER; + } + + if(Block == NULL && *BlockSize != NULL ) + { + *Progress = ConfigResp; + return EFI_INVALID_PARAMETER; + } + + ConfigStringSize = StrSize16(ConfigResp) / 2; + +//find start of OFFSET/WIDTH/VALUE block + if(!CheckPattern(ConfigResp, &OffsetPattern)) { //for ConfigToBlock function ConfigResp is allowed not to have standard header GUID=...NAME=. + do { + while((ConfigResp[i] != L'&') && (ConfigResp[i] != 0)) + i++; + + if(ConfigResp[i] == 0) { +//TODO: should it be like this??? +//Intel's style - if there is no OFFSET/WIDTH/VALUE blocks - return EFI_SUCCESS +/* + *Progress = ConfigResp; + return EFI_NOT_FOUND; +*/ + *Progress = &ConfigResp[i]; + return EFI_SUCCESS; + } + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigResp[i], &OffsetPattern)) + break; + } while(1); + } + + do + { + ProgressMarker = i - 1; //set ProgressMarker to '&' + + Status = GetPatternValue(ConfigResp, &i, &OffsetPattern, &Offset); + if(EFI_ERROR(Status)) + { + *Progress = &ConfigResp[ProgressMarker]; + return Status; + } + + Status = GetPatternValue(ConfigResp, &i, &WidthPattern, &Width); + if(EFI_ERROR(Status)) + { + *Progress = &ConfigResp[ProgressMarker]; + return Status; + } + +//provided block is too small to accumulate value + if(*BlockSize < (Offset + Width)) + { + *BlockSize = Offset + Width; + return EFI_DEVICE_ERROR; + } + + Status = GetStringValue(ConfigResp, &i, &Block[Offset], Width); + if(EFI_ERROR(Status)) + { + *Progress = &ConfigResp[ProgressMarker]; + return Status; + } + + } while(i < ConfigStringSize); + + *BlockSize = Offset + Width - 1; //set index of last updated byte + *Progress = &ConfigResp[ConfigStringSize - 1]; //set Progress to null-terminator + + return EFI_SUCCESS; +} + +EFI_STATUS HiiGetAltConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_STRING AltCfgId, + OUT EFI_STRING *AltCfgResp +) +{ + BOOLEAN LastString = FALSE; + EFI_STATUS Status; + UINTN Index; + UINTN StrSize; + EFI_STRING ConfigString = ConfigResp; + + + if(ConfigResp == NULL || AltCfgResp == NULL) + return EFI_INVALID_PARAMETER; + + if(!CheckPattern(ConfigString, &GuidPattern)) + return EFI_INVALID_PARAMETER; + + do { + Status = ExtractConfigString(ConfigString, &Index, AltCfgResp); + if(EFI_ERROR(Status)) + return Status; + + if(*AltCfgResp != NULL) { + Status = CheckAltCfg(*AltCfgResp, Guid, Name, DevicePath, AltCfgId); + if(!EFI_ERROR(Status)) + return Status; + + ConfigString += Index; + pBS->FreePool(*AltCfgResp); + } else { + LastString = TRUE; + StrSize = StrSize16(ConfigString); + Status = pBS->AllocatePool(EfiBootServicesData, StrSize, AltCfgResp); + if(EFI_ERROR(Status)) + return Status; + + MemCpy(*AltCfgResp, ConfigString, StrSize); + Status = CheckAltCfg(*AltCfgResp, Guid, Name, DevicePath, AltCfgId); + if(EFI_ERROR(Status)) + pBS->FreePool(*AltCfgResp); + + return Status; + + } + } while(!LastString); + + return EFI_NOT_FOUND; +} + +// *************************** Service functions (not for public use) ********************** + +VOID StringToBlock( + IN CHAR16 *String, + IN UINTN StringSize, + OUT UINT8 *Block) +{ + UINT8 LowNibble, HiNibble; + UINTN i, j; + + j = 0; + + for(i = 0; i < StringSize; i += 2) + { + if(i == StringSize - 1) { //odd number need to fill with zeroes + HiNibble = 0; + LowNibble = HexValue((UINT8)String[i]); + } else { + HiNibble = HexValue((UINT8)String[i]); + LowNibble = HexValue((UINT8)String[i + 1]); + } + Block[j] = (HiNibble << 4) | LowNibble; + j++; + } +} + +BOOLEAN CheckIfHexDigit(CHAR16 Char) +{ + if(Char < 0x30 || Char > 0x66) + return FALSE; + + if(Char > 0x39 && Char < 0x41) + return FALSE; + + if(Char > 0x46 && Char < 0x61) + return FALSE; + + return TRUE; +} + +UINT8 HexValue(CHAR8 Char) +{ + if(Char >= 0x30 && Char <= 0x39) //symbols 0...9 + return Char - 0x30; + + if(Char >= 0x41 && Char <= 0x46) //symbols A...F + return Char - 0x37; + + return Char - 0x57; //symbols a...f +} + + +UINT32 GetValue(CHAR16 *String, UINTN Start, UINTN End) +{ + UINT32 Result = 0; + UINTN i; + UINT8 Nibble; + UINT8 NibbleCount = 0; + + for(i = Start; i < End; i++) + { + Nibble = HexValue((UINT8) String[i]); + if(Nibble == 0 && NibbleCount == 0) //skip leading zeros + continue; + + if(NibbleCount >= 8) //provided value exceed 4 bytes + return 0xffffffff; + + Result <<= 4; + Result |= Nibble; + NibbleCount++; + } + return Result; +} + +EFI_STATUS GetStringValue( + CHAR16 *String, + UINTN *Index, + UINT8 *Output, + UINT32 Width) +{ + EFI_STATUS Status; + UINTN Start; + UINTN i; + UINT8 *Result; + UINTN HexSymbolsCount; + UINT8 SmallBuffer[20]; + UINTN ResultBufferSize = 20; + + Start = *Index; + + if(!CheckPattern(&String[Start], &ValuePattern)) + return EFI_INVALID_PARAMETER; + + Start += ValuePattern.Length / 2; + i = Start; + + while((String[i] != L'&') && (String[i] != 0)) { + if(!CheckIfHexDigit(String[i])) + return EFI_INVALID_PARAMETER; + i++; + } + + HexSymbolsCount = i - Start; + + if(Width > 20) { + Status = pBS->AllocatePool(EfiBootServicesData, Width, &Result); + if(EFI_ERROR(Status)) + return Status; + ResultBufferSize = Width; + } else { + Result = SmallBuffer; + } + + MemSet(Result, ResultBufferSize, 0); + StringToBlock(&String[Start], HexSymbolsCount, Result); + +//now write the result swapped(INTEL's style) + if(Width > 1) + WriteSwappedBuffer(Output, Result, Width); + else + *Output = *Result; + + if(Width > 20) + pBS->FreePool(Result); + + i++; //skip delimiter + + *Index = i; + + return EFI_SUCCESS; +} + +EFI_STATUS GetPatternValue( + CHAR16 *String, + UINTN *Index, + NAME_PATTERN *Pattern, + UINT32 *Value) +{ + UINT32 Result; + UINTN Start; + UINTN i; + BOOLEAN EndPattern = FALSE; + + if(Pattern->Tag[0] == L'V' || Pattern->Tag[0] == L'W') + EndPattern = TRUE; + + Start = *Index; + + if(!CheckPattern(&String[Start], Pattern)) + return EFI_INVALID_PARAMETER; + + Start += Pattern->Length / 2; + i = Start; + + while((String[i] != L'&') && (String[i] != 0)) + { + if(!CheckIfHexDigit(String[i])) + return EFI_INVALID_PARAMETER; + i++; + } + + if(String[i] == 0 && !EndPattern) //unexpected end of string + return EFI_INVALID_PARAMETER; + + Result = GetValue(String, Start, i); + i++; //skip delimiter + + *Value = Result; + *Index = i; + + return EFI_SUCCESS; +} + +EFI_STATUS FindDeviceHandle( + IN CHAR16 *ConfigString, + OUT EFI_HANDLE *Handle) +{ + UINTN i = 0; + UINTN DpLength; + UINT8 *DevicePath; + EFI_STATUS Status; + +//scan config string to find PATH pattern + do + { + while((ConfigString[i] != L'&') && (ConfigString[i] != 0)) + i++; + + if(ConfigString[i] == 0) + return EFI_NOT_FOUND; + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigString[i], &PathPattern)) + break; + } while(1); + +//if we get here, we have pointer set on PATH pattern + Status = ExtractDevicePath(&ConfigString[i], &DevicePath, &DpLength); + if(EFI_ERROR(Status)) + return Status; + + Status = SearchDevicePath(DevicePath, DpLength, Handle); + pBS->FreePool(DevicePath); + + return Status; +} + +EFI_STATUS ExtractDevicePath(CHAR16 *ConfigString, UINT8 **DevicePath, UINTN *DpLength) +{ + EFI_STATUS Status; + UINTN Length = 0; + UINTN i = 5; //set pointer to skip first four symbols "PATH=" + + while(CheckIfHexDigit(ConfigString[i])) //determine device path length in characters + { + Length++; + i++; + } + + Status = pBS->AllocatePool( + EfiBootServicesData, + (Length / 2), + DevicePath); + if (EFI_ERROR(Status)) + return Status; + + StringToBlock(&ConfigString[5], Length, *DevicePath); + *DpLength = Length / 2; + + return EFI_SUCCESS; +} + +EFI_STATUS SearchDevicePath(UINT8 *DevicePath, UINTN DpLength, EFI_HANDLE *Handle) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) PrivateData.PackList.pHead; + PACKAGE_LINK *PackageLink; + + while(Record != NULL) + { + PackageLink = (PACKAGE_LINK *) Record->PackageList.pHead; + while(PackageLink != NULL) + { + if(PackageLink->Package.Type == EFI_HII_PACKAGE_DEVICE_PATH) + { + if(CheckDevicePath(DevicePath, DpLength, &PackageLink->Package)) + { + *Handle = Record->DriverHandle; + return EFI_SUCCESS; + } + } + PackageLink = (PACKAGE_LINK *)PackageLink->Link.pNext; + } + Record = (PACKAGE_LIST_RECORD *)Record->Link.pNext; + } + return EFI_NOT_FOUND; +} + +static BOOLEAN CheckDevicePath( + IN UINT8 *DevicePath, + IN UINTN DpLength, + IN EFI_HII_PACKAGE_HEADER *Package) +{ + UINTN Length; + UINT8 *Dp = (UINT8 *)Package; + + Dp += sizeof(EFI_HII_PACKAGE_HEADER); + + Length = Package->Length - sizeof(EFI_HII_PACKAGE_HEADER); + if(Length != DpLength) + return FALSE; + if(MemCmp(DevicePath, Dp, Length)) + return FALSE; + + return TRUE; +} + + +EFI_STATUS ExtractConfigString(CHAR16 *String, UINTN *NextIndex, CHAR16 **NewString) +{ + EFI_STATUS Status; + UINTN i = 0; + CHAR16 *Eos; + +//scan config string to find next GUID pattern + do + { + while((String[i] != L'&') && (String[i] != 0)) + i++; + + if(String[i] == 0) + { + *NewString = NULL; //config string contains only one string + return EFI_SUCCESS; + } + + i++; //shift pointer to next symbol + if(CheckPattern(&String[i], &GuidPattern)) + break; + } while(1); + +//as we are here i points to next config string + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * i, + NewString); + if (EFI_ERROR(Status)) + return Status; + + MemCpy(*NewString, String, (i - 1) * 2); + Eos = *NewString; + Eos[i - 1] = 0; //put null terminator + + *NextIndex = i; + return EFI_SUCCESS; +} + +BOOLEAN CheckPattern(CHAR16 *String, NAME_PATTERN *Pattern) +{ + if(MemCmp(String, Pattern->Tag, Pattern->Length)) + return FALSE; + else + return TRUE; +} + +EFI_STATUS CollectResults(CHAR16 *Result, UINTN Symbols, RESULT_BLOCK *ResultBlock) +{ + EFI_STATUS Status; + UINTN StrSize; + CHAR16 *Helper; + + StrSize = (Symbols != 0) ? Symbols : StrSize16(Result) / 2; //we need size in CHAR16, not bytes + + if(ResultBlock->MaxResultStringSize < (StrSize + ResultBlock->CurrentSize)) + { + Status = ReallocResultString((StrSize + ResultBlock->CurrentSize) * 2, ResultBlock); + if (EFI_ERROR(Status)) + return Status; + } + + Helper = ResultBlock->ResultString; + if(ResultBlock->CurrentSize != 0) //we have to change null-terminator to '&' symbol + Helper[ResultBlock->CurrentSize - 1] = L'&'; + + MemCpy(&Helper[ResultBlock->CurrentSize], Result, StrSize * sizeof(CHAR16)); + ResultBlock->CurrentSize += StrSize; + + return EFI_SUCCESS; +} + +EFI_STATUS ReallocResultString(UINTN NewSize, RESULT_BLOCK *ResultBlock) +{ + CHAR16 *Pointer; + EFI_STATUS Status; + + ResultBlock->MaxResultStringSize = NewSize; + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * ResultBlock->MaxResultStringSize, + &Pointer); + if (EFI_ERROR(Status)) + return Status; + + MemCpy(Pointer, ResultBlock->ResultString, ResultBlock->CurrentSize * sizeof(CHAR16)); + pBS->FreePool(ResultBlock->ResultString); + ResultBlock->ResultString = Pointer; + + return EFI_SUCCESS; +} + +EFI_STATUS CollectValueResults(UINT8* Value, UINT32 Width, RESULT_BLOCK *ResultBlock) +{ + CHAR16 ValueHeader[] = L"VALUE="; + UINT32 i; + UINT8 Nibble; + EFI_STATUS Status; + CHAR16 *ValueString; + CHAR16 *Ptr; + UINTN StringSize; + +//first determine necessary string size, including null-terminator in CHAR16 symbols + StringSize = Width * 2 + 6 + 1; //each byte requires two symbols plus &VALUE= size plus null terminator + + Status = pBS->AllocatePool(EfiBootServicesData, StringSize * 2, &ValueString); + if(EFI_ERROR(Status)) + return Status; + +//copy header + MemCpy(ValueString, ValueHeader, 12); + Ptr = ValueString + 6; + +//write value in reversed order + for(i = 0; i < Width; i++) + { + Nibble = Value[Width - i - 1] >> 4; + *Ptr++ = HexDigit[Nibble]; + Nibble = Value[Width - i - 1] & 0xf; + *Ptr++ = HexDigit[Nibble]; + } + +//set null-terminator + *Ptr = 0; + Status = CollectResults(ValueString, 0, ResultBlock); + pBS->FreePool(ValueString); + return Status; +} + +VOID WriteSwappedBuffer( + OUT UINT8 *Output, + IN UINT8 *Input, + IN UINTN Size) +{ + UINTN i; + + for(i = 0; i < Size; i++) + Output[i] = Input[Size - i - 1]; +} + +EFI_STATUS CheckAltCfg ( + IN EFI_STRING ConfigString, + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_STRING AltCfgId +) +{ + EFI_STATUS Status; + UINTN i = 0; + UINTN j; + UINT32 Size; + UINT32 CfgId; + +//scan config string to find ALTCFG pattern + do { + while((ConfigString[i] != L'&') && (ConfigString[i] != 0)) + i++; + + if(ConfigString[i] == 0) //ALTCFG pattern not found + break; + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigString[i], &AltCfgPattern)) + break; + } while(1); + + if(ConfigString[i] == 0 && AltCfgId != NULL) //we have current config but needed alt one + return EFI_NOT_FOUND; + + if(ConfigString[i] != 0 && AltCfgId == NULL) //we have alt config but needed current one + return EFI_NOT_FOUND; + + if(ConfigString[i] != 0 && AltCfgId != NULL) { + j = i; + Status = GetPatternValue(ConfigString, &j, &AltCfgPattern, &CfgId); + if(EFI_ERROR(Status) || *AltCfgId != (UINT16)CfgId) + return EFI_NOT_FOUND; //we have alt config, but it's not matched + +//if we're here alt config is matched +//we need to remove "ALTCFG=XXXX" from string as per spec but SCT expects "ALTCFG=" pattern in output string + + //j already points to the next pattern + Size = StrSize16(&ConfigString[j]); + MemCpy(&ConfigString[i], &ConfigString[j], Size); + + } + + if(Guid != NULL && !HiiCompareGuid(ConfigString, Guid)) + return EFI_NOT_FOUND; //guid not matched + + if(Name != NULL && !CompareName(ConfigString, Name)) + return EFI_NOT_FOUND; //name not matched + + if(DevicePath != NULL && !CompareDevicePath(ConfigString, DevicePath)) + return EFI_NOT_FOUND; //DevicePath not matched + + return EFI_SUCCESS; +} + +BOOLEAN HiiCompareGuid( + IN EFI_STRING ConfigString, + IN CONST EFI_GUID *Guid +) +{ + CHAR16 *Pointer = ConfigString; + UINTN Length; + EFI_GUID AltGuid; + EFI_GUID *VarGuid = Guid; + + if(!CheckPattern(ConfigString, &GuidPattern)) + return FALSE; + + Pointer += 5; //skip "GUID=" pattern + Length = 32; //length of guid in symbols + StringToBlock(Pointer, Length, (UINT8 *)&AltGuid); + + return !guidcmp(VarGuid, &AltGuid); +} + +BOOLEAN CompareName( + IN EFI_STRING ConfigString, + IN CONST EFI_STRING Name +) +{ + CHAR16 *Pointer = ConfigString; + UINTN Length; + CHAR16 AltName[80]; + EFI_STRING VarName = Name; + UINTN i = 0; + + do { + while((ConfigString[i] != L'&') && (ConfigString[i] != 0)) + i++; + + if(ConfigString[i] == 0) //NAME pattern not found + return FALSE; + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigString[i], &NamePattern)) + break; + } while(1); + + Pointer = &ConfigString[i]; + Pointer += 5; //skip "NAME=" pattern + Length = 80; //length of name buffer + StringToChar16(Pointer, &Length, AltName); + + return !StrCmp16(VarName, AltName); +} + +BOOLEAN CompareDevicePath( + IN EFI_STRING ConfigString, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath +) +{ + UINTN Length; + EFI_DEVICE_PATH_PROTOCOL *AltDevicePath; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarDp = DevicePath; + BOOLEAN Result; + UINTN i = 0; + + do { + while((ConfigString[i] != L'&') && (ConfigString[i] != 0)) + i++; + + if(ConfigString[i] == 0) //PATH pattern not found + return FALSE; + + i++; //shift pointer to next symbol + if(CheckPattern(&ConfigString[i], &PathPattern)) + break; + } while(1); + + Status = ExtractDevicePath(&ConfigString[i], (UINT8 **)&AltDevicePath, &Length); + if(EFI_ERROR(Status)) + return FALSE; + + Result = !DPCmp(VarDp, AltDevicePath); + pBS->FreePool(AltDevicePath); + return Result; +} + +VOID StringToChar16( + IN CHAR16 *String, + IN OUT UINTN *Size, + OUT CHAR16 *Block +) +{ + UINTN i, j; + + i = 0; + j = 0; + + while( CheckIfHexDigit(String[i]) && CheckIfHexDigit(String[i + 1]) && + CheckIfHexDigit(String[i + 2]) && CheckIfHexDigit(String[i + 3]) && + j < *Size - 1 ) + { + Block[j] = HexValue((UINT8)String[i]) & 0x000f; + Block[j] <<= 4; + Block[j] |= HexValue((UINT8)String[i + 1]); + Block[j] <<= 4; + Block[j] |= HexValue((UINT8)String[i + 2]); + Block[j] <<= 4; + Block[j] |= HexValue((UINT8)String[i + 3]); + + i += 4; + j++; + } + *Size = j; //number of words processed + Block[j] = 0; //put null-terminator +} + +VOID StripValuePattern( + IN OUT EFI_STRING String, + IN UINTN Size +) +{ + EFI_STATUS Status; + EFI_STRING NewString; + UINTN i = 0; + UINTN j = 0; + + Status = pBS->AllocatePool(EfiBootServicesData, Size, &NewString); + + while(String[i] != 0) { + if(String[i] == L'&') { + if(CheckPattern(&String[i + 1], &ValuePattern)) { + i++; + while((String[i] != L'&') && (String[i] != 0)) + i++; + if(String[i] == 0) + break; + } + } + + NewString[j++] = String[i++]; + } + + NewString[j] = 0; + MemCpy(String, NewString, (j + 1) * 2); + pBS->FreePool(NewString); +} + +EFI_STATUS InitResultBlock( + IN OUT RESULT_BLOCK *ResultBlock +) +{ + EFI_STATUS Status; + ResultBlock->MaxResultStringSize = INITIAL_RESULT_STRING_SIZE; + ResultBlock->CurrentSize = 0; + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * ResultBlock->MaxResultStringSize, + &(ResultBlock->ResultString)); + return Status; +} + +#pragma warning (default : 4090) + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_DXE/UefiHii/HiiDatabase.c b/Core/CORE_DXE/UefiHii/HiiDatabase.c new file mode 100644 index 0000000..fef10c6 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiDatabase.c @@ -0,0 +1,1814 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiDatabase.c 14 5/21/12 4:55p Artems $ +// +// $Revision: 14 $ +// +// $Date: 5/21/12 4:55p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/HiiDatabase.c $ +// +// 14 5/21/12 4:55p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio +// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c +// +// 13 1/05/12 5:05p Artems +// EIP 76735: Font FFS file is not loaded in framework mode, when in +// nested FV +// +// 12 5/13/11 6:14p Artems +// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and +// AmiHiiSetString +// to avoid collusion with EdkII native library functions +// +// 11 5/05/11 4:13p Artems +// Add signal "layout changed" event if current layout is deleted +// +// 10 1/05/11 12:41p Artems +// EIP 50995: Added checking of driver handle before adding packages to +// HII database +// +// 9 6/23/10 5:06p Artems +// Restored fix killed by previous check-in +// +// 8 6/10/10 4:35p Artems +// EIP 39692 fix - call notification after adding package +// +// 7 3/09/10 6:41p Artems +// EIP 35698: Removed DeleteSimpleFonts call +// +// 6 2/03/10 10:28a Artems +// Fixed bug in HiiExportPacks function +// +// 5 1/29/10 5:43p Artems +// EIP 34553 Updated function ExportPackageLists to support NULL pointer +// as input +// +// 4 1/07/10 12:29p Felixp +// Code updated to use library instances of the Protocol GUID variables. +// +// 3 12/04/09 11:16a Artems +// Remove keyboard layout functionality added +// +// 2 11/09/09 11:51a Felixp +// New package list function is updated to report error when package list +// with existing GUID is passed. +// +// 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: HiiDatabase.c +// +// Description: Hii database protocol functions implementation +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#pragma warning (disable : 4090) + +#include <AmiDxeLib.h> +#include "HiiPrivate.h" +#include <Protocol/DevicePath.h> +#include <Protocol/HiiUtilities.h> + +extern HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol; +extern DBE_KEY_FIELD StringDbKeyField; + +EFI_GUID NullGuid = NULL_GUID; + +SIMPLE_FONT DefaultFont[0x10000]; + +HII_DATABASE_PRIVATE_DATA PrivateData = +{ +//Database protocol members + { + HiiNewPack, + HiiRemovePack, + HiiUpdatePack, + HiiListPacks, + HiiExportPacks, + HiiRegisterNotify, + HiiUnregisterNotify, + HiiFindKeyboardLayouts, + HiiGetKeyboardLayout, + HiiSetKeyboardLayout, + HiiGetPackageListHandle + }, +//String protocol members + { + HiiNewString, + AmiHiiGetString, //EdkII compatibility library already has function HiiGetString + AmiHiiSetString, //EdkII compatibility library already has function HiiSetString + HiiGetLanguages, + HiiGetSecondLanguages + }, +//Font protocol members + { + HiiStringToImage, + HiiStringIdToImage, + HiiGetGlyph, + HiiGetFontInfo + }, +//Config Routing protocol members + { + HiiExtractConfig, + HiiExportConfig, + HiiRouteConfig, + HiiBlockToConfig, + HiiConfigToBlock, + HiiGetAltConfig + }, +// Linked list of package lists + { + 0, + NULL, + NULL + }, +//Linked list of notify functions + { + 0, + NULL, + NULL + }, +//Linked list of keyboard layouts + { + 0, + NULL, + NULL + }, +//Linked list of global fonts + { + 0, + NULL, + NULL + }, +//Current KeyLayout + NULL +}; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiDatabaseEntryPoint +// +// Description: +// This function is HII driver entry point +// +// Input: +// IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table +// +// Output: +// EFI_SUCCESS - Function executed successfully, HII protocols installed +// EFI_ERROR - Some error occured during execution +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiDriverEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + EFI_HANDLE HiiHandle = NULL; + + InitAmiLib(ImageHandle,SystemTable); + + pBS = SystemTable->BootServices; + + //install HII Protocols + Status = pBS->InstallMultipleProtocolInterfaces( + &HiiHandle, + &gEfiHiiDatabaseProtocolGuid, + &(PrivateData.DatabaseProtocol), + &gEfiHiiStringProtocolGuid, + &(PrivateData.StringProtocol), + &gEfiHiiFontProtocolGuid, + &(PrivateData.FontProtocol), + &gEfiHiiConfigRoutingProtocolGuid, + &(PrivateData.ConfigRoutingProtocol), + &gHiiUtilitiesProtocolGuid, + &HiiUtilitiesProtocol, + NULL); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiBdsEntryPoint +// +// Description: +// This function is HII driver BDS entry point +// +// Input: +// IN EFI_HANDLE ImageHandle - Image handle +// IN EFI_SYSTEM_TABLE *SystemTable - pointer to system table +// +// Output: +// EFI_SUCCESS - Function executed successfully, system font is loaded +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiBdsEntryPoint( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS Status; + EFI_HANDLE HiiHandle = NULL; + + InitAmiLib(ImageHandle,SystemTable); + Status = LoadSystemFont(); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetPackHandle +// +// Description: +// This function is HII Database protocol function GetPackageHandle implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HII_HANDLE PackageListHandle - PackageList handle +// OUT EFI_HANDLE *DriverHandle - Pointer, where to store found Driver handle +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - PackageListHandle is invalid +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetPackageListHandle ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageListHandle, + OUT EFI_HANDLE *DriverHandle) +{ + PACKAGE_LIST_RECORD *Record; + + Record = (PACKAGE_LIST_RECORD *) PackageListHandle; + + if (DriverHandle == NULL) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_INVALID_PARAMETER; + + *DriverHandle = Record->DriverHandle; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiRegisterNotify +// +// Description: +// This function is HII Database protocol function RegisterPackageNotify implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN UINT8 PackageType - Package type +// IN EFI_GUID *PackageGuid - Pointer to Package guid +// IN EFI_HII_DATABASE_NOTIFY PackageNotifyFn - Function to be called +// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notify type +// OUT EFI_HANDLE *NotifyHandle - Pointer, where to store created Notify handle +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - PackageGuid is not NULL and PackageType is not Guid package +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiRegisterNotify ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType, + OUT EFI_HANDLE *NotifyHandle) +{ + NOTIFY_RECORD *NewRecord; + + if (NotifyHandle == NULL) + return EFI_INVALID_PARAMETER; + + if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) || + (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) + return EFI_INVALID_PARAMETER; + + NewRecord = NewNotifyRecord(); + if (NewRecord == NULL) + return EFI_OUT_OF_RESOURCES; + + if(PackageType == EFI_HII_PACKAGE_TYPE_GUID) + NewRecord->PackageGuid = *PackageGuid; + else + NewRecord->PackageGuid = NullGuid; + + NewRecord->PackageType = PackageType; + NewRecord->NotifyType = NotifyType; + NewRecord->PackageNotifyFn = PackageNotifyFn; + + DListAdd(&(PrivateData.NotifyList), (DLINK *) NewRecord); + + if(NotifyHandle != NULL) + *NotifyHandle = NewRecord; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiUnregisterNotify +// +// Description: +// This function is HII Database protocol function UnregisterPackageNotify implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HANDLE NotificationHandle - Notify handle +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - NotificationHandle is not valid +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiUnregisterNotify ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle) +{ + NOTIFY_RECORD *Record; + + Record = (NOTIFY_RECORD *) NotificationHandle; + + if (Record->Signature != NOTIFY_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + DListDelete(&(PrivateData.NotifyList), (DLINK *) Record); + Record->Signature = 0xffffffff; //invalidate signature to avoid future use of this memory + pBS->FreePool(Record); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiRemovePack +// +// Description: +// This function is HII Database protocol function RemovePackageList implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HII_HANDLE Handle - Handle of package list to be removed from database +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - Handle is not valid +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiRemovePack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle; + PACKAGE_LINK *Package; + PACKAGE_LINK *Link; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + Package = (PACKAGE_LINK *) Record->PackageList.pHead; + + while(Package != NULL) + { + Link = Package; + Package = (PACKAGE_LINK *) Package->Link.pNext; + RemovePackage(Handle, Link); + } + + DListDelete(&(PrivateData.PackList), (DLINK *) Record); + Record->Signature = 0xffffffff; //invalidate signature to avoid future collisions + pBS->FreePool(Record); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiNewPack +// +// Description: +// This function is HII Database protocol function NewPackageList implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to package list to be added to database +// IN EFI_HANDLE DriverHandle - Driver handle +// OUT EFI_HII_HANDLE *Handle - Pointer to EFI_HII_HANDLE where to store created handle +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - Handle or PackageList is NULL +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiNewPack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList, + IN CONST EFI_HANDLE DriverHandle, + OUT EFI_HII_HANDLE *Handle) +{ + PACKAGE_LIST_RECORD *NewRecord; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DpProtocol; + UINT32 DpPackageSize; + EFI_HII_PACKAGE_HEADER *Buffer; + + if((PackageList == NULL) || (Handle == NULL)) + return EFI_INVALID_PARAMETER; + + // Check the Package list GUID and DriverHandle to guarantee this GUID is unique in database. + if(CheckIfPresent(&(PackageList->PackageListGuid), DriverHandle)) + return EFI_ALREADY_STARTED; //package list already present + + NewRecord = NewPackageListRecord(); + if(NewRecord == NULL) + return EFI_OUT_OF_RESOURCES; + + NewRecord->DriverHandle = DriverHandle; + NewRecord->Guid = PackageList->PackageListGuid; + + Status = AddPackages((EFI_HII_HANDLE)NewRecord, PackageList, FALSE); + if(EFI_ERROR(Status) && (NewRecord->PackageList.Size != 0)) + { + DeleteList(&(NewRecord->PackageList)); + pBS->FreePool(NewRecord); + return EFI_OUT_OF_RESOURCES; + } + + + Status = pBS->HandleProtocol(DriverHandle, &gEfiDevicePathProtocolGuid, &DpProtocol); + if(!EFI_ERROR(Status)) + { + DpPackageSize = (UINT32)DPLength(DpProtocol); + Status = pBS->AllocatePool( + EfiBootServicesData, + DpPackageSize + sizeof(EFI_HII_PACKAGE_HEADER), + &Buffer); + if (EFI_ERROR(Status)) + { + DeleteList(&(NewRecord->PackageList)); + pBS->FreePool(NewRecord); + return EFI_OUT_OF_RESOURCES; + } + + Buffer->Type = EFI_HII_PACKAGE_DEVICE_PATH; + Buffer->Length = DpPackageSize + sizeof(EFI_HII_PACKAGE_HEADER); + + (UINT8 *)Buffer += sizeof(EFI_HII_PACKAGE_HEADER); + MemCpy(Buffer, DpProtocol, DpPackageSize); + (UINT8 *)Buffer -= sizeof(EFI_HII_PACKAGE_HEADER); + + Status = AddPackage((EFI_HII_HANDLE)NewRecord, Buffer, EFI_HII_DATABASE_NOTIFY_NEW_PACK); + if (EFI_ERROR(Status)) + { + DeleteList(&(NewRecord->PackageList)); + pBS->FreePool(NewRecord); + return EFI_OUT_OF_RESOURCES; + } + pBS->FreePool(Buffer); + } + + DListAdd(&(PrivateData.PackList), (DLINK *)NewRecord); + *Handle = NewRecord; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiListPacks +// +// Description: +// This function is HII Database protocol function ListPackageLists implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN UINT8 PackageType - Package type +// IN EFI_GUID *PackageGuid - Pointer to package guid +// IN OUT UINTN *HandleBufferLength - Pointer to allocated buffer size value +// OUT EFI_HII_HANDLE *Handle - Pointer to EFI_HII_HANDLE buffer where to store found handles +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - HandleBufferLength is NULL +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// EFI_NOT_FOUND - No handles found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiListPacks ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle) +{ + UINTN RequiredSize = 0; + UINT32 i, Count = 0; + EFI_STATUS Status; + PACKAGE_LIST_RECORD *List; + BOOLEAN InternalBuffer = TRUE; + BOOLEAN Found; + EFI_HII_HANDLE *MatchedHandles; + + if(HandleBufferLength == NULL) + return EFI_INVALID_PARAMETER; + + if (*HandleBufferLength > 0 && Handle == NULL) + return EFI_INVALID_PARAMETER; + + if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) || + (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) + return EFI_INVALID_PARAMETER; + + List = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead); + + if(PackageType == EFI_HII_PACKAGE_TYPE_ALL) + { + RequiredSize = sizeof(EFI_HII_HANDLE) * PrivateData.PackList.Size; + + if(*HandleBufferLength < RequiredSize) + { + *HandleBufferLength = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + + for(i = 0; i < PrivateData.PackList.Size; i++) + { + Handle[i] = List; + List = (PACKAGE_LIST_RECORD *)List->Link.pNext; + } + } + else + { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_HII_HANDLE) * PrivateData.PackList.Size, + (VOID **)&MatchedHandles); + if(EFI_ERROR(Status)) + InternalBuffer = FALSE; + + //parsing package lists to find matches. If internal buffer present found handles will be + //stored to avoid repeat parsing + for(i = 0; i < PrivateData.PackList.Size; i++) + { + Found = FindAndRemovePackages( + (EFI_HII_HANDLE)List, + PackageType, + PackageGuid, + TRUE); + if(Found) + { + if(InternalBuffer) + MatchedHandles[Count] = (EFI_HII_HANDLE)List; + Count++; + } + List = (PACKAGE_LIST_RECORD *) List->Link.pNext; + } + + if(Count == 0) + return EFI_NOT_FOUND; + + RequiredSize = Count * sizeof(EFI_HII_HANDLE); + + if(*HandleBufferLength < RequiredSize) + { + *HandleBufferLength = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + + if(InternalBuffer) + { + for(i = 0; i < Count; i++) + Handle[i] = MatchedHandles[i]; + pBS->FreePool(MatchedHandles); + } + else + { + Count = 0; + for(i = 0; i < PrivateData.PackList.Size; i++) + { + Found = FindAndRemovePackages( + (EFI_HII_HANDLE)List, + PackageType, + PackageGuid, + TRUE); + if(Found) + { + Handle[Count] = (EFI_HII_HANDLE)List; + Count++; + } + List = (PACKAGE_LIST_RECORD *) List->Link.pNext; + } + } + } + + *HandleBufferLength = RequiredSize; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiUpdatePack +// +// Description: +// This function is HII Database protocol function UpdatePackageList implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HII_HANDLE Handle - Handle of package list to be updated +// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to new Package list +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - Handle is invalid +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiUpdatePack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList) +{ + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle; + EFI_STATUS Status; + + if (PackageList == NULL) + return EFI_INVALID_PARAMETER; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) + return EFI_NOT_FOUND; + + Status = AddPackages(Handle, PackageList, TRUE); + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiExportPacks +// +// Description: +// This function is HII Database protocol function ExportPackageLists implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_HII_HANDLE Handle - Handle of package list to be exported +// IN OUT UINTN *BufferSize - Pointer to export buffer size value +// OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer - Pointer to buffer where to export package lists +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - Handle is invalid +// EFI_BUFFER_TOO_SMALL - Export buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiExportPacks ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer) +{ + EFI_STATUS Status; + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle; + UINT32 Size = 0; + UINTN PackageListSize; + UINTN RequiredSize = 0; + UINTN MaxPackageListSize = 0; + VOID *IntBuffer; + +//Conformance check, as required by SCT + if (BufferSize == NULL) + return EFI_INVALID_PARAMETER; + + if (*BufferSize > 0 && Buffer == NULL) + return EFI_INVALID_PARAMETER; +//End of conformace check + + if (Record != NULL) //we need to export only specific package list + return ExportPack(Handle, BufferSize, Buffer, TRUE); + +//we need to return all package lists + Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead); + + while(Record != NULL) { + //first determine required buffer size + PackageListSize = 0; + Status = ExportPack((EFI_HII_HANDLE)Record, &PackageListSize, NULL, TRUE); + if(Status == EFI_BUFFER_TOO_SMALL) { + RequiredSize += PackageListSize; + MaxPackageListSize = (MaxPackageListSize > PackageListSize) ? MaxPackageListSize : PackageListSize; + } + Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext); + } + + if(*BufferSize < RequiredSize) { + *BufferSize = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + + Status = pBS->AllocatePool(EfiBootServicesData, MaxPackageListSize, &IntBuffer); + if(EFI_ERROR(Status)) + return Status; + + Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead); + + while(Record != NULL) { + //export all package lists one by one + PackageListSize = MaxPackageListSize; + Status = ExportPack((EFI_HII_HANDLE)Record, &PackageListSize, IntBuffer, FALSE); + if(!EFI_ERROR(Status)) { + MemCpy(Buffer, IntBuffer, PackageListSize); + (UINT8 *)Buffer += PackageListSize; + } + Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext); + } + + pBS->FreePool(IntBuffer); + *BufferSize = RequiredSize; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiFindKeyboardLayouts +// +// Description: +// This function is HII Database protocol function FindKeyboardLayouts implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN OUT UINT16 *KeyGuidBufferLength - Pointer to allocated buffer size value +// OUT EFI_GUID *KeyGuidBuffer - Pointer to EFI_GUID buffer where to store found layouts +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - KeyGuidBufferLength or KeyGuidBuffer is NULL +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// EFI_NOT_FOUND - No layouts found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiFindKeyboardLayouts ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN OUT UINT16 *KeyGuidBufferLength, + OUT EFI_GUID *KeyGuidBuffer) +{ + UINT16 RequiredSize; + KEY_LAYOUT_LINK *Link; + UINT16 i; + + if(KeyGuidBufferLength == NULL || KeyGuidBuffer == NULL) + return EFI_INVALID_PARAMETER; + + if(PrivateData.KeyLayoutList.Size == 0) + return EFI_NOT_FOUND; + + RequiredSize = (UINT16) PrivateData.KeyLayoutList.Size * sizeof(EFI_GUID); + if(RequiredSize > *KeyGuidBufferLength) + { + *KeyGuidBufferLength = RequiredSize; + return EFI_BUFFER_TOO_SMALL; + } + + Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead; + for(i = 0; i < PrivateData.KeyLayoutList.Size; i++) + { + KeyGuidBuffer[i] = Link->Layout.Guid; + Link = (KEY_LAYOUT_LINK *) Link->Link.pNext; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiSetKeyboardLayout +// +// Description: +// This function is HII Database protocol function SetKeyboardLayout implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_GUID *KeyGuid - Pointer to EFI_GUID of layout to set +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - KeyGuid is NULL +// EFI_NOT_FOUND - Given layout not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +//dummy function for signal event procedure +VOID SetKbLayoutNotifyFn(IN EFI_EVENT Event, IN VOID *Context) {} + +EFI_STATUS HiiSetKeyboardLayout ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_GUID *KeyGuid) +{ + EFI_HII_KEYBOARD_LAYOUT* Layout; + EFI_STATUS Status; + + if(KeyGuid == NULL) + return EFI_INVALID_PARAMETER; + + Layout = FindLayoutByGuid(KeyGuid); + if(Layout == NULL) + return EFI_NOT_FOUND; + + PrivateData.CurrentLayout = Layout; + Status = SignalKbLayoutChangedEvent(); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetKeyboardLayout +// +// Description: +// This function is HII Database protocol function GetKeyboardLayout implementation +// +// Input: +// IN EFI_HII_DATABASE_PROTOCOL *This - Pointer to EFI_HII_DATABASE_PROTOCOL structure +// IN EFI_GUID *KeyGuid - Pointer to EFI_GUID of layout to set +// IN OUT UINT16 *KeyGuidBufferLength - Pointer to allocated buffer size value +// OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout - Pointer to EFI_HII_KEYBOARD_LAYOUT where to store layout +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_INVALID_PARAMETER - KeyboardLayout or KeyGuidBufferLength is NULL +// EFI_NOT_FOUND - Given layout not found +// EFI_BUFFER_TOO_SMALL - Allocated buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetKeyboardLayout ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_GUID *KeyGuid, + IN OUT UINT16 *KeyGuidBufferLength, + OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout) +{ + EFI_HII_KEYBOARD_LAYOUT *Layout; + + if(KeyGuidBufferLength == NULL) + return EFI_INVALID_PARAMETER; + + if(*KeyGuidBufferLength != 0 && KeyboardLayout == NULL) + return EFI_INVALID_PARAMETER; + + if(KeyGuid == NULL) + Layout = PrivateData.CurrentLayout; + else + Layout = FindLayoutByGuid(KeyGuid); + + if(Layout == NULL) + return EFI_NOT_FOUND; + + if(Layout->LayoutLength > *KeyGuidBufferLength) + { + *KeyGuidBufferLength = Layout->LayoutLength; + return EFI_BUFFER_TOO_SMALL; + } + + MemCpy(KeyboardLayout, Layout, Layout->LayoutLength); + return EFI_SUCCESS; +} + +//********************** Service functions implementation *************************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddPackages +// +// Description: +// This function adds packages from PackageList to package list with given handle +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list where to add packages +// IN EFI_HII_PACKAGE_LIST_HEADER *PackageList - Pointer to package list which packages to add +// IN BOOLEAN Update - Flag which defines packages should be added or updated +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_ERROR - Some error occured during execution +// +// Notes: +// If Update is TRUE control flow goes as described in UpdatePackageList function definition (see UEFI +// specification v2.1) Otherwise control flow goes as described in NewPackageList function definition +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddPackages( + IN EFI_HII_HANDLE Handle, + IN EFI_HII_PACKAGE_LIST_HEADER *PackageList, + BOOLEAN Update) +{ + UINT8 Passes; + EFI_GUID *Guid; + UINT8 PackageType; + EFI_STATUS Status; + EFI_HII_DATABASE_NOTIFY_TYPE NotifyType; + EFI_HII_PACKAGE_LIST_HEADER *SavePointer; + UINT32 ControlSize; + + SavePointer = PackageList; + ControlSize = PackageList->PackageLength; + + if(Update) + { + Passes = 2; //set number of passes + NotifyType = EFI_HII_DATABASE_NOTIFY_ADD_PACK; + } + else + { + Passes = 1; //set number of passes + NotifyType = EFI_HII_DATABASE_NOTIFY_NEW_PACK; + } + + while(Passes--) + { + (UINT8 *)PackageList += sizeof(EFI_HII_PACKAGE_LIST_HEADER); + ControlSize -= sizeof(EFI_HII_PACKAGE_LIST_HEADER); + + while(((EFI_HII_PACKAGE_HEADER *)PackageList)->Type != EFI_HII_PACKAGE_END && ControlSize > 0) + { + if(Update) + { + PackageType = ((EFI_HII_PACKAGE_HEADER *)PackageList)->Type; + if(PackageType == EFI_HII_PACKAGE_TYPE_GUID) + Guid = (EFI_GUID *) &(((EFI_HII_GUID_PACKAGE_HDR *)PackageList)->Guid); + else + Guid = NULL; + FindAndRemovePackages(Handle, PackageType, Guid, FALSE); + } + else + { + Status = AddPackage(Handle, (EFI_HII_PACKAGE_HEADER *)PackageList, NotifyType); + if(EFI_ERROR(Status)) + return Status; + } + + ControlSize -= ((EFI_HII_PACKAGE_HEADER *)PackageList)->Length; + (UINT8 *)PackageList += ((EFI_HII_PACKAGE_HEADER *)PackageList)->Length; + } + Update = FALSE; + PackageList = SavePointer; + ControlSize = PackageList->PackageLength; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddPackage +// +// Description: +// This function adds package to package list with given handle +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list where to add package +// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to add +// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notify type to be signalled +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_ERROR - Some error occured during execution +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddPackage( + IN EFI_HII_HANDLE Handle, + IN EFI_HII_PACKAGE_HEADER *Package, + EFI_HII_DATABASE_NOTIFY_TYPE NotifyType) +{ + PACKAGE_LINK *NewLink; + UINT32 Size; + DLIST *PackageList; + EFI_STATUS Status = EFI_SUCCESS; + + PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList); + + Size = Package->Length; + NewLink = (PACKAGE_LINK *) CreateNewLink(Size); + if(NewLink == NULL) + return EFI_OUT_OF_RESOURCES; + MemCpy(&(NewLink->Package), Package, Size); + + switch(Package->Type) + { + case EFI_HII_PACKAGE_STRINGS: + Status = ParseStringsPackage( + (PACKAGE_LIST_RECORD *)Handle, + (EFI_HII_STRING_PACKAGE_HDR *)Package); + break; + case EFI_HII_PACKAGE_SIMPLE_FONTS: + Status = ParseSimpleFontsPackage((EFI_HII_SIMPLE_FONT_PACKAGE_HDR *)Package); + break; + case EFI_HII_PACKAGE_FONTS: + Status = ParseFontsPackage((EFI_HII_FONT_PACKAGE_HDR *)Package); + break; + case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + Status = ParseKeyLayoutPackage((EFI_HII_KEYBOARD_PACKAGE_HDR *)Package); + break; + default: + break; + } + + if(EFI_ERROR(Status)) + return Status; + + DListAdd(PackageList, (DLINK *)NewLink); + + if(PrivateData.NotifyList.Size > 0) + InvokeRegisteredNotify(Package, Handle, NotifyType); + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindAndRemovePackages +// +// Description: +// This function finds or removes packages from package list with given handle +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list where to find package +// IN UINT8 PackageType - Package type to find +// IN EFI_GUID *PackageGuid - Pointer to package guid to find +// IN BOOLEAN FindOnly - Flag, which determines should package be found or removed +// +// Output: +// TRUE - Package of given type found +// +// Notes: +// If FindOnly is TRUE, function returns TRUE when first package of given type is found. Otherwise +// function removes all packages of given type from package list and returns FALSE +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN FindAndRemovePackages ( + IN EFI_HII_HANDLE Handle, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN BOOLEAN FindOnly ) +{ + DLIST *PackageList; + PACKAGE_LINK *Link; + PACKAGE_LINK *FoundLink; + + + PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList); + Link = (PACKAGE_LINK *)(PackageList->pHead); + + while(Link != NULL) + { + if(MatchPackage(PackageType, PackageGuid, &(Link->Package))) + { + if(FindOnly) + return TRUE; + else + { + FoundLink = Link; + Link = (PACKAGE_LINK *)Link->Link.pPrev; + RemovePackage(Handle, FoundLink); + } + } + if(Link == NULL) //we removed first element from list + Link = (PACKAGE_LINK *)(PackageList->pHead); + else + Link = (PACKAGE_LINK *)Link->Link.pNext; + } + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RemovePackage +// +// Description: +// This function removes package from package list with given handle +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list where to add package +// IN PACKAGE_LINK *Package - Pointer to package to remove +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID RemovePackage ( + IN EFI_HII_HANDLE Handle, + IN PACKAGE_LINK *Package ) +{ + DLIST *PackageList; + + PackageList = &(((PACKAGE_LIST_RECORD *)Handle)->PackageList); + + if(PrivateData.NotifyList.Size > 0) + InvokeRegisteredNotify(&(Package->Package), Handle, EFI_HII_DATABASE_NOTIFY_REMOVE_PACK); + + switch(Package->Package.Type) + { + case EFI_HII_PACKAGE_STRINGS: + DeleteStringsFromDatabase(&(((PACKAGE_LIST_RECORD *)Handle)->StringDb)); + DeleteList(&(((PACKAGE_LIST_RECORD *)Handle)->LanguageList)); + break; + case EFI_HII_PACKAGE_SIMPLE_FONTS: +// DeleteSimpleFonts((EFI_HII_SIMPLE_FONT_PACKAGE_HDR *)&(Package->Package)); + break; + case EFI_HII_PACKAGE_FONTS: +// DeleteFonts((EFI_HII_FONT_PACKAGE_HDR *)&(Package->Package)); + break; + case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + DeleteKeyboardLayout((EFI_HII_KEYBOARD_PACKAGE_HDR *)&(Package->Package)); + break; + default: + break; + } + DListDelete(PackageList, (DLINK *)Package); + pBS->FreePool(Package); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: InvokeRegisteredNotify +// +// Description: +// This function invokes registered notify function if package types match +// +// Input: +// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to match +// IN EFI_HII_HANDLE Handle - Handle of package list to whom given package belongs +// IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType - Notification type +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID InvokeRegisteredNotify ( + IN EFI_HII_PACKAGE_HEADER *Package, + IN EFI_HII_HANDLE Handle, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType) +{ + NOTIFY_RECORD *Record; + + Record = (NOTIFY_RECORD *)(PrivateData.NotifyList.pHead); + + while(Record != NULL) + { + if(MatchPackage(Record->PackageType, &(Record->PackageGuid), Package) && + (NotifyType & Record->NotifyType)) + Record->PackageNotifyFn(Record->PackageType, + &(Record->PackageGuid), + Package, + Handle, + NotifyType); + Record = (NOTIFY_RECORD *)(Record->Link.pNext); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NewPackageListRecord +// +// Description: +// This function creates new PACKAGE_LIST_RECORD structure and returns pointer to it +// +// Input: +// None +// +// Output: +// PACKAGE_LIST_RECORD* - pointer to newly created structure +// NULL - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +PACKAGE_LIST_RECORD* NewPackageListRecord( VOID ) +{ + EFI_STATUS Status; + PACKAGE_LIST_RECORD *Record; + + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(PACKAGE_LIST_RECORD), + &Record); + if (EFI_ERROR(Status)) + return NULL; + + Record->Signature = PACKAGE_LIST_RECORD_SIGNATURE; + + DListInit(&(Record->PackageList)); + DListInit(&(Record->LanguageList)); + DListInit(&(Record->StringFontList)); + + Record->StringDb.InitialCount = 20; + Record->StringDb.RecordCount = 0; + Record->StringDb.KeyField = &StringDbKeyField; + Record->StringDb.MemoryType = EfiBootServicesData; + Record->StringDb.KeyCount = 1; + + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(VOID *) * 20, + &(Record->StringDb.IndexArray)); + + if (EFI_ERROR(Status)) + { + pBS->FreePool(Record); + return NULL; + } + + return Record; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: NewNotifyRecord +// +// Description: +// This function creates new NOTIFY_RECORD structure and returns pointer to it +// +// Input: +// None +// +// Output: +// NOTIFY_RECORD* - pointer to newly created structure +// NULL - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +NOTIFY_RECORD* NewNotifyRecord( VOID ) +{ + EFI_STATUS Status; + NOTIFY_RECORD *Record; + + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(NOTIFY_RECORD), + &Record); + if (EFI_ERROR(Status)) + return NULL; + + Record->Signature = NOTIFY_LIST_RECORD_SIGNATURE; + + return Record; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CreateNewLink +// +// Description: +// This function creates new link structure for linked list and returns pointer to it +// +// Input: +// IN UINT32 Size - size of the link stucture in bytes +// +// Output: +// VOID* - pointer to newly created structure +// NULL - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID* CreateNewLink(UINT32 Size) +{ + EFI_STATUS Status; + VOID *Buffer; + + Status = pBS->AllocatePool( + EfiBootServicesData, + Size + sizeof(DLINK), + &Buffer); + if (EFI_ERROR(Status)) + return NULL; + + return Buffer; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DeleteList +// +// Description: +// This function deletes linked list and frees allocated memory +// +// Input: +// IN DLIST *List - Pointer to linked list to be deleted +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID DeleteList(DLIST *List) +{ + DLINK *Current; + DLINK *Next; + + Current = List->pHead; + + while(Current != NULL) + { + Next = Current->pNext; + pBS->FreePool(Current); + Current = Next; + } + + List->pHead = NULL; + List->pTail = NULL; + List->Size = 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchPackage +// +// Description: +// This function checks if given package matches given type and guid +// +// Input: +// IN UINT8 PackageType - Package type to match +// IN EFI_GUID *PackageGuid - Pointer to package guid to match +// IN EFI_HII_PACKAGE_HEADER *Package - Pointer to package to check +// +// Output: +// TRUE - package matches given type and guid +// FALSE - package don't match +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchPackage( + IN UINT8 PackageType, + IN EFI_GUID *PackageGuid, + IN EFI_HII_PACKAGE_HEADER *Package) +{ + if(PackageType != Package->Type) + return FALSE; + + if(PackageType == EFI_HII_PACKAGE_TYPE_GUID) + { + if(guidcmp(PackageGuid, &(((EFI_HII_GUID_PACKAGE_HDR *)Package)->Guid))) + return FALSE; + } + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CheckIfPresent +// +// Description: +// This function checks if package list with given guid already in database +// +// Input: +// IN EFI_GUID *Guid - Pointer to package list guid to check +// IN EFI_HANDLE DriverHandle - Driver handle +// +// Output: +// TRUE - package list already present in database +// FALSE - package list with given guid not found in database +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CheckIfPresent( + IN EFI_GUID *Guid, + IN EFI_HANDLE DriverHandle) +{ + PACKAGE_LIST_RECORD *Record; + + Record = (PACKAGE_LIST_RECORD *)(PrivateData.PackList.pHead); + + while(Record != NULL) + { + if((!guidcmp(Guid, &(Record->Guid))) && (DriverHandle == Record->DriverHandle)) + return TRUE; + Record = (PACKAGE_LIST_RECORD *)(Record->Link.pNext); + } + + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseKeyLayoutPackage +// +// Description: +// This function extracts keyboard layout from package and saves it in private area +// +// Input: +// IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package - Pointer to keyboard layout package +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseKeyLayoutPackage( + IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package) +{ + KEY_LAYOUT_LINK *Link; + UINT16 i; + UINT8 *Pointer; + UINT32 Size; + + Pointer = (UINT8 *)Package; + Pointer += sizeof(EFI_HII_KEYBOARD_PACKAGE_HDR); + + for(i = 0; i < Package->LayoutCount; i++) + { + Size = ((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->LayoutLength; + Link = (KEY_LAYOUT_LINK *) CreateNewLink(Size); + if(Link == NULL) + return EFI_OUT_OF_RESOURCES; + MemCpy(&(Link->Layout), Pointer, Size); + DListAdd(&(PrivateData.KeyLayoutList), (DLINK *)Link); + Pointer += Size; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DeleteKeyboardLayout +// +// Description: +// This function removes keyboard layouts existing in package from HII database +// +// Input: +// IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package - Pointer to keyboard layout package +// +// Output: +// EFI_SUCCESS - Function executed successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DeleteKeyboardLayout( + IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package) +{ + KEY_LAYOUT_LINK *Link; + UINT16 i; + UINT8 *Pointer; + UINT32 Size; + + Pointer = (UINT8 *)Package; + Pointer += sizeof(EFI_HII_KEYBOARD_PACKAGE_HDR); + + for(i = 0; i < Package->LayoutCount; i++) + { + Size = ((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->LayoutLength; + Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead; + while(Link != NULL) + { + if(!guidcmp(&(((EFI_HII_KEYBOARD_LAYOUT *)Pointer)->Guid), &(Link->Layout.Guid))) + break; + Link = (KEY_LAYOUT_LINK *)Link->Link.pNext; + } + + if(Link != NULL) { + if(PrivateData.CurrentLayout == &(Link->Layout)) { + PrivateData.CurrentLayout = NULL; + SignalKbLayoutChangedEvent(); + } + + DListDelete(&(PrivateData.KeyLayoutList), (DLINK *)Link); + } + Pointer += Size; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindLayoutByGuid +// +// Description: +// This function finds keyboard layout in private area by given guid +// +// Input: +// IN EFI_GUID *Guid - Pointer to guid of keyboard layout +// +// Output: +// EFI_HII_KEYBOARD_LAYOUT* - Pointer to found layout +// NULL - layout not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_HII_KEYBOARD_LAYOUT* FindLayoutByGuid( + IN EFI_GUID *Guid) +{ + KEY_LAYOUT_LINK *Link; + + Link = (KEY_LAYOUT_LINK *)PrivateData.KeyLayoutList.pHead; + while(Link != NULL) + { + if(!guidcmp(Guid, &(Link->Layout.Guid))) + return &(Link->Layout); + Link = (KEY_LAYOUT_LINK *)Link->Link.pNext; + } + return NULL; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseSimpleFontsPackage +// +// Description: +// This function extracts simple fonts from package and saves in private area +// +// Input: +// IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package - Pointer to simple font package +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseSimpleFontsPackage( + IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package) +{ + EFI_STATUS Status; + UINT16 i; + UINT16 Symbol; + EFI_NARROW_GLYPH *NGlyph; + EFI_WIDE_GLYPH *WGlyph; + + NGlyph = Package->NarrowGlyphs; + WGlyph = (EFI_WIDE_GLYPH *)NGlyph; + (UINT8 *)WGlyph += Package->NumberOfNarrowGlyphs * sizeof(EFI_NARROW_GLYPH); + + for(i = 0; i < Package->NumberOfNarrowGlyphs; i++) + { + Symbol = NGlyph[i].UnicodeWeight; + if(DefaultFont[Symbol].NarrowGlyph == NULL) + { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_NARROW_GLYPH), + &(DefaultFont[Symbol].NarrowGlyph)); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + DefaultFont[Symbol].NarrowGlyph[0] = NGlyph[i]; + } + } + + for(i = 0; i < Package->NumberOfWideGlyphs; i++) + { + Symbol = WGlyph[i].UnicodeWeight; + if(DefaultFont[Symbol].WideGlyph == NULL) + { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_WIDE_GLYPH), + &(DefaultFont[Symbol].WideGlyph)); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + + DefaultFont[Symbol].WideGlyph[0] = WGlyph[i]; + } + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DeleteStringsFromDatabase +// +// Description: +// This function removes HII strings from private storage and frees allocated memory +// +// Input: +// IN DBE_DATABASE *Database - Pointer to private strings storage +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID DeleteStringsFromDatabase(DBE_DATABASE *Database) +{ + VOID *FreeLink; + UINTN *Pointer; + UINTN i; + + if(Database->RecordCount == 0) + return; + + Pointer = (UINTN *)(Database->IndexArray); + + for(i = 0; i < Database->RecordCount; i++) + { + FreeLink = (VOID *)(UINTN)(*Pointer); + pBS->FreePool(FreeLink); + Pointer++; + } + + MemSet(Database->IndexArray, Database->RecordCount * Database->KeyCount, 0); + Database->RecordCount = 0; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DeleteSimpleFonts +// +// Description: +// This function removes simple fonts from private area and frees allocated memory +// +// Input: +// IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package - Pointer to simple font package which fonts +// should be removed +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID DeleteSimpleFonts(IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package) +{ + UINT16 i; + UINT16 Symbol; + EFI_NARROW_GLYPH *NGlyph; + EFI_WIDE_GLYPH *WGlyph; + + NGlyph = Package->NarrowGlyphs; + WGlyph = (EFI_WIDE_GLYPH *)NGlyph; + (UINT8 *)WGlyph += Package->NumberOfNarrowGlyphs * sizeof(EFI_NARROW_GLYPH); + + for(i = 0; i < Package->NumberOfNarrowGlyphs; i++) + { + Symbol = NGlyph[i].UnicodeWeight; + if(DefaultFont[Symbol].NarrowGlyph != NULL) + { + pBS->FreePool(DefaultFont[Symbol].NarrowGlyph); + DefaultFont[Symbol].NarrowGlyph = NULL; + } + } + + for(i = 0; i < Package->NumberOfWideGlyphs; i++) + { + Symbol = WGlyph[i].UnicodeWeight; + if(DefaultFont[Symbol].WideGlyph != NULL) + { + pBS->FreePool(DefaultFont[Symbol].WideGlyph); + DefaultFont[Symbol].WideGlyph = NULL; + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ExportPack +// +// Description: +// This function exports the package list with given handle into provided buffer +// +// Input: +// IN EFI_HII_HANDLE Handle - Handle of package list to be exported +// IN OUT UINTN *BufferSize - Pointer to export buffer size value +// OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer - Pointer to buffer where to export package lists +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_BUFFER_TOO_SMALL - Export buffer too small +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ExportPack ( + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer, + IN BOOLEAN FirstCall ) +{ + EFI_STATUS Status; + PACKAGE_LIST_RECORD *Record = (PACKAGE_LIST_RECORD *) Handle; + PACKAGE_LINK *Link; + UINT32 Size = 0; + + if (Record->Signature != PACKAGE_LIST_RECORD_SIGNATURE) //handle is not valid, return NOT FOUND as SCT requirement + return EFI_NOT_FOUND; + + if(FirstCall) { + //on the subsequent call we don't need to update string packages again + Status = UpdateStringPackages(Handle); + if(EFI_ERROR(Status)) + return Status; + } + + Link = (PACKAGE_LINK *)Record->PackageList.pHead; + while(Link != NULL) + { + Size += Link->Package.Length; + Link = (PACKAGE_LINK *)Link->Link.pNext; + } + + Size += sizeof(EFI_HII_PACKAGE_LIST_HEADER); + + if(Size > *BufferSize) + { + *BufferSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = Size; + Buffer->PackageListGuid = Record->Guid; + Buffer->PackageLength = Size; + (UINT8 *)Buffer += sizeof(EFI_HII_PACKAGE_LIST_HEADER); + + Link = (PACKAGE_LINK *)Record->PackageList.pHead; + while(Link != NULL) + { + Size = Link->Package.Length; + MemCpy(Buffer, &(Link->Package), Size); + (UINT8 *)Buffer += Size; + Link = (PACKAGE_LINK *)Link->Link.pNext; + } + + return EFI_SUCCESS; +} + +EFI_STATUS SignalKbLayoutChangedEvent( + VOID) +{ + EFI_EVENT Event; + EFI_GUID SetKeyboardLayoutEventGuid = EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID; + EFI_STATUS Status; + + Status = pBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + SetKbLayoutNotifyFn, + NULL, + &SetKeyboardLayoutEventGuid, + &Event); + if(EFI_ERROR(Status)) + return Status; + + pBS->SignalEvent(Event); + pBS->CloseEvent(Event); + + return EFI_SUCCESS; +} + +#pragma warning (default : 4090) + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2007, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/UefiHii/HiiFont.c b/Core/CORE_DXE/UefiHii/HiiFont.c new file mode 100644 index 0000000..739520c --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiFont.c @@ -0,0 +1,1035 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFont.c 3 3/18/13 8:31a Thomaschen $ +// +// $Revision: 3 $ +// +// $Date: 3/18/13 8:31a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFont.c $ +// +// 3 3/18/13 8:31a Thomaschen +// Update to rev.16. +// +// 16 3/11/13 4:40p Artems +// [TAG] EIP110240 +// [Category] Improvement +// [Description] Raise the TPL of StringToImage function to TPL_NOTIFY +// to protect internal global data +// [Files] HiiFont.c +// +// 15 1/24/13 11:12a Artems +// [TAG] EIP112874 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] System displays output in wrong colors +// [RootCause] If system failed to find font, described in passed font +// info structure it also ignored passed colors +// [Solution] Preserve passed colors even if font not found +// [Files] HiiFont.c +// +// 14 12/26/12 1:40p Artems +// [TAG] EIP109050 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Memory leal in call to GetGlyph function +// [RootCause] GetGlyph function called GetFontInfo function to obtain +// proper font and didn't release font info buffer +// [Solution] Fixed GetGlyph function +// [Files] HiiFont.c +// +// 13 11/14/12 5:58p Artems +// [TAG] EIP105534 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] system hangs during SCT execution +// [RootCause] Incorrect handling of FORM_FEED escape character in +// StringToImage function +// [Solution] Graphics console - added flag to ignore line breaks +// HiiFont - fixed multiline drawing logic +// [Files] Gc.c HiiFont.c HiiFontEx.c +// +// 12 9/25/12 5:46p Artems +// [TAG] EIP101224 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] System freezes +// [RootCause] Memory leak in StringToImage function. When called many +// times may lead to memory exhaustion +// [Solution] Fixed memory leak +// [Files] HiiFont.c +// +// 11 6/27/12 4:16p Artems +// [TAG] EIP93526 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Aptio 4 - Proportional Font EFI_HII_OUT_FLAG_WRAP issue +// [RootCause] Passed drawing flags contained both Clip and Wrap. Clip +// gets analyzed first so clipping control flow was enacted +// [Solution] Changed order of drawind flags analysis +// [Files] HiiFont.c +// +// 10 6/15/12 12:19p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] project doesn't build in 32-bit mode +// [RootCause] Signed/Unsigned mismatch reported by 32-bit compiler +// [Solution] typecasted one parameter to signed +// [Files] HiiFont.c HiiFontEx.c +// +// 9 6/14/12 6:31p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio fixed SCT reported +// bugs +// [Files] HiiFont.c HiiFontEx.c +// +// 8 5/24/12 2:58p Artems +// [TAG] EIP83593 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] No symbols are shown in GSE +// [RootCause] Incorrect BaseLineOffset was set. Transparent drawing was +// not supported +// [Solution] Set correct BaseLineOffset. Add check for transparency +// flag +// [Files] HiiFont.c +// +// 7 5/22/12 4:14p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio. Removed unused +// functions +// [Files] HiiFont.c +// +// 6 5/21/12 6:28p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio +// [Files] HiiDatabase.c HiiFont.c HiiFontEx.c HiiPrivate.h HiiString.c +// +// 5 10/25/11 7:04p Artems +// EIP 70530: Fixed bugs reported by SCT 2.3.1 +// +// 4 5/17/11 4:05p Artems +// EIP 59787: Bug fix - when drawing multi-line string X position wasn't +// updated to start of new line +// +// 3 5/13/11 6:14p Artems +// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and +// AmiHiiSetString +// to avoid collusion with EdkII native library functions +// +// 2 12/03/09 6:04p Artems +// SCT bug fix +// +// 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: HiiFont.c +// +// Description: Hii font protocol functions implementation +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <AmiDxeLib.h> +#include "HiiPrivate.h" + +const EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black = { 0, 0, 0, 0 }; +const EFI_GRAPHICS_OUTPUT_BLT_PIXEL White = { 0xff, 0xff, 0xff, 0 }; + +extern HII_DATABASE_PRIVATE_DATA PrivateData; +extern SIMPLE_FONT DefaultFont[0x10000]; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefForegroundColor; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefBackgroundColor; + +static UINTN TextStartX; +static UINTN TextStartY; +static EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ImageBlt; //buffer, where to draw + +EFI_FONT_HANDLE CurFont; //font to use +CHAR16 *DrawString; //string to draw +EFI_HII_OUT_FLAGS DrawFlags = 0; +DLIST DrawLines = {0, NULL, NULL}; +UINTN ImageWidth; +UINTN ImageHeight; + +#pragma optimize( "", off ) +EFI_STATUS CheckParameters(VOID *One, VOID *Two) +{ + return (One == NULL || Two == NULL) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; +} +#pragma optimize( "", on ) + +//**************************** Protocol functions implementation *************************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiStringToImage +// +// Description: +// This function is HII Font protocol function StringToImage implementation +// +// Input: +// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure +// IN EFI_HII_OUT_FLAGS Flags - Drawing flags +// IN EFI_STRING String - String to draw +// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info +// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer +// IN UINTN BltX - start horizontal position +// IN UINTN BltY - start vertical position +// OUT EFI_HII_ROW_INFO **RowInfoArray - Pointer to returned row info array +// OUT UINTN *RowInfoArraySize - Pointer to store row info array size +// OUT UINTN *ColumnInfoArray - Pointer to returned column info array +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiStringToImage( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN CONST EFI_STRING String, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewBlt = NULL; + EFI_IMAGE_OUTPUT *Io = *Blt; + EFI_HII_ROW_INFO *RowInfo; + UINTN i, j; + UINTN Offset; + DRAW_LINE *Link; + UINTN Delta = 0; + EFI_FONT_DISPLAY_INFO *Info = NULL; + EFI_TPL OldTpl; + + Status = CheckParameters(String, Blt); + if(EFI_ERROR(Status)) + return Status; + + if (Io == NULL) { + // + // These two flag cannot be used if Blt is NULL upon entry. + // + if ((Flags & EFI_HII_OUT_FLAG_TRANSPARENT) == EFI_HII_OUT_FLAG_TRANSPARENT) + return EFI_INVALID_PARAMETER; + + if ((Flags & EFI_HII_OUT_FLAG_CLIP) == EFI_HII_OUT_FLAG_CLIP) + return EFI_INVALID_PARAMETER; + } + // + // These two flags require that EFI_HII_OUT_FLAG_CLIP be also set. + // + if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_X) + return EFI_INVALID_PARAMETER; + + if ((Flags & (EFI_HII_OUT_FLAG_CLIP | EFI_HII_OUT_FLAG_CLIP_CLEAN_Y)) == EFI_HII_OUT_FLAG_CLIP_CLEAN_Y) + return EFI_INVALID_PARAMETER; + // + // This flag cannot be used with EFI_HII_OUT_FLAG_CLIP_CLEAN_X. + // + if ((Flags & (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) == (EFI_HII_OUT_FLAG_WRAP | EFI_HII_OUT_FLAG_CLIP_CLEAN_X)) + return EFI_INVALID_PARAMETER; + +//check string size - if two bytes - means empty string - do nothing + i = StrSize16(String); + + if(i <= 2) + return EFI_SUCCESS; + + OldTpl = pBS->RaiseTPL(TPL_NOTIFY); + +//first initialize global variables and split string +/* SCT assumes that EFI_HII_OUT_FLAG_CLIP flag is implied when direct to screen output is performed + unless EFI_HII_OUT_FLAG_WRAP flag is set */ + DrawFlags = Flags; + if(Flags & EFI_HII_IGNORE_LINE_BREAK || + (Flags & EFI_HII_DIRECT_TO_SCREEN && !(Flags & EFI_HII_OUT_FLAG_WRAP))) + DrawFlags |= EFI_HII_OUT_FLAG_CLIP; + + DrawString = String; + TextStartX = BltX; + TextStartY = BltY; + CurFont = NULL; + Status = HiiGetFontInfo(This, &CurFont, StringInfo, &Info, NULL); + if(EFI_ERROR(Status)) { + CurFont = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE; + Info = NULL; + } + + if (Info != NULL) { + DefForegroundColor = Info->ForegroundColor; + DefBackgroundColor = Info->BackgroundColor; + pBS->FreePool(Info); //it's no longer needed + } else { + if(StringInfo != NULL) { //even though correct font not found we preserve passed colors if any + DefForegroundColor = StringInfo->ForegroundColor; + DefBackgroundColor = StringInfo->BackgroundColor; + } else { + DefForegroundColor = White; + DefBackgroundColor = Black; + } + } + + Status = SplitByLineBreaks(DrawString); + if(EFI_ERROR(Status)) { + pBS->RestoreTPL(OldTpl); + return EFI_OUT_OF_RESOURCES; + } + + if(Io != NULL) { + if(!(Flags & EFI_HII_DIRECT_TO_SCREEN)) { + //if we're drawing on given bitmap - take its size + ImageWidth = Io->Width; + ImageHeight = Io->Height; + NewBlt = Io->Image.Bitmap; + } else { + //make sure we fit in screen resolution + ImageWidth = Io->Width - BltX; + ImageHeight = Io->Height - BltY; + + //clear TextStartX and TextStartY + TextStartX = 0; + TextStartY = 0; + } + /* since bitmap size is fixed we have to adjust text to fit in */ + Status = AdjustLineSize(); + if(EFI_ERROR(Status)) { + pBS->RestoreTPL(OldTpl); + return EFI_OUT_OF_RESOURCES; + } + } else { + //calculate size of the image + GetDrawImageSize(&ImageWidth, &ImageHeight); + //add to required image size initial offset + ImageWidth += BltX; + ImageHeight += BltY; + } + + if(NewBlt == NULL) { + /* buffer not initialized because of DirectToScreen flag or Io == NULL */ + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ImageWidth * ImageHeight, + &NewBlt); + if (EFI_ERROR(Status)) { + pBS->RestoreTPL(OldTpl); + return EFI_OUT_OF_RESOURCES; + } + MemSet(NewBlt, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ImageWidth * ImageHeight, 0); + } + + ImageBlt = NewBlt; + Draw(); + + if(Flags & EFI_HII_DIRECT_TO_SCREEN) + { + EFI_GRAPHICS_OUTPUT_PROTOCOL *Screen; + + if(ImageWidth < Io->Width) //we need to draw a subrectange, calculate Delta + Delta = ImageWidth * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + + Screen = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)(Io->Image.Screen); + Status = Screen->Blt(Screen, ImageBlt, EfiBltBufferToVideo, + 0, 0, BltX, BltY, ImageWidth, ImageHeight, Delta); + pBS->FreePool(ImageBlt); + } + +//Prepare return info if needed + Link = (DRAW_LINE *)(DrawLines.pHead); + if(RowInfoArray != NULL && Link->LineHeight != 0) { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_HII_ROW_INFO) * DrawLines.Size, + &RowInfo); + if (EFI_ERROR(Status)) { + pBS->RestoreTPL(OldTpl); + return EFI_OUT_OF_RESOURCES; + } + + i = 0; + while(Link != NULL) { + RowInfo[i].BaselineOffset = 0; //I'm still confused with this one, but SCT is happy + RowInfo[i].EndIndex = Link->EndIndex; + RowInfo[i].LineHeight = Link->LineHeight; + RowInfo[i].LineWidth = Link->LineWidth; + RowInfo[i].StartIndex = Link->StartIndex; + + i++; + Link = (DRAW_LINE *)Link->Link.pNext; + } + *RowInfoArray = RowInfo; + if(RowInfoArraySize != NULL) + *RowInfoArraySize = DrawLines.Size; + } else { + if(RowInfoArray != NULL) + *RowInfoArray = NULL; + if(RowInfoArraySize != NULL) + *RowInfoArraySize = 0; + } + + if(Io == NULL) { + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_IMAGE_OUTPUT), &Io); + if (EFI_ERROR(Status)) { + pBS->RestoreTPL(OldTpl); + return EFI_OUT_OF_RESOURCES; + } + + Io->Height = (UINT16)ImageHeight; + Io->Width = (UINT16)ImageWidth; + Io->Image.Bitmap = NewBlt; + + *Blt = Io; + } + + if(ColumnInfoArray != NULL) { + i = 0; + Link = (DRAW_LINE *)(DrawLines.pHead); + while(Link != NULL) + { + Offset = TextStartX; + for(j = Link->StartIndex; j <= Link->EndIndex; j++) + { + BOOLEAN Dummy; + EFI_HII_GLYPH_INFO Cell; + ColumnInfoArray[i] = Offset; + IntGetGlyph(CurFont, DrawString[j], &Cell, NULL, &Dummy); + i++; + Offset += Cell.AdvanceX; + } + Link = (DRAW_LINE *)Link->Link.pNext; + } + } + +//clean up + DeleteList(&DrawLines); + pBS->RestoreTPL(OldTpl); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiStringIdToImage +// +// Description: +// This function is HII Font protocol function StringIdToImage implementation +// +// Input: +// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure +// IN EFI_HII_OUT_FLAGS Flags - Drawing flags +// IN EFI_HII_HANDLE PackageList - Handle of package list where string resides +// IN EFI_STRING_ID StringId - String Id +// IN CHAR8 *Language - Language Id +// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info +// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer +// IN UINTN BltX - start horizontal position +// IN UINTN BltY - start vertical position +// OUT EFI_HII_ROW_INFO **RowInfoArray - Pointer to returned row info array +// OUT UINTN *RowInfoArraySize - Pointer to store row info array size +// OUT UINTN *ColumnInfoArray - Pointer to returned column info array +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiStringIdToImage ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST CHAR8* Language, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL) +{ + CHAR16 String[0x100]; + UINTN StringSize = 0x100; + EFI_STATUS Status; + + Status = AmiHiiGetString(NULL, Language, PackageList, StringId, String, &StringSize, NULL); + + if(EFI_ERROR(Status)) + { + if(Status == EFI_BUFFER_TOO_SMALL) + { + Status = pBS->AllocatePool( + EfiBootServicesData, + sizeof(CHAR16) * StringSize, + (VOID **)&String); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + } + else + return Status; + + Status = AmiHiiGetString(NULL, Language, PackageList, StringId, String, &StringSize, NULL); + } + + Status = HiiStringToImage(This, Flags, String, StringInfo, Blt, BltX, BltY, + RowInfoArray, RowInfoArraySize, ColumnInfoArray); + + if(StringSize > 0x100) + pBS->FreePool(String); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetGlyph +// +// Description: +// This function is HII Font protocol function GetGlyph implementation +// +// Input: +// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure +// IN CHAR16 Char - Symbol, which glyph to return +// IN EFI_FONT_DISPLAY_INFO *StringInfo - Pointer to display info +// IN OUT EFI_IMAGE_OUTPUT **Blt - Pointer to output buffer +// OUT UINTN *Baseline - Pointer to baseline placeholder +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetGlyph ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN CHAR16 Char, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo, + OUT EFI_IMAGE_OUTPUT **Blt, + OUT UINTN *Baseline OPTIONAL +) +{ + EFI_STATUS Status; + BOOLEAN GlyphNotFound = FALSE; + EFI_IMAGE_OUTPUT *Output; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Bitmap; + EFI_FONT_HANDLE Font; + EFI_FONT_DISPLAY_INFO *Info = NULL; + EFI_HII_GLYPH_INFO Cell; + UINT8 *GlyphBlock; + BOOLEAN Free; + + if(Blt == NULL || *Blt != NULL) + return EFI_INVALID_PARAMETER; + + Font = NULL; + Status = HiiGetFontInfo(This, &Font, StringInfo, &Info, NULL); + if(EFI_ERROR(Status)) { + Font = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE; + Info = NULL; + } + +//prepare global data values, used in drawing + if(Info != NULL) { + DefForegroundColor = Info->ForegroundColor; + DefBackgroundColor = Info->BackgroundColor; + pBS->FreePool(Info); + } else { + if(StringInfo != NULL) { + DefForegroundColor = StringInfo->ForegroundColor; + DefBackgroundColor = StringInfo->BackgroundColor; + } else { + DefForegroundColor = White; + DefBackgroundColor = Black; + } + } + + Status = IntGetGlyph(Font, Char, &Cell, &GlyphBlock, &Free); + if(EFI_ERROR(Status)) + return Status; + if(Status == EFI_WARN_UNKNOWN_GLYPH) + GlyphNotFound = TRUE; + +//allocate memory for output bitmap + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * Cell.Width * Cell.Height, + &Bitmap); + if (EFI_ERROR(Status)) + return EFI_OUT_OF_RESOURCES; + +//allocate memory for output data + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof(EFI_IMAGE_OUTPUT), + &Output); + if (EFI_ERROR(Status)) { + pBS->FreePool(Bitmap); + return EFI_OUT_OF_RESOURCES; + } + + Output->Width = Cell.Width; + Output->Height = Cell.Height; + Output->Image.Bitmap = Bitmap; + + ImageWidth = Output->Width; + ImageHeight = Output->Height; + +//now we are ready to draw the glyph + DrawGlyph(0, 0, ImageWidth, ImageHeight, GlyphBlock, FALSE, Bitmap, Cell.Width); + if(Free) + pBS->FreePool(GlyphBlock); + + *Blt = Output; + + if(Baseline != NULL) { + if((UINTN)Font == DEFAULT_FONT_HANDLE) + *Baseline = (Cell.Width == EFI_GLYPH_WIDTH) ? 4 : 5; //fixed value for system font + else + *Baseline = (Cell.OffsetY < 0) ? -(Cell.OffsetY) : 0; + } + + return (GlyphNotFound) ? EFI_WARN_UNKNOWN_GLYPH : EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: HiiGetFontInfo +// +// Description: +// This function is HII Font protocol function GetFontInfo implementation +// +// Input: +// IN EFI_HII_FONT_PROTOCOL *This - Pointer to EFI_HII_FONT_PROTOCOL structure +// IN OUT EFI_FONT_HANDLE *FontHandle - Pointer to font handle +// IN EFI_FONT_DISPLAY_INFO *StringInfoIn - Pointer to display info +// OUT EFI_FONT_DISPLAY_INFO *StringInfoOut - Pointer to output display info +// IN EFI_STRING *String - Pointer to string to test +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS HiiGetFontInfo ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn, + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut, + IN CONST EFI_STRING String OPTIONAL +) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fg; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Bg; + EFI_HII_FONT_STYLE FStyle; + UINT16 FSize; + CHAR16 *FName; + FONT_MATCH_MASK Fm; + EFI_STATUS Status; + EFI_FONT_DISPLAY_INFO FdInfo; + + if (StringInfoIn == NULL) { + /* use default values */ + FdInfo.FontInfoMask = EFI_FONT_INFO_SYS_FONT | + EFI_FONT_INFO_SYS_SIZE | + EFI_FONT_INFO_SYS_STYLE | + EFI_FONT_INFO_SYS_FORE_COLOR | + EFI_FONT_INFO_SYS_BACK_COLOR; + } else { + FdInfo = *StringInfoIn; + FName = (CHAR16 *)StringInfoIn->FontInfo.FontName; + } + // + // Check the font information mask to make sure it is valid. + // + if (((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) == + (EFI_FONT_INFO_SYS_FONT | EFI_FONT_INFO_ANY_FONT)) || + ((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) == + (EFI_FONT_INFO_SYS_SIZE | EFI_FONT_INFO_ANY_SIZE)) || + ((FdInfo.FontInfoMask & (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) == + (EFI_FONT_INFO_SYS_STYLE | EFI_FONT_INFO_ANY_STYLE)) || + ((FdInfo.FontInfoMask & (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) == + (EFI_FONT_INFO_RESIZE | EFI_FONT_INFO_ANY_SIZE)) || + ((FdInfo.FontInfoMask & (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE)) == + (EFI_FONT_INFO_RESTYLE | EFI_FONT_INFO_ANY_STYLE))) + return EFI_INVALID_PARAMETER; + +/* first deal with color attributes */ + Fg = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_FORE_COLOR) ? White : StringInfoIn->ForegroundColor; + Bg = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_BACK_COLOR) ? Black : StringInfoIn->BackgroundColor; + +/* retrieve supplied information */ + FStyle = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_STYLE) ? EFI_HII_FONT_STYLE_NORMAL : StringInfoIn->FontInfo.FontStyle; + FSize = (FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_SIZE) ? EFI_GLYPH_HEIGHT : StringInfoIn->FontInfo.FontSize; + + if(FdInfo.FontInfoMask & EFI_FONT_INFO_SYS_FONT) { + if(*FontHandle == (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE) { + /* we already returned system font, so no other matches for system font present */ + *FontHandle = NULL; + return EFI_NOT_FOUND; + } + /* return system font information and handle */ + *FontHandle = (EFI_FONT_HANDLE)(UINTN)DEFAULT_FONT_HANDLE; + if(StringInfoOut != NULL) { + Status = FillFontInfo(*FontHandle, StringInfoOut); + if(EFI_ERROR(Status)) + return Status; + (*StringInfoOut)->ForegroundColor = Fg; + (*StringInfoOut)->BackgroundColor = Bg; + (*StringInfoOut)->FontInfoMask = FdInfo.FontInfoMask; + } + return EFI_SUCCESS; + } + + Fm.MatchName = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_FONT) ? MATCH_INGNORE : MATCH_STRICT; + Fm.MatchStyle = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_STYLE) ? MATCH_INGNORE : + (FdInfo.FontInfoMask & EFI_FONT_INFO_RESTYLE) ? MATCH_LOOSE : MATCH_STRICT; + Fm.MatchSize = (FdInfo.FontInfoMask & EFI_FONT_INFO_ANY_SIZE) ? MATCH_INGNORE : + (FdInfo.FontInfoMask & EFI_FONT_INFO_RESIZE) ? MATCH_LOOSE : MATCH_STRICT; + + Status = FindFont(FontHandle, FName, FStyle, FSize, Fm, String); + if(!EFI_ERROR(Status) && (StringInfoOut != NULL)) { + /* font found, prepare font info */ + Status = FillFontInfo(*FontHandle, StringInfoOut); + if(EFI_ERROR(Status)) + return Status; + (*StringInfoOut)->ForegroundColor = Fg; + (*StringInfoOut)->BackgroundColor = Bg; + (*StringInfoOut)->FontInfoMask = FdInfo.FontInfoMask; + } + + return Status; +} + + + +// *************************** Service functions (not for public use) ********************** + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsLineBreak +// +// Description: +// This function checks if given symbol is a line break +// +// Input: +// IN CHAR16 Char - Symbol to test +// +// Output: +// TRUE - Symbol is a linebreak +// FALSE - Symbol is not a linebreak +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsLineBreak(CHAR16 Char) +{ + switch(Char) + { + case 0x000c: + case 0x000d: + case 0x2028: + case 0x2029: + return TRUE; + default: + break; + } + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IsLineBreakOpp +// +// Description: +// This function checks if given symbol is a line break opportunity +// +// Input: +// IN CHAR16 Char - Symbol to test +// +// Output: +// TRUE - Symbol is a linebreak opportunity +// FALSE - Symbol is not a linebreak opportunity +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN IsLineBreakOpp(CHAR16 Char) +{ + if(IsLineBreak(Char)) + return TRUE; + + if(Char >= 0x2000 && Char <= 0x200a) + return TRUE; + + switch (Char) + { + case 0x0020: + case 0x1680: + case 0x2013: + case 0x205f: + return TRUE; + default: + break; + } + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SplitByLineBreaks +// +// Description: +// This function splits given string into lines on linebreaks +// +// Input: +// IN EFI_STRING String - string to split +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS SplitByLineBreaks(EFI_STRING String) +{ + UINT32 Size; + UINT32 i; + DRAW_LINE *Link; + + Size = StrSize16(String) / 2; //size in symbols + Link = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5); + if(Link == NULL) + return EFI_OUT_OF_RESOURCES; + + Link->StartIndex = 0; + if(DrawFlags & EFI_HII_IGNORE_LINE_BREAK) + { + Link->EndIndex = Size - 2; //ignore null terminator + UpdateLineSize(Link); + DListAdd(&DrawLines, (DLINK *)Link); + return EFI_SUCCESS; + } + + for(i = 0; i < (Size - 1); i++) + { + if(IsLineBreak(String[i])) + { + Link->EndIndex = i; + UpdateLineSize(Link); + DListAdd(&DrawLines, (DLINK *)Link); + Link = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5); + if(Link == NULL) + return EFI_OUT_OF_RESOURCES; + i++; + Link->StartIndex = i; + } + } + Link->EndIndex = Size - 2; + UpdateLineSize(Link); + DListAdd(&DrawLines, (DLINK *)Link); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AdjustLineSize +// +// Description: +// This function analyzes lines of the string and makes them fit into drawing area size +// +// Input: +// None +// +// Output: +// EFI_SUCCESS - Function executed successfully +// EFI_OUT_OF_RESOURCES - Not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AdjustLineSize(VOID) +{ + DRAW_LINE *Link; + UINTN TextHeight = ImageHeight - TextStartY; + UINTN TextWidth = ImageWidth - TextStartX; + EFI_STATUS Status; + + Link = (DRAW_LINE *)(DrawLines.pHead); + while(Link != NULL) { +//first detect line height + if(TextHeight >= Link->LineHeight) { + /* line is visible entirely */ + TextHeight -= Link->LineHeight; + } else { + /* line is visible partially */ + if(DrawFlags & EFI_HII_OUT_FLAG_CLIP_CLEAN_Y || TextHeight == 0) { + Link->LineHeight = 0; //mark line as invisible and stop adjusting - all subsequent lines will be invisible + return EFI_SUCCESS; + } else { + Link->LineHeight = TextHeight; + TextHeight = 0; + } + } + +//second detect line width + if(Link->LineWidth > TextWidth) { + /* line needs clipping of wrapping */ + if(DrawFlags & EFI_HII_OUT_FLAG_WRAP) { + /* wrapping mode */ + Status = WrapLine(Link, TextWidth); + if(EFI_ERROR(Status)) + return Status; + } else { + /* clipping mode */ + ClipLine(Link, TextWidth, ((DrawFlags & EFI_HII_OUT_FLAG_CLIP_CLEAN_X) ? TRUE : FALSE)); + } + } +//proceed to next line + Link = (DRAW_LINE *)Link->Link.pNext; + } + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: Draw +// +// Description: +// This function draws lines of the string +// +// Input: +// None +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID Draw(VOID) +{ + DRAW_LINE *Link; + UINTN i; + CHAR16 CurrentSymbol; + BOOLEAN Transparent = FALSE; + EFI_STATUS Status; + + EFI_HII_GLYPH_INFO Cell; + UINT8 *GlyphBlock; + BOOLEAN Free; + + POINT_COORD gl_st; + POINT_COORD gl_size; + RECT_COORD glyph; + + POINT_COORD ln_st; + POINT_COORD ln_size; + RECT_COORD line; + + POINT_COORD origin; + + glyph.st = &gl_st; + glyph.size = &gl_size; + + line.st = &ln_st; + line.size = &ln_size; + ln_st.y = TextStartY; //line start coordinate Y + + if(DrawFlags & EFI_HII_OUT_FLAG_TRANSPARENT) + Transparent = TRUE; + + Link = (DRAW_LINE *)(DrawLines.pHead); + while(Link != NULL && Link->LineHeight != 0) //loop by strings + { + /* init line rectangle */ + ln_st.x = TextStartX; //line start coordinate X + ln_size.x = Link->LineWidth; //line width + ln_size.y = Link->LineHeight; //line height + + origin.x = ln_st.x; + origin.y = ln_st.y + Link->BaseLineOffset; + + for(i = Link->StartIndex; i <= Link->EndIndex; i++) + { + CurrentSymbol = DrawString[i]; + if((DrawFlags & EFI_HII_IGNORE_LINE_BREAK) && IsLineBreak(CurrentSymbol)) + continue; + + Status = IntGetGlyph(CurFont, CurrentSymbol, &Cell, &GlyphBlock, &Free); + if(EFI_ERROR(Status)) + return; + + if(Status == EFI_WARN_UNKNOWN_GLYPH && (DrawFlags & EFI_HII_IGNORE_IF_NO_GLYPH)) { + if(Free) + pBS->FreePool(GlyphBlock); + continue; + } + /* init glyph rectangle */ + gl_st.x = origin.x + Cell.OffsetX; + gl_st.y = origin.y - (Cell.Height + Cell.OffsetY); + gl_size.x = Cell.Width; + gl_size.y = Cell.Height; + + if(CheckVisible(&glyph, &line)) { + /* symbol is visible at least partially */ + /* at this point symbol rect coordinates were adjusted to fit visible area */ + DrawGlyph(gl_st.x, gl_st.y, gl_size.x, gl_size.y, GlyphBlock, Transparent, ImageBlt, Cell.Width); + } + + ln_st.x += Cell.AdvanceX; + ln_size.x = ((INTN)ln_size.x <= Cell.AdvanceX) ? 0 : ln_size.x - Cell.AdvanceX; + origin.x += Cell.AdvanceX; + + if(Free) + pBS->FreePool(GlyphBlock); + } //end of drawing line + + ln_st.y += ln_size.y; + Link = (DRAW_LINE *)Link->Link.pNext; + } +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/UefiHii/HiiFontEx.c b/Core/CORE_DXE/UefiHii/HiiFontEx.c new file mode 100644 index 0000000..32557da --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiFontEx.c @@ -0,0 +1,1332 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c 2 9/17/13 10:19p Thomaschen $ +// +// $Revision: 2 $ +// +// $Date: 9/17/13 10:19p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiFontEx.c $ +// +// 2 9/17/13 10:19p Thomaschen +// Update for EIP105534 and EIP126176. +// +// 1 11/21/12 4:08a Wesleychen +// Update rev.6 for EIP105534. +// 11 5/16/13 5:01p Artems +// [TAG] EIP123904 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] HiiFont and HiiConfig SCT tests are failed +// [RootCause] Regression bugs when implementing new features or spec +// updates +// [Solution] Fixed code logic +// [Files] HiiConfig.c HiiFontEx.c +// +// 10 5/02/13 1:52p Artems +// [TAG] EIP121673 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Incorrect line width returned by function StringToImage +// [RootCause] When determine line width function ignored flag +// "IGNORE_IF_NO_GLYPH" +// so line width was bigger if some glyphs were absent +// [Solution] Modified code logic to not count width of absent glyphs +// [Files] HiiFontEx.c +// +// 9 5/02/13 1:43p Artems +// [TAG] EIP113105 +// [Category] Spec Update +// [Severity] Important +// [Description] Wording for proportional font display was vague. After +// clarification +// code logic was slightly changed +// [Files] HiiFontEx.c HiiPrivate.h +// +// 8 3/26/13 3:18p Artems +// [TAG] EIP119250 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] System hang on Setup entry +// [RootCause] Incorrect boundaries checking in HiiFontEx.c function +// CheckVisible() +// [Solution] Changed checking condition +// [Files] HiiFontEx.c +// +// 7 2/25/13 4:44p Artems +// [TAG] EIP101673 +// [Category] New Feature +// [Description] Add support for AMI custom large fixed font +// [Files] HiiDatabase.c HiiFontEx.c HiiPrivate.h UefiHiiUtils.c GC.c +// new LargeFont Core modulePart +// +// 6 11/14/12 6:03p Artems +// [TAG] EIP105534 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] system hangs during SCT execution +// [RootCause] Incorrect handling of FORM_FEED escape character in +// StringToImage function +// [Solution] Graphics console - added flag to ignore line breaks +// HiiFont - fixed multiline drawing logic +// [Files] Gc.c HiiFont.c HiiFontEx.c +// +// 5 8/24/12 5:34p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] One character is not displayed properly +// [RootCause] Never accounted for the case, where character is +// completely below base line +// [Solution] added check that character height is less than OffsetY +// [Files] HiiFontEx.c +// +// 4 6/15/12 12:21p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] doesn't build in 32-bit mode +// [RootCause] Signed/Unsigned mismatch reported by 32-bit compiler +// [Solution] typecasted one parameter to INTN +// [Files] HiiFont.c HiiFontEx.c +// +// 3 6/14/12 6:32p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support for Aptio fixed SCT reported +// bugs +// [Files] HiiFont.c HiiFontEx.c +// +// 2 5/24/12 3:00p Artems +// [TAG] EIP83593 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] system dead loops in HiiGetFontInfo function +// [RootCause] When loop through linked list of installed fonts pointer +// was not updated +// [Solution] Added pointer update +// [Files] HiiFontEx.c +// +// 1 5/22/12 3:29p Artems +// [TAG] EIP83593 +// [Category] New Feature +// [Description] Proportional font support +// [Files] HiiFontEx.c HiiFont.c HiiDatabase.c HiiString.c HiiPrivate.h +// UefiHii.h +// +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: HiiFontEx.c +// +// Description: Proportional font support +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include <UefiHii.h> +#include <AmiDxeLib.h> +#include "HiiPrivate.h" + +#define LOOSE_SIZE_MARGIN 4 + +extern HII_DATABASE_PRIVATE_DATA PrivateData; +extern SIMPLE_FONT DefaultFont[]; +extern EFI_FONT_HANDLE CurFont; //font to use +extern CHAR16 *DrawString; //string to draw +extern EFI_HII_OUT_FLAGS DrawFlags; +extern DLIST DrawLines; +extern UINTN ImageWidth; +extern UINTN ImageHeight; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefForegroundColor; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL DefBackgroundColor; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DuplicateGlyph +// +// Description: +// This function duplicates glyph from Origin and assigns it to the Char +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// IN CHAR16 Char - character to assign glyph to +// IN CHAR16 Origin - character to assign glyph from +// +// Output: +// EFI_NOT_FOUND - glyph for Origin character not found +// EFI_SUCCESS - glyph created successfully +// EFI_OUT_OF_RESOURCES - not enough memory to duplicate glyph +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS DuplicateGlyph( + IN OUT FONT_LINK *Font, + IN CHAR16 Char, + IN CHAR16 Origin +) +{ + EFI_STATUS Status; + GLYPH_LINK *Link = (GLYPH_LINK *)Font->Glyphs.pHead; + GLYPH_LINK *New; + + while(Link != NULL) { + if(Link->Char == Origin) + break; + Link = (GLYPH_LINK *) Link->Link.pNext; + } + + if(Link == NULL) + return EFI_NOT_FOUND; + + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &New); + if(!EFI_ERROR(Status)) { + New->Char = Char; + New->Cell = Link->Cell; + New->GlyphBlock = Link->GlyphBlock; + DListAdd(&(Font->Glyphs), (DLINK *)New); + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: AddGlyphs +// +// Description: +// This function adds glyphs to specified font +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// IN EFI_HII_GLYPH_INFO Cell - variable that contains font dimensions +// IN UINT8 *GlyphBlock - pointer to glyph block +// IN UINT16 Count - number of glyphs to add +// IN CHAR16 Char - first character to assign glyph to +// OUT UINTN *BytesProcessed - number of bytes from glyph block that were assigned +// +// Output: +// EFI_SUCCESS - glyph created successfully +// EFI_OUT_OF_RESOURCES - not enough memory to add glyphs +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS AddGlyphs( + IN OUT FONT_LINK *Font, + IN EFI_HII_GLYPH_INFO Cell, + IN UINT8 *GlyphBlock, + IN UINT16 Count, + IN CHAR16 Char, + OUT UINTN *BytesProcessed +) +{ + EFI_STATUS Status; + GLYPH_LINK *Glyph; + UINTN Bytes = ((Cell.Width + 7) / 8) * Cell.Height; + UINTN i; + + for(i = 0; i < Count; i++) { + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(GLYPH_LINK), &Glyph); + if(EFI_ERROR(Status)) + return Status; + + Glyph->Cell = Cell; + Glyph->Char = Char; + Char++; + Glyph->GlyphBlock = GlyphBlock; + GlyphBlock += Bytes; + DListAdd(&(Font->Glyphs), (DLINK *)Glyph); + } + + *BytesProcessed = Bytes * Count; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseGlyphs +// +// Description: +// This function parses packed glyphs and creates glyphs for characters +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseGlyphs( + IN OUT FONT_LINK *Font +) +{ + EFI_STATUS Status; + CHAR16 Current = 1; + EFI_HII_GLYPH_INFO Default = Font->FontPackage->Cell; + EFI_HII_GLYPH_INFO CurCell; + UINT8 *Walker = (UINT8 *)Font->FontPackage; + UINT8 *EndMarker; + UINTN Bytes; + UINT16 CurCount; + static const EFI_HII_GLYPH_INFO ZeroCell = { 0, 0, 0, 0, 0 }; + EFI_HII_GLYPH_INFO ChangeCell; + UINTN BelowBaseLine; + UINTN AboveBaseLine; + UINTN MaxBelowBaseLine = 0; + UINTN MaxAboveBaseLine = 0; + + EndMarker = Walker + Font->FontPackage->Header.Length; + Walker += Font->FontPackage->GlyphBlockOffset; + ChangeCell = Default; + + do { + switch (*Walker) { + case EFI_HII_GIBT_SKIP1: + Current += ((EFI_HII_GIBT_SKIP1_BLOCK *)Walker)->SkipCount; + Walker += sizeof(EFI_HII_GIBT_SKIP1_BLOCK); + break; + case EFI_HII_GIBT_SKIP2: + Current += ((EFI_HII_GIBT_SKIP2_BLOCK *)Walker)->SkipCount; + Walker += sizeof(EFI_HII_GIBT_SKIP2_BLOCK); + break; + case EFI_HII_GIBT_EXT1: + Walker += sizeof(EFI_HII_GIBT_EXT1_BLOCK); + break; + case EFI_HII_GIBT_EXT2: + Walker += sizeof(EFI_HII_GIBT_EXT2_BLOCK); + break; + case EFI_HII_GIBT_EXT4: + Walker += sizeof(EFI_HII_GIBT_EXT4_BLOCK); + break; + case EFI_HII_GIBT_DEFAULTS: + Default = ((EFI_HII_GIBT_DEFAULTS_BLOCK *)Walker)->Cell; + ChangeCell = Default; + Walker += sizeof(EFI_HII_GIBT_DEFAULTS_BLOCK); + break; + case EFI_HII_GIBT_END: + break; + case EFI_HII_GIBT_GLYPH: + CurCell = ((EFI_HII_GIBT_GLYPH_BLOCK *)Walker)->Cell; + ChangeCell = CurCell; + Walker += sizeof(EFI_HII_GIBT_GLYPH_BLOCK); + Status = AddGlyphs(Font, CurCell, Walker, 1, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current++; + break; + case EFI_HII_GIBT_GLYPH_DEFAULT: + Walker += sizeof(EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK); + Status = AddGlyphs(Font, Default, Walker, 1, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current++; + break; + case EFI_HII_GIBT_GLYPHS: + CurCell = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Cell; + CurCount = ((EFI_HII_GIBT_GLYPHS_BLOCK *)Walker)->Count; + ChangeCell = CurCell; + Walker += sizeof(EFI_HII_GIBT_GLYPHS_BLOCK); + Status = AddGlyphs(Font, CurCell, Walker, CurCount, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current += CurCount; + break; + case EFI_HII_GIBT_GLYPHS_DEFAULT: + CurCount = ((EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK *)Walker)->Count; + Walker += sizeof(EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK); + Status = AddGlyphs(Font, Default, Walker, CurCount, Current, &Bytes); + if(EFI_ERROR(Status)) + return Status; + Walker += Bytes; + Current += CurCount; + break; + case EFI_HII_GIBT_DUPLICATE: + Status = DuplicateGlyph(Font, Current, ((EFI_HII_GIBT_DUPLICATE_BLOCK *)Walker)->CharValue); + if(EFI_ERROR(Status)) + return Status; + Walker += sizeof(EFI_HII_GIBT_DUPLICATE_BLOCK); + Current++; + break; + default: + return EFI_NOT_FOUND; + } + + if(MemCmp(&ChangeCell, (VOID *)&ZeroCell, sizeof(EFI_HII_GLYPH_INFO))) { + if(ChangeCell.OffsetY < 0) { + BelowBaseLine = (UINTN)(0 - ChangeCell.OffsetY); + AboveBaseLine = (ChangeCell.Height > BelowBaseLine) ? (ChangeCell.Height - BelowBaseLine) : 0; + } else { + AboveBaseLine = ChangeCell.Height + ChangeCell.OffsetY; + BelowBaseLine = 0; + } + MaxBelowBaseLine = (MaxBelowBaseLine >= BelowBaseLine) ? MaxBelowBaseLine : BelowBaseLine; + MaxAboveBaseLine = (MaxAboveBaseLine >= AboveBaseLine) ? MaxAboveBaseLine : AboveBaseLine; + ChangeCell = ZeroCell; + } + + } while(*Walker != 0 && Walker <= EndMarker); + + Font->FontHeight = MaxBelowBaseLine + MaxAboveBaseLine; + Font->FontBaseLine = MaxAboveBaseLine; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: RepackGlyphBlock +// +// Description: +// This function repacks glyph block of AMI custom font package to be similar +// to proportional font glyph block for easier processing +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS RepackGlyphBlock( + IN UINT8 *GlyphBlock, + IN UINT16 Width, + IN UINT16 Height +) +{ + EFI_STATUS Status; + UINTN Size; + UINT8 *Tmp; + UINT16 Line; + UINT16 i, j, k = 0; + + Line = (Width + 7) / 8; //how many bytes describe one line of glyph + Size = Line * Height; + Status = pBS->AllocatePool(EfiBootServicesData, Size, &Tmp); + if(EFI_ERROR(Status)) + return Status; + + for(i = 0; i < Height; i++) { + for(j = 0; j < Line; j++) { + Tmp[k] = GlyphBlock[i + j * Height]; + k++; + } + } + MemCpy(GlyphBlock, Tmp, Size); + pBS->FreePool(Tmp); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseAmiGlyphs +// +// Description: +// This function parses custom AMI packed glyphs and creates glyphs for characters +// +// Input: +// IN OUT FONT_LINK *Font - pointer to current font +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseAmiGlyphs( + IN OUT FONT_LINK *Font +) +{ + EFI_STATUS Status; + EFI_NARROW_GLYPH *Walker; + EFI_HII_GLYPH_INFO CurCell; + AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *AmiHdr; + UINT16 i; + UINTN Bytes; + + AmiHdr = (AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage; + CurCell.Width = AmiHdr->Width; + CurCell.Height = AmiHdr->Height; + CurCell.OffsetX = 0; + CurCell.OffsetY = 0; + Walker = (EFI_NARROW_GLYPH *)(AmiHdr + 1); + for(i = 0; i < AmiHdr->NumberOfNarrowGlyphs; i++) { + CurCell.AdvanceX = (Walker->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : CurCell.Width; + Status = RepackGlyphBlock(Walker->GlyphCol1, CurCell.Width, CurCell.Height); + if(EFI_ERROR(Status)) + return Status; + Status = AddGlyphs(Font, CurCell, Walker->GlyphCol1, 1, Walker->UnicodeWeight, &Bytes); + if(EFI_ERROR(Status)) + return Status; + + Walker = (EFI_NARROW_GLYPH *)(Walker->GlyphCol1 + Bytes); + } + + Font->FontHeight = AmiHdr->Height; + Font->FontBaseLine = AmiHdr->Height; + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ParseFontsPackage +// +// Description: +// This function parses font package +// +// Input: +// IN EFI_HII_FONT_PACKAGE_HDR *Package - pointer to font package +// +// Output: +// EFI_ERROR - some error was encountered during parsing +// EFI_SUCCESS - glyph created successfully +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ParseFontsPackage( + IN EFI_HII_FONT_PACKAGE_HDR *Package +) +{ + EFI_STATUS Status; + EFI_HII_FONT_PACKAGE_HDR *Copy; + FONT_LINK *Font; + +/* first make global copy of the package */ + Status = pBS->AllocatePool(EfiBootServicesData, Package->Header.Length, &Copy); + if(EFI_ERROR(Status)) + return Status; + MemCpy(Copy, Package, Package->Header.Length); + +/* create Font link */ + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(FONT_LINK), &Font); + if(EFI_ERROR(Status)) + return Status; + +/* initialize font link */ + Font->FontPackage = Copy; + DListInit(&(Font->Glyphs)); + + if(Package->Header.Type == AMI_HII_PACKAGE_FONTS) + Status = ParseAmiGlyphs(Font); + else + Status = ParseGlyphs(Font); + + if(!EFI_ERROR(Status)) + DListAdd(&(PrivateData.FontList), (DLINK *)Font); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchName +// +// Description: +// This function checks whether passed name matches name of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN CHAR16 *FontName - pointer to font name to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - names are matched +// FALSE - names are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchName( + IN FONT_LINK *Font, + IN CHAR16 *FontName, + IN FONT_MATCH_MASK Mask +) +{ + UINT8 *Walker; + + if(Mask.MatchName == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS && + !Wcscmp(FontName, L"Ami font")) + return TRUE; + + Walker = (UINT8 *)Font->FontPackage; + Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR); + /* now Walker points to font name */ + if(Wcscmp(FontName, (CHAR16 *)Walker)) + return FALSE; + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchStyle +// +// Description: +// This function checks whether passed style matches style of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN EFI_HII_FONT_STYLE FontStyle - font style to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - styles are matched +// FALSE - styles are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchStyle( + IN FONT_LINK *Font, + IN EFI_HII_FONT_STYLE FontStyle, + IN FONT_MATCH_MASK Mask +) +{ + EFI_HII_FONT_STYLE Cur; + + if(Mask.MatchStyle == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) + Cur = EFI_HII_FONT_STYLE_NORMAL; + else + Cur = Font->FontPackage->FontStyle; + + if(FontStyle == Cur) + return TRUE; + +/* when restyle is ordered we support interchange between Normal, Bold and Italic styles */ + if(Mask.MatchStyle == MATCH_LOOSE && + FontStyle <= 3 && + Cur <= 3) + return TRUE; + + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchSize +// +// Description: +// This function checks whether passed size matches size of the passed font +// +// Input: +// IN FONT_LINK *Font - pointer to font +// IN UINT16 FontSize - font size to match with +// IN FONT_MATCH_MASK Mask - matching rules +// +// Output: +// TRUE - sizes are matched +// FALSE - sizes are not matched +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchSize( + IN FONT_LINK *Font, + IN UINT16 FontSize, + IN FONT_MATCH_MASK Mask +) +{ + UINT16 Cur; + + if(Mask.MatchSize == MATCH_INGNORE) + return TRUE; + + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) + Cur = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height; + else + Cur = Font->FontPackage->Cell.Height; + + if(FontSize == Cur) + return TRUE; + +/* when resize is ordered we support interchange sizes within +/- LOOSE_SIZE_MARGIN from given size */ + if(Mask.MatchSize == MATCH_LOOSE && + Cur <= FontSize + LOOSE_SIZE_MARGIN && + Cur >= FontSize - LOOSE_SIZE_MARGIN) + return TRUE; + + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindGlyph +// +// Description: +// This function checks whether glyph for passed character is present, and returns it +// if necessary +// +// Input: +// IN DLIST Glyphs - linked list of glyphs to search within +// IN CHAR16 Char - character value to return glyph for +// OUT GLYPH_LINK **Match OPTIONAL - pointer to store returned glyph +// +// Output: +// TRUE - glyph found +// FALSE - glyph not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN FindGlyph( + IN DLIST Glyphs, + IN CHAR16 Char, + OUT GLYPH_LINK **Match OPTIONAL +) +{ + GLYPH_LINK *Link = (GLYPH_LINK *)Glyphs.pHead; + + while(Link != NULL) { + if(Link->Char == Char) { + if(Match != NULL) + *Match = Link; + return TRUE; + } + Link = (GLYPH_LINK *)Link->Link.pNext; + } + return FALSE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MatchString +// +// Description: +// This function checks whether all character glyphs are present for given string +// +// Input: +// IN FONT_LINK *Font - pointer to the font +// IN CONST EFI_STRING String - pointer to the string to check +// +// Output: +// TRUE - all glyphs are present +// FALSE - some glyphs are missing +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN MatchString( + IN FONT_LINK *Font, + IN CONST EFI_STRING String +) +{ + CHAR16 *Tst; + + if(String == NULL) + return TRUE; + + Tst = String; + + while(*Tst != 0) { + if(!FindGlyph(Font->Glyphs, *Tst, NULL)) + return FALSE; + Tst++; + } + return TRUE; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FindFont +// +// Description: +// This function tries to find font in database, that meets the criteria +// +// Input: +// IN OUT EFI_FONT_HANDLE *FontHandle - handle in database to start search from +// IN CHAR16 *FontName - pointer to the font name +// IN EFI_HII_FONT_STYLE FontStyle - font style +// IN UINT16 FontSize - font size +// IN FONT_MATCH_MASK Mask - matching rules +// IN CONST EFI_STRING String - pointer to string to verify glyphs presence +// +// Output: +// EFI_SUCCESS - font found +// EFI_NOT_FOUND - font not found +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FindFont( + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CHAR16 *FontName, + IN EFI_HII_FONT_STYLE FontStyle, + IN UINT16 FontSize, + IN FONT_MATCH_MASK Mask, + IN CONST EFI_STRING String +) +{ + FONT_LINK *Font; + + if(PrivateData.FontList.Size == 0) + /* no fonts in database */ + return EFI_NOT_FOUND; + + Font = (FONT_LINK *)PrivateData.FontList.pHead; + +/* check if handle passed is not NULL or dummy default font handle */ + if((UINTN)(*FontHandle) != NULL && (UINTN)(*FontHandle) != DEFAULT_FONT_HANDLE) { + while(Font != NULL) { + if((VOID *)Font == *FontHandle) + break; + Font = (FONT_LINK *)Font->Link.pNext; + } + if(Font == NULL) { + /* end of font list - no matches */ + *FontHandle = NULL; + return EFI_NOT_FOUND; + } + + /* match found, it was last returned font, move to the next */ + Font = (FONT_LINK *)Font->Link.pNext; + if(Font == NULL) { + /* end of font list, last returned font was last indeed */ + *FontHandle = NULL; + return EFI_NOT_FOUND; + } + } + + while(Font != NULL) { + /* loop through font list to find the match */ + if(MatchName(Font, FontName, Mask) && + MatchStyle(Font, FontStyle, Mask) && + MatchSize(Font, FontSize, Mask) && + MatchString(Font, String)) { + /* match is found */ + *FontHandle = (EFI_FONT_HANDLE)Font; + return EFI_SUCCESS; + } + Font = (FONT_LINK *)Font->Link.pNext; + } + *FontHandle = NULL; + return EFI_NOT_FOUND; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: FillFontInfo +// +// Description: +// This function returns EFI_FONT_DISPLAY_INFO data for given font +// +// Input: +// IN EFI_FONT_HANDLE FontHandle - font handle to return info about +// OUT EFI_FONT_DISPLAY_INFO **StringInfoOut - pointer where to store returned info +// +// Output: +// EFI_SUCCESS - info returned +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS FillFontInfo( + IN EFI_FONT_HANDLE FontHandle, + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut +) +{ + UINTN NameSize; + EFI_FONT_DISPLAY_INFO *Ret; + FONT_LINK *Font; + UINT8 *Walker; + EFI_STATUS Status; + static CHAR16 DefaultFontName[] = L"System font"; + + Font = (FONT_LINK *)FontHandle; + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + Walker = (UINT8 *)Font->FontPackage; + Walker += sizeof(EFI_HII_FONT_PACKAGE_HDR); + } else { + Walker = (UINT8 *)DefaultFontName; + } + + NameSize = Wcslen((CHAR16 *)Walker) * sizeof(CHAR16); + +/* font display info structure includes font info structure, where one CHAR16 already reserved + that's why Wcslen used instead fo Wcssize - null-terminator already accounted for */ + Status = pBS->AllocatePool(EfiBootServicesData, sizeof(EFI_FONT_DISPLAY_INFO) + NameSize, &Ret); + if(!EFI_ERROR(Status)) { + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + if(Font->FontPackage->Header.Type == AMI_HII_PACKAGE_FONTS) { + Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL; + Ret->FontInfo.FontSize = ((AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR *)Font->FontPackage)->Height; + } else { + Ret->FontInfo.FontStyle = Font->FontPackage->FontStyle; + Ret->FontInfo.FontSize = Font->FontPackage->Cell.Height; + } + } else { + Ret->FontInfo.FontStyle = EFI_HII_FONT_STYLE_NORMAL; + Ret->FontInfo.FontSize = EFI_GLYPH_HEIGHT; + } + Wcscpy(Ret->FontInfo.FontName, (CHAR16 *)Walker); + *StringInfoOut = Ret; + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: IntGetGlyph +// +// Description: +// This function returns glyph for given charactef from given font +// +// Input: +// IN EFI_FONT_HANDLE FontHandle - font handle of the desired font +// IN CHAR16 Char - character to return glyph for +// OUT EFI_HII_GLYPH_INFO *Cell - pointer to store info about glyph dimensions +// OUT UINT8 **GlyphBlock OPTIONAL - pointer to store glyph +// OUT BOOLEAN *Free - pointer to return flag was memory allocated for glyph and +// should be freed by caller +// +// Output: +// EFI_SUCCESS - glyph returned +// EFI_NOT_FOUND - glyph not found +// EFI_OUT_OF_RESOURCES - not enough memory to perform operation +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS IntGetGlyph( + IN EFI_FONT_HANDLE FontHandle, + IN CHAR16 Char, + OUT EFI_HII_GLYPH_INFO *Cell, + OUT UINT8 **GlyphBlock OPTIONAL, + OUT BOOLEAN *Free +) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS AllocStatus; + FONT_LINK *Font; + GLYPH_LINK *GlyphLink; + BOOLEAN Found; + SIMPLE_FONT Glyph; + UINT8 *WideGlyphBlock; + UINTN i; + + *Free = FALSE; + Font = (FONT_LINK *)FontHandle; + + if((UINTN)Font != DEFAULT_FONT_HANDLE) { + Found = FindGlyph(Font->Glyphs, Char, &GlyphLink); + if(!Found) { + Status = EFI_WARN_UNKNOWN_GLYPH; + Found = FindGlyph(Font->Glyphs, 0xfffd, &GlyphLink); + } + if(Found) { + *Cell = GlyphLink->Cell; + if(GlyphBlock) + *GlyphBlock = GlyphLink->GlyphBlock; + return Status; + } + Glyph = DefaultFont[0xfffd]; + } else { + /* Default font requested */ + Glyph = DefaultFont[(UINTN)Char]; + if(Glyph.NarrowGlyph == NULL && Glyph.WideGlyph == NULL) { + Glyph = DefaultFont[0xfffd]; + Status = EFI_WARN_UNKNOWN_GLYPH; + } + } +/* if we're here we use system font - either because it was requested, or +because supplied font doesn't have requested character or 0xfffd character +!!!! It is assumed that system font always have 0xfffd character font */ + Cell->Height = EFI_GLYPH_HEIGHT; + Cell->OffsetX = 0; + Cell->OffsetY = 0; + if(Glyph.NarrowGlyph != NULL) { + Cell->Width = EFI_GLYPH_WIDTH; + Cell->AdvanceX = ((Glyph.NarrowGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDTH; + if(GlyphBlock) + *GlyphBlock = (Glyph.NarrowGlyph)->GlyphCol1; + } else if(Glyph.WideGlyph != NULL) { + Cell->Width = EFI_GLYPH_WIDE_WIDTH; + Cell->AdvanceX = ((Glyph.WideGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDE_WIDTH; + if(GlyphBlock) { + AllocStatus = pBS->AllocatePool(EfiBootServicesData, sizeof(UINT8) * 2 * EFI_GLYPH_HEIGHT, &WideGlyphBlock); + if(EFI_ERROR(AllocStatus)) + return AllocStatus; + for(i = 0; i < EFI_GLYPH_HEIGHT; i++) { + WideGlyphBlock[2 * i] = (Glyph.WideGlyph)->GlyphCol1[i]; + WideGlyphBlock[2 * i + 1] = (Glyph.WideGlyph)->GlyphCol2[i]; + } + *GlyphBlock = WideGlyphBlock; + *Free = TRUE; + } + } else { + Cell->AdvanceX = 0; + return EFI_NOT_FOUND; + } + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UpdateLineSize +// +// Description: +// This function updates dimensions in pixels of given line based on glyphs of current font +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID UpdateLineSize( + IN OUT DRAW_LINE *Line +) +{ + EFI_STATUS Status; + UINTN Width = 0; + UINTN i; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + + for(i = Line->StartIndex; i <= Line->EndIndex; i++) { + if((DrawFlags & EFI_HII_IGNORE_LINE_BREAK) && IsLineBreak(DrawString[i])) + continue; + + Status = IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if(Status == EFI_WARN_UNKNOWN_GLYPH && (DrawFlags & EFI_HII_IGNORE_IF_NO_GLYPH)) + continue; + + Width = (Cell.AdvanceX < 0) ? Width : Width + (UINT16)Cell.AdvanceX; + } + Line->LineWidth = Width; + Line->LineHeight = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontHeight; + Line->BaseLineOffset = ((UINTN)CurFont == DEFAULT_FONT_HANDLE) ? Cell.Height : ((FONT_LINK *)CurFont)->FontBaseLine; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ClipLine +// +// Description: +// This function updates dimensions in pixels of given line to fit given width +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// IN UINTN Width - width to fit +// IN BOOLEAN ClipClean - clipping mode +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID ClipLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width, + IN BOOLEAN ClipClean +) +{ + UINTN Excess; + UINTN i; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + + Excess = Line->LineWidth - Width; + + for(i = Line->EndIndex; i >= Line->StartIndex; i--) { + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if ((INTN)Excess <= Cell.AdvanceX) + break; + Excess -= Cell.AdvanceX; + Line->LineWidth -= Cell.AdvanceX; + } + + if(Excess == Cell.AdvanceX || ClipClean) { + /* remove excess character */ + i--; + Line->LineWidth -= Cell.AdvanceX; + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if(Cell.AdvanceX == 0) + /* the previous character is non-spacing -remove it also */ + i--; + } else { + /* perform partial clipping */ + Line->LineWidth -= Excess; + } + Line->EndIndex = i; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: WrapLine +// +// Description: +// This function updates dimensions in pixels of given line to fit given width +// and creates additional line if necessary +// +// Input: +// IN OUT DRAW_LINE *Line - pointer to the line structure +// IN UINTN Width - width to fit +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS WrapLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width +) +{ + UINTN Excess; + UINTN i; + UINTN NewEnd; + UINTN NewStart; + DRAW_LINE *NewLine; + EFI_HII_GLYPH_INFO Cell; + BOOLEAN Dummy; + UINTN Save; + + Excess = Line->LineWidth - Width; + + for(i = Line->EndIndex; (i >= Line->StartIndex && i != 0); i--) { + IntGetGlyph(CurFont, DrawString[i], &Cell, NULL, &Dummy); + if ((INTN)Excess <= Cell.AdvanceX) + break; + Excess -= Cell.AdvanceX; + } + if(i == 0 || i == Line->StartIndex) { + Line->EndIndex = i; + Line->LineWidth = 0; + return EFI_SUCCESS; + } else { + Save = i; //save index of first excess character + } //we will you it if no break opp arises for clip_clean operation + +/* we skipped excessed characters - start search for line break opp */ + for(; (i >= Line->StartIndex && i != 0); i--) { + if(IsLineBreakOpp(DrawString[i])) { + /* we found line break opportunity */ + NewEnd = Line->EndIndex; + NewStart = i + 1; + Line->EndIndex = i; + UpdateLineSize(Line); + if(Line->LineWidth > Width) + /* case when line-break opp character is partially visible - skip it */ + Line->EndIndex--; + /* add a new line */ + NewLine = (DRAW_LINE *)CreateNewLink(sizeof(UINTN) * 5); + if(NewLine == NULL) + return EFI_OUT_OF_RESOURCES; + NewLine->StartIndex = NewStart; + NewLine->EndIndex = NewEnd; + UpdateLineSize(NewLine); + DListInsert(&DrawLines, (DLINK *)NewLine, (DLINK *)Line); + return EFI_SUCCESS; + } + } +/* if we're here, no line break opp present, use clip clean */ + Line->EndIndex = Save - 1; + UpdateLineSize(Line); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetDrawImageSize +// +// Description: +// This function returns size of image necessary to fit processing string +// including all wraps and clips +// +// Input: +// OUT UINTN *Width - pointer to store required width +// OUT UINTN *Height - pointer to store required height +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID GetDrawImageSize( + OUT UINTN *Width, + OUT UINTN *Height +) +{ + DRAW_LINE *Link; + UINTN MaxWidth = 0; + UINTN MaxHeight = 0; + + Link = (DRAW_LINE *)(DrawLines.pHead); + while(Link != NULL) + { + MaxWidth = (MaxWidth < Link->LineWidth) ? Link->LineWidth : MaxWidth; + MaxHeight += Link->LineHeight; + Link = (DRAW_LINE *)Link->Link.pNext; + } + *Width = MaxWidth; + *Height = MaxHeight; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: PixelSet +// +// Description: +// This function checks whether pixel with given coordinates is set in given glyph +// +// Input: +// IN UINTN PosX - X coordinate of pixel +// IN UINTN PosY - Y coordinate of pixel +// IN UINT8 *GlyphBlock - pointer to glyph array +// IN UINT16 CharWidth - width of character described by glyph +// +// Output: +// TRUE - pixel is set +// FALSE - pixel is not set +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN PixelSet( + IN UINTN PosX, + IN UINTN PosY, + IN UINT8 *GlyphBlock, + IN UINT16 CharWidth +) +{ + UINTN Step; + UINTN Index; + UINT8 Bit; + + Step = (CharWidth + 7) / 8; + Index = (PosY * Step) + (PosX / 8); + + Bit = (0x80 >> (PosX % 8)); + + return (Bit & GlyphBlock[Index]); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: DrawGlyph +// +// Description: +// This function draws given glyph on given bitmap +// +// Input: +// IN UINTN StartX - start X coordinate of glyph +// IN UINTN StartY - start Y coordinate of glyph +// IN UINTN SizeX - width of glyph +// IN UINTN SizeY - height of glyph +// IN UINT8 *GlyphBlock - pointer to glyph array +// IN BOOLEAN Transparent - flag if image should be transparent +// IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt - bitmap to draw on +// IN UINT16 CharWidth - width of character described by glyph +// +// Output: +// None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID DrawGlyph( + IN UINTN StartX, + IN UINTN StartY, + IN UINTN SizeX, + IN UINTN SizeY, + IN UINT8 *GlyphBlock, + IN BOOLEAN Transparent, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt, + IN UINT16 CharWidth +) +{ + UINTN i; + UINTN j; + UINTN Index; + UINTN Base; + + Base = StartX + StartY * ImageWidth; + for(i = 0; i < SizeY; i++ ) { + for(j = 0; j < SizeX; j++) { + Index = Base + i * ImageWidth + j; + if(PixelSet(j, i, GlyphBlock, CharWidth)) { + Blt[Index] = DefForegroundColor; + } else if (!Transparent) { + Blt[Index] = DefBackgroundColor; + } + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: CheckVisible +// +// Description: +// This function checks whether glyph is withing given image rectangle, +// and clips glyph rectangle if necessary +// +// Input: +// IN OUT RECT_COORD *Glyph - pointer to glyph rectangle +// IN RECT_COORD *Image - pointer to image rectangle +// +// Output: +// TRUE - glyph is visible (at least partially) +// FALSE - glyph is out of image boundaries +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +BOOLEAN CheckVisible( + IN OUT RECT_COORD *Glyph, + IN RECT_COORD *Image +) +{ + UINTN delta_x; + UINTN delta_y; + +/* check whether glyph within given image rectangle */ + if(Glyph->st->x >= (Image->st->x + Image->size->x) || + Glyph->st->y >= (Image->st->y + Image->size->y)) + return FALSE; + +/* clip glyph size if necessary */ + delta_x = (Image->st->x < Glyph->st->x) ? Glyph->st->x - Image->st->x : 0; + delta_y = (Image->st->y < Glyph->st->y) ? Glyph->st->y - Image->st->y : 0; + + if(Glyph->size->x > (Image->size->x - delta_x)) + Glyph->size->x = Image->size->x - delta_x; + + if(Glyph->size->y > (Image->size->y - delta_y)) + Glyph->size->y = Image->size->y - delta_y; + return TRUE; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2012, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/UefiHii/HiiPrivate.h b/Core/CORE_DXE/UefiHii/HiiPrivate.h new file mode 100644 index 0000000..9023189 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/HiiPrivate.h @@ -0,0 +1,885 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiPrivate.h 2 9/18/13 1:41a Thomaschen $ +// +// $Revision: 2 $ +// +// $Date: 9/18/13 1:41a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/CORE_DXE/UefiHii/HiiPrivate.h $ +// +// 2 9/18/13 1:41a Thomaschen +// Update for EIP126176. +// +// 16 5/02/13 1:48p Artems +// [TAG] EIP113105 +// [Category] Spec Update +// [Severity] Important +// [Description] Wording for proportional font display was vague. After +// clarification +// code logic was slightly changed +// [Files] HiiFontEx.c HiiPrivate.h +// +// 14 2/25/13 4:45p Artems +// [TAG] EIP101673 +// [Category] New Feature +// [Description] Add support for AMI custom large fixed font +// [Files] HiiDatabase.c HiiFontEx.c HiiPrivate.h UefiHiiUtils.c GC.c +// new LargeFont Core modulePart +// +// 13 8/15/12 3:36p 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 +// +// 12 5/22/12 4:16p 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 +// +// 11 1/05/12 5:05p Artems +// EIP 76735: Font FFS file is not loaded in framework mode, when in +// nested FV +// +// 10 5/13/11 6:14p Artems +// Renamed functions HiiGetString and HiiSetString to AmiHiiGetString and +// AmiHiiSetString +// to avoid collusion with EdkII native library functions +// +// 9 5/13/11 5:17p Artems +// Function CompareGuid (native EdkII) renamed to HiiCompareGuid to avoid +// collusion +// +// 8 5/05/11 4:14p Artems +// Add signal "layout changed" event if current layout is deleted +// +// 7 1/05/11 12:41p Artems +// EIP 50995: Added checking of driver handle before adding packages to +// HII database +// +// 6 11/05/10 5:17p Artems +// EIP 46880: Fixed bug, where two functions referred to the same global +// pointer +// +// 5 9/30/10 6:11p Artems +// EIP 44657 Added GetAltConfig functionality +// +// 4 1/29/10 5:43p Artems +// EIP 34553 Updated function ExportPackageLists to support NULL pointer +// as input +// +// 3 12/04/09 11:16a Artems +// Remove keyboard layout functionality added +// +// 2 12/03/09 6:04p Artems +// SCT bug fix +// +// 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: HiiPrivate.h +// +// Description: +// +//<AMI_FHDR_END> +//********************************************************************** +#ifndef __HII_PRIVATE__H__ +#define __HII_PRIVATE__H__ +#ifdef __cplusplus +extern "C" { +#endif + +#include <AmiDxeLib.h> +#include <Protocol/HiiDatabase.h> +#include <Protocol/HiiString.h> +#include <Protocol/HiiFont.h> +#include <Protocol/HiiConfigRouting.h> + +#define NULL_GUID \ + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } + +#define PACKAGE_LIST_RECORD_SIGNATURE 0x53524c80 //"PLRS" +#define NOTIFY_LIST_RECORD_SIGNATURE 0x53524c4e //"NLRS" + +#define DEFAULT_FONT_HANDLE 0xDEADF000 +#define AMI_HII_PACKAGE_FONTS 0xE1 + +#pragma pack (push,1) + +typedef struct _PACKAGE_LIST_RECORD { + DLINK Link; + UINT32 Signature; + EFI_GUID Guid; + EFI_HANDLE DriverHandle; + DLIST PackageList; + DLIST LanguageList; + DLIST StringFontList; + DBE_DATABASE StringDb; +} PACKAGE_LIST_RECORD; + +typedef struct _NOTIFY_RECORD { + DLINK Link; + UINT32 Signature; + UINT8 PackageType; + EFI_GUID PackageGuid; + EFI_HII_DATABASE_NOTIFY PackageNotifyFn; + EFI_HII_DATABASE_NOTIFY_TYPE NotifyType; +} NOTIFY_RECORD; + +typedef struct _HII_DATABASE_PRIVATE_DATA { + EFI_HII_DATABASE_PROTOCOL DatabaseProtocol; + EFI_HII_STRING_PROTOCOL StringProtocol; + EFI_HII_FONT_PROTOCOL FontProtocol; + EFI_HII_CONFIG_ROUTING_PROTOCOL ConfigRoutingProtocol; + DLIST PackList; + DLIST NotifyList; + DLIST KeyLayoutList; + DLIST FontList; + EFI_HII_KEYBOARD_LAYOUT *CurrentLayout; +} HII_DATABASE_PRIVATE_DATA; + +typedef struct _PACKAGE_LINK { + DLINK Link; + EFI_HII_PACKAGE_HEADER Package; +} PACKAGE_LINK; + +typedef struct _KEY_LAYOUT_LINK { + DLINK Link; + EFI_HII_KEYBOARD_LAYOUT Layout; +} KEY_LAYOUT_LINK; + +typedef struct _SIMPLE_FONT { + EFI_NARROW_GLYPH *NarrowGlyph; + EFI_WIDE_GLYPH *WideGlyph; +} SIMPLE_FONT; + +typedef struct _FONT_LINK { + DLINK Link; + EFI_HII_FONT_PACKAGE_HDR *FontPackage; + UINTN FontHeight; + UINTN FontBaseLine; + DLIST Glyphs; +} FONT_LINK; + +typedef struct _STRING_FONT_LINK { + DLINK Link; + UINT16 FontId; + UINT32 FontInfoSize; +// EFI_FONT_INFO FontInfo; +} STRING_FONT_LINK; + +typedef struct _GLYPH_LINK { + DLINK Link; + CHAR16 Char; + EFI_HII_GLYPH_INFO Cell; + UINT8 *GlyphBlock; +} GLYPH_LINK; + +typedef struct _LANGUAGE_LINK { + DLINK Link; + UINT16 LastStringId; + CHAR8 Language[1]; +} LANGUAGE_LINK; + +typedef struct _STRING_RECORD { + UINT16 StringId; + UINT16 LanguageId; + UINT16 FontId; + CHAR16 String[1]; +} STRING_RECORD; + +typedef struct _DRAW_LINE { + DLINK Link; + UINTN StartIndex; + UINTN EndIndex; + UINTN LineHeight; + UINTN LineWidth; + UINTN BaseLineOffset; +} DRAW_LINE; + +typedef struct _NAME_PATTERN +{ + UINTN Length; + CHAR16 *Tag; +} NAME_PATTERN; + +typedef struct { + CHAR16 *ResultString; + UINTN MaxResultStringSize; + UINTN CurrentSize; +} RESULT_BLOCK; + +#define MATCH_INGNORE 0 +#define MATCH_STRICT 1 +#define MATCH_LOOSE 2 + +typedef struct { + UINT32 MatchName : 1; + UINT32 MatchSize : 2; + UINT32 MatchStyle : 2; + UINT32 Reserved : 1; +} FONT_MATCH_MASK; + +typedef struct { + UINTN x; + UINTN y; +} POINT_COORD; + +typedef struct { + POINT_COORD *st; + POINT_COORD *size; +} RECT_COORD; + +typedef struct { + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT8 Height; + UINT8 Width; +// EFI_NARROW_GLYPH NarrowGlyphs[]; //based on height and width given +} AMICUSTOM_SIMPLE_FONT_PACKAGE_HDR; + +#pragma pack (pop) + +//************ Database Protocol functions definition ************************** + +EFI_STATUS HiiNewPack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList, + IN CONST EFI_HANDLE DriverHandle, + OUT EFI_HII_HANDLE *Handle +); + +EFI_STATUS HiiRemovePack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle +); + +EFI_STATUS HiiUpdatePack ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList +); + +EFI_STATUS HiiListPacks ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle +); + +EFI_STATUS HiiExportPacks ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer +); + +EFI_STATUS HiiRegisterNotify ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType, + OUT EFI_HANDLE *NotifyHandle +); + +EFI_STATUS HiiUnregisterNotify ( + IN CONST EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + +EFI_STATUS HiiFindKeyboardLayouts ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN OUT UINT16 *KeyGuidBufferLength, + OUT EFI_GUID *KeyGuidBuffer +); + +EFI_STATUS HiiGetKeyboardLayout ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_GUID *KeyGuid, + IN OUT UINT16 *KeyGuidBufferLength, + OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout +); + +EFI_STATUS HiiSetKeyboardLayout ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_GUID *KeyGuid +); + +EFI_STATUS HiiGetPackageListHandle ( + IN EFI_HII_DATABASE_PROTOCOL *This, + IN EFI_HII_HANDLE PackageListHandle, + OUT EFI_HANDLE *DriverHandle +); + +//************************* String protocol functions definition ********** + +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 +); + +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 +); + +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 +); + +EFI_STATUS HiiGetLanguages ( + IN CONST EFI_HII_STRING_PROTOCOL *This, + IN EFI_HII_HANDLE PackageList, + IN OUT CHAR8 *Languages, + IN OUT UINTN *LanguagesSize +); + +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 +); + +//************************* Font protocol functions definition **************** + +EFI_STATUS HiiStringToImage( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN CONST EFI_STRING String, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL +); + +EFI_STATUS HiiStringIdToImage ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN EFI_HII_OUT_FLAGS Flags, + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST CHAR8* Language, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo OPTIONAL, + IN OUT EFI_IMAGE_OUTPUT **Blt, + IN UINTN BltX, + IN UINTN BltY, + OUT EFI_HII_ROW_INFO **RowInfoArray OPTIONAL, + OUT UINTN *RowInfoArraySize OPTIONAL, + OUT UINTN *ColumnInfoArray OPTIONAL +); + +EFI_STATUS HiiGetGlyph ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN CHAR16 Char, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfo, + OUT EFI_IMAGE_OUTPUT **Blt, + OUT UINTN *Baseline OPTIONAL +); + +EFI_STATUS HiiGetFontInfo ( + IN CONST EFI_HII_FONT_PROTOCOL *This, + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CONST EFI_FONT_DISPLAY_INFO *StringInfoIn, + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut, + IN CONST EFI_STRING String OPTIONAL +); + +//************************* Config Routing protocol functions definition ****** + +EFI_STATUS HiiExtractConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +); + +EFI_STATUS HiiExportConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + OUT EFI_STRING *Results +); + +EFI_STATUS HiiRouteConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +); + +EFI_STATUS HiiBlockToConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigRequest, + IN CONST UINT8 *Block, + IN CONST UINTN BlockSize, + OUT EFI_STRING *Config, + OUT EFI_STRING *Progress +); + +EFI_STATUS HiiConfigToBlock ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN OUT CONST UINT8 *Block, + IN OUT UINTN *BlockSize, + OUT EFI_STRING *Progress +); + +EFI_STATUS HiiGetAltConfig ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + IN CONST EFI_STRING ConfigResp, + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_STRING AltCfgId, + OUT EFI_STRING *AltCfgResp +); + +//*************************Service functions (not for public use)************** + +VOID InvokeRegisteredNotify ( + IN EFI_HII_PACKAGE_HEADER *Package, + IN EFI_HII_HANDLE Handle, + IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType +); + +BOOLEAN FindAndRemovePackages ( + IN EFI_HII_HANDLE Handle, + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN BOOLEAN FindOnly +); + +VOID RemovePackage ( + IN EFI_HII_HANDLE Handle, + IN PACKAGE_LINK *Package +); + +EFI_STATUS AddPackage( + IN EFI_HII_HANDLE Handle, + IN EFI_HII_PACKAGE_HEADER *Package, + EFI_HII_DATABASE_NOTIFY_TYPE NotifyType +); + +EFI_STATUS AddPackages( + IN EFI_HII_HANDLE Handle, + IN EFI_HII_PACKAGE_LIST_HEADER *PackageList, + BOOLEAN Update +); + +EFI_STATUS UpdateStringPackages( + IN EFI_HII_HANDLE Handle +); + +UINTN GetStringBlockSize( + IN PACKAGE_LIST_RECORD *PackageList, + IN CHAR8 *Language +); + +VOID GetStringBlock( + IN PACKAGE_LIST_RECORD *PackageList, + IN CHAR8 *Language, + IN UINT8 *Buffer +); + +BOOLEAN MatchPackage( + IN UINT8 PackageType, + IN EFI_GUID *PackageGuid, + IN EFI_HII_PACKAGE_HEADER *Package +); + +BOOLEAN CheckIfPresent( + IN EFI_GUID *Guid, + IN EFI_HANDLE DriverHandle +); + +EFI_HII_KEYBOARD_LAYOUT* FindLayoutByGuid( + IN EFI_GUID *Guid +); + +EFI_STATUS ParseKeyLayoutPackage( + IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package +); + +EFI_STATUS DeleteKeyboardLayout( + IN EFI_HII_KEYBOARD_PACKAGE_HDR *Package +); + +EFI_STATUS ParseSimpleFontsPackage( + IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package +); + +EFI_STATUS ParseFontsPackage( + IN EFI_HII_FONT_PACKAGE_HDR *Package +); + +EFI_STATUS ParseStringsPackage( + PACKAGE_LIST_RECORD *PackageList, + IN EFI_HII_STRING_PACKAGE_HDR *Package +); + +PACKAGE_LIST_RECORD* NewPackageListRecord( + VOID +); + +NOTIFY_RECORD* NewNotifyRecord( + VOID +); + +VOID* CreateNewLink( + UINT32 Size +); + +VOID DeleteList( + DLIST *List +); + +VOID DeleteStringsFromDatabase(DBE_DATABASE *Database); +VOID DeleteSimpleFonts(IN EFI_HII_SIMPLE_FONT_PACKAGE_HDR *Package); + +UINT32 StrSize8(CHAR8 *String); + +UINT32 StrSize16(CHAR16 *String); + +VOID StrCpy8(CHAR8 *Dest, CHAR8 *Src); + +VOID StrCpy16(CHAR16 *Dest, CHAR16 *Src); + +INTN StrCmp8(CHAR8 *Dest, CHAR8 *Src); + +INTN StrCmp16(CHAR16 *Dest, CHAR16 *Src); + +EFI_STATUS AddLanguage( + PACKAGE_LIST_RECORD *PackageList, + CHAR8 *Language, + CHAR16* LanguageName, + UINT16 LastStringId +); + +EFI_STATUS GetLanguageId( + PACKAGE_LIST_RECORD *PackageList, + CHAR8 *Language, + UINT16 *LanguageId, + LANGUAGE_LINK **Found +); + +EFI_STATUS AddString( + PACKAGE_LIST_RECORD *PackageList, + UINT16 LanguageId, + UINT16 StringId, + UINT16 FontId, + EFI_STRING String +); + +EFI_STATUS ExtractStrings( + PACKAGE_LIST_RECORD *PackageList, + UINT16 LanguageId, + UINT16 *StringId, + UINT16 FontId, + UINT16 StringCount, + BOOLEAN Compressed, + VOID *StringBlock +); + +BOOLEAN IsLineBreak(CHAR16 Char); + +BOOLEAN IsLineBreakOpp(CHAR16 Char); + +UINTN GetGlyphWidth(CHAR16 Char); + +UINTN GetLineLength(UINTN StartIndex, UINTN EndIndex); + +UINTN GetClipLineLength( + UINTN StartIndex, + UINTN MaxLength, + BOOLEAN ClipClean, + UINTN *EndIndex +); + +UINTN GetWrapIndex( + UINTN StartIndex, + UINTN MaxLength, + UINTN *EndIndex, + UINTN *StartIndex2 +); + +UINTN GetMaxLineLength(VOID); + +EFI_STATUS SplitByLineBreaks(EFI_STRING String); + +EFI_STATUS AdjustLineSize(VOID); + +VOID DrawNarrowGlyph( + UINTN StartX, + UINTN StartY, + UINTN SizeX, + UINTN SizeY, + CHAR16 Char, + BOOLEAN Transparent, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt +); + +VOID DrawWideGlyph( + UINTN StartX, + UINTN StartY, + UINTN SizeX, + UINTN SizeY, + CHAR16 Char, + BOOLEAN Transparent, + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt +); + +VOID Draw(VOID); + +BOOLEAN CheckPattern(CHAR16 *String, NAME_PATTERN *Pattern); + +EFI_STATUS ExtractConfigString(CHAR16 *String, UINTN *NextIndex, CHAR16 **NewString); + +BOOLEAN CheckDevicePath( + IN UINT8 *DevicePath, + IN UINTN DeviceLength, + IN EFI_HII_PACKAGE_HEADER *Package); + +EFI_STATUS SearchDevicePath(UINT8 *DevicePach, UINTN DpLength, EFI_HANDLE *Handle); + +EFI_STATUS ExtractDevicePath(CHAR16 *ConfigString, UINT8 **DevicePath, UINTN *DpLength); + +EFI_STATUS FindDeviceHandle( + IN CHAR16 *ConfigString, + OUT EFI_HANDLE *Handle); + +BOOLEAN IsHexDigit(CHAR16 Char); +UINT8 HexValue(CHAR8 Char); + +VOID StringToBlock( + IN CHAR16 *String, + IN UINTN StringSize, + OUT UINT8 *Block); + +EFI_STATUS CollectResults(CHAR16 *Result, UINTN Symbols, RESULT_BLOCK *ResultBlock); + +UINT32 GetValue(CHAR16 *String, UINTN Start, UINTN End); + +EFI_STATUS GetPatternValue( + CHAR16 *String, + UINTN *Index, + NAME_PATTERN *Pattern, + UINT32 *Value); + +EFI_STATUS GetStringValue( + CHAR16 *String, + UINTN *Index, + UINT8 *Output, + UINT32 Width); + +EFI_STATUS ReallocResultString(UINTN NewSize, RESULT_BLOCK *ResultBlock); + +EFI_STATUS CollectValueResults(UINT8 *Value, UINT32 Width, RESULT_BLOCK *ResultBlock); + +EFI_STATUS InitResultBlock(RESULT_BLOCK *ResultBlock); + +VOID WriteSwappedBuffer( + OUT UINT8 *Output, + IN UINT8 *Input, + IN UINTN Size); + +EFI_STATUS LoadSystemFont(); + +EFI_STATUS ExportPack( + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer, + IN BOOLEAN FirstCall +); + +VOID StringToChar16( + IN CHAR16 *String, + IN OUT UINTN *Size, + OUT CHAR16 *Block +); + +BOOLEAN CompareDevicePath( + IN EFI_STRING ConfigString, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath +); + +BOOLEAN CompareName( + IN EFI_STRING ConfigString, + IN CONST EFI_STRING Name +); + +BOOLEAN HiiCompareGuid( + IN EFI_STRING ConfigString, + IN CONST EFI_GUID *Guid +); + +EFI_STATUS CheckAltCfg ( + IN EFI_STRING ConfigString, + IN CONST EFI_GUID *Guid, + IN CONST EFI_STRING Name, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_STRING AltCfgId +); + +EFI_STATUS SignalKbLayoutChangedEvent( + VOID +); + +EFI_STATUS FillFontInfo( + IN EFI_FONT_HANDLE FontHandle, + OUT EFI_FONT_DISPLAY_INFO **StringInfoOut +); + +EFI_STATUS FindFont( + IN OUT EFI_FONT_HANDLE *FontHandle, + IN CHAR16 *FontName, + IN EFI_HII_FONT_STYLE FontStyle, + IN UINT16 FontSize, + IN FONT_MATCH_MASK Mask, + IN CONST EFI_STRING String +); + +EFI_STATUS IntGetGlyph( + IN EFI_FONT_HANDLE Font, + IN CHAR16 Char, + OUT EFI_HII_GLYPH_INFO *Cell, + OUT UINT8 **GlyphBlock OPTIONAL, + OUT BOOLEAN *Free +); + +VOID UpdateLineSize( + IN OUT DRAW_LINE *Line +); + +VOID ClipLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width, + IN BOOLEAN ClipClean +); + +BOOLEAN CheckVisible( + IN OUT RECT_COORD *Glyph, + IN RECT_COORD *Image +); + +VOID DrawGlyph( + IN UINTN StartX, + IN UINTN StartY, + IN UINTN SizeX, + IN UINTN SizeY, + IN UINT8 *GlyphBlock, + IN BOOLEAN Transparent, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt, + IN UINT16 CharWidth +); + +VOID GetDrawImageSize( + OUT UINTN *Width, + OUT UINTN *Height +); + +EFI_STATUS WrapLine( + IN OUT DRAW_LINE *Line, + IN UINTN Width +); + +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 GetAvailableFontId( + IN PACKAGE_LIST_RECORD *PackageList +); + +EFI_STATUS FindStringFontInfoByTemplate( + IN PACKAGE_LIST_RECORD *PackageList, + IN EFI_FONT_INFO *Template, + OUT UINT16 *FontId +); + +EFI_STATUS FindStingFontInfoById( + IN PACKAGE_LIST_RECORD *PackageList, + IN UINT16 FontId, + OUT EFI_FONT_INFO **Info +); + +VOID CreateLanguageName( + IN CHAR8 *RfcName, + OUT CHAR16* OutName, + UINTN MaxSize +); + +/****** DO NOT WRITE BELOW THIS LINE *******/ +#ifdef __cplusplus +} +#endif +#endif +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//*************************************************************************
\ No newline at end of file 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 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/CORE_DXE/UefiHii/UefiHii.cif b/Core/CORE_DXE/UefiHii/UefiHii.cif new file mode 100644 index 0000000..4e82128 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/UefiHii.cif @@ -0,0 +1,18 @@ +<component> + name = "UefiHii" + category = ModulePart + LocalRoot = "Core\CORE_DXE\UefiHii\" + RefName = "UefiHii" +[files] +"UefiHii.sdl" +"HiiConfig.c" +"HiiDatabase.c" +"HiiFont.c" +"HiiFontEx.c" +"HiiPrivate.h" +"HiiString.c" +"Hii.chm" +"UefiHiiUtils.c" +"HiAccessConfig.c" +"hii21ExportConfig.c" +<endComponent> diff --git a/Core/CORE_DXE/UefiHii/UefiHii.sdl b/Core/CORE_DXE/UefiHii/UefiHii.sdl new file mode 100644 index 0000000..9bdae97 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/UefiHii.sdl @@ -0,0 +1,15 @@ +TOKEN + Name = "UefiHii_SUPPORT" + Value = "1" + Help = "Main switch to enable UefiHii support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "UefiHii_DIR" + Help = "Path to UefiHii Module in Project" +End + diff --git a/Core/CORE_DXE/UefiHii/UefiHiiUtils.c b/Core/CORE_DXE/UefiHii/UefiHiiUtils.c new file mode 100644 index 0000000..d58aed3 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/UefiHiiUtils.c @@ -0,0 +1,750 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, 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/UefiHiiUtils.c 16 5/22/12 4:38p Artems $ +// +// $Revision: 16 $ +// +// $Date: 5/22/12 4:38p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/UefiHiiUtils.c $ +// +// 16 5/22/12 4:38p Artems +// [TAG] EIP N/A +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] In certain cases system font is absent +// [RootCause] When font FFS file is not found system doesn't publish +// system font +// [Solution] If font FFS file is not found, publish font supplied with +// Core +// [Files] UefiHiiUtils.c +// +// 15 4/30/12 3:52p Artems +// [TAG] EIP N/A +// [Category] Improvement +// [Description] Modified GraphicsConsole driver to output whole string +// instead of symbol-by-symbol output +// [Files] Gc.c, AmiDxeLib.h, EfiLib.c, UefiHiiUtils.c +// +// 14 1/05/12 5:05p Artems +// EIP 76735: Font FFS file is not loaded in framework mode, when in +// nested FV +// +// 13 1/05/11 12:12p Artems +// EIP 51298: BufferSize value gets corrupted after call to ConfigToBlock +// function - fixed +// +// 12 10/07/10 12:18p Felixp +// Minor bug fix in LoadSystemFont: don't call FreePool if font section +// has not been read. +// +// 11 10/01/10 4:44p Artems +// Added implementation of function SetBrowserData +// +// 10 3/22/10 3:25p Felixp +// SetCallback bug fix (the bug introduced during previous check in). +// +// 9 3/12/10 2:21p Felixp +// Enhencement: LoadResources is updated to properly publish the packages +// when NumberOfCallbacks is zero. +// +// 7 2/23/10 10:30p Felixp +// SetBrowserData function is added. +// +// 6 2/19/10 4:15p Felixp +// GetString function is updated: if the string is not defined for the +// PlatformLang , try with the default language. +// If still no luck, try English. +// +// 5 2/12/10 5:47p Felixp +// Bug fix in LoadResources and LoadString functions +// (memory corruption in projects with more than one supported language). +// +// 4 11/25/09 11:27a Felixp +// Action parameter of the Callback function is updated based on UEFI +// errata +// +// 3 11/24/09 4:39p Felixp +// +// 2 11/24/09 11:27a Felixp +// GetString udpated: if PlatformLang variable does not exist use default +// language instead of English. +// +// 1 10/09/09 6:12p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: UefiHiiUtils.c +// +// Description: UEFI 2.1 HII Utilities Protocol Implementation +// +//<AMI_FHDR_END> +//********************************************************************** +#include <AmiDxeLib.h> +#include <Protocol/HiiUtilities.h> +#include <Protocol/HiiDatabase.h> +#include <Protocol/HiiString.h> +#include <Protocol/FormBrowser2.h> +#include <Protocol/HiiConfigRouting.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/DevicePath.h> +#include "HiiPrivate.h" + +EFI_STATUS HiiAccessExtractConfig( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results +); +EFI_STATUS HiiAccessRouteConfig( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +); +EFI_STATUS HiiAccessFormCallback( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest +); + +VOID StripValuePattern( + IN OUT EFI_STRING String, + IN UINTN Size +); + +UINT32 StrSize16( + IN CHAR16 *String +); + +static EFI_HII_DATABASE_PROTOCOL *HiiDatabase=NULL; +static EFI_HII_STRING_PROTOCOL *HiiString=NULL; +static EFI_FORM_BROWSER2_PROTOCOL *FormBrowser = NULL; +static EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting = NULL; + +static EFI_GUID HiiResourcesFfsSectionGuid= HII_RESOURCES_FFS_SECTION_GUID; +static EFI_GUID EfiVariableGuid = EFI_GLOBAL_VARIABLE; +static CHAR8 *PlatformLang = NULL; + +extern const char *DefaultLanguageCode; +extern SIMPLE_FONT DefaultFont[]; + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: SetCallback +// +// Description: +// EFI_STATUS SetCallback(EFI_HII_IFR_PACK *pIfr, +// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo, +// CALLBACK_INFO **CallBackFound) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS SetCallback( + EFI_LOADED_IMAGE_PROTOCOL *Image, + EFI_IFR_FORM_SET *FormSet, UINTN NumberOfCallbacks, + CALLBACK_INFO *CallbackInfo, CALLBACK_INFO **CallBackFound, + EFI_HANDLE *CallbackHandle +) +{ + UINTN i; + EFI_STATUS Status; + EFI_HANDLE Handle=NULL; + EFI_DEVICE_PATH_PROTOCOL *pPath, *pPath2; + CALLBACK_INFO *CallbackInfoPtr; + + static EFI_HII_CONFIG_ACCESS_PROTOCOL DefaultConfigAccess = { + HiiAccessExtractConfig, HiiAccessRouteConfig, HiiAccessFormCallback + }; + static CALLBACK_INFO DefaultCallbackInfo = { + NULL,&DefaultConfigAccess, 0, 0, NULL + }; + static VENDOR_DEVICE_PATH FormSetDevicePathNode = { + { + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, + sizeof(VENDOR_DEVICE_PATH) + }, + {0} + }; + + for( i=0 + ; i<NumberOfCallbacks + && ( CallbackInfo[i].pGuid == NULL + || guidcmp(&FormSet->Guid,CallbackInfo[i].pGuid) != 0 + ) + ; i++ + ); + if (i==NumberOfCallbacks){ + CallbackInfoPtr = &DefaultCallbackInfo; + }else{ + CallbackInfoPtr = &CallbackInfo[i]; + if (CallbackInfoPtr->pFormCallback == NULL){ + CallbackInfoPtr->pFormCallback = &DefaultConfigAccess; + }else{ + if (CallbackInfoPtr->pFormCallback->ExtractConfig==NULL) + CallbackInfoPtr->pFormCallback->ExtractConfig = + HiiAccessExtractConfig; + if (CallbackInfoPtr->pFormCallback->RouteConfig==NULL) + CallbackInfoPtr->pFormCallback->RouteConfig = + HiiAccessRouteConfig; + if (CallbackInfoPtr->pFormCallback->Callback==NULL) + CallbackInfoPtr->pFormCallback->Callback = + HiiAccessFormCallback; + } + } + Status=pBS->HandleProtocol(Image->DeviceHandle, &guidDevicePath, &pPath); + if (EFI_ERROR(Status)) pPath=NULL; + pPath = DPAddNode(pPath, Image->FilePath); + FormSetDevicePathNode.Guid = FormSet->Guid; + pPath2 = DPAddNode(pPath, &FormSetDevicePathNode.Header); + pBS->FreePool(pPath); + Status = pBS->InstallMultipleProtocolInterfaces( + &Handle, + &guidDevicePath, pPath2, + &gEfiHiiConfigAccessProtocolGuid, CallbackInfoPtr->pFormCallback, + NULL + ); + if (EFI_ERROR(Status)) return Status; + if (CallbackHandle) *CallbackHandle=Handle; + if (CallBackFound){ + *CallBackFound= (CallbackInfoPtr == &DefaultCallbackInfo) + ? NULL + : CallbackInfoPtr; + } + return EFI_SUCCESS; +} + +static EFI_STATUS PublishPackages( + IN VOID *PackagePointers, IN UINTN NumberOfPackages, + IN EFI_GUID *PackageGuid, IN EFI_HANDLE DriverHandle OPTIONAL, + OUT EFI_HII_HANDLE *HiiHandle +){ + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *PackageList; + UINTN i; + UINT32 PackageLength; + UINT8 *PackagePtr; + EFI_HII_PACKAGE_HEADER **Packages = PackagePointers; + if (NumberOfPackages==0) return EFI_SUCCESS; + if ( !HiiDatabase + && EFI_ERROR(Status=pBS->LocateProtocol( + &gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase + )) + ) return Status; + //calculate the package list length + PackageLength = sizeof(EFI_HII_PACKAGE_LIST_HEADER) + + sizeof(EFI_HII_PACKAGE_HEADER); //package list terminator + for(i=0; i<NumberOfPackages; i++){ + PackageLength += Packages[i]->Length; + } + PackageList = Malloc(PackageLength); + if(PackageList==NULL) return EFI_OUT_OF_RESOURCES; + PackageList->PackageListGuid = *PackageGuid; + PackageList->PackageLength = PackageLength; + + PackagePtr = (UINT8*)(PackageList+1); + for( i=0; i<NumberOfPackages; i++){ + pBS->CopyMem(PackagePtr, Packages[i], Packages[i]->Length); + PackagePtr += Packages[i]->Length; + } + ((EFI_HII_PACKAGE_HEADER *)PackagePtr)->Length = sizeof(EFI_HII_PACKAGE_HEADER); + ((EFI_HII_PACKAGE_HEADER *)PackagePtr)->Type = EFI_HII_PACKAGE_END; + + Status = HiiDatabase->NewPackageList( + HiiDatabase, PackageList, DriverHandle, HiiHandle + ); + pBS->FreePool(PackageList); + return Status; +} + +UINT32 GetNumerOfResourcePackages( + HII_RESOURCE_SECTION_HEADER *pSection, UINTN SectionSize +){ + EFI_HII_PACKAGE_HEADER *PackagePtr; + UINT32 NumberOfPackages = 0; + PackagePtr = (EFI_HII_PACKAGE_HEADER*)(pSection+1); + while(PackagePtr < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){ + PackagePtr = (EFI_HII_PACKAGE_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length); + NumberOfPackages++; + } + return NumberOfPackages; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: LoadStrings +// +// Description: +// EFI_STATUS LoadStrings(EFI_HANDLE ImageHandle, +// EFI_HII_HANDLE *HiiHandle) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS LoadStrings( + EFI_HANDLE ImageHandle, EFI_HII_HANDLE *HiiHandle +) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + HII_RESOURCE_SECTION_HEADER *pSection; + UINTN SectionSize; + EFI_HII_PACKAGE_HEADER *pPack; + EFI_HII_PACKAGE_HEADER **StringPackagPtr; + UINTN NumberOfStringPackages; + if (EFI_ERROR(Status=pBS->HandleProtocol( + ImageHandle, &gEfiLoadedImageProtocolGuid, &Image + )) + ) return Status; +#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1 +{ +#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_ + UINT8 *pData; + pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize); + if (!pData) return EFI_NOT_FOUND; + pSection = Malloc(SectionSize); + pBS->CopyMem(pSection,pData,SectionSize); + Status = EFI_SUCCESS; +} +#else +{ + Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize); + if (EFI_ERROR(Status)) return Status; +} +#endif + //Calculate number of packages. + //Original value of pSection->NumberOfPackages treats string packages + //for multiple languages as a single package. We need the real number of packages. + pSection->NumberOfPackages = GetNumerOfResourcePackages(pSection,SectionSize); + + pPack = (EFI_HII_PACKAGE_HEADER *)(pSection + 1); + + StringPackagPtr = Malloc(pSection->NumberOfPackages*sizeof(EFI_HII_PACKAGE_HEADER*)); + NumberOfStringPackages=0; + while(pPack < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){ + if (pPack->Type != EFI_HII_PACKAGE_STRINGS){ + Status=EFI_INVALID_PARAMETER; + break; + } + StringPackagPtr[NumberOfStringPackages++]=pPack; + pPack = (EFI_HII_PACKAGE_HEADER*)((UINT8*)pPack+pPack->Length); + } + Status = PublishPackages( + StringPackagPtr, NumberOfStringPackages, + &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid, + NULL, HiiHandle + ); + pBS->FreePool(StringPackagPtr); + pBS->FreePool(pSection); + return Status; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: LoadResources +// +// Description: +// EFI_STATUS LoadResources(EFI_HANDLE ImageHandle, +// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo, +// INIT_HII_PACK InitFunction) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS LoadResources( + EFI_HANDLE ImageHandle, UINTN NumberOfCallbacks, + CALLBACK_INFO *CallbackInfo, INIT_HII_PACK InitFunction +) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_LOADED_IMAGE_PROTOCOL *Image; + HII_RESOURCE_SECTION_HEADER *pSection; + UINTN SectionSize; + CALLBACK_INFO *pCallBackFound; + if (EFI_ERROR(Status=pBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, &Image))) return Status; +#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1 +{ +#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_ + UINT8 *pData; + pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize); + if (!pData) return EFI_NOT_FOUND; + pSection = Malloc(SectionSize); + pBS->CopyMem(pSection,pData,SectionSize); +} +#else +{ + Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize); + if (EFI_ERROR(Status)) return Status; +} +#endif +{ + EFI_HII_PACKAGE_HEADER **IfrPackagPtr, **GlobalPackagPtr, **SharedPackagPtr; + UINTN NumberOfIfrPackages, NumberOfGlobalPackages, NumberOfSharedPackages, i; + UINT8 *PackagePtrBuffer; + EFI_HII_PACKAGE_HEADER *PackagePtr; + + //Calculate number of packages. + //Original value of pSection->NumberOfPackages treats string packages + //for multiple languages as a single package. We need the real number of packages. + pSection->NumberOfPackages = GetNumerOfResourcePackages(pSection,SectionSize); + + PackagePtrBuffer = Malloc(3*pSection->NumberOfPackages*sizeof(EFI_HII_PACKAGE_HEADER*)); + IfrPackagPtr = (EFI_HII_PACKAGE_HEADER**)PackagePtrBuffer; + GlobalPackagPtr = IfrPackagPtr+pSection->NumberOfPackages; + SharedPackagPtr = GlobalPackagPtr+pSection->NumberOfPackages; + NumberOfIfrPackages = 0; + NumberOfGlobalPackages = 0; + NumberOfSharedPackages = 0; + + PackagePtr = (EFI_HII_PACKAGE_HEADER*)(pSection+1); + while(PackagePtr < (EFI_HII_PACKAGE_HEADER*)((UINT8*)pSection+SectionSize)){ + switch(PackagePtr->Type){ + case EFI_HII_PACKAGE_FORMS: + IfrPackagPtr[NumberOfIfrPackages++]=PackagePtr; + break; + case EFI_HII_PACKAGE_FONTS: case EFI_HII_PACKAGE_KEYBOARD_LAYOUT: + GlobalPackagPtr[NumberOfGlobalPackages++]=PackagePtr; + break; + default: + SharedPackagPtr[NumberOfSharedPackages++]=PackagePtr; + break; + } + PackagePtr = (EFI_HII_PACKAGE_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length); + } + Status = PublishPackages( + GlobalPackagPtr, NumberOfGlobalPackages, + &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid, + NULL, &HiiHandle + ); + for(i=0; i<NumberOfIfrPackages; i++){ + EFI_HANDLE CallbackHandle; + + SharedPackagPtr[NumberOfSharedPackages]=IfrPackagPtr[i]; + SetCallback( + Image, (EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1), + NumberOfCallbacks,CallbackInfo,&pCallBackFound,&CallbackHandle + ); + Status = PublishPackages( + SharedPackagPtr, NumberOfSharedPackages+1, + &((EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1))->Guid, + CallbackHandle, &HiiHandle + ); + if (pCallBackFound) pCallBackFound->HiiHandle=HiiHandle; + if (InitFunction) InitFunction(HiiHandle,pCallBackFound); + pCallBackFound=NULL; + } + pBS->FreePool(PackagePtrBuffer); + pBS->FreePool(pSection); +} + return EFI_SUCCESS; +} + +//TODO: header +static EFI_STATUS GetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, + IN OUT UINTN *StringSize, OUT EFI_STRING String +){ + EFI_STATUS Status; + + if ( !HiiString + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, &HiiString)) + ) return EFI_NOT_FOUND; + if (PlatformLang==NULL){ + UINTN Size; + if (EFI_ERROR(GetEfiVariable( + L"PlatformLang", &EfiVariableGuid, NULL, &Size, &PlatformLang + ))) PlatformLang = (CHAR8*)DefaultLanguageCode; + } + Status = HiiString->GetString( + HiiString, PlatformLang, HiiHandle,StringId, String, StringSize, NULL + ); + // If the string representation for the PlatformLang is not defined, + // try with the default language. + // If still no luck, try English + if (Status==EFI_INVALID_LANGUAGE){ + Status = HiiString->GetString( + HiiString, (CHAR8*)DefaultLanguageCode, HiiHandle, + StringId, String, StringSize, NULL + ); + if (Status==EFI_INVALID_LANGUAGE) + Status = HiiString->GetString( + HiiString, LANGUAGE_CODE_ENGLISH, HiiHandle, + StringId, String, StringSize, NULL + ); + } + return Status; +} + +//TODO header +static EFI_STATUS SetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, IN EFI_STRING String +){ + CHAR8 *LanguageList = NULL; + UINTN Size = 0; + EFI_STATUS Status; + + if ( !HiiString + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiStringProtocolGuid, NULL, &HiiString)) + ) return EFI_NOT_FOUND; + + Status = HiiString->GetLanguages(HiiString, HiiHandle, LanguageList, &Size); + if (Status!=EFI_BUFFER_TOO_SMALL) return Status; + LanguageList = Malloc(Size); + Status = HiiString->GetLanguages(HiiString, HiiHandle, LanguageList, &Size); + if (!EFI_ERROR(Status)){ + CHAR8 *CurrentLang, *EndOfCurrentLang; + EndOfCurrentLang = LanguageList; + while(EndOfCurrentLang < LanguageList+Size){ + CHAR8 OriginalChar; + CurrentLang = EndOfCurrentLang; + while(*EndOfCurrentLang!=';'&&*EndOfCurrentLang!=0) EndOfCurrentLang++; + OriginalChar = *EndOfCurrentLang; + *EndOfCurrentLang = 0; + Status = HiiString->SetString( + HiiString, HiiHandle, StringId, CurrentLang, String, NULL + ); + if (EFI_ERROR(Status)) break; + *EndOfCurrentLang = OriginalChar; + EndOfCurrentLang++; + } + } + pBS->FreePool(LanguageList); + return Status; +} + +static EFI_STATUS GetBrowserData( + IN UINTN *BufferSize, OUT VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid, OPTIONAL + IN CONST CHAR16 *VarStoreName OPTIONAL +){ + UINTN StringDataSize = 0; + CHAR16 *StringData = NULL; + EFI_STATUS Status; + EFI_STRING Progress; + + if ( !FormBrowser + && EFI_ERROR(pBS->LocateProtocol(&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser)) + ) return EFI_NOT_FOUND; + if ( !HiiConfigRouting + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting)) + ) return EFI_NOT_FOUND; + + Status = FormBrowser->BrowserCallback( + FormBrowser, &StringDataSize, StringData, TRUE, + VarStoreGuid, VarStoreName + ); + if (Status!=EFI_BUFFER_TOO_SMALL) return Status; + StringData = Malloc(StringDataSize); + Status = FormBrowser->BrowserCallback( + FormBrowser, &StringDataSize, StringData, TRUE, + VarStoreGuid, VarStoreName + ); + if (!EFI_ERROR(Status)){ + StringDataSize = *BufferSize; //preserve passed buffer size value, as + //ConfigToBlock may change it as per UEFI 2.1 spec + //it will contain index of last updated byte + Status = HiiConfigRouting->ConfigToBlock( + HiiConfigRouting, StringData, Buffer, BufferSize, &Progress + ); + *BufferSize = StringDataSize; //restore original value + } + pBS->FreePool(StringData); + return Status; +} + +static EFI_STATUS SetBrowserData( + IN UINTN BufferSize, IN VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid, OPTIONAL //TODO: Can it be optional??? + IN CONST CHAR16 *VarStoreName OPTIONAL +) +{ + UINTN StringDataSize = 0; + CHAR16 *StringData = NULL; + EFI_STATUS Status; + EFI_STRING Config; + EFI_STRING Progress; + + if ( !FormBrowser + && EFI_ERROR(pBS->LocateProtocol(&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser)) + ) return EFI_NOT_FOUND; + if ( !HiiConfigRouting + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting)) + ) return EFI_NOT_FOUND; + + Status = FormBrowser->BrowserCallback( + FormBrowser, &StringDataSize, StringData, TRUE, + VarStoreGuid, VarStoreName + ); + if (Status!=EFI_BUFFER_TOO_SMALL) return Status; + StringData = Malloc(StringDataSize); + Status = FormBrowser->BrowserCallback( + FormBrowser, &StringDataSize, StringData, TRUE, + VarStoreGuid, VarStoreName + ); + if (EFI_ERROR(Status)) + return Status; + +//we have StringData in format &OFFSET=XXXX&WIDTH=XXXX&VALUE=XXXX&OFFSET=... +//in order for function BlockToConfig to work we need to modify StringData as follows: +//&OFFSET=XXXX&WIDTH=XXXX&OFFSET=... (i.e. remove all &VALUE=XXX patterns) + + StripValuePattern(StringData, StringDataSize); + + Status = HiiConfigRouting->BlockToConfig( + HiiConfigRouting, StringData, Buffer, BufferSize, + &Config, &Progress + ); + + if(!EFI_ERROR(Status)) { + StringDataSize = StrSize16(Config); + Status = FormBrowser->BrowserCallback( + FormBrowser, &StringDataSize, Config, FALSE, + VarStoreGuid, VarStoreName + ); + pBS->FreePool(Config); + } + + pBS->FreePool(StringData); + return Status; +} + +EFI_STATUS LoadSystemFont(){ +///// Load Font Pack +#define FONT_FFS_FILE_GUID { 0xdac2b117, 0xb5fb, 0x4964, { 0xa3, 0x12, 0xd, 0xcc, 0x77, 0x6, 0x1b, 0x9b } } +static EFI_GUID FontFfsFileGuid = FONT_FFS_FILE_GUID; +extern UINT8 UsStdNarrowGlyphData[]; + EFI_FIRMWARE_VOLUME_PROTOCOL *pFV; + UINTN DataSize; + EFI_GUID *pSectionGuid = NULL; + UINT32 Authentication; + EFI_HANDLE *pHandle; + UINTN Number,i; + EFI_STATUS FontStatus; + EFI_HII_PACKAGE_HEADER *FontPackage; + EFI_HII_HANDLE HiiFontHandle; + + FontPackage = (EFI_HII_PACKAGE_HEADER*)&UsStdNarrowGlyphData; + FontStatus = pBS->LocateHandleBuffer(ByProtocol,&guidFV, NULL, &Number, &pHandle); + for(i=0;i<Number; i++) + { + FontStatus=pBS->HandleProtocol(pHandle[i], &guidFV, &pFV); + if (EFI_ERROR(FontStatus)) continue; + pSectionGuid=NULL; + DataSize=0; + FontStatus=pFV->ReadSection ( + pFV,&FontFfsFileGuid, + EFI_SECTION_FREEFORM_SUBTYPE_GUID,0, &pSectionGuid, &DataSize, + &Authentication + ); + if (!EFI_ERROR(FontStatus)) + { + FontPackage=(EFI_HII_PACKAGE_HEADER*)((UINT32*)(pSectionGuid+1)+1); + break; + } + } + + if (FontPackage->Type!=EFI_HII_PACKAGE_SIMPLE_FONTS){ + //The font package is in the Framework HII format + //Convert the header to the UEFI HII format + DataSize=FontPackage->Length; + FontPackage = (EFI_HII_PACKAGE_HEADER*)((UINT8*)FontPackage+2); + FontPackage->Type=EFI_HII_PACKAGE_SIMPLE_FONTS; + FontPackage->Length=(UINT32)DataSize; + } + FontStatus = PublishPackages(&FontPackage, 1, &FontFfsFileGuid, NULL, &HiiFontHandle); + if (pSectionGuid!=NULL) pBS->FreePool(pSectionGuid); + return FontStatus; +} + +static EFI_STATUS UtilGetGlyphWidth( + IN CHAR16 Char, + OUT UINT16 *Width +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + if(DefaultFont[(UINTN)Char].NarrowGlyph != NULL) { + *Width = ((DefaultFont[(UINTN)Char].NarrowGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDTH; + } else if(DefaultFont[(UINTN)Char].WideGlyph != NULL) { + *Width = ((DefaultFont[(UINTN)Char].WideGlyph)->Attributes & EFI_GLYPH_NON_SPACING) ? 0 : EFI_GLYPH_WIDE_WIDTH; + } else if(DefaultFont[0xfffd].NarrowGlyph != NULL) { + *Width = EFI_GLYPH_WIDTH; + Status = EFI_WARN_UNKNOWN_GLYPH; + } else if(DefaultFont[0xfffd].WideGlyph != NULL) { + *Width = EFI_GLYPH_WIDE_WIDTH; + Status = EFI_WARN_UNKNOWN_GLYPH; + } else { + *Width = 0; + Status = EFI_WARN_UNKNOWN_GLYPH; + } + return Status; +} + +HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol = { + LoadResources, LoadStrings, PublishPackages, + GetBrowserData, SetBrowserData, GetString, SetString, UtilGetGlyphWidth +}; + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_DXE/UefiHii/hii21ExportConfig.c b/Core/CORE_DXE/UefiHii/hii21ExportConfig.c new file mode 100644 index 0000000..91480c0 --- /dev/null +++ b/Core/CORE_DXE/UefiHii/hii21ExportConfig.c @@ -0,0 +1,1143 @@ +//*****************************************************************// +//*****************************************************************// +//*****************************************************************// +//** **// +//** (C)Copyright 2010, American Megatrends, Inc. **// +//** **// +//** All Rights Reserved. **// +//** **// +//** 5555 Oakbrook Pkwy, Building 200,Norcross, Georgia 30093 **// +//** **// +//** Phone (770)-246-8600 **// +//** **// +//*****************************************************************// +//*****************************************************************// +//*****************************************************************// +// $Archive: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/hii21ExportConfig.c $ +// +// $Author: Artems $ +// +// $Revision: 1 $ +// +// $Date: 1/25/11 3:20p $ +// +//*****************************************************************// +//*****************************************************************// +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/UefiHii/hii21ExportConfig.c $ +// +// 1 1/25/11 3:20p Artems +// +// +//*****************************************************************// +//*****************************************************************// + +//<AMI_FHDR_START> +//---------------------------------------------------------------------------- +// +// Name: hii21ExportConfig.c +// +// Description: This file contains code to perform the ExportConfig Operation of Config +// roughting protocol. +// +//---------------------------------------------------------------------------- +//<AMI_FHDR_END> + + +#include "token.h" +#include "efi.h" +//#include "devicepath.h" +#include <AmiDxeLib.h> + +#ifndef EFI_PROTOCOL_DEFINITION +#define TSE_STRINGIZE(a) #a +#define EFI_PROTOCOL_DEFINITION(a) TSE_STRINGIZE(Protocol/a.h) +#endif + +#include EFI_PROTOCOL_DEFINITION(HiiDatabase) +#include EFI_PROTOCOL_DEFINITION(HiiConfigRouting) +#include EFI_PROTOCOL_DEFINITION(devicepath) + +typedef struct _VARSTORE_INFO +{ + EFI_GUID VariableGuid; //Varies EFI_GUID for the NVRAM variable store for this data + VOID* VariableHandle; //Varies HII Handle to the formset that contains this VarStore + UINT16 VariableSize; //Varies The size of Buffer Varstore + struct _VARSTORE_INFO *Next; + char *VariableName; //Varies Variable store name +}VARSTORE_INFO; + + +// Helper Functions +EFI_HII_DATABASE_PROTOCOL *gHiiDatabase; +EFI_BOOT_SERVICES *gBS; +EFI_HII_CONFIG_ROUTING_PROTOCOL * gHiiConfigRouting; + +VARSTORE_INFO *gVarInfoHead = NULL; +VARSTORE_INFO *gpVarInfo; + +EFI_HII_HANDLE *HiiGetHandles(UINT16 *NumberOfHiiHandles); +VOID * _HiiGetForm( EFI_HII_HANDLE Handle, UINTN *Length ); +VOID _HiiGetVariable(EFI_HII_HANDLE Handle, UINT8 * buff); +EFI_STATUS GetVarStoreConfig(VARSTORE_INFO *VarInfo, EFI_STRING *result); +EFI_STATUS GetConfigHeader(VARSTORE_INFO *VarInfo, EFI_STRING *Configuration, UINTN *Length); +EFI_STATUS GetBlockName(EFI_STRING *Configuration, UINTN *Length, UINTN Size); +EFI_STATUS _VerifyResponseString(EFI_STRING Configuration, BOOLEAN NameValue); +EFI_STATUS _ConstructConfigHdr ( + IN OUT CHAR16 *ConfigHdr, + IN OUT UINTN *StrBufferLen, + IN EFI_GUID *Guid, + IN CHAR16 *Name, OPTIONAL + IN EFI_HANDLE *DriverHandle + ); + +EFI_STATUS +BufferToHexString ( + IN OUT CHAR16 *Str, + IN UINT8 *Buffer, + IN UINTN BufferSize + ); +EFI_STATUS +UnicodeToConfigString ( + IN OUT CHAR16 *ConfigString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *UnicodeString + ); +VOID +SwapBuffer ( + IN OUT UINT8 *Buffer, + IN UINTN BufferSize + ); +EFI_STATUS +BufToHexString ( + IN OUT CHAR16 *Str, + IN OUT UINTN *HexStringBufferLength, + IN UINT8 *Buf, + IN UINTN Len + ); +CHAR16 +NibbleToHexChar ( + IN UINT8 Nibble + ); +VOID +ToLower ( + IN OUT CHAR16 *Str + ); +VOID StrCpy8(CHAR8 *dest, CHAR8 *src); +VOID +EfiStrCpy ( + IN CHAR16 *Destination, + IN CHAR16 *Source + ); + +VOID +EfiStrCat ( + IN CHAR16 *Destination, + IN CHAR16 *Source + ); + + +//=== HELPER Functions ====================// +VOID * +EfiLibAllocatePool ( + IN UINTN AllocationSize + ) +{ + return Malloc(AllocationSize); +} + +VOID * +EfiLibAllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return MallocZ(AllocationSize); +} + +UINTN +EfiStrLen ( + IN CHAR16 *String + ); + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemFreePointer +// +// Description: function to free the pointers +// +// Input: VOID **ptr +// +// Output: void +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MemFreePointer( VOID **ptr ) +{ + if ( ( ptr == NULL ) || ( *ptr == NULL ) ) + return; + + gBS->FreePool( *ptr ); + *ptr = NULL; +} + +UINTN StrLen8(CHAR8 *string) +{ + UINTN i=0; + while(string[i]) + i++; + + return i; +} + + +CHAR8 *StrDup8( CHAR8 *string ) +{ + CHAR8 *text; + + text = EfiLibAllocateZeroPool(1 + StrLen8( string )); + if ( text != NULL ) + StrCpy8( text, string ); + + return text; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemCopy +// +// Description: function to copy a memory +// +// Input: VOID *dest, VOID *src, UINTN size +// +// Output: void +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MemCopy( VOID *dest, VOID *src, UINTN size ) +{ + gBS->CopyMem( dest, src, size ); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MemReallocateZeroPool +// +// Description: function to reuse a allocated buffer +// +// Input: VOID *oldBuffer, UINTN oldSize, UINTN newSize +// +// Output: void +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID *MemReallocateZeroPool( VOID *oldBuffer, UINTN oldSize, UINTN newSize ) +{ + VOID *buffer; + + buffer = EfiLibAllocateZeroPool( newSize ); + if ( buffer == NULL ) + return buffer; + + if ( newSize < oldSize ) + oldSize = newSize; + + if ( oldBuffer != NULL ) + MemCopy( buffer, oldBuffer, oldSize ); + + MemFreePointer( (VOID **)&oldBuffer ); + + return buffer; +} + +//<AMI_PHDR_START> +//-------------------------------------------------------------------------- +// +// Name: StrDup8to16 +// +// Description: Duplicates a String from CHAR8 to CHAR16 +// +// Input: CHAR8* string +// +// Output: CHAR16 * +// +// +//-------------------------------------------------------------------------- +//<AMI_PHDR_END> +CHAR16 *StrDup8to16( CHAR8 *string ) +{ + CHAR16 *text; + UINTN i; + + text = EfiLibAllocatePool( (1 + StrLen8( string )) * sizeof(CHAR16)); + if ( text != NULL ) + { + i=0; + while(text[i] = (CHAR16)string[i]) + i++; + } + + return text; +} + + +INTN +EfiStrnCmp ( + IN CHAR16 *String, + IN CHAR16 *String2, + IN UINTN Length + ) +/*++ + +Routine Description: + This function compares the Unicode string String to the Unicode + string String2 for len characters. If the first len characters + of String is identical to the first len characters of String2, + then 0 is returned. If substring of String sorts lexicographically + after String2, the function returns a number greater than 0. If + substring of String sorts lexicographically before String2, the + function returns a number less than 0. + +Arguments: + String - Compare to String2 + String2 - Compare to String + Length - Number of Unicode characters to compare + +Returns: + 0 - The substring of String and String2 is identical. + > 0 - The substring of String sorts lexicographically after String2 + < 0 - The substring of String sorts lexicographically before String2 + +--*/ +{ + while (*String && Length != 0) { + if (*String != *String2) { + break; + } + String += 1; + String2 += 1; + Length -= 1; + } + return Length > 0 ? *String - *String2 : 0; +} + +UINTN +EfiDevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return DPLength(DevicePath); +} + + +VOID InitGlobels(VOID) +{ + gBS=pBS; + gBS->LocateProtocol(&gEfiHiiDatabaseProtocolGuid, NULL, &gHiiDatabase); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: Hii21ExportConfigHelper +// +// Description: Helper function to perform ExportConfig Operation of Config +// roughting protocol. +// +// Parameter: EFI_HII_CONFIG_ROUTING_PROTOCOL *This, IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase, +// OUT EFI_STRING *Results +// +// Return value: Status +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS Hii21ExportConfigHelper ( + IN CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *This, + OUT EFI_STRING *Results +) +{ + EFI_HII_HANDLE *HiiHandleList; + UINT16 NumberOfHiiHandles = 0; + UINTN i; + UINT8 *FormSet; + UINT8 *ifrData; + UINTN Length; + EFI_STRING result=NULL; + UINTN OldSize,NewSize; + + if(Results == NULL) + return EFI_INVALID_PARAMETER; + + *Results = NULL; + InitGlobels(); + gHiiConfigRouting = (EFI_HII_CONFIG_ROUTING_PROTOCOL*)This; + + // To get the All the Valid Hii Handles. + HiiHandleList = HiiGetHandles(&NumberOfHiiHandles); + gpVarInfo = gVarInfoHead = NULL; + + for(i=0;i<NumberOfHiiHandles;i++) + { + Length = 0; + // To get the FormPackage + FormSet = _HiiGetForm( HiiHandleList[i], &Length); + // donot contain valid package. + if(FormSet == NULL) + continue; + ifrData = (UINT8*)(FormSet + sizeof(EFI_HII_PACKAGE_HEADER)); + _HiiGetVariable(HiiHandleList[i], ifrData); + + // Free the FormPackage + MemFreePointer(&FormSet); + } + + + gpVarInfo = gVarInfoHead; + OldSize = NewSize = 0; + while( gpVarInfo != NULL ) + { + VARSTORE_INFO *tmpVarInfo; + EFI_STATUS Status; + + Status = GetVarStoreConfig(gpVarInfo, &result); + if(!EFI_ERROR(Status)) + { + NewSize = OldSize + (EfiStrLen(result)*2)+10; + *Results = MemReallocateZeroPool(*Results, OldSize, NewSize); + if(OldSize) + EfiStrCat(*Results,L"&"); + EfiStrCat(*Results,result); + MemFreePointer(&result); + OldSize = NewSize; + } + + MemFreePointer(&gpVarInfo->VariableName); + tmpVarInfo = gpVarInfo; + gpVarInfo = gpVarInfo->Next; + MemFreePointer(&tmpVarInfo); + } + + // free the Hii Handles + MemFreePointer((VOID**)&HiiHandleList); + return EFI_SUCCESS; +} + + +BOOLEAN IsVarStoreFound(EFI_HII_HANDLE Handle, EFI_IFR_VARSTORE *varstore) +{ + VARSTORE_INFO * VarInfo; +// EFI_GUID SetupGuid = SETUP_GUID; + + VarInfo = gVarInfoHead; + while( VarInfo != NULL ) + { + if( MemCmp( (UINT8*)&VarInfo->VariableGuid,(UINT8*) &(varstore->Guid) , sizeof(EFI_GUID)) == 0) + if(Strcmp(VarInfo->VariableName, (char*)varstore->Name) ==0) + { +// In Aptio, There are many Variables used in multiple Vfr. + +/* +// Setup Variable even if it differ handle the variable info is same. + if( (MemCmp( (UINT8*)&VarInfo->VariableGuid,(UINT8*) &SetupGuid , sizeof(EFI_GUID)) == 0) && + (Strcmp(VarInfo->VariableName, "Setup") == 0) ) + return TRUE; +// For not SETUP_DATA if the Handle is different it can be different Variable + else if(VarInfo->VariableHandle == Handle) +*/ + return TRUE; + + } + VarInfo = VarInfo->Next; + } + return FALSE; +} + +VOID _HiiGetVariable(EFI_HII_HANDLE Handle, UINT8 * buff) +{ + EFI_IFR_OP_HEADER *Header; + UINTN ScopeCount = 0; + EFI_IFR_VARSTORE *varstore; + + //go thru the forms get the variables. + do + { + Header = (EFI_IFR_OP_HEADER*)(buff); + switch(Header->OpCode ) + { + case EFI_IFR_END_OP: + ScopeCount--; + break; + + case EFI_IFR_VARSTORE_OP: + if(!IsVarStoreFound(Handle, (EFI_IFR_VARSTORE *)buff)) + { + if( gVarInfoHead == NULL) + { + gVarInfoHead = EfiLibAllocateZeroPool(sizeof(VARSTORE_INFO)); + gVarInfoHead->Next = NULL; + gpVarInfo = gVarInfoHead; + } + else + { + gpVarInfo->Next = EfiLibAllocateZeroPool(sizeof(VARSTORE_INFO)); + gpVarInfo = gpVarInfo->Next; + gpVarInfo->Next = NULL; + } + + varstore = (EFI_IFR_VARSTORE*)buff; + + MemCopy(&gpVarInfo->VariableGuid, &(varstore->Guid), sizeof(EFI_GUID)); + gpVarInfo->VariableHandle = (VOID*)Handle; + gpVarInfo->VariableSize = varstore->Size; + gpVarInfo->VariableName = StrDup8((char*)varstore->Name); + } + default: + if(Header->Scope) + { + ScopeCount++; + } + break; + + } + buff += Header->Length; + }while(ScopeCount != 0); + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: _HiiGetForm +// +// Description: +// +// Parameter: +// +// Return value: +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID *_HiiGetForm( EFI_HII_HANDLE Handle, UINTN *Length ) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_HII_PACKAGE_HEADER *pkgHdr; + EFI_IFR_OP_HEADER *opHeader = NULL; + VOID *hiiFormPackage=NULL; + UINT8 *formPkBuffer = NULL; + UINT8 *pkgOffset; + UINT8 end = 0; + UINT32 offset = 0; + UINTN len=10; + //SETUP_LINK DummySetupLink; + + if(Length == NULL) + Length = &len; + + hiiFormPackage = EfiLibAllocateZeroPool(*Length); + + status = gHiiDatabase->ExportPackageLists(gHiiDatabase, Handle, Length, hiiFormPackage); + if(status == EFI_BUFFER_TOO_SMALL) + { + MemFreePointer(&hiiFormPackage); + // + // Allocate space for retrieval of IFR data + // + hiiFormPackage = EfiLibAllocateZeroPool(*Length); + + if (hiiFormPackage == NULL) + { + hiiFormPackage = NULL; + goto DONE; + } + // + // Get all the packages associated with this HiiHandle + // + status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, Length, hiiFormPackage); + if(EFI_ERROR(status)) + { + MemFreePointer(&hiiFormPackage); + hiiFormPackage = NULL; + goto DONE; + } + }else if(EFI_ERROR(status)) + { + hiiFormPackage = NULL; + goto DONE; + } + + offset = sizeof(EFI_HII_PACKAGE_LIST_HEADER); + + while(offset < ((EFI_HII_PACKAGE_LIST_HEADER*)hiiFormPackage)->PackageLength) + { + pkgOffset = ((UINT8*)hiiFormPackage) + offset; + pkgHdr = (EFI_HII_PACKAGE_HEADER*)pkgOffset; + switch(pkgHdr->Type) + { + case EFI_HII_PACKAGE_FORMS: + formPkBuffer = (UINT8*)EfiLibAllocateZeroPool(pkgHdr->Length); + if(formPkBuffer == NULL) + { + goto DONE; + } + + MemCopy(formPkBuffer, pkgHdr, pkgHdr->Length); + + opHeader = (EFI_IFR_OP_HEADER*)((UINT8*)formPkBuffer + sizeof(EFI_HII_PACKAGE_HEADER)); + if(opHeader->OpCode != EFI_IFR_FORM_SET_OP) + { + MemFreePointer(&formPkBuffer); + formPkBuffer = NULL; + *Length = 0; + goto DONE; + } + + end = 1; + break; + case EFI_HII_PACKAGE_END: + end = 1; + break; + default: + break; + } + if(end) + { + break; + } + offset += pkgHdr->Length; + } + + MemFreePointer(&hiiFormPackage); + +DONE: + return formPkBuffer; +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Procedure: HiiGetHandles +// +// Description: gets all the HII handles +// +// Parameter: No of handles +// +// Return value: EFI_HII_HANDLE * +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_HII_HANDLE *HiiGetHandles(UINT16 *NumberOfHiiHandles) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_HII_HANDLE *hiiHandleBuffer = NULL; + UINTN handleBufferLength = sizeof(EFI_HII_HANDLE); + + hiiHandleBuffer = EfiLibAllocatePool(handleBufferLength); + + status = gHiiDatabase->ListPackageLists (gHiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, NULL, + &handleBufferLength, hiiHandleBuffer); + if (status == EFI_BUFFER_TOO_SMALL) + { + // + // Free the old pool + // + MemFreePointer ((VOID**)&hiiHandleBuffer); + // + // Allocate new pool with correct value + // + hiiHandleBuffer = EfiLibAllocatePool(handleBufferLength); + + // + // Get the Handles of the packages that were registered with Hii + // + gBS->SetMem(hiiHandleBuffer,handleBufferLength,0); + status = gHiiDatabase->ListPackageLists (gHiiDatabase, EFI_HII_PACKAGE_TYPE_ALL, + NULL, &handleBufferLength, hiiHandleBuffer); + + if (EFI_ERROR (status)) + { + MemFreePointer((VOID**)&hiiHandleBuffer); + hiiHandleBuffer = NULL; + goto DONE; + } + }else if(EFI_ERROR(status)) + { + MemFreePointer((VOID**)&hiiHandleBuffer); + hiiHandleBuffer = NULL; + goto DONE; + } + + *NumberOfHiiHandles = (UINT16)(handleBufferLength / sizeof(EFI_HII_HANDLE)); + +DONE: + return hiiHandleBuffer; +} + + + + +EFI_STATUS GetVarStoreConfig(VARSTORE_INFO *VarInfo, EFI_STRING *result) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_STRING configuration = NULL; + EFI_STRING progress = NULL; + //EFI_STRING result = NULL; + //EFI_STRING stringPtr = NULL; + UINTN length = 1; + //UINT8 *buffer = NULL; + + configuration = EfiLibAllocateZeroPool(length); + if(configuration == NULL) + { + status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + // + // Construct the Configuration Header String + // + status = GetConfigHeader(VarInfo, &configuration, &length); + if(EFI_ERROR(status)) + { + //TSE_DEBUG ( (TSE_DBG_LEVEL, "\nGetConfigHeader FAIL\n" )); + goto DONE; + } + +/* if(VariableInfo->ExtendedAttibutes & VARIABLE_ATTRIBUTE_NAMEVALUE) + { + }else +*/ + { + status = GetBlockName(&configuration, &length, VarInfo->VariableSize); + if(EFI_ERROR(status)) + { + //TSE_DEBUG ( (TSE_DBG_LEVEL, "\n GetBlockname FAIL\n" )); + goto DONE; + } + } + + // Invoke Config Routing Route Config + status = gHiiConfigRouting->ExtractConfig(gHiiConfigRouting, configuration, &progress, result); + + if(EFI_ERROR(status)) + *result = NULL; + + status = _VerifyResponseString(*result, /*(VariableInfo->ExtendedAttibutes & VARIABLE_ATTRIBUTE_NAMEVALUE)? TRUE :*/ FALSE); + +DONE: + if(configuration) + { + MemFreePointer(&configuration); + } + + return status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: _VerifyResponseString +// +// Description: Verifies Correctness of Response String. This is to prevent +// crashing if the result pointer is pointing to an invalid location. +// +// Parameter: EFI_STRING *Configuration +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS _VerifyResponseString(EFI_STRING Configuration, BOOLEAN NameValue) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_STRING config = Configuration; + CHAR16 *keyWord[] = {L"GUID=", L"&NAME=", L"&PATH=", L"&OFFSET=0&WIDTH=", L"&VALUE="}; + UINT32 i = 0; + UINT32 count = NameValue? 3 : 5; // If Name Value Check only upto &Path else check until &Value. + + if(EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0) + { + status = EFI_NOT_FOUND; + goto DONE; + } + + for(i = 1; i < count; i++) + { + for(;EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0 && (config != (Configuration + EfiStrLen(Configuration))); config++) + ; + if(EfiStrnCmp(config, keyWord[i], EfiStrLen(keyWord[i])) != 0) + { + status = EFI_NOT_FOUND; + goto DONE; + } + } + +DONE: + return status; +} + + + +EFI_STATUS GetConfigHeader(VARSTORE_INFO *VarInfo, EFI_STRING *Configuration, UINTN *Length) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_STRING configuration = NULL; + EFI_HANDLE driverHandle; + UINTN length = 0; + CHAR16 *VarName=NULL; + + // + // Retrieve the Device Path from Handle + // + status = gHiiDatabase->GetPackageListHandle(gHiiDatabase, VarInfo->VariableHandle, &driverHandle); + if(EFI_ERROR(status)) + { + goto DONE; + } + + // + // Construct the Configuration Header String + // + VarName = StrDup8to16(VarInfo->VariableName); + status = _ConstructConfigHdr(configuration, &length, &VarInfo->VariableGuid, VarName, driverHandle); + if(EFI_ERROR(status)) + { + if(status == EFI_BUFFER_TOO_SMALL) + { + MemFreePointer(&configuration); + configuration = (UINT16*)EfiLibAllocateZeroPool(length); + if(configuration == NULL) + { + status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + status = _ConstructConfigHdr(configuration, &length, &VarInfo->VariableGuid, VarName, driverHandle); + } + } + + if(EFI_ERROR(status)) + { + goto DONE; + } + + if(*Configuration) + { + MemFreePointer(Configuration); + } + *Configuration = configuration; + *Length = length; + +DONE: + MemFreePointer(&VarName); + return status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: _ConstructConfigHdr +// +// Description: Construct <ConfigHdr> using routing information GUID/NAME/PATH. +// +// Parameter: IN OUT CHAR16 *ConfigHdr, +// IN OUT UINTN *StrBufferLen, +// IN EFI_GUID *Guid, +// IN CHAR16 *Name, OPTIONAL +// IN EFI_HANDLE *DriverHandle +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS _ConstructConfigHdr ( + IN OUT CHAR16 *ConfigHdr, + IN OUT UINTN *StrBufferLen, + IN EFI_GUID *Guid, + IN CHAR16 *Name, OPTIONAL + IN EFI_HANDLE *DriverHandle + ) +{ + EFI_STATUS Status; + UINTN NameStrLen; + UINTN DevicePathSize; + UINTN BufferSize; + CHAR16 *StrPtr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (Name == NULL) + { + // + // There will be no "NAME" in <ConfigHdr> for Name/Value storage + // + NameStrLen = 0; + } else + { + // + // For buffer storage + // + NameStrLen = EfiStrLen (Name); + } + + // + // Retrieve DevicePath Protocol associated with this HiiPackageList + // + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + if (EFI_ERROR (Status)) + { + return Status; + } + + DevicePathSize = EfiDevicePathSize (DevicePath); + + // + // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL> + // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | + // + BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16); + if (*StrBufferLen < BufferSize) + { + *StrBufferLen = BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + *StrBufferLen = BufferSize; + + StrPtr = ConfigHdr; + + EfiStrCpy (StrPtr, L"GUID="); + StrPtr += 5; + BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID)); + StrPtr += 32; + + // + // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044" + // + EfiStrCpy (StrPtr, L"&NAME="); + StrPtr += 6; + if (Name != NULL) + { + BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16); + UnicodeToConfigString (StrPtr, &BufferSize, Name); + StrPtr += (NameStrLen * 4); + } + + EfiStrCpy (StrPtr, L"&PATH="); + StrPtr += 6; + BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize); + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: GetBlockName +// +// Description: +// +// Parameter: EFI_STRING *Configuration, UINTN *Length, UINTN Size +// +// Return value: EFI_STATUS +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetBlockName(EFI_STRING *Configuration, UINTN *Length, UINTN Size) +{ + EFI_STATUS status = EFI_SUCCESS; + UINTN length = 0; + UINTN finalLen = 0; + CHAR16 *tempBuffer = NULL; + + length = (EfiStrLen(L"&OFFSET=0&WIDTH=") + sizeof(Size) + 1) * sizeof(CHAR16); + tempBuffer = (CHAR16*)EfiLibAllocateZeroPool(length); + if(tempBuffer == NULL) + { + status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + Swprintf_s(tempBuffer, length, L"&OFFSET=0&WIDTH=%x", Size); + + length = EfiStrLen(*Configuration) * sizeof(CHAR16); + finalLen = (EfiStrLen(*Configuration) + EfiStrLen(tempBuffer) + 1) * sizeof(CHAR16); + *Configuration = MemReallocateZeroPool(*Configuration, length, finalLen); + if(*Configuration == NULL) + { + status = EFI_OUT_OF_RESOURCES; + goto DONE; + } + + EfiStrCat(*Configuration, tempBuffer); + + MemFreePointer(&tempBuffer); + *Length = finalLen; + +DONE: + return status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: BufferToHexString +// +// Description: Converts binary buffer to Unicode string in reversed byte order from BufToHexString(). +// +// Input: Str - String for output +// Buffer - Binary buffer. +// BufferSize - Size of the buffer in bytes. +// +// Output: EFI_SUCCESS - The function completed successfully. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +BufferToHexString ( + IN OUT CHAR16 *Str, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + EFI_STATUS Status; + UINT8 *NewBuffer; + UINTN StrBufferLen; + + NewBuffer = EfiLibAllocatePool (BufferSize); + MemCopy(NewBuffer, Buffer, BufferSize); + + SwapBuffer (NewBuffer, BufferSize); + + StrBufferLen = BufferSize * 2 + 1; + Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize); + + gBS->FreePool (NewBuffer); + // + // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. + // + ToLower (Str); + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: UnicodeToConfigString +// +// Description: Convert Unicode string to binary representation Config string, e.g. +// "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e. +// "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). +// +// Input: ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+ +// StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string. +// Includes tailing '\0' character. +// On output: +// If return EFI_SUCCESS, containing length of Unicode string buffer. +// If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. +// UnicodeString - Original Unicode string. +// +// Output: EFI_SUCCESS - Routine success. +// EFI_BUFFER_TOO_SMALL - The string buffer is too small. +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +UnicodeToConfigString ( + IN OUT CHAR16 *ConfigString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *UnicodeString + ) +{ + UINTN Index; + UINTN Len; + UINTN BufferSize; + CHAR16 *String; + + Len = EfiStrLen (UnicodeString); + BufferSize = (Len * 4 + 1) * sizeof (CHAR16); + + if (*StrBufferLen < BufferSize) { + *StrBufferLen = BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + *StrBufferLen = BufferSize; + String = ConfigString; + + for (Index = 0; Index < Len; Index++) { + BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2); + + ConfigString += 4; + UnicodeString += 1; + } + + // + // Add tailing '\0' character + // + *ConfigString = L'\0'; + + // + // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. + // + ToLower (String); + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: ToLower +// +// Description: Converts the unicode character of the string from uppercase to lowercase. +// +// Input: Str - String to be converted +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +ToLower ( + IN OUT CHAR16 *Str + ) +{ + CHAR16 *Ptr; + + for (Ptr = Str; *Ptr != L'\0'; Ptr++) { + if (*Ptr >= L'A' && *Ptr <= L'Z') { + *Ptr = (CHAR16) (*Ptr - L'A' + L'a'); + } + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: SwapBuffer +// +// Description: Swap bytes in the buffer. +// +// Input: Buffer - Binary buffer. +// BufferSize - Size of the buffer in bytes. +// +// Output: None +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID +SwapBuffer ( + IN OUT UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + UINTN Index; + UINT8 Temp; + UINTN SwapCount; + + SwapCount = BufferSize / 2; + for (Index = 0; Index < SwapCount; Index++) { + Temp = Buffer[Index]; + Buffer[Index] = Buffer[BufferSize - 1 - Index]; + Buffer[BufferSize - 1 - Index] = Temp; + } +} + |