system76-edk2/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c
ajfish 2ce311322c Removed cross references from PciCf8Lib and PciExpressLib class to PciLib class.
Added PeCoffLoaderGetMachineType to the PeCoffGetEntryPointLibrary Class. Document to be updated.

Added the PeCoffLoaderImageReadFromMemory() and PeCoffLoaderRelocateImageForRuntime () to the PcCoffLib. 

Updated EfiImage.h and removed EFI_IMAGE_OPTIONAL_HEADER and EFI_IMAGE_NT_HEADERS as they were replaced with checking the MachineType.

PeCoffLib – Added checks for MachineType so the PeCoff lib can load any PE32 or PE32+ image. The relocations are still limited to IA32, X64, IPF, and EBC. I also added a re-relocator function to remove PeLoader Code from Runtime Lib. Even though there is only one instance of the re-relocator I wanted to get all the PeCoff loader code together.

Replaced DEBUG_CODE() macro with DEBUG_CODE_START() and DEBUG_CODE_END() so you can debug through the DEBUG_CODE() macros. Also removed PE/COFF code and replaced with library usage.

I also updated the IO Instrinsic lib to use _ReadWriteBarrior() to help with sync problems

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1103 6f19259b-4bc3-4df7-8a09-765794883524
2006-07-26 15:23:35 +00:00

282 lines
8.6 KiB
C

/*++
Copyright (c) 2006, 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
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.
Module Name:
PciDriverOverride.c
Abstract:
PCI Bus Driver
Revision History
--*/
#include "pcibus.h"
EFI_STATUS
InitializePciDriverOverrideInstance (
PCI_IO_DEVICE *PciIoDevice
)
/*++
Routine Description:
Initializes a PCI Driver Override Instance
Arguments:
Returns:
None
--*/
// TODO: PciIoDevice - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
GetDriver (
IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
IN OUT EFI_HANDLE *DriverImageHandle
)
/*++
Routine Description:
Get a overriding driver image
Arguments:
Returns:
None
--*/
// TODO: This - add argument and description to function comment
// TODO: DriverImageHandle - add argument and description to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_NOT_FOUND - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
{
PCI_IO_DEVICE *PciIoDevice;
LIST_ENTRY *CurrentLink;
PCI_DRIVER_OVERRIDE_LIST *Node;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;
while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {
Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);
if (*DriverImageHandle == NULL) {
*DriverImageHandle = Node->DriverImageHandle;
return EFI_SUCCESS;
}
if (*DriverImageHandle == Node->DriverImageHandle) {
if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||
CurrentLink->ForwardLink == NULL) {
return EFI_NOT_FOUND;
}
//
// Get next node
//
Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);
*DriverImageHandle = Node->DriverImageHandle;
return EFI_SUCCESS;
}
CurrentLink = CurrentLink->ForwardLink;
}
return EFI_INVALID_PARAMETER;
}
EFI_STATUS
AddDriver (
IN PCI_IO_DEVICE *PciIoDevice,
IN EFI_HANDLE DriverImageHandle
)
/*++
Routine Description:
Add a overriding driver image
Arguments:
Returns:
None
--*/
// TODO: PciIoDevice - add argument and description to function comment
// TODO: DriverImageHandle - add argument and description to function comment
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
PCI_DRIVER_OVERRIDE_LIST *Node;
EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader;
EFI_DRIVER_OS_HANDOFF_HEADER *NewDriverOsHandoffHeader;
EFI_DRIVER_OS_HANDOFF *DriverOsHandoff;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE DeviceHandle;
UINTN NumberOfEntries;
UINTN Size;
UINTN Index;
Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
if (EFI_ERROR (Status)) {
return Status;
}
Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
if (Node == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
Node->DriverImageHandle = DriverImageHandle;
InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));
PciIoDevice->BusOverride = TRUE;
if (PeCoffLoaderGetMachineType ((VOID *)(UINTN)LoadedImage->ImageBase) != EFI_IMAGE_MACHINE_EBC) {
return EFI_SUCCESS;
}
DriverOsHandoffHeader = NULL;
Status = EfiGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader);
if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) {
for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) {
DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader) +
DriverOsHandoffHeader->HeaderSize +
Index * DriverOsHandoffHeader->SizeOfEntries);
DevicePath = DriverOsHandoff->DevicePath;
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) {
if (DeviceHandle == PciIoDevice->Handle) {
return EFI_SUCCESS;
}
}
}
NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1;
} else {
NumberOfEntries = 1;
}
Status = gBS->AllocatePool (
EfiRuntimeServicesData,
sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF),
(VOID **) &NewDriverOsHandoffHeader
);
if (EFI_ERROR (Status)) {
return Status;
}
if (DriverOsHandoffHeader == NULL) {
NewDriverOsHandoffHeader->Version = 0;
NewDriverOsHandoffHeader->HeaderSize = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER);
NewDriverOsHandoffHeader->SizeOfEntries = sizeof (EFI_DRIVER_OS_HANDOFF);
NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;
} else {
gBS->CopyMem (
NewDriverOsHandoffHeader,
DriverOsHandoffHeader,
DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries
);
NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;
}
DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader +
NewDriverOsHandoffHeader->HeaderSize +
(NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries);
//
// Fill in the EFI_DRIVER_OS_HANDOFF structure
//
DriverOsHandoff->Type = EfiUgaDriverFromPciRom;
//
// Compute the size of the device path
//
Size = GetDevicePathSize (PciIoDevice->DevicePath);
if (Size == 0) {
DriverOsHandoff->DevicePath = NULL;
} else {
//
// Allocate space for duplicate device path
//
Status = gBS->AllocatePool (
EfiRuntimeServicesData,
Size,
(VOID **) &DriverOsHandoff->DevicePath
);
if (EFI_ERROR (Status)) {
gBS->FreePool (NewDriverOsHandoffHeader);
return Status;
}
//
// Make copy of device path
//
CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size);
}
DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize;
Status = gBS->AllocatePool (
EfiRuntimeServicesData,
(UINTN) DriverOsHandoff->PciRomSize,
(VOID **) &DriverOsHandoff->PciRomImage
);
if (EFI_ERROR (Status)) {
gBS->FreePool (NewDriverOsHandoffHeader);
return Status;
}
gBS->CopyMem (
DriverOsHandoff->PciRomImage,
PciIoDevice->PciIo.RomImage,
(UINTN) DriverOsHandoff->PciRomSize
);
Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader);
if (EFI_ERROR (Status)) {
return Status;
}
if (DriverOsHandoffHeader != NULL) {
gBS->FreePool (DriverOsHandoffHeader);
}
return EFI_SUCCESS;
}