IntelFrameworkModulePkg: Add Compatibility Support Module (CSM) drivers
Added these drivers: * LegacyBiosDxe * BlockIoDxe * KeyboardDxe * Snp16Dxe * VideoDxe Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
782
IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
Normal file
782
IntelFrameworkModulePkg/Csm/BiosThunk/BlockIoDxe/BiosBlkIo.c
Normal file
@@ -0,0 +1,782 @@
|
||||
/** @file
|
||||
EFI glue for BIOS INT 13h block devices.
|
||||
|
||||
This file is coded to EDD 3.0 as defined by T13 D1386 Revision 4
|
||||
Availible on http://www.t13.org/#Project drafts
|
||||
Currently at ftp://fission.dt.wdc.com/pub/standards/x3t13/project/d1386r4.pdf
|
||||
|
||||
Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions
|
||||
of the BSD License which accompanies this distribution. The
|
||||
full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "BiosBlkIo.h"
|
||||
|
||||
//
|
||||
// Global data declaration
|
||||
//
|
||||
//
|
||||
// EFI Driver Binding Protocol Instance
|
||||
//
|
||||
EFI_DRIVER_BINDING_PROTOCOL gBiosBlockIoDriverBinding = {
|
||||
BiosBlockIoDriverBindingSupported,
|
||||
BiosBlockIoDriverBindingStart,
|
||||
BiosBlockIoDriverBindingStop,
|
||||
0x3,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
//
|
||||
// Semaphore to control access to global variables mActiveInstances and mBufferUnder1Mb
|
||||
//
|
||||
EFI_LOCK mGlobalDataLock = EFI_INITIALIZE_LOCK_VARIABLE(TPL_APPLICATION);
|
||||
|
||||
//
|
||||
// Number of active instances of this protocol. This is used to allocate/free
|
||||
// the shared buffer. You must acquire the semaphore to modify.
|
||||
//
|
||||
UINTN mActiveInstances = 0;
|
||||
|
||||
//
|
||||
// Pointer to the beginning of the buffer used for real mode thunk
|
||||
// You must acquire the semaphore to modify.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS mBufferUnder1Mb = 0;
|
||||
|
||||
//
|
||||
// Address packet is a buffer under 1 MB for all version EDD calls
|
||||
//
|
||||
EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb;
|
||||
|
||||
//
|
||||
// This is a buffer for INT 13h func 48 information
|
||||
//
|
||||
BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb;
|
||||
|
||||
//
|
||||
// Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB
|
||||
// 0xFE00 bytes is the max transfer size supported.
|
||||
//
|
||||
VOID *mEdd11Buffer;
|
||||
|
||||
EFI_GUID mUnknownDevGuid = UNKNOWN_DEVICE_GUID;
|
||||
|
||||
/**
|
||||
Driver entry point.
|
||||
|
||||
@param ImageHandle Handle of driver image.
|
||||
@param SystemTable Pointer to system table.
|
||||
|
||||
@retval EFI_SUCCESS Entrypoint successfully executed.
|
||||
@retval Others Fail to execute entrypoint.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BiosBlockIoDriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Install protocols
|
||||
//
|
||||
Status = EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gBiosBlockIoDriverBinding,
|
||||
ImageHandle,
|
||||
&gBiosBlockIoComponentName,
|
||||
&gBiosBlockIoComponentName2
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
|
||||
//
|
||||
return gBS->InstallMultipleProtocolInterfaces (
|
||||
&ImageHandle,
|
||||
&gEfiLegacyBiosGuid,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Check whether the driver supports this device.
|
||||
|
||||
@param This The Udriver binding protocol.
|
||||
@param Controller The controller handle to check.
|
||||
@param RemainingDevicePath The remaining device path.
|
||||
|
||||
@retval EFI_SUCCESS The driver supports this controller.
|
||||
@retval other This device isn't supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BiosBlockIoDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
PCI_TYPE00 Pci;
|
||||
|
||||
//
|
||||
// See if the Legacy BIOS Protocol is available
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &DevicePath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
//
|
||||
// Open the IO Abstraction(s) needed to perform the supported test
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &PciIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// See if this is a PCI VGA Controller by looking at the Command register and
|
||||
// Class Code Register
|
||||
//
|
||||
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = EFI_UNSUPPORTED;
|
||||
if (Pci.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE ||
|
||||
(Pci.Hdr.ClassCode[2] == PCI_BASE_CLASS_INTELLIGENT && Pci.Hdr.ClassCode[1] == PCI_SUB_CLASS_INTELLIGENT)
|
||||
) {
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Done:
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the device with this driver.
|
||||
|
||||
@param This The driver binding instance.
|
||||
@param Controller Handle of device to bind driver to.
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS The controller is controlled by the driver.
|
||||
@retval Other This controller cannot be started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BiosBlockIoDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
UINT8 DiskStart;
|
||||
UINT8 DiskEnd;
|
||||
BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
|
||||
EFI_DEVICE_PATH_PROTOCOL *PciDevPath;
|
||||
UINTN Index;
|
||||
UINTN Flags;
|
||||
UINTN TmpAddress;
|
||||
BOOLEAN DeviceEnable;
|
||||
|
||||
//
|
||||
// Initialize variables
|
||||
//
|
||||
PciIo = NULL;
|
||||
PciDevPath = NULL;
|
||||
|
||||
DeviceEnable = FALSE;
|
||||
|
||||
//
|
||||
// See if the Legacy BIOS Protocol is available
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
//
|
||||
// Open the IO Abstraction(s) needed
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &PciIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &PciDevPath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
//
|
||||
// Enable the device and make sure VGA cycles are being forwarded to this VGA device
|
||||
//
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationEnable,
|
||||
EFI_PCI_DEVICE_ENABLE,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
DeviceEnable = TRUE;
|
||||
|
||||
//
|
||||
// Check to see if there is a legacy option ROM image associated with this PCI device
|
||||
//
|
||||
Status = LegacyBios->CheckPciRom (
|
||||
LegacyBios,
|
||||
Controller,
|
||||
NULL,
|
||||
NULL,
|
||||
&Flags
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
//
|
||||
// Post the legacy option ROM if it is available.
|
||||
//
|
||||
Status = LegacyBios->InstallPciRom (
|
||||
LegacyBios,
|
||||
Controller,
|
||||
NULL,
|
||||
&Flags,
|
||||
&DiskStart,
|
||||
&DiskEnd,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
//
|
||||
// All instances share a buffer under 1MB to put real mode thunk code in
|
||||
// If it has not been allocated, then we allocate it.
|
||||
//
|
||||
if (mBufferUnder1Mb == 0) {
|
||||
//
|
||||
// Should only be here if there are no active instances
|
||||
//
|
||||
ASSERT (mActiveInstances == 0);
|
||||
|
||||
//
|
||||
// Acquire the lock
|
||||
//
|
||||
EfiAcquireLock (&mGlobalDataLock);
|
||||
|
||||
//
|
||||
// Allocate below 1MB
|
||||
//
|
||||
mBufferUnder1Mb = 0x00000000000FFFFF;
|
||||
Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb);
|
||||
|
||||
//
|
||||
// Release the lock
|
||||
//
|
||||
EfiReleaseLock (&mGlobalDataLock);
|
||||
|
||||
//
|
||||
// Check memory allocation success
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// In checked builds we want to assert if the allocate failed.
|
||||
//
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
mBufferUnder1Mb = 0;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
TmpAddress = (UINTN) mBufferUnder1Mb;
|
||||
//
|
||||
// Adjusting the value to be on proper boundary
|
||||
//
|
||||
mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress);
|
||||
|
||||
TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER;
|
||||
//
|
||||
// Adjusting the value to be on proper boundary
|
||||
//
|
||||
mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress);
|
||||
|
||||
TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE);
|
||||
//
|
||||
// Adjusting the value to be on proper boundary
|
||||
//
|
||||
mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress);
|
||||
}
|
||||
//
|
||||
// Allocate the private device structure for each disk
|
||||
//
|
||||
for (Index = DiskStart; Index < DiskEnd; Index++) {
|
||||
|
||||
Status = gBS->AllocatePool (
|
||||
EfiBootServicesData,
|
||||
sizeof (BIOS_BLOCK_IO_DEV),
|
||||
(VOID **) &BiosBlockIoPrivate
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
//
|
||||
// Zero the private device structure
|
||||
//
|
||||
ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV));
|
||||
|
||||
//
|
||||
// Initialize the private device structure
|
||||
//
|
||||
BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE;
|
||||
BiosBlockIoPrivate->ControllerHandle = Controller;
|
||||
BiosBlockIoPrivate->LegacyBios = LegacyBios;
|
||||
BiosBlockIoPrivate->PciIo = PciIo;
|
||||
|
||||
BiosBlockIoPrivate->Bios.Floppy = FALSE;
|
||||
BiosBlockIoPrivate->Bios.Number = (UINT8) Index;
|
||||
BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C');
|
||||
BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE;
|
||||
|
||||
if (BiosInitBlockIo (BiosBlockIoPrivate)) {
|
||||
SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath);
|
||||
|
||||
//
|
||||
// Install the Block Io Protocol onto a new child handle
|
||||
//
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&BiosBlockIoPrivate->Handle,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&BiosBlockIoPrivate->BlockIo,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
BiosBlockIoPrivate->DevicePath,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePool (BiosBlockIoPrivate);
|
||||
}
|
||||
//
|
||||
// Open For Child Device
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &BiosBlockIoPrivate->PciIo,
|
||||
This->DriverBindingHandle,
|
||||
BiosBlockIoPrivate->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
|
||||
} else {
|
||||
gBS->FreePool (BiosBlockIoPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (PciIo != NULL) {
|
||||
if (DeviceEnable) {
|
||||
PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationDisable,
|
||||
EFI_PCI_DEVICE_ENABLE,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
if (PciDevPath != NULL) {
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
}
|
||||
if (mBufferUnder1Mb != 0 && mActiveInstances == 0) {
|
||||
gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
|
||||
|
||||
//
|
||||
// Clear the buffer back to 0
|
||||
//
|
||||
EfiAcquireLock (&mGlobalDataLock);
|
||||
mBufferUnder1Mb = 0;
|
||||
EfiReleaseLock (&mGlobalDataLock);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Successfully installed, so increment the number of active instances
|
||||
//
|
||||
EfiAcquireLock (&mGlobalDataLock);
|
||||
mActiveInstances++;
|
||||
EfiReleaseLock (&mGlobalDataLock);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Stop the device handled by this driver.
|
||||
|
||||
@param This The driver binding protocol.
|
||||
@param Controller The controller to release.
|
||||
@param NumberOfChildren The number of handles in ChildHandleBuffer.
|
||||
@param ChildHandleBuffer The array of child handle.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
@retval Others Fail to uninstall protocols attached on the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BiosBlockIoDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN AllChildrenStopped;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate;
|
||||
UINTN Index;
|
||||
|
||||
//
|
||||
// Decrement the number of active instances
|
||||
//
|
||||
if (mActiveInstances != 0) {
|
||||
//
|
||||
// Add a check since the stop function will be called 2 times for each handle
|
||||
//
|
||||
EfiAcquireLock (&mGlobalDataLock);
|
||||
mActiveInstances--;
|
||||
EfiReleaseLock (&mGlobalDataLock);
|
||||
}
|
||||
|
||||
if ((mActiveInstances == 0) && (mBufferUnder1Mb != 0)) {
|
||||
//
|
||||
// Free our global buffer
|
||||
//
|
||||
Status = gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
EfiAcquireLock (&mGlobalDataLock);
|
||||
mBufferUnder1Mb = 0;
|
||||
EfiReleaseLock (&mGlobalDataLock);
|
||||
}
|
||||
|
||||
AllChildrenStopped = TRUE;
|
||||
|
||||
for (Index = 0; Index < NumberOfChildren; Index++) {
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlockIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
BiosBlockIoPrivate = BIOS_BLOCK_IO_FROM_THIS (BlockIo);
|
||||
|
||||
//
|
||||
// Release PCI I/O and Block IO Protocols on the clild handle.
|
||||
//
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&BiosBlockIoPrivate->BlockIo,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
BiosBlockIoPrivate->DevicePath,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
AllChildrenStopped = FALSE;
|
||||
}
|
||||
//
|
||||
// Shutdown the hardware
|
||||
//
|
||||
BiosBlockIoPrivate->PciIo->Attributes (
|
||||
BiosBlockIoPrivate->PciIo,
|
||||
EfiPciIoAttributeOperationDisable,
|
||||
EFI_PCI_DEVICE_ENABLE,
|
||||
NULL
|
||||
);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
ChildHandleBuffer[Index]
|
||||
);
|
||||
|
||||
gBS->FreePool (BiosBlockIoPrivate);
|
||||
}
|
||||
|
||||
if (!AllChildrenStopped) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Build device path for device.
|
||||
|
||||
@param BaseDevicePath Base device path.
|
||||
@param Drive Legacy drive.
|
||||
@param DevicePath Device path for output.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetBiosInitBlockIoDevicePath (
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
|
||||
IN BIOS_LEGACY_DRIVE *Drive,
|
||||
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH VendorNode;
|
||||
|
||||
Status = EFI_UNSUPPORTED;
|
||||
|
||||
//
|
||||
// BugBug: Check for memory leaks!
|
||||
//
|
||||
if (Drive->EddVersion == EDD_VERSION_30) {
|
||||
//
|
||||
// EDD 3.0 case.
|
||||
//
|
||||
Status = BuildEdd30DevicePath (BaseDevicePath, Drive, DevicePath);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// EDD 1.1 device case or it is unrecognized EDD 3.0 device
|
||||
//
|
||||
ZeroMem (&VendorNode, sizeof (VendorNode));
|
||||
VendorNode.DevicePath.Header.Type = HARDWARE_DEVICE_PATH;
|
||||
VendorNode.DevicePath.Header.SubType = HW_VENDOR_DP;
|
||||
SetDevicePathNodeLength (&VendorNode.DevicePath.Header, sizeof (VendorNode));
|
||||
CopyMem (&VendorNode.DevicePath.Guid, &mUnknownDevGuid, sizeof (EFI_GUID));
|
||||
VendorNode.LegacyDriveLetter = Drive->Number;
|
||||
*DevicePath = AppendDevicePathNode (BaseDevicePath, &VendorNode.DevicePath.Header);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Build device path for EDD 3.0.
|
||||
|
||||
@param BaseDevicePath Base device path.
|
||||
@param Drive Legacy drive.
|
||||
@param DevicePath Device path for output.
|
||||
|
||||
@retval EFI_SUCCESS The device path is built successfully.
|
||||
@retval EFI_UNSUPPORTED It is failed to built device path.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
BuildEdd30DevicePath (
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *BaseDevicePath,
|
||||
IN BIOS_LEGACY_DRIVE *Drive,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
||||
)
|
||||
{
|
||||
//
|
||||
// AVL UINT64 Address;
|
||||
// AVL EFI_HANDLE Handle;
|
||||
//
|
||||
EFI_DEV_PATH Node;
|
||||
UINT32 Controller;
|
||||
|
||||
Controller = (UINT32) Drive->Parameters.InterfacePath.Pci.Controller;
|
||||
|
||||
ZeroMem (&Node, sizeof (Node));
|
||||
if ((AsciiStrnCmp ("ATAPI", Drive->Parameters.InterfaceType, 5) == 0) ||
|
||||
(AsciiStrnCmp ("ATA", Drive->Parameters.InterfaceType, 3) == 0)
|
||||
) {
|
||||
//
|
||||
// ATA or ATAPI drive found
|
||||
//
|
||||
Node.Atapi.Header.Type = MESSAGING_DEVICE_PATH;
|
||||
Node.Atapi.Header.SubType = MSG_ATAPI_DP;
|
||||
SetDevicePathNodeLength (&Node.Atapi.Header, sizeof (ATAPI_DEVICE_PATH));
|
||||
Node.Atapi.SlaveMaster = Drive->Parameters.DevicePath.Atapi.Master;
|
||||
Node.Atapi.Lun = Drive->Parameters.DevicePath.Atapi.Lun;
|
||||
Node.Atapi.PrimarySecondary = (UINT8) Controller;
|
||||
} else {
|
||||
//
|
||||
// Not an ATA/ATAPI drive
|
||||
//
|
||||
if (Controller != 0) {
|
||||
ZeroMem (&Node, sizeof (Node));
|
||||
Node.Controller.Header.Type = HARDWARE_DEVICE_PATH;
|
||||
Node.Controller.Header.SubType = HW_CONTROLLER_DP;
|
||||
SetDevicePathNodeLength (&Node.Controller.Header, sizeof (CONTROLLER_DEVICE_PATH));
|
||||
Node.Controller.ControllerNumber = Controller;
|
||||
*DevicePath = AppendDevicePathNode (*DevicePath, &Node.DevPath);
|
||||
}
|
||||
|
||||
ZeroMem (&Node, sizeof (Node));
|
||||
|
||||
if (AsciiStrnCmp ("SCSI", Drive->Parameters.InterfaceType, 4) == 0) {
|
||||
//
|
||||
// SCSI drive
|
||||
//
|
||||
Node.Scsi.Header.Type = MESSAGING_DEVICE_PATH;
|
||||
Node.Scsi.Header.SubType = MSG_SCSI_DP;
|
||||
SetDevicePathNodeLength (&Node.Scsi.Header, sizeof (SCSI_DEVICE_PATH));
|
||||
|
||||
//
|
||||
// Lun is miss aligned in both EDD and Device Path data structures.
|
||||
// thus we do a byte copy, to prevent alignment traps on IA-64.
|
||||
//
|
||||
CopyMem (&Node.Scsi.Lun, &Drive->Parameters.DevicePath.Scsi.Lun, sizeof (UINT16));
|
||||
Node.Scsi.Pun = Drive->Parameters.DevicePath.Scsi.Pun;
|
||||
|
||||
} else if (AsciiStrnCmp ("USB", Drive->Parameters.InterfaceType, 3) == 0) {
|
||||
//
|
||||
// USB drive
|
||||
//
|
||||
Node.Usb.Header.Type = MESSAGING_DEVICE_PATH;
|
||||
Node.Usb.Header.SubType = MSG_USB_DP;
|
||||
SetDevicePathNodeLength (&Node.Usb.Header, sizeof (USB_DEVICE_PATH));
|
||||
Node.Usb.ParentPortNumber = (UINT8) Drive->Parameters.DevicePath.Usb.Reserved;
|
||||
|
||||
} else if (AsciiStrnCmp ("1394", Drive->Parameters.InterfaceType, 4) == 0) {
|
||||
//
|
||||
// 1394 drive
|
||||
//
|
||||
Node.F1394.Header.Type = MESSAGING_DEVICE_PATH;
|
||||
Node.F1394.Header.SubType = MSG_1394_DP;
|
||||
SetDevicePathNodeLength (&Node.F1394.Header, sizeof (F1394_DEVICE_PATH));
|
||||
Node.F1394.Guid = Drive->Parameters.DevicePath.FireWire.Guid;
|
||||
|
||||
} else if (AsciiStrnCmp ("FIBRE", Drive->Parameters.InterfaceType, 5) == 0) {
|
||||
//
|
||||
// Fibre drive
|
||||
//
|
||||
Node.FibreChannel.Header.Type = MESSAGING_DEVICE_PATH;
|
||||
Node.FibreChannel.Header.SubType = MSG_FIBRECHANNEL_DP;
|
||||
SetDevicePathNodeLength (&Node.FibreChannel.Header, sizeof (FIBRECHANNEL_DEVICE_PATH));
|
||||
Node.FibreChannel.WWN = Drive->Parameters.DevicePath.FibreChannel.Wwn;
|
||||
Node.FibreChannel.Lun = Drive->Parameters.DevicePath.FibreChannel.Lun;
|
||||
|
||||
} else {
|
||||
DEBUG (
|
||||
(
|
||||
DEBUG_BLKIO, "It is unrecognized EDD 3.0 device, Drive Number = %x, InterfaceType = %s\n",
|
||||
Drive->Number,
|
||||
Drive->Parameters.InterfaceType
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Node.DevPath.Type == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*DevicePath = AppendDevicePathNode (BaseDevicePath, &Node.DevPath);
|
||||
return EFI_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user