diff options
author | xli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-12-08 07:33:23 +0000 |
---|---|---|
committer | xli24 <xli24@6f19259b-4bc3-4df7-8a09-765794883524> | 2006-12-08 07:33:23 +0000 |
commit | c587fa4b280c7d2439729a8d4f20784e95d1c9cb (patch) | |
tree | d0dd2c3da8e139d90ac363513e59e2950a23518b | |
parent | 060919cc058d1cf0c7549201a4b502f720dcb5fb (diff) | |
download | edk2-platforms-c587fa4b280c7d2439729a8d4f20784e95d1c9cb.tar.xz |
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
-rw-r--r-- | EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c | 401 |
1 files changed, 350 insertions, 51 deletions
diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c index c9b1eede1c..05e1b26348 100644 --- a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c @@ -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,
@@ -430,6 +458,290 @@ Returns: }
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)) {
+ //
+ // 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) {
//
- // If the FileSystem protocol does not contain a BlkIo protocol,
- // then build it
+ // No such file or the file is not a EFI application, delete this boot option
//
+ BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);
+ } else {
BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList);
BootOptionNumber++;
}
|