git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3852 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			579 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			579 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
 | 
						|
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.             
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "pcibus.h"
 | 
						|
#include "PciResourceSupport.h"
 | 
						|
 | 
						|
#include <IndustryStandard/Pci23.h>
 | 
						|
 | 
						|
//
 | 
						|
// Module global for a template of the PCI option ROM Image Device Path Node
 | 
						|
//
 | 
						|
MEMMAP_DEVICE_PATH  mPciOptionRomImageDevicePathNodeTemplate = {
 | 
						|
  {                 
 | 
						|
    HARDWARE_DEVICE_PATH,
 | 
						|
    HW_MEMMAP_DP,
 | 
						|
    sizeof (MEMMAP_DEVICE_PATH)
 | 
						|
  },
 | 
						|
  EfiMemoryMappedIO,
 | 
						|
  0,
 | 
						|
  0
 | 
						|
};
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetOpRomInfo (
 | 
						|
  IN PCI_IO_DEVICE    *PciIoDevice
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    PciIoDevice - add argument and description to function comment
 | 
						|
// TODO:    EFI_NOT_FOUND - add return value to function comment
 | 
						|
// TODO:    EFI_SUCCESS - add return value to function comment
 | 
						|
{
 | 
						|
  UINT8                           RomBarIndex;
 | 
						|
  UINT32                          AllOnes;
 | 
						|
  UINT64                          Address;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  UINT8                           Bus;
 | 
						|
  UINT8                           Device;
 | 
						|
  UINT8                           Function;
 | 
						|
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
 | 
						|
 | 
						|
  Bus             = PciIoDevice->BusNumber;
 | 
						|
  Device          = PciIoDevice->DeviceNumber;
 | 
						|
  Function        = PciIoDevice->FunctionNumber;
 | 
						|
 | 
						|
  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // offset is 0x30 if is not ppb
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // 0x30
 | 
						|
  //
 | 
						|
  RomBarIndex = PCI_DEVICE_ROMBAR;
 | 
						|
 | 
						|
  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
 | 
						|
    //
 | 
						|
    // if is ppb
 | 
						|
    //
 | 
						|
 | 
						|
    //
 | 
						|
    // 0x38
 | 
						|
    //
 | 
						|
    RomBarIndex = PCI_BRIDGE_ROMBAR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // the bit0 is 0 to prevent the enabling of the Rom address decoder
 | 
						|
  //
 | 
						|
  AllOnes = 0xfffffffe;
 | 
						|
  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
 | 
						|
 | 
						|
  Status = PciRootBridgeIoWrite (
 | 
						|
                                  PciRootBridgeIo,
 | 
						|
                                  &PciIoDevice->Pci,
 | 
						|
                                  EfiPciWidthUint32,
 | 
						|
                                  Address,
 | 
						|
                                  1,
 | 
						|
                                  &AllOnes
 | 
						|
                                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // read back
 | 
						|
  //
 | 
						|
  Status = PciRootBridgeIoRead (
 | 
						|
                                  PciRootBridgeIo,
 | 
						|
                                  &PciIoDevice->Pci,
 | 
						|
                                  EfiPciWidthUint32,
 | 
						|
                                  Address,
 | 
						|
                                  1,
 | 
						|
                                  &AllOnes
 | 
						|
                                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Bits [1, 10] are reserved
 | 
						|
  //
 | 
						|
  AllOnes &= 0xFFFFF800;
 | 
						|
  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
LoadOpRomImage (
 | 
						|
  IN PCI_IO_DEVICE   *PciDevice,
 | 
						|
  IN UINT64          RomBase
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 
 | 
						|
    Load option rom image for specified PCI device
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    PciDevice - add argument and description to function comment
 | 
						|
// TODO:    RomBase - add argument and description to function comment
 | 
						|
// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
 | 
						|
// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
 | 
						|
// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
 | 
						|
{
 | 
						|
  UINT8                     RomBarIndex;
 | 
						|
  UINT8                     Indicator;
 | 
						|
  UINT16                    OffsetPcir;
 | 
						|
  UINT32                    RomBarOffset;
 | 
						|
  UINT32                    RomBar;
 | 
						|
  EFI_STATUS                retStatus;
 | 
						|
  BOOLEAN                   FirstCheck;
 | 
						|
  UINT8                     *Image;
 | 
						|
  PCI_EXPANSION_ROM_HEADER  *RomHeader;
 | 
						|
  PCI_DATA_STRUCTURE        *RomPcir;
 | 
						|
  UINT64                    RomSize;
 | 
						|
  UINT64                    RomImageSize;
 | 
						|
  UINT8                     *RomInMemory;
 | 
						|
  UINT8                     CodeType;
 | 
						|
 | 
						|
  RomSize       = PciDevice->RomSize;
 | 
						|
 | 
						|
  Indicator     = 0;
 | 
						|
  RomImageSize  = 0;
 | 
						|
  RomInMemory   = NULL;
 | 
						|
  CodeType      = 0xFF;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the RomBarIndex
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // 0x30
 | 
						|
  //
 | 
						|
  RomBarIndex = PCI_DEVICE_ROMBAR;
 | 
						|
  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
 | 
						|
    //
 | 
						|
    // if is ppb
 | 
						|
    //
 | 
						|
 | 
						|
    //
 | 
						|
    // 0x38
 | 
						|
    //
 | 
						|
    RomBarIndex = PCI_BRIDGE_ROMBAR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate memory for Rom header and PCIR
 | 
						|
  //
 | 
						|
  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
 | 
						|
  if (RomHeader == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
 | 
						|
  if (RomPcir == NULL) {
 | 
						|
    gBS->FreePool (RomHeader);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  RomBar = (UINT32) RomBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enable RomBar
 | 
						|
  //
 | 
						|
  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
 | 
						|
 | 
						|
  RomBarOffset  = RomBar;
 | 
						|
  retStatus     = EFI_NOT_FOUND;
 | 
						|
  FirstCheck    = TRUE;
 | 
						|
 | 
						|
  do {
 | 
						|
    PciDevice->PciRootBridgeIo->Mem.Read (
 | 
						|
                                      PciDevice->PciRootBridgeIo,
 | 
						|
                                      EfiPciWidthUint8,
 | 
						|
                                      RomBarOffset,
 | 
						|
                                      sizeof (PCI_EXPANSION_ROM_HEADER),
 | 
						|
                                      (UINT8 *) RomHeader
 | 
						|
                                      );
 | 
						|
 | 
						|
    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | 
						|
      RomBarOffset = RomBarOffset + 512;
 | 
						|
      if (FirstCheck) {
 | 
						|
        break;
 | 
						|
      } else {
 | 
						|
        RomImageSize = RomImageSize + 512;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    FirstCheck  = FALSE;
 | 
						|
    OffsetPcir  = RomHeader->PcirOffset;
 | 
						|
    PciDevice->PciRootBridgeIo->Mem.Read (
 | 
						|
                                      PciDevice->PciRootBridgeIo,
 | 
						|
                                      EfiPciWidthUint8,
 | 
						|
                                      RomBarOffset + OffsetPcir,
 | 
						|
                                      sizeof (PCI_DATA_STRUCTURE),
 | 
						|
                                      (UINT8 *) RomPcir
 | 
						|
                                      );
 | 
						|
    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
 | 
						|
      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;
 | 
						|
    }
 | 
						|
    Indicator     = RomPcir->Indicator;
 | 
						|
    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;
 | 
						|
    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;
 | 
						|
  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
 | 
						|
 | 
						|
  //
 | 
						|
  // Some Legacy Cards do not report the correct ImageLength so used the maximum
 | 
						|
  // of the legacy length and the PCIR Image Length
 | 
						|
  //
 | 
						|
  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
 | 
						|
    RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));
 | 
						|
  }
 | 
						|
 | 
						|
  if (RomImageSize > 0) {
 | 
						|
    retStatus = EFI_SUCCESS;
 | 
						|
    Image     = AllocatePool ((UINT32) RomImageSize);
 | 
						|
    if (Image == NULL) {
 | 
						|
      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
 | 
						|
      gBS->FreePool (RomHeader);
 | 
						|
      gBS->FreePool (RomPcir);
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Copy Rom image into memory
 | 
						|
    //
 | 
						|
    PciDevice->PciRootBridgeIo->Mem.Read (
 | 
						|
                                      PciDevice->PciRootBridgeIo,
 | 
						|
                                      EfiPciWidthUint8,
 | 
						|
                                      RomBar,
 | 
						|
                                      (UINT32) RomImageSize,
 | 
						|
                                      Image
 | 
						|
                                      );
 | 
						|
    RomInMemory = Image;
 | 
						|
  }
 | 
						|
 | 
						|
  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
 | 
						|
 | 
						|
  PciDevice->PciIo.RomSize  = RomImageSize;
 | 
						|
  PciDevice->PciIo.RomImage = RomInMemory;
 | 
						|
 | 
						|
  PciRomAddImageMapping (
 | 
						|
    NULL,
 | 
						|
    PciDevice->PciRootBridgeIo->SegmentNumber,
 | 
						|
    PciDevice->BusNumber,
 | 
						|
    PciDevice->DeviceNumber,
 | 
						|
    PciDevice->FunctionNumber,
 | 
						|
    (UINT64) (UINTN) PciDevice->PciIo.RomImage,
 | 
						|
    PciDevice->PciIo.RomSize
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Free allocated memory
 | 
						|
  //
 | 
						|
  gBS->FreePool (RomHeader);
 | 
						|
  gBS->FreePool (RomPcir);
 | 
						|
 | 
						|
  return retStatus;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
RomDecode (
 | 
						|
  IN PCI_IO_DEVICE   *PciDevice,
 | 
						|
  IN UINT8           RomBarIndex,
 | 
						|
  IN UINT32          RomBar,
 | 
						|
  IN BOOLEAN         Enable
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
// TODO:    PciDevice - add argument and description to function comment
 | 
						|
// TODO:    RomBarIndex - add argument and description to function comment
 | 
						|
// TODO:    RomBar - add argument and description to function comment
 | 
						|
// TODO:    Enable - add argument and description to function comment
 | 
						|
// TODO:    EFI_SUCCESS - add return value to function comment
 | 
						|
{
 | 
						|
  UINT32              Value32;
 | 
						|
  UINT32              Offset;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
 | 
						|
  PciIo = &PciDevice->PciIo;
 | 
						|
  if (Enable) {
 | 
						|
    //
 | 
						|
    // Clear all bars
 | 
						|
    //
 | 
						|
    for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
 | 
						|
      PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // set the Rom base address: now is hardcode
 | 
						|
    // enable its decoder
 | 
						|
    //
 | 
						|
    Value32 = RomBar | 0x1;
 | 
						|
    PciIoWrite (
 | 
						|
                PciIo,
 | 
						|
                (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
 | 
						|
                RomBarIndex,
 | 
						|
                1,
 | 
						|
                &Value32
 | 
						|
                );
 | 
						|
 | 
						|
    //
 | 
						|
    // Programe all upstream bridge
 | 
						|
    //
 | 
						|
    ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);
 | 
						|
 | 
						|
    //
 | 
						|
    // Setting the memory space bit in the function's command register
 | 
						|
    //
 | 
						|
    PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
 | 
						|
 | 
						|
  } else {
 | 
						|
    
 | 
						|
    //
 | 
						|
    // disable command register decode to memory
 | 
						|
    //
 | 
						|
    PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
 | 
						|
 | 
						|
    //
 | 
						|
    // Destroy the programmed bar in all the upstream bridge.
 | 
						|
    //
 | 
						|
    ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);
 | 
						|
 | 
						|
    //
 | 
						|
    // disable rom decode
 | 
						|
    //
 | 
						|
    Value32 = 0xFFFFFFFE;
 | 
						|
    PciIoWrite (
 | 
						|
                PciIo,
 | 
						|
                (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
 | 
						|
                RomBarIndex,
 | 
						|
                1,
 | 
						|
                &Value32
 | 
						|
                );
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
ProcessOpRomImage (
 | 
						|
  PCI_IO_DEVICE   *PciDevice
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Process the oprom image.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  PciDevice       A pointer to a pci device.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI Status.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
 | 
						|
  Indicator = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Address of the Rom image
 | 
						|
  //
 | 
						|
  RomBar        = PciDevice->PciIo.RomImage;
 | 
						|
  RomBarOffset  = (UINT8 *) RomBar;
 | 
						|
  retStatus     = EFI_NOT_FOUND;
 | 
						|
  FirstCheck    = TRUE;
 | 
						|
 | 
						|
  do {
 | 
						|
    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
 | 
						|
    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | 
						|
      RomBarOffset = RomBarOffset + 512;
 | 
						|
      if (FirstCheck) {
 | 
						|
        break;
 | 
						|
      } else {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    FirstCheck  = FALSE;
 | 
						|
    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
 | 
						|
    ImageSize   = (UINT32) (Pcir->ImageLength * 512);
 | 
						|
    Indicator   = Pcir->Indicator;
 | 
						|
 | 
						|
    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && 
 | 
						|
        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {
 | 
						|
 | 
						|
      if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)  ||
 | 
						|
          (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
 | 
						|
 | 
						|
        ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;
 | 
						|
        ImageSize               = (UINT32) (EfiRomHeader->InitializationSize * 512);
 | 
						|
 | 
						|
        ImageBuffer             = (VOID *) (RomBarOffset + ImageOffset);
 | 
						|
        ImageLength             = ImageSize - (UINT32)ImageOffset;
 | 
						|
        DecompressedImageBuffer = 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 full device path to the PCI Option ROM Image being loaded
 | 
						|
          //
 | 
						|
          mPciOptionRomImageDevicePathNodeTemplate.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)RomBarOffset;
 | 
						|
          mPciOptionRomImageDevicePathNodeTemplate.EndingAddress   = (EFI_PHYSICAL_ADDRESS)(UINTN)(RomBarOffset + ImageSize - 1);
 | 
						|
          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;
 | 
						|
    }
 | 
						|
 | 
						|
  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));
 | 
						|
 | 
						|
  return retStatus;
 | 
						|
 | 
						|
}
 |