alder_lake_bios/Insyde/InsydeModulePkg/Library/SetupUtilityLib/SetupFuncs.c

710 lines
20 KiB
C

/** @file
Setup utility library related functions
;******************************************************************************
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "SetupUtilityLibCommon.h"
STATIC LANGUAGE_DATA_BASE *mSupportedLangTable;
STATIC CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
/**
Get next language from language code list (with separator ';').
If LangCode is NULL, then ASSERT.
If Lang is NULL, then ASSERT.
@param LangCode On input: point to first language in the list.
On output: point to next language in the list, or
NULL if no more language in the list.
@param Lang The first language in the list.
**/
VOID
EFIAPI
SetupUtilityLibGetNextLanguage (
IN OUT CHAR8 **LangCode,
OUT CHAR8 *Lang
)
{
UINTN Index;
CHAR8 *StringPtr;
ASSERT (LangCode != NULL);
ASSERT (*LangCode != NULL);
ASSERT (Lang != NULL);
Index = 0;
StringPtr = *LangCode;
while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
Index++;
}
CopyMem (Lang, StringPtr, Index);
Lang[Index] = 0;
if (StringPtr[Index] == ';') {
Index++;
}
*LangCode = StringPtr + Index;
}
/**
Given a token, return the string.
@param HiiHandle The handle the token is located
@param Token The string reference
@param LanguageString indicate what language string we want to get. if this is a
NULL pointer, using the current language setting to get string
@retval Pointer to the string corresponding to the token or NULL if
it cannot get string from Hii database
**/
CHAR16 *
SetupUtilityLibGetTokenStringByLanguage (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_STRING_ID Token,
IN CHAR8 *LanguageString
)
{
CHAR16 *Buffer;
UINTN BufferLength;
EFI_STATUS Status;
EFI_HII_STRING_PROTOCOL *HiiString;
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
Status = GetSetupUtilityBrowserData (&SuBrowser);
if (EFI_ERROR (Status)) {
return NULL;
}
HiiString = SuBrowser->HiiString;
//
// Set default string size assumption at no more than 256 bytes
//
BufferLength = 0x100;
Buffer = AllocatePool (BufferLength);
if (Buffer == NULL) {
return NULL;
}
ZeroMem (Buffer, BufferLength);
Status = HiiString->GetString (
HiiString,
LanguageString,
HiiHandle,
Token,
Buffer,
&BufferLength,
NULL
);
if (EFI_ERROR (Status)) {
if (Status == EFI_BUFFER_TOO_SMALL) {
//
// Free the old pool
//
FreePool (Buffer);
//
// Allocate new pool with correct value
//
Buffer = AllocatePool (BufferLength);
if (Buffer == NULL) {
return NULL;
}
Status = HiiString->GetString (
HiiString,
LanguageString,
HiiHandle,
Token,
Buffer,
&BufferLength,
NULL
);
if (!EFI_ERROR (Status)) {
//
// return searched string
//
return Buffer;
}
}
//
// Cannot find string, free buffer and return NULL pointer
//
FreePool (Buffer);
Buffer = NULL;
return Buffer;
}
//
// return searched string
//
return Buffer;
}
/**
According the priority of langdef in UNI file to add the supported language code
to supported language database.
@retval EFI_SUCCESS Initialize supported language database successful
@retval Other Get setup utility browser data fail
**/
STATIC
EFI_STATUS
InitializeSupportLanguage (
VOID
)
{
CHAR8 *Language;
CHAR8 Lang[RFC_3066_ENTRY_SIZE];
CHAR8 *SuportedLanguage;
UINTN SupportedLangCnt;
SuportedLanguage = CommonGetVariableData (L"PlatformLangCodes", &gEfiGlobalVariableGuid);
if (SuportedLanguage == NULL) {
return EFI_NOT_FOUND;
}
SupportedLangCnt = 0;
Language = SuportedLanguage;
while (*Language != 0) {
SetupUtilityLibGetNextLanguage (&Language, Lang);
SupportedLangCnt++;
}
mSupportedLangTable = AllocateZeroPool (SupportedLangCnt * RFC_3066_ENTRY_SIZE + sizeof (UINTN));
if (mSupportedLangTable == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FreePool (SuportedLanguage);
SuportedLanguage = CommonGetVariableData (L"PlatformLangCodes", &gEfiGlobalVariableGuid);
if (SuportedLanguage == NULL) {
FreePool (mSupportedLangTable);
mSupportedLangTable = NULL;
return EFI_NOT_FOUND;
}
SupportedLangCnt = 0;
Language = SuportedLanguage;
while (*Language != 0) {
SetupUtilityLibGetNextLanguage (&Language, Lang);
AsciiStrCpyS ((CHAR8 *) &mSupportedLangTable->LangString[SupportedLangCnt * RFC_3066_ENTRY_SIZE], RFC_3066_ENTRY_SIZE, Lang);
SupportedLangCnt++;
}
mSupportedLangTable->LangNum = SupportedLangCnt;
FreePool (SuportedLanguage);
return EFI_SUCCESS;
}
/**
Get supported language database. This funciton will return supported language number
and language string
@param LangNumber Pointer to supported language number
@param LanguageString A double pointer to save the start of supported language string
@retval EFI_SUCCESS Initialize supported language database successful
@retval EFI_INVALID_PARAMETER Input parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Unable allocate memory for language string.
**/
EFI_STATUS
GetLangDatabase (
OUT UINTN *LangNumber,
OUT UINT8 **LanguageString
)
{
UINTN TotalSize;
EFI_STATUS Status;
if (LangNumber == NULL || LanguageString == NULL) {
return EFI_INVALID_PARAMETER;
}
if (mSupportedLangTable == NULL) {
Status = InitializeSupportLanguage ();
if (EFI_ERROR(Status) || mSupportedLangTable == NULL) {
return Status;
}
}
TotalSize = mSupportedLangTable->LangNum * RFC_3066_ENTRY_SIZE;
*LanguageString = AllocateZeroPool (TotalSize);
if (*LanguageString == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (*LanguageString, mSupportedLangTable->LangString, TotalSize);
*LangNumber = mSupportedLangTable->LangNum;
return EFI_SUCCESS;
}
/**
Get SETUP_UTILITY_BROWSER_DATA instance from gEfiSetupUtilityBrowserProtocolGuid
@param SuBrowser Double pointer point to SETUP_UTILITY_BROWSER_DATA instance
@retval EFI_SUCCESS Get SETUP_UTILITY_BROWSER_DATA instance successful
@retval Other Cannot locate gEfiSetupUtilityBrowserProtocolGuid
**/
EFI_STATUS
GetSetupUtilityBrowserData (
OUT SETUP_UTILITY_BROWSER_DATA **SuBrowser
)
{
EFI_STATUS Status;
EFI_SETUP_UTILITY_BROWSER_PROTOCOL *Interface;
Status = gBS->LocateProtocol (
&gEfiSetupUtilityBrowserProtocolGuid,
NULL,
(VOID **) &Interface
);
if (EFI_ERROR (Status)) {
return Status;
}
*SuBrowser = EFI_SETUP_UTILITY_BROWSER_FROM_THIS (Interface);
return Status;;
}
/**
According platform setting to configure setup variable
@param VariableGuid An optional field to indicate the target variable GUID name to use.
@param VariableName An optional field to indicate the target human-readable variable name.
@param BufferSize On input: Length in bytes of buffer to hold retrived data.
On output:
If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired.
@param Buffer Buffer to hold retrived data.
@param RetrieveData TRUE : Get setup variable from broswer
FALSE: Set current setuputility setting to browser
@retval EFI_SUCCESS Setup variable configuration successful
@retval EFI_ABORTED Setup variable configuration failed
**/
EFI_STATUS
SetupVariableConfig (
IN EFI_GUID *VariableGuid, OPTIONAL
IN CHAR16 *VariableName, OPTIONAL
IN UINTN BufferSize,
IN UINT8 *Buffer,
IN BOOLEAN RetrieveData
)
{
BOOLEAN Success;
if (RetrieveData) {
Success = HiiGetBrowserData (VariableGuid, VariableName, BufferSize, Buffer);
} else {
Success = HiiSetBrowserData (VariableGuid, VariableName, BufferSize, Buffer, NULL);
}
if (!Success) {
DEBUG ((EFI_D_ERROR, "SetupVariableConfig %s variable (%g, %s) fail\n", RetrieveData ? L"Get" : L"Set", VariableGuid, VariableName));
}
return Success ? EFI_SUCCESS : EFI_ABORTED;
}
/**
Convert ASCII string to Unicode string in fixed length.
@param AsciiString Input ASCII string
@param UnicodeString Output Unicode string
@param Length The string length of ASCII
@retval EFI_SUCCESS Convert ASCII to Unicode string successfully
**/
EFI_STATUS
SetupUtilityLibAsciiToUnicode (
IN CHAR8 *AsciiString,
IN CHAR16 *UnicodeString,
IN UINTN Length
)
{
UINT8 Index;
for (Index = 0; Index < Length; Index++) {
UnicodeString[Index] = (CHAR16) AsciiString[Index];
}
return EFI_SUCCESS;
}
/**
Function to update the ATA strings into Model Name -- Size
@param IdentifyDriveInfo Data of ATA or ATAPI device
@param BufSize Output buffer size
@param BootString Buffer to contain output string
@retval EFI_SUCCESS Update ATA string successfully
**/
EFI_STATUS
SetupUtilityLibUpdateAtaString(
IN EFI_IDENTIFY_DATA *IdentifyDriveInfo,
IN UINTN BufSize,
IN OUT CHAR16 **BootString
)
{
CHAR8 *TempString;
UINT16 Index;
CHAR8 Temp8;
TempString = AllocateZeroPool (0x100);
if (TempString == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
TempString,
IdentifyDriveInfo->AtapiData.ModelName,
sizeof(IdentifyDriveInfo->AtapiData.ModelName)
);
//
// Swap the IDE string since Identify Drive format is inverted
//
Index = 0;
while (TempString[Index] != 0 && TempString[Index+1] != 0) {
Temp8 = TempString[Index];
TempString[Index] = TempString[Index+1];
TempString[Index+1] = Temp8;
Index +=2;
}
SetupUtilityLibAsciiToUnicode (TempString, *BootString, (UINTN) Index);
FreePool(TempString);
return EFI_SUCCESS;
}
/**
Check if language code is support in system or not.
@param[in] LangCode Pointer to the language code
@retval TRUE Language code is support in system.
@retval FALSE Language code is not support in system.
**/
BOOLEAN
SetupUtilityLibIsLangCodeSupport (
IN CHAR8 *LangCode
)
{
CHAR8 *SuuportedLanguage;
CHAR8 *LangStrings;
BOOLEAN Support;
CHAR8 Lang[RFC_3066_ENTRY_SIZE];
if (LangCode == NULL) {
return FALSE;
}
SuuportedLanguage = CommonGetVariableData (L"PlatformLangCodes", &gEfiGlobalVariableGuid);
if (SuuportedLanguage == NULL) {
return FALSE;
}
Support = FALSE;
LangStrings = SuuportedLanguage;
while (*LangStrings != 0) {
SetupUtilityLibGetNextLanguage (&LangStrings, Lang);
if (AsciiStrCmp (Lang, LangCode) == 0) {
Support = TRUE;
break;
}
}
FreePool (SuuportedLanguage);
return Support;
}
/**
Get variable store size in bytes from HII package
@param[in] Package HII package data
@param[in] FormsetGuid Formset GUID
@param[in] VarStoreGuid Variable store GUID
@param[in] VarStoreName Variable store name
@param[out] VarStoreSize Variable store size
@retval EFI_SUCCESS Get size successfully
@retval EFI_INVALID_PARAMETER Package or FormsetGuid is NULL or it is not form package
@retval EFI_NOT_FOUND Form package or variable store is not found
**/
STATIC
EFI_STATUS
GetVarStoreSizeFromPackage (
IN UINT8 *Package,
IN EFI_GUID *FormsetGuid,
IN EFI_GUID *VarStoreGuid,
IN CHAR8 *VarStoreName,
OUT UINT16 *VarStoreSize
)
{
EFI_HII_PACKAGE_HEADER *PackageHeader;
UINT32 Offset;
EFI_IFR_OP_HEADER *OpCodeHdr;
BOOLEAN IsCurrentFormset;
EFI_IFR_VARSTORE *VarStore;
if (Package == NULL || FormsetGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
if (PackageHeader->Type != EFI_HII_PACKAGE_FORMS) {
return EFI_INVALID_PARAMETER;
}
IsCurrentFormset = FALSE;
Offset = sizeof (EFI_HII_PACKAGE_HEADER);
while (Offset < PackageHeader->Length) {
OpCodeHdr = (EFI_IFR_OP_HEADER *) (Package + Offset);
if (OpCodeHdr->OpCode == EFI_IFR_FORM_SET_OP) {
if (CompareGuid ((EFI_GUID *) (VOID *) (&((EFI_IFR_FORM_SET *) OpCodeHdr)->Guid), FormsetGuid)) {
IsCurrentFormset = TRUE;
} else {
IsCurrentFormset = FALSE;
}
}
if (IsCurrentFormset && OpCodeHdr->OpCode == EFI_IFR_VARSTORE_OP) {
VarStore = (EFI_IFR_VARSTORE *) OpCodeHdr;
if (CompareGuid ((EFI_GUID *) (VOID *) (&VarStore->Guid), VarStoreGuid) &&
AsciiStrCmp ((CHAR8 *) VarStore->Name, VarStoreName) == 0) {
*VarStoreSize = VarStore->Size;
return EFI_SUCCESS;
}
}
Offset += OpCodeHdr->Length;
}
return EFI_NOT_FOUND;
}
/**
Get variable store size in bytes
@param[in] HiiHandle An EFI_HII_HANDLE that corresponds to the desired package list in the HII database
@param[in] FormsetGuid Formset GUID
@param[in] VarStoreGuid Variable store GUID
@param[in] VarStoreName Variable store name
@return The size of variable store in bytes
**/
UINT16
GetVarStoreSize (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_GUID *FormsetGuid,
IN EFI_GUID *VarStoreGuid,
IN CHAR8 *VarStoreName
)
{
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
UINTN HiiPackageListSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
EFI_HII_PACKAGE_HEADER *PackageHeader;
UINT32 Offset;
UINT32 PackageListLength;
UINT16 VarStoreSize;
VarStoreSize = 0;
if (HiiHandle == NULL || FormsetGuid == NULL || VarStoreGuid == NULL || VarStoreName == NULL) {
return VarStoreSize;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return VarStoreSize;
}
//
// Get HII package list
//
HiiPackageList = NULL;
HiiPackageListSize = 0;
Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &HiiPackageListSize, HiiPackageList);
if (Status != EFI_BUFFER_TOO_SMALL) {
return VarStoreSize;
}
HiiPackageList = AllocateZeroPool (HiiPackageListSize);
if (HiiPackageList == NULL) {
return VarStoreSize;
}
Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &HiiPackageListSize, HiiPackageList);
if (EFI_ERROR (Status)) {
FreePool (HiiPackageList);
return VarStoreSize;
}
//
// In HII package list, find the variable store size which match the formset GUID, variable store GUID and name.
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
while (Offset < PackageListLength) {
Package = (UINT8 *) HiiPackageList + Offset;
PackageHeader = (EFI_HII_PACKAGE_HEADER *) Package;
if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {
Status = GetVarStoreSizeFromPackage (Package, FormsetGuid, VarStoreGuid, VarStoreName, &VarStoreSize);
if (!EFI_ERROR (Status)) {
break;
}
}
Offset += PackageHeader->Length;
}
FreePool (HiiPackageList);
return VarStoreSize;
}
/**
Send goto hot key event.
@param[in] FormId Target form ID
@param[in] QuestionId Target question ID
@retval EFI_SUCCESS Send goto hot key event successfully.
@retval Other Locate form browser protocol failed or notify event failed.
**/
EFI_STATUS
SendGotoHotKeyNotify (
IN UINT16 FormId,
IN UINT16 QuestionId
)
{
EFI_STATUS Status;
H2O_FORM_BROWSER_PROTOCOL *FBProtocol;
H2O_DISPLAY_ENGINE_EVT_HOT_KEY HotKeyNotify;
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &FBProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
ZeroMem (&HotKeyNotify, sizeof (HotKeyNotify));
HotKeyNotify.Hdr.Size = sizeof (H2O_DISPLAY_ENGINE_EVT_HOT_KEY);
HotKeyNotify.Hdr.Type = H2O_DISPLAY_ENGINE_EVT_TYPE_HOT_KEY;
HotKeyNotify.Hdr.Target = H2O_DISPLAY_ENGINE_EVT_TARGET_FORM_BROWSER;
HotKeyNotify.HotKeyAction = HotKeyGoTo;
HotKeyNotify.HotKeyTargetFormId = FormId;
HotKeyNotify.HotKeyTargetQuestionId = QuestionId;
return FBProtocol->Notify (FBProtocol, &HotKeyNotify.Hdr);
}
/**
Send shut down notify to close the freeze confirm dialog
@retval EFI_SUCCESS shut down the freeze confirm dialog successfully
**/
EFI_STATUS
SendShutDNotifyForInternal (
VOID
)
{
EFI_STATUS Status;
H2O_FORM_BROWSER_PROTOCOL *FBProtocol;
H2O_DISPLAY_ENGINE_EVT_SHUT_D ShutDNotify;
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &FBProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
ZeroMem (&ShutDNotify, sizeof (ShutDNotify));
ShutDNotify.Hdr.Size = sizeof (H2O_DISPLAY_ENGINE_EVT_SHUT_D);
ShutDNotify.Hdr.Target = H2O_DISPLAY_ENGINE_EVT_TARGET_BROADCAST;
ShutDNotify.Hdr.Type = H2O_DISPLAY_ENGINE_EVT_TYPE_SHUT_D;
return FBProtocol->Notify (FBProtocol, &ShutDNotify.Hdr);
}
/**
Load the default value of all varstores belong to setup utility library.
@retval EFI_SUCCESS Load the default value successfully
**/
EFI_STATUS
SetupUtilityLibLoadDefault (
VOID
)
{
BootLoadDefault ();
SecurityLoadDefault ();
return EFI_SUCCESS;
}
/**
Save the current settings of all varstores belong to setup utility library.
@retval EFI_SUCCESS Save the current settings successfully
@retval Other Save the current settings failed.
**/
EFI_STATUS
SetupUtilityLibRouteConfig (
VOID
)
{
EFI_STATUS Status;
//
// If Setup variable is changed, Win 8 fast boot should not be active at next boot.
//
gRT->SetVariable (
L"TargetHddDevPath",
&gEfiGenericVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
Status = SecuritySaveSetting ();
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "SecuritySaveSetting failed!\n"));
}
Status = BootSaveSetting ();
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "BootSaveSetting failed!\n"));
}
return Status;
}