alder_lake_bios/Insyde/InsydeModulePkg/Library/SetupUtilityLib/Boot/BootDevInfo.c

558 lines
17 KiB
C

/** @file
Boot device information relative functions
;******************************************************************************
;* Copyright (c) 2017, 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 "BootDevInfo.h"
BOOT_DEV_INFO *mBootDevInfo = NULL;
UINTN mBootDevInfoCount = 0;
/**
Check the specific BBS Table entry is USB device
@param[in] BbsTable Pointer to BBS table start address
@retval TRUE It is USB device
@retval FALSE It isn't USB device
**/
STATIC
BOOLEAN
IsUsbDevice (
IN BBS_TABLE *BbsTable
)
{
if ((BbsTable->Class == PCI_CLASS_SERIAL) &&
(BbsTable->SubClass == PCI_CLASS_SERIAL_USB)) {
return TRUE;
}
return FALSE;
}
/**
Get the information of Boot#### variable
@param[in] BootOptionNum Boot option number
@param[out] Attributes Pointer to the attribute value of Boot#### variable
@param[out] Description Double pointer to the description string of Boot#### variable
@param[out] FilePathList Double pointer to the file path of Boot#### variable
@param[out] OptionalData Double pointer to the optional data of Boot#### variable
@param[out] Attributes Pointer to the optional data size of Boot#### variable
@retval EFI_SUCCESS Get the information of Boot#### variable successfully
@retval Other Get variable return failed
**/
EFI_STATUS
GetBootOptionVarInfo (
IN UINT16 BootOptionNum,
OUT UINT32 *Attributes OPTIONAL,
OUT CHAR16 **Description OPTIONAL,
OUT EFI_DEVICE_PATH_PROTOCOL **FilePathList OPTIONAL,
OUT UINT8 **OptionalData OPTIONAL,
OUT UINTN *OptionalDataSize OPTIONAL
)
{
UINT16 VarName[10];
EFI_STATUS Status;
UINT8 *Variable;
UINTN VariableSize;
UINT8 *Ptr;
UINT32 Attr;
UINT16 DevPathSize;
CHAR16 *Desc;
UINTN DescSize;
EFI_DEVICE_PATH_PROTOCOL *DevPath;
UINT8 *Optional;
UINTN OptionalSize;
UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", BootOptionNum);
Status = CommonGetVariableDataAndSize (VarName, &gEfiGlobalVariableGuid, &VariableSize, (VOID **) &Variable);
if (EFI_ERROR (Status)) {
return Status;
}
Ptr = Variable;
Attr = *(UINT32 *) Ptr;
Ptr += sizeof (UINT32);
DevPathSize = *(UINT16 *) Ptr;
Ptr += sizeof (UINT16);
Desc = (CHAR16 *) Ptr;
DescSize = StrSize (Desc);
Ptr += DescSize;
DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
Ptr += DevPathSize;
Optional = Ptr;
OptionalSize = VariableSize - (UINTN) (Ptr - Variable);
if (Attributes != NULL) {
*Attributes = Attr;
}
if (Description != NULL) {
*Description = AllocateCopyPool (DescSize, Desc);
if (*Description == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
if (FilePathList != NULL) {
*FilePathList = AllocateCopyPool (DevPathSize, DevPath);
if (*FilePathList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
if (OptionalData != NULL && OptionalDataSize != NULL) {
if (OptionalSize == 0) {
*OptionalData = NULL;
} else {
*OptionalData = AllocateCopyPool (OptionalSize, Optional);
if (*OptionalData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
*OptionalDataSize = OptionalSize;
}
FreePool (Variable);
return EFI_SUCCESS;
}
/**
Get the number of device type in boot type order
@param[in] KernelConfig Pointer to kernel configuration
@return The number of device type in boot type order.
**/
UINT16
GetBootTypeOrderCount (
IN KERNEL_CONFIGURATION *KernelConfig
)
{
UINT16 Index;
for (Index = 0;
Index < sizeof (KernelConfig->BootTypeOrder) && KernelConfig->BootTypeOrder[Index] != 0;
Index++) {
}
return Index;
}
/**
Get the device type of input BBS table.
If the device type is not in KERNEL_CONFIGURATION.BootTypeOrder, return other type.
@param[in] KernelConfig Pointer to kernel configuration
@param[in] BbsEntry Pointer to BBS table
@return the device type or other if not found in BootTypeOrder
**/
STATIC
UINT16
GetDevType (
IN KERNEL_CONFIGURATION *KernelConfig,
IN BBS_TABLE *BbsEntry
)
{
UINT16 DevType;
UINT16 Index;
DevType = IsUsbDevice (BbsEntry) ? BBS_USB : BbsEntry->DeviceType;
for (Index = 0; Index < sizeof (KernelConfig->BootTypeOrder); Index++) {
if (KernelConfig->BootTypeOrder[Index] == DevType) {
return DevType;
}
}
return OTHER_DRIVER;
}
/**
Sync mBootDevInfo to the BootOrder of setup utility browser data
@retval EFI_SUCCESS Sync the boot order successfully.
@retval Other Fail to get browser data.
**/
STATIC
EFI_STATUS
BootDevInfoSyncToBootOrder (
VOID
)
{
EFI_STATUS Status;
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
UINT16 *BootOrder;
UINT16 BootDeviceNum;
UINT16 Index;
Status = GetSetupUtilityBrowserData (&SuBrowser);
if (EFI_ERROR (Status)) {
return Status;
}
BootOrder = SuBrowser->SUCInfo->BootOrder;
BootDeviceNum = SuBrowser->SUCInfo->AdvBootDeviceNum;
ASSERT (BootDeviceNum == mBootDevInfoCount);
for (Index = 0; Index < BootDeviceNum; Index++) {
BootOrder[Index] = mBootDevInfo[Index].BootOptionNum;
}
return EFI_SUCCESS;
}
/**
Sort boot device info in the sequence of boot order.
@retval EFI_SUCCESS Sort boot device info successfully.
@retval Other Fail to get browser data.
**/
EFI_STATUS
BootDevInfoSortByBootOrder (
VOID
)
{
EFI_STATUS Status;
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
UINT16 *BootOrder;
UINT16 BootDeviceNum;
UINT16 OrderIndex;
UINT16 Index;
BOOT_DEV_INFO TempBootDevInfo;
Status = GetSetupUtilityBrowserData (&SuBrowser);
if (EFI_ERROR (Status)) {
return Status;
}
BootOrder = SuBrowser->SUCInfo->BootOrder;
BootDeviceNum = SuBrowser->SUCInfo->AdvBootDeviceNum;
ASSERT (BootDeviceNum == mBootDevInfoCount);
for (OrderIndex = 0; OrderIndex < BootDeviceNum; OrderIndex++) {
for (Index = 0; Index < mBootDevInfoCount; Index++) {
if (mBootDevInfo[Index].BootOptionNum == BootOrder[OrderIndex]) {
if (Index != OrderIndex) {
CopyMem (&TempBootDevInfo , &mBootDevInfo[OrderIndex], sizeof (BOOT_DEV_INFO));
CopyMem (&mBootDevInfo[OrderIndex], &mBootDevInfo[Index] , sizeof (BOOT_DEV_INFO));
CopyMem (&mBootDevInfo[Index] , &TempBootDevInfo , sizeof (BOOT_DEV_INFO));
}
break;
}
}
ASSERT (Index < mBootDevInfoCount);
}
return EFI_SUCCESS;
}
/**
Sort boot device info by kernel config settings.
@retval EFI_SUCCESS Sort boot device info successfully.
**/
EFI_STATUS
BootDevInfoSortByKernelConfig (
IN KERNEL_CONFIGURATION *KernelConfig
)
{
BOOLEAN IsEfiFirst;
UINTN CurrentIndex;
UINTN Index;
BOOT_DEV_INFO TempDevInfo;
UINTN LegacyDevStartIndex;
UINTN LegacyDevEndIndex;
UINT16 LegacyDevTypeCount;
if (mBootDevInfo == NULL || mBootDevInfoCount == 0) {
return EFI_SUCCESS;
}
if (KernelConfig->BootMenuType != NORMAL_MENU) {
return EFI_SUCCESS;
}
//
// Move all EFI devices to front or back part in mBootDevInfo based on kernel config setting.
//
IsEfiFirst = (BOOLEAN) (KernelConfig->BootNormalPriority == EFI_FIRST);
for (CurrentIndex = 0; CurrentIndex < mBootDevInfoCount; CurrentIndex++) {
if (mBootDevInfo[CurrentIndex].IsEfiBootDev == IsEfiFirst) {
continue;
}
for (Index = CurrentIndex + 1; Index < mBootDevInfoCount; Index++) {
if (mBootDevInfo[Index].IsEfiBootDev == IsEfiFirst) {
CopyMem (&TempDevInfo , &mBootDevInfo[Index] , sizeof (BOOT_DEV_INFO));
CopyMem (&mBootDevInfo[CurrentIndex + 1], &mBootDevInfo[CurrentIndex], sizeof (BOOT_DEV_INFO) * (Index - CurrentIndex));
CopyMem (&mBootDevInfo[CurrentIndex] , &TempDevInfo , sizeof (BOOT_DEV_INFO));
break;
}
}
if (Index == mBootDevInfoCount) {
break;
}
}
//
// Re-order legacy device order by kernel config setting.
//
if (KernelConfig->LegacyNormalMenuType != LEGACY_NORMAL_MENU) {
goto Done;
}
LegacyDevStartIndex = mBootDevInfoCount;
LegacyDevEndIndex = mBootDevInfoCount;
for (Index = 0; Index < mBootDevInfoCount; Index++) {
if (LegacyDevStartIndex == mBootDevInfoCount) {
if (!mBootDevInfo[Index].IsEfiBootDev) {
LegacyDevStartIndex = Index;
}
} else {
if (mBootDevInfo[Index].IsEfiBootDev) {
LegacyDevEndIndex = Index;
break;
}
}
}
if (LegacyDevStartIndex == mBootDevInfoCount) {
goto Done;
}
LegacyDevTypeCount = GetBootTypeOrderCount (KernelConfig);
for (CurrentIndex = 0; CurrentIndex < LegacyDevTypeCount; CurrentIndex++) {
for (Index = LegacyDevStartIndex; Index < LegacyDevEndIndex; Index++) {
if (mBootDevInfo[Index].DevType != KernelConfig->BootTypeOrder[CurrentIndex]) {
continue;
}
if (Index > LegacyDevStartIndex) {
CopyMem (&TempDevInfo , &mBootDevInfo[Index] , sizeof (BOOT_DEV_INFO));
CopyMem (&mBootDevInfo[LegacyDevStartIndex + 1], &mBootDevInfo[LegacyDevStartIndex], sizeof (BOOT_DEV_INFO) * (Index - LegacyDevStartIndex));
CopyMem (&mBootDevInfo[LegacyDevStartIndex] , &TempDevInfo , sizeof (BOOT_DEV_INFO));
}
LegacyDevStartIndex++;
}
}
Done:
BootDevInfoSyncToBootOrder ();
return EFI_SUCCESS;
}
/**
Initialize boot device info.
@retval EFI_SUCCESS Initialize boot device info successfully.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
@retval Other Fail to get browser data.
**/
EFI_STATUS
BootDevInfoInit (
VOID
)
{
EFI_STATUS Status;
SETUP_UTILITY_BROWSER_DATA *SuBrowser;
KERNEL_CONFIGURATION *KernelConfig;
UINT16 *BootOrder;
UINT16 BootDevNum;
BOOT_DEV_INFO *DevInfo;
BOOT_DEV_INFO *DevInfoList;
UINT16 Index;
UINT32 Attribute;
CHAR16 *Description;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT8 *OptionalData;
UINTN OptionalDataSize;
Status = GetSetupUtilityBrowserData (&SuBrowser);
if (EFI_ERROR (Status)) {
return Status;
}
BootDevInfoShutdown ();
KernelConfig = (KERNEL_CONFIGURATION *) SuBrowser->SCBuffer;
BootOrder = SuBrowser->SUCInfo->BootOrder;
BootDevNum = SuBrowser->SUCInfo->AdvBootDeviceNum;
if (BootDevNum == 0) {
return EFI_SUCCESS;
}
DevInfoList = AllocateZeroPool (BootDevNum * sizeof(BOOT_DEV_INFO));
if (DevInfoList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < BootDevNum; Index++) {
Status = GetBootOptionVarInfo (BootOrder[Index], &Attribute, &Description, &DevicePath, &OptionalData, &OptionalDataSize);
if (EFI_ERROR (Status)) {
return Status;
}
DevInfo = &DevInfoList[Index];
DevInfo->BootOptionNum = BootOrder[Index];
DevInfo->pString = Description;
DevInfo->DevicePath = DevicePath;
DevInfo->IsActive = (BOOLEAN) ((Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE);
DevInfo->IsEfiBootDev = (BOOLEAN) ((DevicePath->Type != BBS_DEVICE_PATH) || (DevicePath->SubType != BBS_BBS_DP));
if (DevInfo->IsEfiBootDev) {
DevInfo->BbsEntry = NULL;
DevInfo->DevType = 0;
if (OptionalData != NULL) {
FreePool (OptionalData);
}
} else {
DevInfo->BbsEntry = (BBS_TABLE *) OptionalData;
DevInfo->DevType = (OptionalData == NULL) ? BBS_UNKNOWN : GetDevType (KernelConfig, (BBS_TABLE *) OptionalData);
}
}
mBootDevInfo = DevInfoList;
mBootDevInfoCount = BootDevNum;
BootDevInfoSortByKernelConfig (KernelConfig);
return EFI_SUCCESS;
}
/**
Shutdown boot device info.
**/
VOID
BootDevInfoShutdown (
VOID
)
{
UINTN Index;
BOOT_DEV_INFO *DevInfo;
if (mBootDevInfo == NULL) {
return;
}
for (Index = 0; Index < mBootDevInfoCount; Index++) {
DevInfo = &mBootDevInfo[Index];
if (DevInfo->pString != NULL) {
FreePool (DevInfo->pString);
}
if (DevInfo->BbsEntry != NULL) {
FreePool (DevInfo->BbsEntry);
}
if (DevInfo->DevicePath != NULL) {
FreePool (DevInfo->DevicePath);
}
}
FreePool (mBootDevInfo);
mBootDevInfoCount = 0;
mBootDevInfo = NULL;
}
/**
Get active value by the specific boot option number.
@param[in] BootOptionNum Boot option number
@return Active value of specific boot option or TRUE if it can not find the corresponding boot device info.
**/
BOOLEAN
BootDevInfoGetActiveValue (
IN UINT16 BootOptionNum
)
{
UINT16 Index;
if (mBootDevInfo == NULL) {
return TRUE;
}
for (Index = 0; Index < mBootDevInfoCount; Index++) {
if (mBootDevInfo[Index].BootOptionNum == BootOptionNum) {
return mBootDevInfo[Index].IsActive;
}
}
return TRUE;
}
/**
Set boot device info to variable storage.
@retval EFI_SUCCESS Set to variable storage successfully.
@retval EFI_NOT_FOUND There is no boot device info.
@retval Other There is one boot device info failed to set to variable storage.
**/
EFI_STATUS
BootDevInfoSetToVariable (
VOID
)
{
EFI_STATUS Status;
EFI_STATUS SetVarStatus;
UINT16 Index;
CHAR16 BootOptionName[20];
UINT8 *BootOption;
UINTN BootOptionSize;
UINT32 *Attribute;
UINT32 OrgAttribute;
if (mBootDevInfo == NULL || mBootDevInfoCount == 0) {
return EFI_NOT_FOUND;
}
SetVarStatus = EFI_SUCCESS;
for (Index = 0; Index < mBootDevInfoCount; Index++) {
UnicodeSPrint (BootOptionName, sizeof(BootOptionName), L"Boot%04x", mBootDevInfo[Index].BootOptionNum);
Status = CommonGetVariableDataAndSize (
BootOptionName,
&gEfiGlobalVariableGuid,
&BootOptionSize,
(VOID **) &BootOption
);
if (Status != EFI_SUCCESS || BootOption == NULL) {
continue;
}
Attribute = (UINT32 *) BootOption;
OrgAttribute = *Attribute;
if (mBootDevInfo[Index].IsActive) {
*Attribute |= ((UINT32) LOAD_OPTION_ACTIVE);
} else {
*Attribute &= (~((UINT32) LOAD_OPTION_ACTIVE));
}
if (OrgAttribute != *Attribute) {
Status = CommonSetVariable (
BootOptionName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
BootOptionSize,
BootOption
);
if (EFI_ERROR (Status)) {
SetVarStatus = Status;
}
}
FreePool (BootOption);
}
return SetVarStatus;
}