1713 lines
50 KiB
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;
|
|
}
|