mirror of https://github.com/acidanthera/audk.git
Loaded Image device paths for EFI Drivers loaded from PCI Option ROM
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8025 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
deb7f094d4
commit
8e6b0dcb50
|
@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/PciHostBridgeResourceAllocation.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/LoadFile2.h>
|
||||
#include <Guid/PciHotplugDevice.h>
|
||||
#include <Protocol/PciRootBridgeIo.h>
|
||||
#include <Protocol/PciHotPlugRequest.h>
|
||||
|
@ -129,6 +130,7 @@ typedef struct _PCI_IO_DEVICE {
|
|||
EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
||||
EFI_LOAD_FILE2_PROTOCOL LoadFile2;
|
||||
|
||||
//
|
||||
// PCI configuration space header type
|
||||
|
@ -230,6 +232,9 @@ typedef struct _PCI_IO_DEVICE {
|
|||
#define PCI_IO_DEVICE_FROM_LINK(a) \
|
||||
CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)
|
||||
|
||||
#define PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS(a) \
|
||||
CR (a, PCI_IO_DEVICE, LoadFile2, PCI_IO_DEVICE_SIGNATURE)
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
gEfiDevicePathProtocolGuid # PROTOCOL TO_START
|
||||
gEfiIncompatiblePciDeviceSupportProtocolGuid # PROTOCOL TO_START
|
||||
gEfiUgaIoProtocolGuid # ALWAYS_CONSUMED System Table
|
||||
gEfiLoadFile2ProtocolGuid # SOMETIMES_CONSUMED
|
||||
|
||||
[FeaturePcd.common]
|
||||
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPciVgaEnable
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
Copyright (c) 2006 - 2009, Intel Corporation
|
||||
All rights reserved. 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
|
||||
|
@ -220,6 +220,7 @@ RegisterPciDevice (
|
|||
UINT8 PciExpressCapRegOffset;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
UINT8 Data8;
|
||||
BOOLEAN HasEfiImage;
|
||||
|
||||
//
|
||||
// Install the pciio protocol, device path protocol
|
||||
|
@ -261,7 +262,6 @@ RegisterPciDevice (
|
|||
// Process OpRom
|
||||
//
|
||||
if (!PciIoDevice->AllOpRomProcessed) {
|
||||
PciIoDevice->AllOpRomProcessed = TRUE;
|
||||
|
||||
//
|
||||
// Get the OpRom provided by platform
|
||||
|
@ -279,7 +279,7 @@ RegisterPciDevice (
|
|||
PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
|
||||
//
|
||||
// For OpROM read from gPciPlatformProtocol:
|
||||
// Add the Rom Image to internal database for later PCI light enumeration
|
||||
// Add the Rom Image to internal database for later PCI light enumeration
|
||||
//
|
||||
PciRomAddImageMapping (
|
||||
NULL,
|
||||
|
@ -290,16 +290,46 @@ RegisterPciDevice (
|
|||
(UINT64) (UINTN) PciIoDevice->PciIo.RomImage,
|
||||
PciIoDevice->PciIo.RomSize
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Determine if there are EFI images in the option rom
|
||||
//
|
||||
HasEfiImage = ContainEfiImage (PciIoDevice->PciIo.RomImage, PciIoDevice->PciIo.RomSize);
|
||||
|
||||
if (HasEfiImage) {
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&PciIoDevice->Handle,
|
||||
&gEfiLoadFile2ProtocolGuid,
|
||||
&PciIoDevice->LoadFile2,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
&PciIoDevice->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
PciIoDevice->DevicePath,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
&PciIoDevice->PciIo,
|
||||
NULL
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!PciIoDevice->AllOpRomProcessed) {
|
||||
|
||||
PciIoDevice->AllOpRomProcessed = TRUE;
|
||||
|
||||
//
|
||||
// Dispatch the EFI OpRom for the PCI device.
|
||||
// The OpRom is got from platform in the above code
|
||||
// or loaded from device in previous bus enumeration
|
||||
// or loaded from device in the previous round of bus enumeration
|
||||
//
|
||||
if (PciIoDevice->RomSize > 0) {
|
||||
if (HasEfiImage) {
|
||||
ProcessOpRomImage (PciIoDevice);
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +353,14 @@ RegisterPciDevice (
|
|||
&PciIoDevice->PciIo,
|
||||
NULL
|
||||
);
|
||||
if (HasEfiImage) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
&PciIoDevice->Handle,
|
||||
&gEfiLoadFile2ProtocolGuid,
|
||||
&PciIoDevice->LoadFile2,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -507,6 +545,33 @@ DeRegisterPciDevice (
|
|||
);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Try to uninstall LoadFile2 protocol if exists
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Handle,
|
||||
&gEfiLoadFile2ProtocolGuid,
|
||||
NULL,
|
||||
gPciBusDriverBinding.DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
Handle,
|
||||
&gEfiLoadFile2ProtocolGuid,
|
||||
&PciIoDevice->LoadFile2,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
//
|
||||
// Restore Status
|
||||
//
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->OpenProtocol (
|
||||
Controller,
|
||||
|
@ -825,8 +890,9 @@ CreateRootBridge (
|
|||
//
|
||||
// Initialize the PCI I/O instance structure
|
||||
//
|
||||
Status = InitializePciIoInstance (Dev);
|
||||
Status = InitializePciDriverOverrideInstance (Dev);
|
||||
InitializePciIoInstance (Dev);
|
||||
InitializePciDriverOverrideInstance (Dev);
|
||||
InitializePciLoadFile2 (Dev);
|
||||
|
||||
//
|
||||
// Initialize reserved resource list and
|
||||
|
|
|
@ -19,15 +19,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
@param PciIoDevice Device instance.
|
||||
|
||||
@retval EFI_SUCCESS Operation success.
|
||||
**/
|
||||
EFI_STATUS
|
||||
VOID
|
||||
InitializePciDriverOverrideInstance (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
)
|
||||
{
|
||||
PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,9 +32,8 @@ typedef struct {
|
|||
|
||||
@param PciIoDevice Device instance.
|
||||
|
||||
@retval EFI_SUCCESS Operation success.
|
||||
**/
|
||||
EFI_STATUS
|
||||
VOID
|
||||
InitializePciDriverOverrideInstance (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
Copyright (c) 2006 - 2009, Intel Corporation
|
||||
All rights reserved. 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
|
||||
|
@ -1664,13 +1664,10 @@ CreatePciIoDevice (
|
|||
// Initialize the PCI I/O instance structure
|
||||
//
|
||||
|
||||
Status = InitializePciIoInstance (PciIoDevice);
|
||||
Status = InitializePciDriverOverrideInstance (PciIoDevice);
|
||||
InitializePciIoInstance (PciIoDevice);
|
||||
InitializePciDriverOverrideInstance (PciIoDevice);
|
||||
InitializePciLoadFile2 (PciIoDevice);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePool (PciIoDevice);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the reserved resource list
|
||||
|
|
|
@ -90,15 +90,13 @@ ReportErrorStatusCode (
|
|||
|
||||
@param PciIoDevice Pci device instance.
|
||||
|
||||
@retval EFI_SUCCESS Success operation.
|
||||
**/
|
||||
EFI_STATUS
|
||||
VOID
|
||||
InitializePciIoInstance (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
)
|
||||
{
|
||||
CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,9 +20,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
@param PciIoDevice Pci device instance.
|
||||
|
||||
@retval EFI_SUCCESS Success operation.
|
||||
**/
|
||||
EFI_STATUS
|
||||
VOID
|
||||
InitializePciIoInstance (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
);
|
||||
|
|
|
@ -16,6 +16,202 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
||||
#include <IndustryStandard/Pci23.h>
|
||||
|
||||
/**
|
||||
Load the EFI Image from Option ROM
|
||||
|
||||
@param PciIoDevice PCI IO Device
|
||||
@param FilePath The file path of the EFI Image
|
||||
@param BufferSize On input the size of Buffer in bytes. On output with a return
|
||||
code of EFI_SUCCESS, the amount of data transferred to Buffer.
|
||||
On output with a return code of EFI_BUFFER_TOO_SMALL,
|
||||
the size of Buffer required to retrieve the requested file.
|
||||
@param Buffer The memory buffer to transfer the file to. If Buffer is NULL,
|
||||
then no the size of the requested file is returned in BufferSize.
|
||||
|
||||
@retval EFI_SUCCESS The file was loaded.
|
||||
@retval EFI_UNSUPPORTED BootPolicy is TRUE.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
|
||||
BufferSize has been updated with the size needed to complete the request.
|
||||
**/
|
||||
EFI_STATUS
|
||||
LocalLoadFile2 (
|
||||
IN PCI_IO_DEVICE *PciIoDevice,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *EfiOpRomImageNode;
|
||||
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
|
||||
PCI_DATA_STRUCTURE *Pcir;
|
||||
UINT32 ImageSize;
|
||||
UINT8 *ImageBuffer;
|
||||
UINT32 ImageLength;
|
||||
UINT32 DestinationSize;
|
||||
UINT32 ScratchSize;
|
||||
VOID *Scratch;
|
||||
EFI_DECOMPRESS_PROTOCOL *Decompress;
|
||||
|
||||
EfiOpRomImageNode = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) FilePath;
|
||||
if ((EfiOpRomImageNode == NULL) ||
|
||||
(DevicePathType (FilePath) != MEDIA_DEVICE_PATH) ||
|
||||
(DevicePathSubType (FilePath) != MEDIA_RELATIVE_OFFSET_RANGE_DP) ||
|
||||
(DevicePathNodeLength (FilePath) != sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)) ||
|
||||
(!IsDevicePathEnd (NextDevicePathNode (FilePath))) ||
|
||||
(EfiOpRomImageNode->StartingOffset > EfiOpRomImageNode->EndingOffset) ||
|
||||
(EfiOpRomImageNode->EndingOffset >= PciIoDevice->RomSize) ||
|
||||
(BufferSize == NULL)
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (
|
||||
(UINT8 *) PciIoDevice->PciIo.RomImage + EfiOpRomImageNode->StartingOffset
|
||||
);
|
||||
if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
Pcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) EfiRomHeader + EfiRomHeader->PcirOffset);
|
||||
|
||||
|
||||
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
|
||||
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
|
||||
((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
|
||||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) &&
|
||||
(EfiRomHeader->CompressionType <= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED)
|
||||
) {
|
||||
|
||||
ImageSize = (UINT32) EfiRomHeader->InitializationSize * 512;
|
||||
|
||||
ImageBuffer = (UINT8 *) EfiRomHeader + EfiRomHeader->EfiImageHeaderOffset;
|
||||
ImageLength = ImageSize - EfiRomHeader->EfiImageHeaderOffset;
|
||||
|
||||
if (EfiRomHeader->CompressionType != EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
|
||||
//
|
||||
// Uncompressed: Copy the EFI Image directly to user's buffer
|
||||
//
|
||||
if (Buffer == NULL || *BufferSize < ImageLength) {
|
||||
*BufferSize = ImageLength;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*BufferSize = ImageLength;
|
||||
CopyMem (Buffer, ImageBuffer, ImageLength);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Compressed: Uncompress before copying
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, &Decompress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
Status = Decompress->GetInfo (
|
||||
Decompress,
|
||||
ImageBuffer,
|
||||
ImageLength,
|
||||
&DestinationSize,
|
||||
&ScratchSize
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (Buffer == NULL || *BufferSize < DestinationSize) {
|
||||
*BufferSize = DestinationSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*BufferSize = DestinationSize;
|
||||
Scratch = AllocatePool (ScratchSize);
|
||||
if (Scratch == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Status = Decompress->Decompress (
|
||||
Decompress,
|
||||
ImageBuffer,
|
||||
ImageLength,
|
||||
Buffer,
|
||||
DestinationSize,
|
||||
Scratch,
|
||||
ScratchSize
|
||||
);
|
||||
gBS->FreePool (Scratch);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize a PCI LoadFile2 instance
|
||||
|
||||
@param PciIoDevice - PCI IO Device
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializePciLoadFile2 (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
)
|
||||
{
|
||||
PciIoDevice->LoadFile2.LoadFile = LoadFile2;
|
||||
}
|
||||
|
||||
/**
|
||||
Causes the driver to load a specified file.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param FilePath The device specific path of the file to load.
|
||||
@param BootPolicy Should always be FALSE.
|
||||
@param BufferSize On input the size of Buffer in bytes. On output with a return
|
||||
code of EFI_SUCCESS, the amount of data transferred to Buffer.
|
||||
On output with a return code of EFI_BUFFER_TOO_SMALL,
|
||||
the size of Buffer required to retrieve the requested file.
|
||||
@param Buffer The memory buffer to transfer the file to. If Buffer is NULL,
|
||||
then no the size of the requested file is returned in BufferSize.
|
||||
|
||||
@retval EFI_SUCCESS The file was loaded.
|
||||
@retval EFI_UNSUPPORTED BootPolicy is TRUE.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
|
||||
BufferSize has been updated with the size needed to complete the request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LoadFile2 (
|
||||
IN EFI_LOAD_FILE2_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||
IN BOOLEAN BootPolicy,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer OPTIONAL
|
||||
)
|
||||
{
|
||||
PCI_IO_DEVICE *PciIoDevice;
|
||||
|
||||
if (BootPolicy) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
PciIoDevice = PCI_IO_DEVICE_FROM_LOAD_FILE2_THIS (This);
|
||||
|
||||
return LocalLoadFile2 (
|
||||
PciIoDevice,
|
||||
FilePath,
|
||||
BufferSize,
|
||||
Buffer
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Module global for a template of the PCI option ROM Image Device Path Node
|
||||
//
|
||||
|
@ -124,6 +320,54 @@ GetOpRomInfo (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Check if the RomImage contains EFI Images.
|
||||
|
||||
@param RomImage The ROM address of Image for check.
|
||||
@param RomSize Size of ROM for check.
|
||||
|
||||
@retval TRUE ROM contain EFI Image.
|
||||
@retval FALSE ROM not contain EFI Image.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
ContainEfiImage (
|
||||
IN VOID *RomImage,
|
||||
IN UINT64 RomSize
|
||||
)
|
||||
{
|
||||
PCI_EXPANSION_ROM_HEADER *RomHeader;
|
||||
PCI_DATA_STRUCTURE *RomPcir;
|
||||
BOOLEAN FirstCheck;
|
||||
|
||||
FirstCheck = TRUE;
|
||||
RomHeader = RomImage;
|
||||
|
||||
while ((UINT8 *) RomHeader < (UINT8 *) RomImage + RomSize) {
|
||||
if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
|
||||
if (FirstCheck) {
|
||||
return FALSE;
|
||||
} else {
|
||||
RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + 512);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
FirstCheck = FALSE;
|
||||
RomPcir = (PCI_DATA_STRUCTURE *) ((UINT8 *) RomHeader + RomHeader->PcirOffset);
|
||||
|
||||
if (RomPcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
RomHeader = (PCI_EXPANSION_ROM_HEADER *) ((UINT8 *) RomHeader + RomPcir->Length * 512);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Load option rom image for specified PCI device
|
||||
|
||||
|
@ -396,25 +640,20 @@ ProcessOpRomImage (
|
|||
{
|
||||
UINT8 Indicator;
|
||||
UINT32 ImageSize;
|
||||
UINT16 ImageOffset;
|
||||
VOID *RomBar;
|
||||
UINT8 *RomBarOffset;
|
||||
EFI_HANDLE ImageHandle;
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS RetStatus;
|
||||
BOOLEAN FirstCheck;
|
||||
BOOLEAN SkipImage;
|
||||
UINT32 DestinationSize;
|
||||
UINT32 ScratchSize;
|
||||
UINT8 *Scratch;
|
||||
VOID *ImageBuffer;
|
||||
VOID *DecompressedImageBuffer;
|
||||
UINT32 ImageLength;
|
||||
EFI_DECOMPRESS_PROTOCOL *Decompress;
|
||||
EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
|
||||
PCI_DATA_STRUCTURE *Pcir;
|
||||
EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;
|
||||
|
||||
MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH EfiOpRomImageNode;
|
||||
VOID *Buffer;
|
||||
UINTN BufferSize;
|
||||
|
||||
Indicator = 0;
|
||||
|
||||
//
|
||||
|
@ -428,7 +667,7 @@ ProcessOpRomImage (
|
|||
do {
|
||||
EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
|
||||
if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
|
||||
RomBarOffset = RomBarOffset + 512;
|
||||
RomBarOffset += 512;
|
||||
if (FirstCheck) {
|
||||
break;
|
||||
} else {
|
||||
|
@ -441,120 +680,73 @@ ProcessOpRomImage (
|
|||
ImageSize = (UINT32) (Pcir->ImageLength * 512);
|
||||
Indicator = Pcir->Indicator;
|
||||
|
||||
if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
|
||||
(EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {
|
||||
//
|
||||
// Create Pci Option Rom Image device path header
|
||||
//
|
||||
EfiOpRomImageNode.Header.Type = MEDIA_DEVICE_PATH;
|
||||
EfiOpRomImageNode.Header.SubType = MEDIA_RELATIVE_OFFSET_RANGE_DP;
|
||||
SetDevicePathNodeLength (&EfiOpRomImageNode.Header, sizeof (EfiOpRomImageNode));
|
||||
EfiOpRomImageNode.StartingOffset = (UINTN) RomBarOffset - (UINTN) RomBar;
|
||||
EfiOpRomImageNode.EndingOffset = (UINTN) RomBarOffset + ImageSize - 1 - (UINTN) RomBar;
|
||||
|
||||
if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
|
||||
(EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
|
||||
PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, &EfiOpRomImageNode.Header);
|
||||
ASSERT (PciOptionRomImageDevicePath != NULL);
|
||||
|
||||
ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
|
||||
ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);
|
||||
//
|
||||
// load image and start image
|
||||
//
|
||||
|
||||
ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);
|
||||
ImageLength = ImageSize - (UINT32)ImageOffset;
|
||||
DecompressedImageBuffer = NULL;
|
||||
BufferSize = 0;
|
||||
Buffer = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
ImageHandle = NULL;
|
||||
|
||||
//
|
||||
// decompress here if needed
|
||||
//
|
||||
SkipImage = FALSE;
|
||||
if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
|
||||
SkipImage = TRUE;
|
||||
}
|
||||
|
||||
if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
|
||||
Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
SkipImage = TRUE;
|
||||
} else {
|
||||
SkipImage = TRUE;
|
||||
Status = Decompress->GetInfo (
|
||||
Decompress,
|
||||
ImageBuffer,
|
||||
ImageLength,
|
||||
&DestinationSize,
|
||||
&ScratchSize
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DecompressedImageBuffer = NULL;
|
||||
DecompressedImageBuffer = AllocatePool (DestinationSize);
|
||||
if (DecompressedImageBuffer != NULL) {
|
||||
Scratch = AllocatePool (ScratchSize);
|
||||
if (Scratch != NULL) {
|
||||
Status = Decompress->Decompress (
|
||||
Decompress,
|
||||
ImageBuffer,
|
||||
ImageLength,
|
||||
DecompressedImageBuffer,
|
||||
DestinationSize,
|
||||
Scratch,
|
||||
ScratchSize
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
ImageBuffer = DecompressedImageBuffer;
|
||||
ImageLength = DestinationSize;
|
||||
SkipImage = FALSE;
|
||||
}
|
||||
|
||||
gBS->FreePool (Scratch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SkipImage) {
|
||||
//
|
||||
// Build Memory Mapped device path node to record the image offset into the PCI Option ROM
|
||||
//
|
||||
mPciOptionRomImageDevicePathNodeTemplate.StartingAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (RomBarOffset - (UINT8 *) RomBar);
|
||||
mPciOptionRomImageDevicePathNodeTemplate.EndingAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (RomBarOffset + ImageSize - 1 - (UINT8 *) RomBar);
|
||||
PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, (const EFI_DEVICE_PATH_PROTOCOL *)&mPciOptionRomImageDevicePathNodeTemplate);
|
||||
ASSERT (PciOptionRomImageDevicePath != NULL);
|
||||
|
||||
//
|
||||
// load image and start image
|
||||
//
|
||||
Status = gBS->LoadImage (
|
||||
FALSE,
|
||||
gPciBusDriverBinding.DriverBindingHandle,
|
||||
PciOptionRomImageDevicePath,
|
||||
ImageBuffer,
|
||||
ImageLength,
|
||||
&ImageHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Free the device path after it has been used by LoadImage
|
||||
//
|
||||
gBS->FreePool (PciOptionRomImageDevicePath);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->StartImage (ImageHandle, NULL, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AddDriver (PciDevice, ImageHandle);
|
||||
PciRomAddImageMapping (
|
||||
ImageHandle,
|
||||
PciDevice->PciRootBridgeIo->SegmentNumber,
|
||||
PciDevice->BusNumber,
|
||||
PciDevice->DeviceNumber,
|
||||
PciDevice->FunctionNumber,
|
||||
(UINT64) (UINTN) PciDevice->PciIo.RomImage,
|
||||
PciDevice->PciIo.RomSize
|
||||
);
|
||||
RetStatus = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RomBarOffset = RomBarOffset + ImageSize;
|
||||
} else {
|
||||
RomBarOffset = RomBarOffset + ImageSize;
|
||||
}
|
||||
} else {
|
||||
RomBarOffset = RomBarOffset + ImageSize;
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->LoadImage (
|
||||
FALSE,
|
||||
gPciBusDriverBinding.DriverBindingHandle,
|
||||
PciOptionRomImageDevicePath,
|
||||
Buffer,
|
||||
BufferSize,
|
||||
&ImageHandle
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// load image and start image
|
||||
//
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->LoadImage (
|
||||
FALSE,
|
||||
gPciBusDriverBinding.DriverBindingHandle,
|
||||
PciOptionRomImageDevicePath,
|
||||
Buffer,
|
||||
BufferSize,
|
||||
&ImageHandle
|
||||
);
|
||||
}
|
||||
|
||||
gBS->FreePool (PciOptionRomImageDevicePath);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gBS->StartImage (ImageHandle, NULL, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AddDriver (PciDevice, ImageHandle);
|
||||
PciRomAddImageMapping (
|
||||
ImageHandle,
|
||||
PciDevice->PciRootBridgeIo->SegmentNumber,
|
||||
PciDevice->BusNumber,
|
||||
PciDevice->DeviceNumber,
|
||||
PciDevice->FunctionNumber,
|
||||
(UINT64) (UINTN) PciDevice->PciIo.RomImage,
|
||||
PciDevice->PciIo.RomSize
|
||||
);
|
||||
RetStatus = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
RomBarOffset += ImageSize;
|
||||
|
||||
} while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));
|
||||
|
||||
return RetStatus;
|
||||
|
|
|
@ -14,6 +14,66 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
#ifndef _EFI_PCI_OP_ROM_SUPPORT_H_
|
||||
#define _EFI_PCI_OP_ROM_SUPPORT_H_
|
||||
|
||||
#include <Protocol/LoadFile2.h>
|
||||
|
||||
/**
|
||||
Initialize a PCI LoadFile2 instance
|
||||
|
||||
@param PciIoDevice - PCI IO Device
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializePciLoadFile2 (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
);
|
||||
|
||||
/**
|
||||
Causes the driver to load a specified file.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param FilePath The device specific path of the file to load.
|
||||
@param BootPolicy Should always be FALSE.
|
||||
@param BufferSize On input the size of Buffer in bytes. On output with a return
|
||||
code of EFI_SUCCESS, the amount of data transferred to Buffer.
|
||||
On output with a return code of EFI_BUFFER_TOO_SMALL,
|
||||
the size of Buffer required to retrieve the requested file.
|
||||
@param Buffer The memory buffer to transfer the file to. If Buffer is NULL,
|
||||
then no the size of the requested file is returned in BufferSize.
|
||||
|
||||
@retval EFI_SUCCESS The file was loaded.
|
||||
@retval EFI_UNSUPPORTED BootPolicy is TRUE.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
|
||||
BufferSize has been updated with the size needed to complete the request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LoadFile2 (
|
||||
IN EFI_LOAD_FILE2_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||
IN BOOLEAN BootPolicy,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Check if the RomImage contains EFI Images.
|
||||
|
||||
@param RomImage The ROM address of Image for check.
|
||||
@param RomSize Size of ROM for check.
|
||||
|
||||
@retval TRUE ROM contain EFI Image.
|
||||
@retval FALSE ROM not contain EFI Image.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
ContainEfiImage (
|
||||
IN VOID *RomImage,
|
||||
IN UINT64 RomSize
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Get Pci device's oprom infor bits.
|
||||
|
||||
|
|
|
@ -82,76 +82,33 @@ PciRomAddImageMapping (
|
|||
mNumberOfPciRomImages++;
|
||||
}
|
||||
|
||||
/**
|
||||
Load all option rom image to PCI driver list.
|
||||
|
||||
@param This Pointer to protocol instance EFI_DRIVER_BINDING_PROTOCOL
|
||||
@param PciRootBridgeIo Root bridge Io instance
|
||||
@param PciIoDevice device instance
|
||||
**/
|
||||
EFI_STATUS
|
||||
PciRomGetRomResourceFromPciOptionRomTable (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
|
||||
EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
|
||||
UINTN Index;
|
||||
|
||||
Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
|
||||
PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
|
||||
if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
|
||||
PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
|
||||
PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
|
||||
PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
|
||||
|
||||
PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
|
||||
PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
|
||||
if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
|
||||
mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
|
||||
mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
|
||||
mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
|
||||
|
||||
AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Get Option rom driver's mapping for PCI device.
|
||||
|
||||
@param PciIoDevice Device instance.
|
||||
|
||||
@retval TRUE Found Image mapping.
|
||||
@retval FALSE
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
BOOLEAN
|
||||
PciRomGetImageMapping (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
)
|
||||
{
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
||||
UINTN Index;
|
||||
BOOLEAN Found;
|
||||
|
||||
PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
|
||||
Found = FALSE;
|
||||
|
||||
for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
|
||||
if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
|
||||
mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
|
||||
mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
|
||||
mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
|
||||
Found = TRUE;
|
||||
|
||||
if (mRomImageTable[Index].ImageHandle != NULL) {
|
||||
AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
|
||||
|
@ -162,5 +119,5 @@ PciRomGetImageMapping (
|
|||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return Found;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Option Rom Support for PCI Bus Driver
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
Copyright (c) 2006 - 2009, Intel Corporation
|
||||
All rights reserved. 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
|
||||
|
@ -36,27 +36,17 @@ PciRomAddImageMapping (
|
|||
IN UINT64 RomAddress,
|
||||
IN UINT64 RomLength
|
||||
);
|
||||
/**
|
||||
Load all option rom image to PCI driver list.
|
||||
|
||||
@param This Pointer to protocol instance EFI_DRIVER_BINDING_PROTOCOL.
|
||||
@param PciRootBridgeIo Root bridge Io instance.
|
||||
@param PciIoDevice device instance.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PciRomGetRomResourceFromPciOptionRomTable (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
);
|
||||
|
||||
/**
|
||||
Get Option rom driver's mapping for PCI device.
|
||||
|
||||
@param PciIoDevice Device instance.
|
||||
|
||||
@retval TRUE Found Image mapping.
|
||||
@retval FALSE
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
BOOLEAN
|
||||
PciRomGetImageMapping (
|
||||
PCI_IO_DEVICE *PciIoDevice
|
||||
);
|
||||
|
|
|
@ -1123,6 +1123,33 @@ DevPathFvFilePath (
|
|||
CatPrint (Str, L"%g", &FvFilePath->FvFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert Device Path to a Unicode string for printing.
|
||||
|
||||
@param Str The buffer holding the output string.
|
||||
This buffer contains the length of the
|
||||
string and the maixmum length reserved
|
||||
for the string buffer.
|
||||
@param DevPath The device path.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DevPathRelativeOffsetRange (
|
||||
IN OUT POOL_PRINT *Str,
|
||||
IN VOID *DevPath
|
||||
)
|
||||
{
|
||||
MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
|
||||
|
||||
Offset = DevPath;
|
||||
CatPrint (
|
||||
Str,
|
||||
L"Offset(%lx,%lx)",
|
||||
Offset->StartingOffset,
|
||||
Offset->EndingOffset
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert Device Path to a Unicode string for printing.
|
||||
|
||||
|
@ -1399,6 +1426,11 @@ DEVICE_PATH_STRING_TABLE DevPathTable[] = {
|
|||
MEDIA_PIWG_FW_FILE_DP,
|
||||
DevPathFvFilePath
|
||||
},
|
||||
{
|
||||
MEDIA_DEVICE_PATH,
|
||||
MEDIA_RELATIVE_OFFSET_RANGE_DP,
|
||||
DevPathRelativeOffsetRange,
|
||||
},
|
||||
{
|
||||
BBS_DEVICE_PATH,
|
||||
BBS_BBS_DP,
|
||||
|
|
Loading…
Reference in New Issue