alder_lake_bios/Oem/L05/FeatureCommon/InsydeL05ModulePkg/BootOptionService/BootOptionService.c

1713 lines
50 KiB
C

//;******************************************************************************
//;* Copyright (c) 1983-2015, Insyde Software Corporation. 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 "BootOptionService.h"
static UINT16 *mDefaultBootOrder = NULL;
static UINTN mDefaultBootOrderNumber = 0;
static UINTN mBootTypeOrderLength = 0;
static UINT16 *mBootTypeOrder = NULL;
UINT16 mL05DefaultLegacyBootTypeOrder[] = {
L05_BOOT_TYPE_BBS_FIRST_SATA_HDD,
L05_BOOT_TYPE_BBS_SECOND_SATA_HDD,
BBS_HARDDISK,
BBS_USB,
L05_BOOT_TYPE_BBS_USB_MEMORY,
BBS_EMBED_NETWORK,
BBS_FLOPPY,
BBS_CDROM,
BBS_BEV_DEVICE,
L05_BOOT_TYPE_BBS_USB_FLOPPY,
L05_BOOT_TYPE_BBS_USB_CDROM,
L05_BOOT_TYPE_BBS_USB_HDD
};
UINT16 mL05DefaultEfiBootTypeOrder[] = {
L05_BOOT_TYPE_EFI_PORTABLE_DEVICE,
L05_BOOT_TYPE_EFI_FIRST_SATA_HDD,
L05_BOOT_TYPE_EFI_SECOND_SATA_HDD,
L05_BOOT_TYPE_EFI_HARDDISK,
L05_BOOT_TYPE_EFI_FLOPPY,
L05_BOOT_TYPE_EFI_CDROM,
L05_BOOT_TYPE_EFI_USB_MEMORY,
L05_BOOT_TYPE_EFI_NETWORK,
L05_BOOT_TYPE_EFI_NETWORK_WIFI,
L05_BOOT_TYPE_EFI_LENOVO_CLOUD,
L05_BOOT_TYPE_EFI_LENOVO_CLOUD_WIFI,
L05_BOOT_TYPE_EFI_USB_FLOPPY,
L05_BOOT_TYPE_EFI_USB_CDROM,
L05_BOOT_TYPE_EFI_USB_HDD
};
/**
Converts ASCII characters to Unicode.
@param UnicodeStr The Unicode string to be written to. The buffer must be large enough.
@param AsciiStr The ASCII string to be converted.
**/
CHAR16 *
L05Ascii2Unicode (
OUT CHAR16 *UnicodeStr,
IN CHAR8 *AsciiStr
)
{
CHAR16 *Str;
Str = UnicodeStr;
while (TRUE) {
*(UnicodeStr++) = (CHAR16) *AsciiStr;
if (*(AsciiStr++) == '\0') {
return Str;
}
}
}
EFI_STATUS
L05CheckLegacyDeviceType (
IN BBS_TABLE *BbsItem,
IN OUT UINT16 *DeviceType,
IN CHAR16 *DeviceName,
IN UINTN Index
)
{
EFI_STATUS Status;
EFI_HANDLE *DpHandles;
EFI_BLOCK_IO_PROTOCOL *BlkIo;
USB_MASS_DEVICE *UsbPtr;
UINTN NumberDpHandles;
UINT32 UsbMassSignature;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
USB_MASS_DEVICE *UsbMass;
UINTN DeviceNameLength;
UINT8 *UsbDeviceName;
CHAR16 TempName[100];
UINTN DpHandleIndex;
ZeroMem (TempName, sizeof (CHAR16) * 100);
UsbDeviceName = NULL;
UsbMass = NULL;
DevicePath = NULL;
BlkIo = NULL;
UsbPtr = 0;
NumberDpHandles = 0;
DeviceNameLength = 0;
switch (*DeviceType) {
case BBS_HARDDISK:
//
// Check the device whether it is Hdd or USB Hdd
//
if (L05IsUsbDevice (BbsItem)) {
//
// Check the Usb device whether it is usb memoery or not
//
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &NumberDpHandles, &DpHandles);
for (DpHandleIndex = 0; DpHandleIndex < NumberDpHandles; DpHandleIndex++) {
Status = gBS->HandleProtocol (DpHandles[DpHandleIndex], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath);
if (EFI_ERROR (Status)) {
break;
}
//
// Use blockIO to check usb memory device
//
if (!EFI_ERROR (Status)) {
Status = gBS->HandleProtocol (DpHandles[DpHandleIndex], &gEfiBlockIoProtocolGuid, (VOID **) &BlkIo);
if (!EFI_ERROR (Status)) {
UsbMassSignature = *((UINT32 *) ((UINT8 *) BlkIo - (UINT8 *) &(UsbPtr->BlockIo)));
if (BlkIo->Media->RemovableMedia == TRUE && UsbMassSignature == USB_MASS_SIGNATURE) {
*DeviceType = L05_BOOT_TYPE_BBS_USB_MEMORY;
} else {
*DeviceType = L05_BOOT_TYPE_BBS_USB_HDD;
}
//
// Compare DeviceName(current) and UsbDeviceName(from blockIO)
// if current device name and usbdevice name are the same,
// exit the loop
//
UsbMass = USB_MASS_DEVICE_FROM_BLOCKIO (BlkIo);
DeviceNameLength = sizeof (UsbMass->InquiryData.VendorID) + sizeof (UsbMass->InquiryData.ProductID);
UsbDeviceName = AllocateZeroPool (DeviceNameLength);
AsciiStrnCpyS (UsbDeviceName, DeviceNameLength, (UINT8 *) UsbMass->InquiryData.VendorID, sizeof (UsbMass->InquiryData.VendorID));
AsciiStrnCatS (UsbDeviceName, DeviceNameLength, (UINT8 *) UsbMass->InquiryData.ProductID, sizeof (UsbMass->InquiryData.ProductID));
L05Ascii2Unicode (TempName, UsbDeviceName);
if (StrCmp (TempName, DeviceName) == 0) {
break;
}
}
}
}
} else {
*DeviceType = L05DistinguishSataHddType (BbsItem, Index);
}
break;
case BBS_CDROM:
if (L05IsUsbDevice (BbsItem)) {
*DeviceType = L05_BOOT_TYPE_BBS_USB_CDROM;
} else {
*DeviceType = BBS_CDROM;
}
break;
case BBS_FLOPPY:
if (L05IsUsbDevice (BbsItem)) {
*DeviceType = L05_BOOT_TYPE_BBS_USB_FLOPPY;
} else {
*DeviceType = BBS_FLOPPY;
}
break;
case BBS_BEV_DEVICE:
*DeviceType = BBS_BEV_DEVICE;
break;
default:
break;
}
return EFI_SUCCESS;
}
BOOLEAN
L05IsUsbMemoryDevice (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr
)
{
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
EFI_DEVICE_PATH_PROTOCOL *UsbDevicePath;
EFI_STATUS Status;
EFI_BLOCK_IO_PROTOCOL *BlkIo;
EFI_HANDLE Handle;
BOOLEAN IsUsbMemory;
TempDevicePath = NULL;
UsbDevicePath = NULL;
BlkIo = NULL;
IsUsbMemory = FALSE;
TempDevicePath = DevicePathPtr;
UsbDevicePath = DevicePathPtr;
//
// 1. Check the device whether it is usb device or not
// 2. Use BlockIO to check Usb memory device
// 3. if the device is usb memory, exit the loop
//
while (!IsDevicePathEndType (TempDevicePath) && IsUsbMemory == FALSE) {
switch (DevicePathType (TempDevicePath)) {
case MESSAGING_DEVICE_PATH:
switch (DevicePathSubType (TempDevicePath)) {
case MSG_USB_DP:
Status = gBS->LocateDevicePath (
&gEfiDevicePathProtocolGuid,
&UsbDevicePath,
&Handle
);
if (!EFI_ERROR (Status)) {
Status = gBS->HandleProtocol (
Handle,
&gEfiBlockIoProtocolGuid,
&BlkIo
);
if (!EFI_ERROR (Status)) {
if (BlkIo->Media->RemovableMedia == TRUE) {
IsUsbMemory = TRUE;
break;
}
}
}
break;
default:
break;
}
break;
default:
break;
}
TempDevicePath = NextDevicePathNode (TempDevicePath);
}
if (IsUsbMemory) {
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
L05IsEfiDeviceType (
IN UINT16 DeviceType
)
{
if (DeviceType == L05_UNKNOWN_DEVICE_TYPE) {
return FALSE;
} else if ((DeviceType & L05_EFI_TYPE_MASK) == L05_EFI_TYPE_MASK) {
return TRUE;
}
return FALSE;
}
INT8
L05IsPriorDeviceType (
IN UINT8 BootNormalPriority,
IN UINT16 DeviceType1,
IN UINT16 DeviceType2
)
{
UINTN Priority1;
UINTN Priority2;
UINTN Index;
Priority1 = L05_BOOT_ORDER_NOT_FOUND;
Priority2 = L05_BOOT_ORDER_NOT_FOUND;
Index = 0;
if (L05IsEfiDeviceType (DeviceType1) && !L05IsEfiDeviceType (DeviceType2)) {
if (BootNormalPriority == 0) { // UEFI First
return 1;
} else {
return -1;
}
} else if (!L05IsEfiDeviceType (DeviceType1) && L05IsEfiDeviceType (DeviceType2)) {
if (BootNormalPriority == 0) { // UEFI First
return -1;
} else {
return 1;
}
}
for (Index = 0; Index < mBootTypeOrderLength; Index++) {
if (mBootTypeOrder[Index] == DeviceType1) {
Priority1 = Index;
}
if (mBootTypeOrder[Index] == DeviceType2) {
Priority2 = Index;
}
}
if (Priority1 < Priority2) { // less index means high priority
return 1;
} else if (Priority1 > Priority2) {
return -1;
}
return 0;
}
/*++
Find the Boot type of specfic Device Path
@param[in] DevicePathPtr A pointer to the bevice path.
@param[Out] BootType A pointer to the boot type.
@retval EFI_SUCCESS The function completed successfully.
@retval !EFI_SUCCESS Function error.
--*/
EFI_STATUS
L05DevicePathToBootType (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr,
OUT UINT16 *BootType
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_DEVICE_PATH_PROTOCOL *DevicePathTemp;
UINTN SataPort;
BOOLEAN IsUsbDevice;
BOOLEAN Found;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN UsbMassDevicesCount;
UINTN Index;
UINTN Index2;
EFI_USB_CORE_PROTOCOL *UsbCore;
USB_MASS_STORAGE_DEVICE **UsbMassDevices;
EFI_USB_IO_PROTOCOL *UsbIoInstance;
EFI_FILE_PROTOCOL *FileSystem;
DevicePathNode = NULL;
DevicePath = NULL;
DevicePathTemp = NULL;
FileSystem = NULL;
SataPort = 0;
IsUsbDevice = FALSE;
Found = FALSE;
*BootType = L05_BOOT_TYPE_EFI_UNKNOWN;
//
// Check the device path to find which type it is
//
DevicePathNode = DevicePathPtr;
//
// If device path is USB WWID, expand the USB short device path.
//
DevicePathPtr = (IS_USB_SHORT_FORM_DEVICE_PATH (DevicePathPtr)) ? BdsLibExpandUsbShortFormDevPath (DevicePathPtr) : DevicePathPtr;
if (DevicePathPtr == NULL) {
DevicePathPtr = DevicePathNode;
}
DevicePathNode = DevicePathPtr;
while (!IsDevicePathEnd (DevicePathNode)) {
if ((DevicePathType (DevicePathNode) == BBS_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == BBS_BBS_DP)) {
*BootType = L05_BOOT_TYPE_NON_EFI;
break;
} else if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_USB_CLASS_DP)) {
//
// Check USB Entry for Portable Workspace (e.g. Windows To Go)
//
*BootType = L05_BOOT_TYPE_EFI_PORTABLE_DEVICE;
break;
} else if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_USB_DP)) {
IsUsbDevice = TRUE;
} else if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_SATA_DP)) {
SataPort = ((SATA_DEVICE_PATH *) DevicePathNode)->HBAPortNumber;
} else if (((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_IPv4_DP)) ||
((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_IPv6_DP))
) {
*BootType = L05_BOOT_TYPE_EFI_NETWORK;
break;
} else if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP)) {
if (IsUsbDevice) {
*BootType = L05_BOOT_TYPE_EFI_USB_HDD;
if (L05IsUsbMemoryDevice (DevicePathPtr)) {
*BootType = L05_BOOT_TYPE_EFI_USB_MEMORY;
}
} else {
*BootType = L05DistinguishEfiSataHddType (SataPort);
}
break;
} else if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP)) {
if (IsUsbDevice) {
*BootType = L05_BOOT_TYPE_EFI_USB_CDROM;
} else {
*BootType = L05_BOOT_TYPE_EFI_CDROM;
}
break;
} else if ((DevicePathType (DevicePathNode) == ACPI_DEVICE_PATH) &&
(EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) DevicePathNode)->HID) == 0x0604)) {
*BootType = L05_BOOT_TYPE_EFI_FLOPPY;
break;
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
//
// Check for Lenovo Cloud Boot and Wifi Boot
//
if (*BootType == L05_BOOT_TYPE_EFI_NETWORK) {
DevicePathNode = DevicePathPtr;
while (!IsDevicePathEnd (DevicePathNode)) {
if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_URI_DP)) {
*BootType = (*BootType == L05_BOOT_TYPE_EFI_NETWORK) ? L05_BOOT_TYPE_EFI_LENOVO_CLOUD : L05_BOOT_TYPE_EFI_LENOVO_CLOUD_WIFI;
break;
} else if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_WIFI_DP)) {
*BootType = L05_BOOT_TYPE_EFI_NETWORK_WIFI;
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
}
//
// Only for checking USB floppy
//
if (IsUsbDevice == TRUE && *BootType == L05_BOOT_TYPE_EFI_UNKNOWN) {
Status = gBS->LocateProtocol (&gEfiUsbCoreProtocolGuid, NULL, &UsbCore);
if (EFI_ERROR (Status)) {
return Status;
}
Status = UsbCore->GetUsbDevices (
USB_CORE_USB_MASS_STORAGE,
&UsbMassDevicesCount,
(USB_DEVICE ***) &UsbMassDevices
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->LocateHandleBuffer (
ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
for (Index = 0; Index < HandleCount; Index++) {
gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiUsbIoProtocolGuid,
&UsbIoInstance
);
for (Index2 = 0; Index2 < UsbMassDevicesCount; Index2++) {
if (UsbMassDevices[Index2]->UsbIo == UsbIoInstance) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID *) &DevicePath
);
if (EFI_ERROR (Status)) {
continue;
}
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiSimpleFileSystemProtocolGuid,
(VOID *) &FileSystem
);
if (EFI_ERROR (Status)) {
continue;
}
DevicePathNode = DevicePathPtr;
while (!IsDevicePathEnd (DevicePathNode)) {
Found = FALSE;
DevicePathTemp = DevicePath;
while (!IsDevicePathEnd (DevicePathTemp)) {
if (CompareMem (DevicePathNode, DevicePathTemp, *((UINT16 *) (DevicePathNode->Length))) == 0) {
Found = TRUE;
break;
}
DevicePathTemp = NextDevicePathNode (DevicePathTemp);
}
if (!Found) {
break;
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
if (Found) {
if (UsbMassDevices[Index2]->Media->RemovableMedia &&
(UsbMassDevices[Index2]->Transport->Protocol == USB_MASS_STORE_CBI0 ||
UsbMassDevices[Index2]->Transport->Protocol == USB_MASS_STORE_CBI1)) {
*BootType = L05_BOOT_TYPE_EFI_USB_FLOPPY;
}
}
}
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS
L05BootOptionNoToBootType (
IN UINT16 BootOptionNo,
OUT UINT16 *BootType
)
{
EFI_STATUS Status;
CHAR16 BootString[10];
UINT8 *Buffer;
UINTN BufferSize;
UINT8 *Ptr;
UINT16 DevicePathSize;
UINTN Index;
BBS_TABLE *BbsItem;
UINT16 DeviceType;
CHAR16 *DeviceName;
EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr;
UINTN DeviceNameSize;
Status = EFI_SUCCESS;
DeviceNameSize = 0;
Buffer = NULL;
BufferSize = 0;
Ptr = NULL;
DevicePathSize = 0;
Index = 0;
BbsItem = NULL;
DeviceType = 0;
DevicePathPtr = NULL;
CopyMem (BootString, L"Boot", 4 * sizeof (CHAR16));
UnicodeValueToStringS (&(BootString[4]), sizeof (BootString) - (4 * sizeof (CHAR16)), PREFIX_ZERO | RADIX_HEX, BootOptionNo, 4);
Status = gRT->GetVariable (BootString, &gEfiGlobalVariableGuid, NULL, &BufferSize, Buffer);
if (Status == EFI_BUFFER_TOO_SMALL) {
Buffer = AllocateZeroPool (BufferSize);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gRT->GetVariable (BootString, &gEfiGlobalVariableGuid, NULL, &BufferSize, Buffer);
if (EFI_ERROR (Status)) {
BufferSize = 0;
gBS->FreePool (Buffer);
Buffer = NULL;
}
}
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = Buffer;
Ptr += sizeof (UINT32); // skip Load Option Attributes
DevicePathSize = *((UINT16 *) Ptr);
Ptr += sizeof (UINT16); // skip DevicePathSize
DeviceNameSize = StrSize ((UINT16 *) Ptr);
DeviceName = (VOID *) Ptr;
#ifdef L05_ONE_KEY_RECOVERY_ENABLE
if (StrCmp (DeviceName, L05_NOVO_RECOVERY_SYSTEM_NAME) == 0) {
*BootType = L05_BOOT_TYPE_NOVO_RECOVERY_SYSTEM;
gBS->FreePool (Buffer);
return EFI_SUCCESS;
}
#endif
Ptr += DeviceNameSize; // skip Device Name String
DevicePathPtr = (VOID *) Ptr;
Ptr += DevicePathSize; // skip Device Path
//
// Check if the device is EFI device.
//
Status = L05DevicePathToBootType (DevicePathPtr, &DeviceType);
if (DeviceType == L05_BOOT_TYPE_NON_EFI) {
BbsItem = (BBS_TABLE *) Ptr;
DeviceType = BbsItem->DeviceType;
Ptr += sizeof (BBS_TABLE);
Index = *((UINT16 *) Ptr);
L05CheckLegacyDeviceType (BbsItem, &DeviceType, DeviceName, Index);
}
*BootType = DeviceType;
gBS->FreePool (Buffer);
return EFI_SUCCESS;
}
EFI_STATUS
L05CheckPxeNetWorkType (
IN UINT16 BootOptionNo,
IN UINT8 *NetworkType
)
{
EFI_STATUS Status;
CHAR16 BootString[10];
UINT8 *Buffer;
UINTN BufferSize;
UINT8 *Ptr;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
BOOLEAN IsWifiDevice;
Status = EFI_SUCCESS;
Buffer = NULL;
BufferSize = 0;
Ptr = NULL;
DevicePath = NULL;
IsWifiDevice = FALSE;
CopyMem (BootString, L"Boot", 4 * sizeof (CHAR16));
UnicodeValueToStringS (&(BootString[4]), sizeof (BootString) - (4 * sizeof (CHAR16)), PREFIX_ZERO | RADIX_HEX, BootOptionNo, 4);
Status = gRT->GetVariable (BootString, &gEfiGlobalVariableGuid, NULL, &BufferSize, Buffer);
if (Status == EFI_BUFFER_TOO_SMALL) {
Buffer = AllocateZeroPool (BufferSize);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gRT->GetVariable (BootString, &gEfiGlobalVariableGuid, NULL, &BufferSize, Buffer);
if (EFI_ERROR (Status)) {
BufferSize = 0;
gBS->FreePool (Buffer);
Buffer = NULL;
}
}
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Is a Device?
//
Ptr = (UINT8 *) Buffer;
//
// Attribute = *(UINT32 *) Ptr;
//
Ptr += sizeof (UINT32);
//
// FilePathSize = *(UINT16 *) Ptr;
//
Ptr += sizeof (UINT16);
//
// Description = (CHAR16 *) Ptr;
//
Ptr += StrSize ((CHAR16 *) Ptr);
//
// Now Ptr point to Device Path
//
DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
*NetworkType = 0xFF;
Status = EFI_NOT_FOUND;
while (!IsDevicePathEnd (DevicePath)) {
if (DevicePath->Type == MESSAGING_DEVICE_PATH && DevicePath->SubType == MSG_IPv4_DP) {
*NetworkType = (IsWifiDevice) ? L05_NETWORK_WIFI_IPV4 : L05_NETWORK_IPV4;
Status = EFI_SUCCESS;
} else if (DevicePath->Type == MESSAGING_DEVICE_PATH && DevicePath->SubType == MSG_IPv6_DP) {
*NetworkType = (IsWifiDevice) ? L05_NETWORK_WIFI_IPV6 : L05_NETWORK_IPV6;;
Status = EFI_SUCCESS;
} else if (DevicePath->Type == MESSAGING_DEVICE_PATH && DevicePath->SubType == MSG_URI_DP) {
if (IsWifiDevice) {
*NetworkType = (*NetworkType == L05_NETWORK_WIFI_IPV4) ? L05_NETWORK_HTTP_WIFI_IPV4 : L05_NETWORK_HTTP_WIFI_IPV6;
} else {
*NetworkType = (*NetworkType == L05_NETWORK_IPV4) ? L05_NETWORK_HTTP_IPV4 : L05_NETWORK_HTTP_IPV6;
}
Status = EFI_SUCCESS;
break;
} else if (DevicePath->Type == MESSAGING_DEVICE_PATH && DevicePath->SubType == MSG_WIFI_DP) {
IsWifiDevice = TRUE;
}
DevicePath = NextDevicePathNode (DevicePath);
}
return Status;
}
EFI_STATUS
L05ModifyBootOrder (
IN UINT8 BootNormalPriority,
IN UINT16 NewPositionPolicy,
IN BBS_TABLE *CurrentBbsItem,
IN UINTN BbsTableIndex,
IN OUT UINT16 *BootOrderList,
IN OUT UINTN *BootOrderListSize
)
{
EFI_STATUS Status;
UINT16 CurrentDeviceType;
UINT16 DeviceType;
UINT16 CurrentBootOptionNo;
UINTN BootOrderNumber;
UINTN Index;
UINTN TempIndex;
UINTN SameDeviceIndex;
UINTN PriorDeviceIndex;
UINTN NewDeviceIndex;
INT8 IsPrior;
UINT16 *Buffer;
UINTN FirstIndex;
UINTN LastIndex;
UINTN LegacyBootTypeOrderLength;
UINT16 *LegacyBootTypeOrder;
UINTN EfiBootTypeOrderLength;
UINT16 *EfiBootTypeOrder;
SYSTEM_CONFIGURATION *SystemConfiguration;
Status = EFI_SUCCESS;
CurrentDeviceType = 0;
DeviceType = 0;
CurrentBootOptionNo = 0;
BootOrderNumber = 0;
Index = 0;
TempIndex = 0;
SameDeviceIndex = L05_BOOT_ORDER_NOT_FOUND;
PriorDeviceIndex = L05_BOOT_ORDER_NOT_FOUND;
NewDeviceIndex = L05_BOOT_ORDER_NOT_FOUND;
IsPrior = 0;
Buffer = NULL;
LegacyBootTypeOrderLength = 0;
LegacyBootTypeOrder = NULL;
EfiBootTypeOrderLength = 0;
EfiBootTypeOrder = NULL;
SystemConfiguration = NULL;
if (BootOrderList == NULL) {
return EFI_ABORTED;
}
if (*BootOrderListSize == 0) {
return EFI_ABORTED;
}
Status = OemSvcSetBootTypeOrder (&LegacyBootTypeOrder, &LegacyBootTypeOrderLength, &EfiBootTypeOrder, &EfiBootTypeOrderLength);
switch (Status) {
case EFI_MEDIA_CHANGED:
mBootTypeOrderLength = LegacyBootTypeOrderLength;
mBootTypeOrder = LegacyBootTypeOrder;
break;
case EFI_UNSUPPORTED:
default:
mBootTypeOrderLength = sizeof (mL05DefaultLegacyBootTypeOrder) / sizeof (UINT16);
mBootTypeOrder = mL05DefaultLegacyBootTypeOrder;
break;
}
CurrentDeviceType = CurrentBbsItem->DeviceType;
if (CurrentDeviceType == BBS_HARDDISK) {
if (L05IsUsbDevice (CurrentBbsItem)) {
CurrentDeviceType = BBS_USB;
} else {
CurrentDeviceType = L05DistinguishSataHddType (CurrentBbsItem, BbsTableIndex);
}
}
BootOrderNumber = *BootOrderListSize / sizeof (UINT16);
if (BootOrderNumber == 1) {
return EFI_SUCCESS; // if there is only one boot device, we don't need to modify boot order
} else if (BootOrderNumber > L05_MAX_BOOT_ORDER) {
return EFI_ABORTED;
}
Buffer = AllocateCopyPool (*BootOrderListSize, BootOrderList);
FirstIndex = 0;
LastIndex = BootOrderNumber - 1;
for (Index = 0; Index < BootOrderNumber; Index++) {
Status = L05BootOptionNoToBootType (Buffer[Index], &DeviceType);
if (BootNormalPriority == 0) { // UEFI First
if (!L05IsEfiDeviceType (DeviceType)) {
FirstIndex = Index;
break;
}
} else { // Legacy First
if (L05IsEfiDeviceType (DeviceType)) {
if (Index != 0) {
LastIndex = Index - 1;
} else {
LastIndex = 0;
}
break;
}
}
}
CurrentBootOptionNo = Buffer[FirstIndex];
for (Index = 0; Index < (LastIndex - FirstIndex + 1) ; Index++) {
TempIndex = LastIndex - Index;
if (Buffer[TempIndex] == CurrentBootOptionNo) {
continue;
}
Status = L05BootOptionNoToBootType (Buffer[TempIndex], &DeviceType);
if (EFI_ERROR (Status)) {
gBS->FreePool (Buffer);
return Status;
}
IsPrior = L05IsPriorDeviceType (BootNormalPriority, DeviceType, CurrentDeviceType);
if ((IsPrior == 0) && (SameDeviceIndex == L05_BOOT_ORDER_NOT_FOUND)) {
SameDeviceIndex = TempIndex; // it should be after the last device with the same type
break;
}
if ((IsPrior > 0) && (PriorDeviceIndex == L05_BOOT_ORDER_NOT_FOUND)) {
PriorDeviceIndex = TempIndex; // it should be after the last device with prior device type
}
}
if (SameDeviceIndex != L05_BOOT_ORDER_NOT_FOUND) {
NewDeviceIndex = SameDeviceIndex; // it should be after a device with the same type
} else if (PriorDeviceIndex != L05_BOOT_ORDER_NOT_FOUND) {
NewDeviceIndex = PriorDeviceIndex; // or it should be after the last device with prior device type
} else {
NewDeviceIndex = FirstIndex; // if priority of all other devices is lower than this, this device should be the first
}
for (Index = FirstIndex; Index < NewDeviceIndex; Index++) {
Buffer[Index] = Buffer[Index + 1];
}
Buffer[NewDeviceIndex] = CurrentBootOptionNo;
CopyMem (BootOrderList, Buffer, *BootOrderListSize);
gBS->FreePool (Buffer);
return EFI_SUCCESS;
}
/*++
Find the position of a EFI Boot option.
@param[in] BootNormalPriority Normal priority of boot.
@param[in] BootOrderList A pointer to the boot order list.
@param[in] BootOrderNum Number of boot order.
@param[in] DevicePath A pointer to the device path.
@param[Out] NewPosition A pointer to the new position.
@retval EFI_SUCCESS The function completed successfully.
@retval !EFI_SUCCESS Function error.
--*/
EFI_STATUS
L05ModifyBootOptionPosition (
IN UINT8 BootNormalPriority,
IN UINT16 *BootOrderList,
IN UINTN BootOrderNum,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT UINTN *NewPosition
)
{
EFI_STATUS Status;
UINT16 NewBootType;
UINT16 BootType;
UINTN LastSameTypePosition;
UINTN LastPriorTypePosition;
UINTN FirstPostTypePosition;
UINTN Index;
UINTN FirstIndex;
UINTN LastIndex;
INT8 IsPrior;
UINTN LegacyBootTypeOrderLength;
UINT16 *LegacyBootTypeOrder;
UINTN EfiBootTypeOrderLength;
UINT16 *EfiBootTypeOrder;
Status = EFI_SUCCESS;
LastSameTypePosition = L05_MAX_BOOT_ORDER;
LastPriorTypePosition = L05_MAX_BOOT_ORDER;
FirstPostTypePosition = L05_MAX_BOOT_ORDER;
IsPrior = 0;
LegacyBootTypeOrderLength = 0;
LegacyBootTypeOrder = NULL;
EfiBootTypeOrderLength = 0;
EfiBootTypeOrder = NULL;
Status = OemSvcSetBootTypeOrder (&LegacyBootTypeOrder, &LegacyBootTypeOrderLength, &EfiBootTypeOrder, &EfiBootTypeOrderLength);
switch (Status) {
case EFI_MEDIA_CHANGED:
mBootTypeOrderLength = EfiBootTypeOrderLength;
mBootTypeOrder = EfiBootTypeOrder;
break;
case EFI_UNSUPPORTED:
default:
mBootTypeOrderLength = sizeof (mL05DefaultEfiBootTypeOrder) / sizeof (UINT16);
mBootTypeOrder = mL05DefaultEfiBootTypeOrder;
break;
}
Status = L05DevicePathToBootType (DevicePath, &NewBootType);
//
// Don't need to check boot order if no item exists
//
if ((BootOrderList == NULL) || (BootOrderNum == 0)) {
*NewPosition = 0;
return EFI_SUCCESS;
}
if (BootOrderNum > L05_MAX_BOOT_ORDER) {
return EFI_ABORTED;
}
FirstIndex = 0;
LastIndex = BootOrderNum - 1;
for (Index = 0; Index < BootOrderNum; Index++) {
Status = L05BootOptionNoToBootType (BootOrderList[Index], &BootType);
if (BootNormalPriority == 0) { // UEFI First
if (!L05IsEfiDeviceType (BootType)) {
if (Index != 0) {
LastIndex = Index - 1;
} else {
LastIndex = 0;
}
break;
}
} else { // Legacy First
if (L05IsEfiDeviceType (BootType)) {
FirstIndex = Index;
break;
}
}
}
//
// Put the new device 1. after device of the same type
// 2. after device of higher priority
// 3. before device of lower priority
//
for (Index = FirstIndex; Index <= LastIndex ; Index++) {
Status = L05BootOptionNoToBootType (BootOrderList[Index], &BootType);
if (!EFI_ERROR (Status)) {
IsPrior = L05IsPriorDeviceType (BootNormalPriority, BootType, NewBootType);
if (IsPrior == 0) {
LastSameTypePosition = Index;
} else if (IsPrior > 0) {
LastPriorTypePosition = Index;
} else if ((IsPrior < 0) && (FirstPostTypePosition == L05_MAX_BOOT_ORDER)) {
FirstPostTypePosition = Index;
}
}
}
if (LastSameTypePosition != L05_MAX_BOOT_ORDER) {
*NewPosition = LastSameTypePosition + 1;
} else if (LastPriorTypePosition != L05_MAX_BOOT_ORDER) {
*NewPosition = LastPriorTypePosition + 1;
} else if (FirstPostTypePosition != L05_MAX_BOOT_ORDER) {
*NewPosition = FirstPostTypePosition;
} else {
*NewPosition = Index;
}
return EFI_SUCCESS;
}
EFI_STATUS
L05SortBootOrderByDefault (
IN OUT UINT16 *BootOrderList,
IN UINTN BootOrderNumber,
IN UINT8 BootType
)
{
EFI_STATUS Status;
UINT16 *BootOrderListDeviceType;
UINT16 DeviceType;
UINTN Index;
UINTN Index2;
UINTN BootIndex;
UINTN LegacyBootTypeOrderLength;
UINT16 *LegacyBootTypeOrder;
UINTN EfiBootTypeOrderLength;
UINT16 *EfiBootTypeOrder;
UINTN BootTypeOrderLength;
UINT16 *BootTypeOrder;
Status = EFI_SUCCESS;
BootOrderListDeviceType = NULL;
DeviceType = 0;
Index = 0;
Index2 = 0;
BootIndex = 0;
LegacyBootTypeOrderLength = 0;
LegacyBootTypeOrder = NULL;
EfiBootTypeOrderLength = 0;
EfiBootTypeOrder = NULL;
BootTypeOrderLength = 0;
BootTypeOrder = NULL;
if (BootOrderList == NULL) {
return EFI_ABORTED;
}
if (BootOrderNumber == 0) {
return EFI_ABORTED;
}
if (BootOrderNumber == 1) {
return EFI_SUCCESS; // if there is only one boot device, we don't need to modify boot order
} else if (BootOrderNumber > L05_MAX_BOOT_ORDER) {
return EFI_ABORTED;
}
if (mDefaultBootOrder != NULL) {
if (BootOrderNumber == mDefaultBootOrderNumber) {
//
// If we have already created default boot order, we don't need to sort again.
//
CopyMem (BootOrderList, mDefaultBootOrder, mDefaultBootOrderNumber * sizeof (UINT16));
return EFI_SUCCESS;
} else {
return EFI_ABORTED;
}
}
Status = OemSvcSetBootTypeOrder (&LegacyBootTypeOrder, &LegacyBootTypeOrderLength, &EfiBootTypeOrder, &EfiBootTypeOrderLength);
switch (Status) {
case EFI_MEDIA_CHANGED:
if (BootType == EFI_BOOT_TYPE) {
BootTypeOrderLength = EfiBootTypeOrderLength;
BootTypeOrder = EfiBootTypeOrder;
} else {
BootTypeOrderLength = LegacyBootTypeOrderLength;
BootTypeOrder = LegacyBootTypeOrder;
}
break;
case EFI_UNSUPPORTED:
default:
if (BootType == EFI_BOOT_TYPE) {
BootTypeOrderLength = sizeof (mL05DefaultEfiBootTypeOrder) / sizeof (UINT16);
BootTypeOrder = mL05DefaultEfiBootTypeOrder;
} else {
BootTypeOrderLength = sizeof (mL05DefaultLegacyBootTypeOrder) / sizeof (UINT16);
BootTypeOrder = mL05DefaultLegacyBootTypeOrder;
}
break;
}
BootOrderListDeviceType = AllocateZeroPool (BootOrderNumber * sizeof (UINT16));
if (BootOrderListDeviceType == NULL) {
return EFI_OUT_OF_RESOURCES;
}
mDefaultBootOrder = AllocateZeroPool (BootOrderNumber * sizeof (UINT16));
if (mDefaultBootOrder == NULL) {
gBS->FreePool (BootOrderListDeviceType);
return EFI_OUT_OF_RESOURCES;
}
mDefaultBootOrderNumber = BootOrderNumber;
for (Index = 0; Index < BootOrderNumber; Index++) {
Status = L05BootOptionNoToBootType (BootOrderList[Index], &DeviceType);
if (EFI_ERROR (Status)) {
DeviceType = L05_UNKNOWN_DEVICE_TYPE;
} else {
for (Index2 = 0; Index2 < BootTypeOrderLength; Index2++) {
if (DeviceType == BootTypeOrder[Index2]) {
break;
}
}
if (Index2 == BootTypeOrderLength) {
//
// Mark any device type which is not on the list as unknown device type.
//
DeviceType = L05_UNKNOWN_DEVICE_TYPE;
}
}
BootOrderListDeviceType[Index] = DeviceType;
}
for (Index = 0; Index < BootTypeOrderLength; Index++) {
for (Index2 = 0; Index2 < BootOrderNumber; Index2++) {
if (BootOrderListDeviceType[Index2] == BootTypeOrder[Index]) {
mDefaultBootOrder[BootIndex] = BootOrderList[Index2];
BootIndex++;
}
}
if (BootIndex == BootOrderNumber) {
//
// All item are sorted;
//
break;
}
}
for (Index2 = 0; Index2 < BootOrderNumber; Index2++) {
if (BootOrderListDeviceType[Index2] == L05_UNKNOWN_DEVICE_TYPE) {
//
// If there is any device which device type is unknown, attach that to the end of list.
//
mDefaultBootOrder[BootIndex] = BootOrderList[Index2];
BootIndex++;
}
}
L05SortPxeOfBootOrder (mDefaultBootOrder, mDefaultBootOrderNumber);
CopyMem (BootOrderList, mDefaultBootOrder, mDefaultBootOrderNumber * sizeof (UINT16));
return EFI_SUCCESS;
}
EFI_STATUS
L05RemoveDeviceTypeFromBootOrder (
IN OUT UINT16 *BootOrderList,
IN OUT UINT16 *BootOrderNumber,
IN UINT16 DeviceType
)
{
EFI_STATUS Status;
UINT16 Type;
UINTN Index;
UINT16 *NewBootOrderList;
UINT16 NewBootOrderNumber;
Status = EFI_SUCCESS;
Type = 0;
Index = 0;
NewBootOrderList = NULL;
NewBootOrderNumber = 0;
NewBootOrderList = AllocateZeroPool (*BootOrderNumber * sizeof (UINT16));
if (NewBootOrderList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < *BootOrderNumber; Index++) {
Status = L05BootOptionNoToBootType (BootOrderList[Index], &Type);
if (Type != DeviceType) {
NewBootOrderList[NewBootOrderNumber] = BootOrderList[Index];
NewBootOrderNumber++;
}
}
ZeroMem (BootOrderList, (*BootOrderNumber * sizeof (UINT16)));
CopyMem (BootOrderList, NewBootOrderList, (NewBootOrderNumber * sizeof (UINT16)));
*BootOrderNumber = NewBootOrderNumber;
gBS->FreePool (NewBootOrderList);
return EFI_SUCCESS;
}
EFI_STATUS
L05SortPxeOfBootOrder (
IN OUT UINT16 *BootOrderList,
IN OUT UINTN BootOrderNumber
)
{
EFI_STATUS Status;
UINT8 NetworkType;
SYSTEM_CONFIGURATION *SystemConfiguration;
UINT8 Index;
TEMP_SAVE_NETWORK_INDEX *TempAllBootOrder;
TEMP_SAVE_NETWORK_INDEX SwapTempBootOrder;
SystemConfiguration = NULL;
TempAllBootOrder = NULL;
if (BootOrderList == NULL) {
return EFI_ABORTED;
}
if (BootOrderNumber == 0) {
return EFI_ABORTED;
}
SystemConfiguration = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
if (SystemConfiguration == NULL) {
return EFI_NOT_FOUND;
}
TempAllBootOrder = AllocateZeroPool (sizeof (TEMP_SAVE_NETWORK_INDEX) * BootOrderNumber);
for (Index = 0; Index < BootOrderNumber; Index++) {
Status = L05CheckPxeNetWorkType (BootOrderList [Index], &NetworkType);
TempAllBootOrder[Index].BootOrderList = BootOrderList[Index];
TempAllBootOrder[Index].NetwortType = NetworkType;
}
//
// According to SCU's Ipv4First item, we re-order PXE devices sequence
// take the network type to recognize IPv4/IPv6 devices
//
for (Index = 0; Index < (BootOrderNumber - 1); Index++) {
if (((TempAllBootOrder[Index].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_MASK &&
(TempAllBootOrder[Index + 1].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_MASK) ||
((TempAllBootOrder[Index].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_WIFI_MASK &&
(TempAllBootOrder[Index + 1].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_WIFI_MASK) ||
((TempAllBootOrder[Index].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_HTTP_MASK &&
(TempAllBootOrder[Index + 1].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_HTTP_MASK) ||
((TempAllBootOrder[Index].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_HTTP_WIFI_MASK &&
(TempAllBootOrder[Index + 1].NetwortType & L05_NETWORK_TYPE_MASK) == L05_NETWORK_HTTP_WIFI_MASK)) {
if (SystemConfiguration->L05PxeIpv4First == 1) {
//
// When the system use Ipv4 first, the sequence doesn't follow it and we re-order it
//
if (TempAllBootOrder[Index].NetwortType > TempAllBootOrder[Index + 1].NetwortType) {
SwapTempBootOrder.BootOrderList = TempAllBootOrder[Index].BootOrderList;
SwapTempBootOrder.NetwortType = TempAllBootOrder[Index].NetwortType;
TempAllBootOrder[Index].BootOrderList = TempAllBootOrder[Index + 1].BootOrderList;
TempAllBootOrder[Index].NetwortType = TempAllBootOrder[Index + 1].NetwortType;
TempAllBootOrder[Index + 1].BootOrderList = SwapTempBootOrder.BootOrderList;
TempAllBootOrder[Index + 1].NetwortType = SwapTempBootOrder.NetwortType;
}
} else {
//
// When the system use Ipv6 first, the sequence doesn't follow it and we re-order it
//
if (TempAllBootOrder[Index].NetwortType < TempAllBootOrder[Index + 1].NetwortType) {
SwapTempBootOrder.BootOrderList = TempAllBootOrder[Index].BootOrderList;
SwapTempBootOrder.NetwortType = TempAllBootOrder[Index].NetwortType;
TempAllBootOrder[Index].BootOrderList = TempAllBootOrder[Index + 1].BootOrderList;
TempAllBootOrder[Index].NetwortType = TempAllBootOrder[Index + 1].NetwortType;
TempAllBootOrder[Index + 1].BootOrderList = SwapTempBootOrder.BootOrderList;
TempAllBootOrder[Index + 1].NetwortType = SwapTempBootOrder.NetwortType;
}
}
Index++;
}
}
for (Index = 0; Index < BootOrderNumber; Index++) {
BootOrderList[Index] = TempAllBootOrder[Index].BootOrderList;
}
if (TempAllBootOrder != NULL) {
FreePool (TempAllBootOrder);
}
return EFI_SUCCESS;
}
EFI_STATUS
L05MoveHddToTheTopOfBootOrder (
IN OUT UINT16 *BootOrderList,
IN OUT UINTN BootOrderNumber
)
{
EFI_STATUS Status;
UINTN Index;
UINTN Index1;
UINT16 Temp;
UINTN Pos;
UINT16 *DeviceTypeList;
UINT16 HddType[] = {
L05_BOOT_TYPE_EFI_FIRST_SATA_HDD,
L05_BOOT_TYPE_EFI_SECOND_SATA_HDD,
L05_BOOT_TYPE_EFI_HARDDISK,
L05_BOOT_TYPE_BBS_FIRST_SATA_HDD,
L05_BOOT_TYPE_BBS_SECOND_SATA_HDD
};
Status = EFI_SUCCESS;
Index = 0;
Index1 = 0;
Temp = 0;
Pos = L05_MAX_BOOT_ORDER;
DeviceTypeList = NULL;
if (BootOrderList == NULL) {
return EFI_ABORTED;
}
if (BootOrderNumber == 0) {
return EFI_ABORTED;
}
if (BootOrderNumber == 1) {
return EFI_SUCCESS; // if there is only one boot device, we don't need to modify boot order
} else if (BootOrderNumber > L05_MAX_BOOT_ORDER) {
return EFI_ABORTED;
}
DeviceTypeList = AllocateZeroPool (BootOrderNumber * sizeof (UINT16));
if (DeviceTypeList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < BootOrderNumber; Index++) {
Status = L05BootOptionNoToBootType (BootOrderList[Index], &Temp);
DeviceTypeList[Index] = Temp;
}
for (Index1 = 0; (Index1 < sizeof (HddType) / sizeof (UINT16)) && (Pos == L05_MAX_BOOT_ORDER); Index1++) {
for (Index = 0; Index < BootOrderNumber; Index++) {
if (DeviceTypeList[Index] == HddType[Index1]) {
Pos = Index;
break;
}
}
}
gBS->FreePool (DeviceTypeList);
//
// Only need to sort device when HDD exists and HDD is not the first device.
//
if ((Pos != L05_MAX_BOOT_ORDER) && (Pos != 0)) {
Temp = BootOrderList[Pos];
for (Index = Pos; Index >= 1; Index--) {
BootOrderList[Index] = BootOrderList[Index - 1];
}
BootOrderList[0] = Temp;
}
return EFI_SUCCESS;
}
/**
Compare two device paths.
@param DevicePath1 Input device paths.
@param DevicePath2 Input device paths.
@retval TRUE Device paths are the same.
@retval FALSE Device paths are different.
*/
BOOLEAN
CompareDevicePath (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
)
{
UINTN Size1;
UINTN Size2;
Size1 = GetDevicePathSize (DevicePath1);
Size2 = GetDevicePathSize (DevicePath2);
if (Size1 != Size2) {
return FALSE;
}
if (CompareMem (DevicePath1, DevicePath2, Size1)) {
return FALSE;
}
return TRUE;
}
/**
Check check fast boot device path is valid.
Fast boot device path should record the right block IO device path for boot.
If fast boot device path is invalid, delete TargetHddDevPath variable.
@retval EFI_SUCCESS Fast boot device path is valid.
@retval EFI_UNSUPPORTED Fast boot device path is invalid.
*/
EFI_STATUS
FastBootDevicePathCheck (
)
{
EFI_STATUS Status;
UINTN Size;
UINTN BlockIndex;
UINTN BlockIoHandleCount;
EFI_HANDLE *BlockIoBuffer;
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TargetHddDevPathVar;
BOOLEAN FastBootDevicePathvalid;
BlockIoBuffer = NULL;
BlockIoDevicePath = NULL;
TargetHddDevPathVar = NULL;
FastBootDevicePathvalid = FALSE;
//
// Get TargetHddDevPath variable of fast boot.
//
TargetHddDevPathVar = BdsLibGetVariableAndSize (
L"TargetHddDevPath",
&gEfiGenericVariableGuid,
&Size
);
if (TargetHddDevPathVar == NULL) {
return EFI_UNSUPPORTED;
}
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiBlockIoProtocolGuid,
NULL,
&BlockIoHandleCount,
&BlockIoBuffer
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
for (BlockIndex = 0; BlockIndex < BlockIoHandleCount; BlockIndex++) {
//
// Get block IO device path.
//
Status = gBS->HandleProtocol (
BlockIoBuffer[BlockIndex],
&gEfiDevicePathProtocolGuid,
(VOID **) &BlockIoDevicePath
);
if (EFI_ERROR (Status) || (BlockIoDevicePath == NULL)) {
continue;
}
//
// Compare fast boot device path & block IO device path.
//
if (CompareDevicePath (TargetHddDevPathVar, BlockIoDevicePath)) {
FastBootDevicePathvalid = TRUE;
break;
}
}
if (BlockIoBuffer != NULL) {
gBS->FreePool (BlockIoBuffer);
}
if (FastBootDevicePathvalid) {
return EFI_SUCCESS;
}
//
// Fast boot device path is invalid, delete TargetHddDevPath variable.
//
gRT->SetVariable (
L"TargetHddDevPath",
&gEfiGenericVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0,
NULL
);
return EFI_UNSUPPORTED;
}
/**
Callback function to check fast boot device path is valid when fast boot active.
If device path is invalid, delete TargetHddDevPath variable and connect all the system driver.
@param Event The event that is signaled.
@param Context Pointer to the context data.
**/
VOID
EFIAPI
L05EndOfBdsConnectCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
VOID *Interface;
//
// Check gL05EndOfBdsConnectProtocolGuid is ready.
//
Status = gBS->LocateProtocol (
&gL05EndOfBdsConnectProtocolGuid,
NULL,
(VOID **) &Interface
);
if (EFI_ERROR (Status)) {
return;
}
//
// Check fast boot device path is valid when fast boot active.
// If device path is invalid, connect all the system driver.
//
if (BdsLibIsWin8FastBootActive ()) {
Status = FastBootDevicePathCheck ();
if (EFI_ERROR (Status)) {
BdsLibConnectAll ();
}
}
//
// There is no necessary to trigger this callback function again in any case.
//
gBS->CloseEvent (Event);
return;
}
EFI_STATUS
BootOptionServiceDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_L05_BOOT_OPTION_PROTOCOL *L05BootOrderPtr;
VOID *Registration;
Status = EFI_SUCCESS;
L05BootOrderPtr = NULL;
L05BootOrderPtr = AllocateZeroPool (sizeof (EFI_L05_BOOT_OPTION_PROTOCOL));
if (L05BootOrderPtr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
L05BootOrderPtr->ModifyBootOrder = L05ModifyBootOrder;
L05BootOrderPtr->ModifyBootOptionPosition = L05ModifyBootOptionPosition ;
L05BootOrderPtr->SortBootOrderByDefault = L05SortBootOrderByDefault;
L05BootOrderPtr->RemoveDeviceTypeFromBootOrder = L05RemoveDeviceTypeFromBootOrder;
L05BootOrderPtr->MoveHddToTheTopOfBootOrder = L05MoveHddToTheTopOfBootOrder;
L05BootOrderPtr->SortPxeNetworkOfBootOrder = L05SortPxeOfBootOrder;
L05BootOrderPtr->AddBootDeviceTitleString = L05ChangeDeviceType;
L05BootOrderPtr->UpdateBootOrderForNovoRecovery = L05UpdateBootOrderForNovoRecovery;
L05BootOrderPtr->IsLimitedToInternalStorage = L05IsLimitedToInternalStorage;
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gEfiL05BootOptionProtocolGuid,
EFI_NATIVE_INTERFACE,
L05BootOrderPtr
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Register gL05EndOfBdsConnectProtocolGuid protocol notify function.
//
EfiCreateProtocolNotifyEvent (
&gL05EndOfBdsConnectProtocolGuid,
TPL_NOTIFY,
L05EndOfBdsConnectCallback,
NULL,
&Registration
);
//
// Limited to internal storage.
//
LimitedToInternalStorage ();
return Status;
}