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