diff options
Diffstat (limited to 'Core/CORE_DXE/UefiHii/HiiConfig.c')
-rw-r--r-- | Core/CORE_DXE/UefiHii/HiiConfig.c | 1263 |
1 files changed, 1263 insertions, 0 deletions
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 |