2. Used EdkPciIncompatibleDeviceSupportLib in PciBus driver. 3. Redirect all Pci Configuration access to new APIs added in PciLib.c for PciBus driver. 4. Added one PCD PcdIncompatibleDeviceSupportMask in EdkModulePkg.spd to provide mask of PCI devices incompatibility check. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2562 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			565 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			565 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007, 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:
 | 
						|
 | 
						|
  PciOptionRomSupport.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  PCI Bus Driver
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "pcibus.h"
 | 
						|
#include "PciResourceSupport.h"
 | 
						|
 | 
						|
//
 | 
						|
// Min Max
 | 
						|
//
 | 
						|
#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
						|
#define EFI_MAX(a, b) (((a) > (b)) ? (a) : (b))
 | 
						|
 | 
						|
 | 
						|
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 = EFI_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;
 | 
						|
 | 
						|
  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) {
 | 
						|
          //
 | 
						|
          // load image and start image
 | 
						|
          //
 | 
						|
          Status = gBS->LoadImage (
 | 
						|
                          FALSE,
 | 
						|
                          gPciBusDriverBinding.DriverBindingHandle,
 | 
						|
                          PciDevice->Handle,
 | 
						|
                          ImageBuffer,
 | 
						|
                          ImageLength,
 | 
						|
                          &ImageHandle
 | 
						|
                          );
 | 
						|
          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;
 | 
						|
 | 
						|
}
 |