mirror of https://github.com/acidanthera/audk.git
Support adding boot option from removable media, and removing invalid EFI boot option
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2078 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
060919cc05
commit
c587fa4b28
|
@ -120,6 +120,8 @@ Returns:
|
|||
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||
EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
||||
VOID *Buffer;
|
||||
|
||||
*ExitDataSize = 0;
|
||||
*ExitData = NULL;
|
||||
|
@ -209,6 +211,32 @@ Returns:
|
|||
if (!EFI_ERROR (Status) && IsDevicePathEnd (TempDevicePath)) {
|
||||
FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);
|
||||
if (FilePath) {
|
||||
//
|
||||
// Issue a dummy read to the device to check for media change.
|
||||
// When the removable media is changed, any Block IO read/write will
|
||||
// cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
|
||||
// returned. After the Block IO protocol is reinstalled, subsequent
|
||||
// Block IO read/write will success.
|
||||
//
|
||||
Status = gBS->HandleProtocol (
|
||||
Handle,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlkIo
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Buffer = AllocatePool (BlkIo->Media->BlockSize);
|
||||
if (Buffer != NULL) {
|
||||
BlkIo->ReadBlocks (
|
||||
BlkIo,
|
||||
BlkIo->Media->MediaId,
|
||||
0,
|
||||
BlkIo->Media->BlockSize,
|
||||
Buffer
|
||||
);
|
||||
gBS->FreePool (Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Status = gBS->LoadImage (
|
||||
TRUE,
|
||||
mBdsImageHandle,
|
||||
|
@ -429,6 +457,290 @@ Returns:
|
|||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BdsLibDeleteOptionFromHandle (
|
||||
IN EFI_HANDLE Handle
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Delete the boot option associated with the handle passed in
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - The handle which present the device path to create boot option
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Delete the boot option success
|
||||
|
||||
EFI_NOT_FOUND - If the Device Path is not found in the system
|
||||
|
||||
EFI_OUT_OF_RESOURCES - Lack of memory resource
|
||||
|
||||
Other - Error return value from SetVariable()
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 *BootOrder;
|
||||
UINT8 *BootOptionVar;
|
||||
UINTN BootOrderSize;
|
||||
UINTN BootOptionSize;
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINT16 BootOption[BOOT_OPTION_MAX_CHAR];
|
||||
UINTN DevicePathSize;
|
||||
UINTN OptionDevicePathSize;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
|
||||
UINT8 *TempPtr;
|
||||
CHAR16 *Description;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
BootOrder = NULL;
|
||||
BootOrderSize = 0;
|
||||
|
||||
BootOrder = BdsLibGetVariableAndSize (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
&BootOrderSize
|
||||
);
|
||||
if (NULL == BootOrder) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
DevicePath = DevicePathFromHandle (Handle);
|
||||
if (DevicePath == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
DevicePathSize = GetDevicePathSize (DevicePath);
|
||||
|
||||
Index = 0;
|
||||
while (Index < BootOrderSize / sizeof (UINT16)) {
|
||||
UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
|
||||
BootOptionVar = BdsLibGetVariableAndSize (
|
||||
BootOption,
|
||||
&gEfiGlobalVariableGuid,
|
||||
&BootOptionSize
|
||||
);
|
||||
if (NULL == BootOptionVar) {
|
||||
gBS->FreePool (BootOrder);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
TempPtr = BootOptionVar;
|
||||
TempPtr += sizeof (UINT32) + sizeof (UINT16);
|
||||
Description = (CHAR16 *) TempPtr;
|
||||
TempPtr += StrSize ((CHAR16 *) TempPtr);
|
||||
OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
||||
OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);
|
||||
|
||||
//
|
||||
// Check whether the device path match
|
||||
//
|
||||
if ((OptionDevicePathSize == DevicePathSize) &&
|
||||
(CompareMem (DevicePath, OptionDevicePath, DevicePathSize) == 0)) {
|
||||
BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize);
|
||||
gBS->FreePool (BootOptionVar);
|
||||
break;
|
||||
}
|
||||
|
||||
gBS->FreePool (BootOptionVar);
|
||||
Index++;
|
||||
}
|
||||
|
||||
Status = gRT->SetVariable (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||
BootOrderSize,
|
||||
BootOrder
|
||||
);
|
||||
|
||||
gBS->FreePool (BootOrder);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BdsDeleteAllInvalidEfiBootOption (
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Delete all invalid EFI boot options. The probable invalid boot option could
|
||||
be Removable media or Network boot device.
|
||||
|
||||
Arguments:
|
||||
|
||||
VOID
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Delete all invalid boot option success
|
||||
|
||||
EFI_NOT_FOUND - Variable "BootOrder" is not found
|
||||
|
||||
EFI_OUT_OF_RESOURCES - Lack of memory resource
|
||||
|
||||
Other - Error return value from SetVariable()
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT16 *BootOrder;
|
||||
UINT8 *BootOptionVar;
|
||||
UINTN BootOrderSize;
|
||||
UINTN BootOptionSize;
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINTN Index2;
|
||||
UINT16 BootOption[BOOT_OPTION_MAX_CHAR];
|
||||
UINTN OptionDevicePathSize;
|
||||
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;
|
||||
EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath;
|
||||
UINT8 *TempPtr;
|
||||
CHAR16 *Description;
|
||||
EFI_HANDLE Handle;
|
||||
BOOLEAN NeedDelete;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
BootOrder = NULL;
|
||||
BootOrderSize = 0;
|
||||
|
||||
BootOrder = BdsLibGetVariableAndSize (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
&BootOrderSize
|
||||
);
|
||||
if (NULL == BootOrder) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
while (Index < BootOrderSize / sizeof (UINT16)) {
|
||||
UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]);
|
||||
BootOptionVar = BdsLibGetVariableAndSize (
|
||||
BootOption,
|
||||
&gEfiGlobalVariableGuid,
|
||||
&BootOptionSize
|
||||
);
|
||||
if (NULL == BootOptionVar) {
|
||||
gBS->FreePool (BootOrder);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
TempPtr = BootOptionVar;
|
||||
TempPtr += sizeof (UINT32) + sizeof (UINT16);
|
||||
Description = (CHAR16 *) TempPtr;
|
||||
TempPtr += StrSize ((CHAR16 *) TempPtr);
|
||||
OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr;
|
||||
OptionDevicePathSize = GetDevicePathSize (OptionDevicePath);
|
||||
|
||||
//
|
||||
// Skip legacy boot option (BBS boot device)
|
||||
//
|
||||
if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) &&
|
||||
(DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) {
|
||||
gBS->FreePool (BootOptionVar);
|
||||
Index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
TempDevicePath = OptionDevicePath;
|
||||
LastDeviceNode = OptionDevicePath;
|
||||
while (!EfiIsDevicePathEnd (TempDevicePath)) {
|
||||
LastDeviceNode = TempDevicePath;
|
||||
TempDevicePath = EfiNextDevicePathNode (TempDevicePath);
|
||||
}
|
||||
//
|
||||
// Skip the boot option that point to a file, since the device path in
|
||||
// removable media boot option doesn't contains a file name.
|
||||
//
|
||||
if (((DevicePathType (LastDeviceNode) == MEDIA_DEVICE_PATH) &&
|
||||
(DevicePathSubType (LastDeviceNode) == MEDIA_FILEPATH_DP)) ||
|
||||
//
|
||||
// Skip boot option for internal Shell, it's always valid
|
||||
//
|
||||
(EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode) != NULL)) {
|
||||
gBS->FreePool (BootOptionVar);
|
||||
Index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
NeedDelete = TRUE;
|
||||
//
|
||||
// Check if it's a valid boot option for removable media
|
||||
//
|
||||
TempDevicePath = OptionDevicePath;
|
||||
Status = gBS->LocateDevicePath (
|
||||
&gEfiSimpleFileSystemProtocolGuid,
|
||||
&TempDevicePath,
|
||||
&Handle
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
NeedDelete = FALSE;
|
||||
}
|
||||
//
|
||||
// Check if it's a valid boot option for network boot device
|
||||
//
|
||||
TempDevicePath = OptionDevicePath;
|
||||
Status = gBS->LocateDevicePath (
|
||||
&gEfiLoadFileProtocolGuid,
|
||||
&TempDevicePath,
|
||||
&Handle
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
NeedDelete = FALSE;
|
||||
}
|
||||
|
||||
if (NeedDelete) {
|
||||
//
|
||||
// Delete this invalid boot option "Boot####"
|
||||
//
|
||||
Status = gRT->SetVariable (
|
||||
BootOption,
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
//
|
||||
// Mark this boot option in boot order as deleted
|
||||
//
|
||||
BootOrder[Index] = 0xffff;
|
||||
}
|
||||
|
||||
gBS->FreePool (BootOptionVar);
|
||||
Index++;
|
||||
}
|
||||
|
||||
//
|
||||
// Adjust boot order array
|
||||
//
|
||||
Index2 = 0;
|
||||
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
|
||||
if (BootOrder[Index] != 0xffff) {
|
||||
BootOrder[Index2] = BootOrder[Index];
|
||||
Index2 ++;
|
||||
}
|
||||
}
|
||||
Status = gRT->SetVariable (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
||||
Index2 * sizeof (UINT16),
|
||||
BootOrder
|
||||
);
|
||||
|
||||
gBS->FreePool (BootOrder);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
BdsLibEnumerateAllBootOption (
|
||||
IN OUT LIST_ENTRY *BdsBootOptionList
|
||||
|
@ -456,11 +768,8 @@ Returns:
|
|||
UINT16 BootOptionNumber;
|
||||
UINTN NumberFileSystemHandles;
|
||||
EFI_HANDLE *FileSystemHandles;
|
||||
UINTN NumberBlkIoHandles;
|
||||
EFI_HANDLE *BlkIoHandles;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
||||
UINTN Index;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
UINTN NumberLoadFileHandles;
|
||||
EFI_HANDLE *LoadFileHandles;
|
||||
VOID *ProtocolInstance;
|
||||
|
@ -471,6 +780,10 @@ Returns:
|
|||
UINTN Size;
|
||||
EFI_FV_FILE_ATTRIBUTES Attributes;
|
||||
UINT32 AuthenticationStatus;
|
||||
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
||||
EFI_HANDLE ImageHandle;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||
BOOLEAN NeedDelete;
|
||||
|
||||
BootOptionNumber = 0;
|
||||
|
||||
|
@ -490,49 +803,11 @@ Returns:
|
|||
REFRESH_LEGACY_BOOT_OPTIONS;
|
||||
|
||||
//
|
||||
// Check all the block IO to create boot option
|
||||
// Delete invalid boot option
|
||||
//
|
||||
gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
NULL,
|
||||
&NumberBlkIoHandles,
|
||||
&BlkIoHandles
|
||||
);
|
||||
for (Index = 0; Index < NumberBlkIoHandles; Index++) {
|
||||
Status = gBS->HandleProtocol (
|
||||
BlkIoHandles[Index],
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlkIo
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!BlkIo->Media->RemovableMedia) {
|
||||
//
|
||||
// Skip fixed Media device on first loop interration
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
DevicePath = DevicePathFromHandle (BlkIoHandles[Index]);
|
||||
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
|
||||
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)
|
||||
) {
|
||||
//
|
||||
// Build the boot option
|
||||
//
|
||||
BdsLibBuildOptionFromHandle (BlkIoHandles[Index], BdsBootOptionList);
|
||||
BootOptionNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
if (NumberBlkIoHandles) {
|
||||
gBS->FreePool (BlkIoHandles);
|
||||
}
|
||||
BdsDeleteAllInvalidEfiBootOption ();
|
||||
//
|
||||
// Parse Fixed Disk Devices.
|
||||
// Parse removable media
|
||||
//
|
||||
gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
|
@ -548,7 +823,7 @@ Returns:
|
|||
(VOID **) &BlkIo
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (BlkIo->Media->RemovableMedia) {
|
||||
if (!BlkIo->Media->RemovableMedia) {
|
||||
//
|
||||
// If the file system handle supports a BlkIo protocol,
|
||||
// skip the removable media devices
|
||||
|
@ -557,14 +832,38 @@ Returns:
|
|||
}
|
||||
}
|
||||
|
||||
DevicePath = DevicePathFromHandle (FileSystemHandles[Index]);
|
||||
if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) &&
|
||||
(DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP)
|
||||
) {
|
||||
//
|
||||
// Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
|
||||
// machinename is ia32, ia64, x64, ...
|
||||
//
|
||||
FilePath = FileDevicePath (FileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);
|
||||
NeedDelete = TRUE;
|
||||
Status = gBS->LoadImage (
|
||||
TRUE,
|
||||
mBdsImageHandle,
|
||||
FilePath,
|
||||
NULL,
|
||||
0,
|
||||
&ImageHandle
|
||||
);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
//
|
||||
// If the FileSystem protocol does not contain a BlkIo protocol,
|
||||
// then build it
|
||||
// Verify the image is a EFI application (and not a driver)
|
||||
//
|
||||
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
|
||||
ASSERT (!EFI_ERROR(Status));
|
||||
|
||||
if (ImageInfo->ImageCodeType == EfiLoaderCode) {
|
||||
NeedDelete = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (NeedDelete) {
|
||||
//
|
||||
// No such file or the file is not a EFI application, delete this boot option
|
||||
//
|
||||
BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
|
||||
} else {
|
||||
BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList);
|
||||
BootOptionNumber++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue