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
		
			
				
	
	
		
			282 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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;
 | |
| }
 |