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

425 lines
13 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2012 - 2016, 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 <UefiDriveIdentification.h>
/*++
Routine Description:
Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
buffer, and the size of the buffer. If failure return NULL.
Arguments:
Name - String part of EFI variable name
VendorGuid - GUID part of EFI variable name
VariableSize - Returns the size of the EFI variable that was read
Returns:
Dynamically allocated memory that contains a copy of the EFI variable.
Caller is responsible freeing the buffer.
NULL - Variable was not read
--*/
VOID *
GetVariableAndSize (
IN CHAR16 *Name,
IN EFI_GUID *VendorGuid,
OUT UINTN *VariableSize
)
{
EFI_STATUS Status;
UINTN BufferSize;
VOID *Buffer;
Buffer = NULL;
//
// Pass in a zero size buffer to find the required buffer size.
//
BufferSize = 0;
Status = gRT->GetVariable (
Name,
VendorGuid,
NULL,
&BufferSize,
Buffer
);
if (Status == EFI_BUFFER_TOO_SMALL) {
//
// Allocate the buffer to return
//
Buffer = AllocateZeroPool (BufferSize);
if (Buffer == NULL) {
return NULL;
}
//
// Read variable into the allocated buffer.
//
Status = gRT->GetVariable (
Name,
VendorGuid,
NULL,
&BufferSize,
Buffer
);
if (EFI_ERROR (Status)) {
BufferSize = 0;
FreePool (Buffer);
Buffer = NULL;
}
}
*VariableSize = BufferSize;
return Buffer;
}
EFI_STATUS
UefiDriveIdentificationEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_EVENT ReadyToBootEvent;
Status = EfiCreateEventReadyToBootEx (
TPL_CALLBACK,
ConvertBootToLBoot,
NULL,
&ReadyToBootEvent
);
return Status;
}
EFI_STATUS
L05VendorDefinedData (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr,
OUT UINT8 *VendorDefinedData
)
{
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
UINTN SataPort;
BOOLEAN IsUsbDevice;
BOOLEAN IsNvmeDevice;
*VendorDefinedData = L05_UNKNOWN_DEVICE_TYPE;
DevicePathNode = DevicePathPtr;
FullDevicePath = NULL;
TempDevicePath = NULL;
SataPort = 0;
IsUsbDevice = FALSE;
IsNvmeDevice = FALSE;
//
// 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;
//
// By L05 Minimum BIOS Spec 1.37, 13 Lenovo UEFI Drive Identification
// Add NVME device path to the Lenovo UEFI driver identify FilePathList.
//
if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP)) {
//
// If it's Device Path that starts with a hard drive path, append it with the front part to compose a
// full device path to check device type.
//
FullDevicePath = BdsExpandPartitionPartialDevicePathToFull ((HARDDRIVE_DEVICE_PATH *) DevicePathNode);
TempDevicePath = (FullDevicePath == NULL) ? DevicePathNode : FullDevicePath;
if (TempDevicePath != NULL) {
while (!IsDevicePathEnd (TempDevicePath)) {
if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (TempDevicePath) == MSG_NVME_NAMESPACE_DP)) {
//
//Check NVMe devcie
//
IsNvmeDevice = TRUE;
break;
}
TempDevicePath = NextDevicePathNode (TempDevicePath);
}
}
}
if (FullDevicePath != NULL) {
gBS->FreePool (FullDevicePath);
}
//
// Check the device path to find which type it is
//
while (!IsDevicePathEnd (DevicePathNode)) {
if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MSG_USB_DP)) {
//
//Check USB devcie
//
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))
) {
//
//Check network device
//
*VendorDefinedData = L05_NETWORK_DEVICE_TYPE;
break;
} else if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MEDIA_HARDDRIVE_DP)) {
//
//Check HardDisk
//
if (IsUsbDevice) {
//
// Removable device type
//
*VendorDefinedData = L05_REMOVABLE_DEVICE_TYPE;
} else if (IsNvmeDevice) {
//
// NVMe device type
//
*VendorDefinedData = L05_NVME_DEVICE_TYPE;
} else {
//
// Fixed device type
//
*VendorDefinedData = L05_FIXED_DEVICE_TYPE;
}
break;
} else if ((DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP)) {
if (IsUsbDevice) {
//
//USB CDROM
//
*VendorDefinedData = L05_REMOVABLE_DEVICE_TYPE;
} else {
//
//CDROM - Optical device
//
*VendorDefinedData = L05_OPTICAL_DEVICE_TYPE;
}
break;
} else if ((DevicePathType (DevicePathNode) == ACPI_DEVICE_PATH) &&
(EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) DevicePathNode)->HID) == 0x0604)) {
if (IsUsbDevice) {
//
//USB Floppy
//
*VendorDefinedData = L05_REMOVABLE_DEVICE_TYPE;
} else {
*VendorDefinedData = L05_FIXED_DEVICE_TYPE;
}
break;
}
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
return EFI_SUCCESS;
}
EFI_STATUS
L05SetLbootVaraible (
IN UINT16 BootOptionNo
)
{
EFI_STATUS Status;
UINT8 *Buffer;
UINTN BufferSize;
L05_BOOT_OPTION *BootOptionPtr;
UINT8 VendorDefinedData;
CHAR16 *DeviceName;
CHAR16 BootString[10];
L05_VENDOR_DEVICE_PATH_WITH_DATA *L05DevicePath;
EFI_DEVICE_PATH_PROTOCOL *OrginalDevicePathPtr;
EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr;
EFI_DEVICE_PATH_PROTOCOL *NewL05DevicePath;
EFI_DEVICE_PATH_PROTOCOL *AddedL05DevicePath;
L05_BOOT_OPTION *L05BootOption;
Status = EFI_SUCCESS;
Buffer = NULL;
BufferSize = 0;
BootOptionPtr = NULL;
OrginalDevicePathPtr = NULL;
DevicePathPtr = NULL;
NewL05DevicePath = NULL;
AddedL05DevicePath = NULL;
L05BootOption = NULL;
CopyMem (BootString, L"Boot", 4 * sizeof (CHAR16));
UnicodeValueToStringS (&(BootString[4]), sizeof (BootString) - (4 * sizeof (CHAR16)), PREFIX_ZERO, BootOptionNo, 4);
Buffer = GetVariableAndSize (
BootString,
&gEfiGlobalVariableGuid,
&BufferSize
);
if (BufferSize == 0) {
return EFI_NOT_FOUND;
}
BootOptionPtr = (L05_BOOT_OPTION *) Buffer;
DeviceName = (VOID *) (&(BootOptionPtr->Description));
DevicePathPtr = (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) (&(BootOptionPtr->Description)) + StrSize (DeviceName));
OrginalDevicePathPtr = (EFI_DEVICE_PATH_PROTOCOL *) Buffer;
L05VendorDefinedData (DevicePathPtr, &VendorDefinedData);
//
//Create new l05 device path
//
L05DevicePath = (L05_VENDOR_DEVICE_PATH_WITH_DATA *) CreateDeviceNode (
MESSAGING_DEVICE_PATH,
MSG_VENDOR_DP,
(UINT16) sizeof (L05_VENDOR_DEVICE_PATH_WITH_DATA)
);
//
//set data to l05 device path (FilePathList[0])
//
L05DevicePath->Guid = gEfiL05LenovoBootOptionGuid;
L05DevicePath->VendorDefinedData[0] = VendorDefinedData;
//
//Set first node to link list
//
AddedL05DevicePath = AppendDevicePathNode (NULL, (EFI_DEVICE_PATH_PROTOCOL *) L05DevicePath);
//
//copy orginal Boot#### device path to l05 devcie path (from FilePathList[1])
//
NewL05DevicePath = AppendDevicePath (AddedL05DevicePath, DevicePathPtr);
//
//Allocate memory for new boot option for LBoot
//
L05BootOption = AllocateZeroPool (BufferSize + (GetDevicePathSize (NewL05DevicePath) - GetDevicePathSize (DevicePathPtr)));
//
//Set Attributes is same as boot#### data
//
L05BootOption->Attributes = BootOptionPtr->Attributes;
//
//Get new device path length and set it to L05 boot option
//
L05BootOption->FilePathListLength = (UINT16) GetDevicePathSize (NewL05DevicePath);
//
//Copy Description to L05 boot option, it same as boot####
//
CopyMem ((VOID *) &(L05BootOption->Description), (VOID *) &(BootOptionPtr->Description), StrSize (DeviceName));
//
//Copy new device path list to L05 boot option
//
CopyMem (((UINT8 *) (&(L05BootOption->Description)) + StrSize (DeviceName)), NewL05DevicePath, L05BootOption->FilePathListLength);
//
//Copy option data, it same as boot####
//
CopyMem (((UINT8 *) (&(L05BootOption->Description)) + StrSize (DeviceName) + L05BootOption->FilePathListLength),
((UINT8 *) (&(BootOptionPtr->Description)) + StrSize (DeviceName) + BootOptionPtr->FilePathListLength),
BufferSize - (sizeof (L05BootOption->Attributes) + sizeof (L05BootOption->FilePathListLength) + StrSize (DeviceName) + BootOptionPtr->FilePathListLength));
CopyMem (BootString, L"lBoot", 5 * sizeof (CHAR16));
UnicodeValueToStringS (&(BootString[5]), sizeof (BootString) - (5 * sizeof (CHAR16)), PREFIX_ZERO, BootOptionNo, 4);
Status = gRT->SetVariable (
BootString,
&gEfiL05LenovoBootOptionGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BufferSize + sizeof (L05_VENDOR_DEVICE_PATH_WITH_DATA),
L05BootOption
);
if (Buffer != NULL) {
FreePool (Buffer);
Buffer = NULL;
}
if (L05BootOption != NULL) {
FreePool (L05BootOption);
L05BootOption = NULL;
}
return EFI_SUCCESS;
}
VOID
ConvertBootToLBoot (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINT16 BootDeviceCount;
UINT16 BootDeviceNum;
UINT16 *BootOrderList;
UINTN BufferSize;
BootDeviceCount = 0;
BootDeviceNum = 0;
BootOrderList = NULL;
BufferSize = 0;
BootOrderList = GetVariableAndSize (
L"BootOrder",
&gEfiGlobalVariableGuid,
&BufferSize
);
if (BufferSize != 0) {
BootDeviceCount = (UINT16) (BufferSize / sizeof (UINT16));
}
for (BootDeviceNum = 0; BootDeviceNum < BootDeviceCount; BootDeviceNum++) {
L05SetLbootVaraible (BootDeviceNum);
}
}