- stoping -> stopping - Pointion -> Position - Arrary -> Array - reseting -> resetting - excute -> execute - isTRUE -> is TRUE - connectted -> connected - Retrive -> Retrieve - dirvers -> drivers - funciton -> function - paramter -> parameter - availible -> available - permenent -> permanent - boundry -> boundary Cc: Jeff Fan <jeff.fan@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gary Lin <glin@suse.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
			
				
	
	
		
			3008 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3008 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
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 "LegacyBiosInterface.h"
 | 
						|
#include <IndustryStandard/Pci30.h>
 | 
						|
 | 
						|
#define PCI_START_ADDRESS(x)   (((x) + 0x7ff) & ~0x7ff)
 | 
						|
 | 
						|
#define MAX_BRIDGE_INDEX  0x20
 | 
						|
typedef struct {
 | 
						|
  UINTN PciSegment;
 | 
						|
  UINTN PciBus;
 | 
						|
  UINTN PciDevice;
 | 
						|
  UINTN PciFunction;
 | 
						|
  UINT8 PrimaryBus;
 | 
						|
  UINT8 SecondaryBus;
 | 
						|
  UINT8 SubordinateBus;
 | 
						|
} BRIDGE_TABLE;
 | 
						|
 | 
						|
#define ROM_MAX_ENTRIES 24
 | 
						|
BRIDGE_TABLE                        Bridges[MAX_BRIDGE_INDEX];
 | 
						|
UINTN                               SortedBridgeIndex[MAX_BRIDGE_INDEX];
 | 
						|
UINTN                               NumberOfBridges;
 | 
						|
LEGACY_PNP_EXPANSION_HEADER  *mBasePnpPtr;
 | 
						|
UINT16                              mBbsRomSegment;
 | 
						|
UINTN                               mHandleCount;
 | 
						|
EFI_HANDLE                          mVgaHandle;
 | 
						|
BOOLEAN                             mIgnoreBbsUpdateFlag;
 | 
						|
BOOLEAN                             mVgaInstallationInProgress  = FALSE;
 | 
						|
UINT32                              mRomCount                   = 0x00;
 | 
						|
ROM_INSTANCE_ENTRY                  mRomEntry[ROM_MAX_ENTRIES];
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Query shadowed legacy ROM parameters registered by RomShadow() previously.
 | 
						|
 | 
						|
  @param  PciHandle        PCI device whos ROM has been shadowed
 | 
						|
  @param  DiskStart        DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
 | 
						|
  @param  DiskEnd          DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
 | 
						|
  @param  RomShadowAddress Address where ROM was shadowed
 | 
						|
  @param  ShadowedSize     Runtime size of ROM
 | 
						|
 | 
						|
  @retval EFI_SUCCESS      Query Logging successful.
 | 
						|
  @retval EFI_NOT_FOUND    No logged data found about PciHandle.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetShadowedRomParameters (
 | 
						|
  IN EFI_HANDLE                         PciHandle,
 | 
						|
  OUT UINT8                             *DiskStart,         OPTIONAL
 | 
						|
  OUT UINT8                             *DiskEnd,           OPTIONAL
 | 
						|
  OUT VOID                              **RomShadowAddress, OPTIONAL
 | 
						|
  OUT UINTN                             *ShadowedSize       OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
  UINTN               Index;
 | 
						|
  UINTN               PciSegment;
 | 
						|
  UINTN               PciBus;
 | 
						|
  UINTN               PciDevice;
 | 
						|
  UINTN               PciFunction;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the PCI I/O Protocol on PciHandle
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  PciHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the location of the PCI device
 | 
						|
  //
 | 
						|
  PciIo->GetLocation (
 | 
						|
           PciIo,
 | 
						|
           &PciSegment,
 | 
						|
           &PciBus,
 | 
						|
           &PciDevice,
 | 
						|
           &PciFunction
 | 
						|
           );
 | 
						|
 | 
						|
  for(Index = 0; Index < mRomCount; Index++) {
 | 
						|
    if ((mRomEntry[Index].PciSegment == PciSegment) &&
 | 
						|
        (mRomEntry[Index].PciBus == PciBus)         &&
 | 
						|
        (mRomEntry[Index].PciDevice == PciDevice)   &&
 | 
						|
        (mRomEntry[Index].PciFunction == PciFunction)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index == mRomCount) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DiskStart != NULL) {
 | 
						|
    *DiskStart = mRomEntry[Index].DiskStart;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DiskEnd != NULL) {
 | 
						|
    *DiskEnd = mRomEntry[Index].DiskEnd;
 | 
						|
  }
 | 
						|
 | 
						|
  if (RomShadowAddress != NULL) {
 | 
						|
    *RomShadowAddress = (VOID *)(UINTN)mRomEntry[Index].ShadowAddress;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ShadowedSize != NULL) {
 | 
						|
    *ShadowedSize = mRomEntry[Index].ShadowedSize;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Every legacy ROM that is shadowed by the Legacy BIOS driver will be
 | 
						|
  registered into this API so that the policy code can know what has
 | 
						|
  happend
 | 
						|
 | 
						|
  @param  PciHandle              PCI device whos ROM is being shadowed
 | 
						|
  @param  ShadowAddress          Address that ROM was shadowed
 | 
						|
  @param  ShadowedSize           Runtime size of ROM
 | 
						|
  @param  DiskStart              DiskStart value from
 | 
						|
                                 EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
 | 
						|
  @param  DiskEnd                DiskEnd value from
 | 
						|
                                 EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Logging successful.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No remaining room for registering another option
 | 
						|
                                 ROM.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
RomShadow (
 | 
						|
  IN  EFI_HANDLE                                  PciHandle,
 | 
						|
  IN  UINT32                                      ShadowAddress,
 | 
						|
  IN  UINT32                                      ShadowedSize,  
 | 
						|
  IN  UINT8                                       DiskStart,
 | 
						|
  IN  UINT8                                       DiskEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if there is room to register another option ROM
 | 
						|
  //
 | 
						|
  if (mRomCount >= ROM_MAX_ENTRIES) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the PCI I/O Protocol on PciHandle
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  PciHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the location of the PCI device
 | 
						|
  //
 | 
						|
  PciIo->GetLocation (
 | 
						|
           PciIo,
 | 
						|
           &mRomEntry[mRomCount].PciSegment,
 | 
						|
           &mRomEntry[mRomCount].PciBus,
 | 
						|
           &mRomEntry[mRomCount].PciDevice,
 | 
						|
           &mRomEntry[mRomCount].PciFunction
 | 
						|
           );
 | 
						|
  mRomEntry[mRomCount].ShadowAddress = ShadowAddress;
 | 
						|
  mRomEntry[mRomCount].ShadowedSize  = ShadowedSize;
 | 
						|
  mRomEntry[mRomCount].DiskStart     = DiskStart;
 | 
						|
  mRomEntry[mRomCount].DiskEnd       = DiskEnd;
 | 
						|
 | 
						|
  mRomCount++;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This
 | 
						|
  information represents every call to RomShadow ()
 | 
						|
 | 
						|
  @param  PciHandle              PCI device to get status for
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Legacy ROM loaded for this device
 | 
						|
  @retval EFI_NOT_FOUND          No Legacy ROM loaded for this device
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IsLegacyRom (
 | 
						|
  IN  EFI_HANDLE                PciHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
  UINTN               Index;
 | 
						|
  UINTN               Segment;
 | 
						|
  UINTN               Bus;
 | 
						|
  UINTN               Device;
 | 
						|
  UINTN               Function;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the PCI I/O Protocol on PciHandle
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  PciHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the location of the PCI device
 | 
						|
  //
 | 
						|
  PciIo->GetLocation (
 | 
						|
           PciIo,
 | 
						|
           &Segment,
 | 
						|
           &Bus,
 | 
						|
           &Device,
 | 
						|
           &Function
 | 
						|
           );
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the option ROM from PciHandle has been previously posted
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < mRomCount; Index++) {
 | 
						|
    if (mRomEntry[Index].PciSegment == Segment &&
 | 
						|
        mRomEntry[Index].PciBus == Bus &&
 | 
						|
        mRomEntry[Index].PciDevice == Device &&
 | 
						|
        mRomEntry[Index].PciFunction == Function
 | 
						|
        ) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the 
 | 
						|
  related information from the header.
 | 
						|
 | 
						|
  @param  Csm16Revision           The PCI interface version of underlying CSM16
 | 
						|
  @param  VendorId                Vendor ID of the PCI device
 | 
						|
  @param  DeviceId                Device ID of the PCI device
 | 
						|
  @param  Rom                     On input pointing to beginning of the raw PCI OpROM
 | 
						|
                                  On output pointing to the first legacy PCI OpROM
 | 
						|
  @param  ImageSize               On input is the size of Raw PCI Rom
 | 
						|
                                  On output is the size of the first legacy PCI ROM
 | 
						|
  @param  MaxRuntimeImageLength   The max runtime image length only valid if OpRomRevision >= 3
 | 
						|
  @param  OpRomRevision           Revision of the PCI Rom
 | 
						|
  @param  ConfigUtilityCodeHeader Pointer to Configuration Utility Code Header
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             Successfully find the legacy PCI ROM
 | 
						|
  @retval EFI_NOT_FOUND           Failed to find the legacy PCI ROM
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetPciLegacyRom (
 | 
						|
  IN     UINT16 Csm16Revision,
 | 
						|
  IN     UINT16 VendorId,
 | 
						|
  IN     UINT16 DeviceId,
 | 
						|
  IN OUT VOID   **Rom,
 | 
						|
  IN OUT UINTN  *ImageSize,
 | 
						|
  OUT    UINTN  *MaxRuntimeImageLength,   OPTIONAL
 | 
						|
  OUT    UINT8  *OpRomRevision,           OPTIONAL
 | 
						|
  OUT    VOID   **ConfigUtilityCodeHeader OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN                 Match;
 | 
						|
  UINT16                  *DeviceIdList;
 | 
						|
  EFI_PCI_ROM_HEADER      RomHeader;
 | 
						|
  PCI_3_0_DATA_STRUCTURE  *Pcir;
 | 
						|
  VOID                    *BackupImage;
 | 
						|
  VOID                    *BestImage;
 | 
						|
 | 
						|
 | 
						|
  if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  BestImage     = NULL;
 | 
						|
  BackupImage   = NULL;
 | 
						|
  RomHeader.Raw = *Rom;
 | 
						|
  while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | 
						|
    if (RomHeader.Generic->PcirOffset == 0 ||
 | 
						|
        (RomHeader.Generic->PcirOffset & 3) !=0 ||
 | 
						|
        *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
 | 
						|
    //
 | 
						|
    // Check signature in the PCI Data Structure.
 | 
						|
    //
 | 
						|
    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((UINTN)(RomHeader.Raw - (UINT8 *) *Rom) + Pcir->ImageLength * 512 > *ImageSize) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
 | 
						|
      Match = FALSE;
 | 
						|
      if (Pcir->VendorId == VendorId) {
 | 
						|
        if (Pcir->DeviceId == DeviceId) {
 | 
						|
          Match = TRUE;
 | 
						|
        } else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) {
 | 
						|
          DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset);
 | 
						|
          //
 | 
						|
          // Checking the device list
 | 
						|
          //
 | 
						|
          while (*DeviceIdList != 0) {
 | 
						|
            if (*DeviceIdList == DeviceId) {
 | 
						|
              Match = TRUE;
 | 
						|
              break;
 | 
						|
            }
 | 
						|
            DeviceIdList ++;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (Match) {
 | 
						|
        if (Csm16Revision >= 0x0300) {
 | 
						|
          //
 | 
						|
          // Case 1: CSM16 3.0
 | 
						|
          //
 | 
						|
          if (Pcir->Revision >= 3) {
 | 
						|
            //
 | 
						|
            // case 1.1: meets OpRom 3.0
 | 
						|
            //           Perfect!!!
 | 
						|
            //
 | 
						|
            BestImage  = RomHeader.Raw;
 | 
						|
            break;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // case 1.2: meets OpRom 2.x
 | 
						|
            //           Store it and try to find the OpRom 3.0
 | 
						|
            //
 | 
						|
            BackupImage = RomHeader.Raw;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Case 2: CSM16 2.x
 | 
						|
          //
 | 
						|
          if (Pcir->Revision >= 3) {
 | 
						|
            //
 | 
						|
            // case 2.1: meets OpRom 3.0
 | 
						|
            //           Store it and try to find the OpRom 2.x
 | 
						|
            //
 | 
						|
            BackupImage = RomHeader.Raw;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // case 2.2: meets OpRom 2.x
 | 
						|
            //           Perfect!!!
 | 
						|
            //
 | 
						|
            BestImage   = RomHeader.Raw;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    
 | 
						|
    if ((Pcir->Indicator & 0x80) == 0x80) {
 | 
						|
      break;
 | 
						|
    } else {
 | 
						|
      RomHeader.Raw += 512 * Pcir->ImageLength;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (BestImage == NULL) {
 | 
						|
    if (BackupImage == NULL) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // The versions of CSM16 and OpRom don't match exactly
 | 
						|
    //
 | 
						|
    BestImage = BackupImage;
 | 
						|
  }
 | 
						|
  RomHeader.Raw = BestImage;
 | 
						|
  Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
 | 
						|
  *Rom       = BestImage;
 | 
						|
  *ImageSize = Pcir->ImageLength * 512;
 | 
						|
 | 
						|
  if (MaxRuntimeImageLength != NULL) {
 | 
						|
    if (Pcir->Revision < 3) {
 | 
						|
      *MaxRuntimeImageLength = 0;
 | 
						|
    } else {
 | 
						|
      *MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (OpRomRevision != NULL) {
 | 
						|
    // 
 | 
						|
    // Optional return PCI Data Structure revision
 | 
						|
    //
 | 
						|
    if (Pcir->Length >= 0x1C) {
 | 
						|
      *OpRomRevision = Pcir->Revision;
 | 
						|
    } else {
 | 
						|
      *OpRomRevision = 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigUtilityCodeHeader != NULL) {
 | 
						|
    //
 | 
						|
    // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM
 | 
						|
    //
 | 
						|
    if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) {
 | 
						|
      *ConfigUtilityCodeHeader = NULL;
 | 
						|
    } else {
 | 
						|
      *ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Build a table of bridge info for PIRQ translation.
 | 
						|
 | 
						|
  @param  RoutingTable         RoutingTable obtained from Platform.
 | 
						|
  @param  RoutingTableEntries  Number of RoutingTable entries.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          New Subordinate bus.
 | 
						|
  @retval EFI_NOT_FOUND        No more Subordinate busses.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
CreateBridgeTable (
 | 
						|
  IN EFI_LEGACY_IRQ_ROUTING_ENTRY         *RoutingTable,
 | 
						|
  IN UINTN                                RoutingTableEntries
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  UINTN               HandleCount;
 | 
						|
  EFI_HANDLE          *HandleBuffer;
 | 
						|
  UINTN               BridgeIndex;
 | 
						|
  UINTN               Index;
 | 
						|
  UINTN               Index1;
 | 
						|
  EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
  PCI_TYPE01          PciConfigHeader;
 | 
						|
  BRIDGE_TABLE        SlotBridges[MAX_BRIDGE_INDEX];
 | 
						|
  UINTN               SlotBridgeIndex;
 | 
						|
 | 
						|
  BridgeIndex = 0x00;
 | 
						|
  SlotBridgeIndex = 0x00;
 | 
						|
 | 
						|
  //
 | 
						|
  // Assumption is table is built from low bus to high bus numbers.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    PciIo->Pci.Read (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint32,
 | 
						|
                 0,
 | 
						|
                 sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
                 &PciConfigHeader
 | 
						|
                 );
 | 
						|
 | 
						|
    if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX)) {
 | 
						|
      PciIo->GetLocation (
 | 
						|
               PciIo,
 | 
						|
               &Bridges[BridgeIndex].PciSegment,
 | 
						|
               &Bridges[BridgeIndex].PciBus,
 | 
						|
               &Bridges[BridgeIndex].PciDevice,
 | 
						|
               &Bridges[BridgeIndex].PciFunction
 | 
						|
               );
 | 
						|
 | 
						|
      Bridges[BridgeIndex].PrimaryBus     = PciConfigHeader.Bridge.PrimaryBus;
 | 
						|
 | 
						|
      Bridges[BridgeIndex].SecondaryBus   = PciConfigHeader.Bridge.SecondaryBus;
 | 
						|
 | 
						|
      Bridges[BridgeIndex].SubordinateBus = PciConfigHeader.Bridge.SubordinateBus;
 | 
						|
 | 
						|
      for (Index1 = 0; Index1 < RoutingTableEntries; Index1++){
 | 
						|
        //
 | 
						|
        // Test whether we have found the Bridge in the slot, must be the one that directly interfaced to the board
 | 
						|
        // Once we find one, store it in the SlotBridges[]
 | 
						|
        //
 | 
						|
        if ((RoutingTable[Index1].Slot != 0) && (Bridges[BridgeIndex].PrimaryBus == RoutingTable[Index1].Bus)
 | 
						|
           && ((Bridges[BridgeIndex].PciDevice << 3) == RoutingTable[Index1].Device)) {
 | 
						|
          CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], sizeof (BRIDGE_TABLE));
 | 
						|
          SlotBridgeIndex++;
 | 
						|
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      ++BridgeIndex;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Pack up Bridges by removing those useless ones
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < BridgeIndex;){
 | 
						|
    for (Index1 = 0; Index1 < SlotBridgeIndex; Index1++) {
 | 
						|
      if (((Bridges[Index].PciBus == SlotBridges[Index1].PrimaryBus) && (Bridges[Index].PciDevice == SlotBridges[Index1].PciDevice)) ||
 | 
						|
        ((Bridges[Index].PciBus >= SlotBridges[Index1].SecondaryBus) && (Bridges[Index].PciBus <= SlotBridges[Index1].SubordinateBus))) {
 | 
						|
        //
 | 
						|
        // We have found one that meets our criteria
 | 
						|
        //
 | 
						|
        Index++;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // This one doesn't meet criteria, pack it
 | 
						|
    //
 | 
						|
    if (Index1 >= SlotBridgeIndex) {
 | 
						|
      for (Index1 = Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ; Index1++) {
 | 
						|
        CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TABLE));
 | 
						|
      }
 | 
						|
 | 
						|
      BridgeIndex--;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  NumberOfBridges = BridgeIndex;
 | 
						|
 | 
						|
  //
 | 
						|
  // Sort bridges low to high by Secondary bus followed by subordinate bus
 | 
						|
  //
 | 
						|
  if (NumberOfBridges > 1) {
 | 
						|
    Index = 0;
 | 
						|
    do {
 | 
						|
      SortedBridgeIndex[Index] = Index;
 | 
						|
      ++Index;
 | 
						|
    } while (Index < NumberOfBridges);
 | 
						|
 | 
						|
    for (Index = 0; Index < NumberOfBridges - 1; Index++) {
 | 
						|
      for (Index1 = Index + 1; Index1 < NumberOfBridges; Index1++) {
 | 
						|
        if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) {
 | 
						|
          SortedBridgeIndex[Index]  = Index1;
 | 
						|
          SortedBridgeIndex[Index1] = Index;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((Bridges[Index].SecondaryBus == Bridges[Index1].SecondaryBus) &&
 | 
						|
            (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBus)
 | 
						|
            ) {
 | 
						|
          SortedBridgeIndex[Index]  = Index1;
 | 
						|
          SortedBridgeIndex[Index1] = Index;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Find base Bridge for device.
 | 
						|
 | 
						|
  @param  Private                Legacy  BIOS Instance data
 | 
						|
  @param  PciBus                 Input = Bus of device.
 | 
						|
  @param  PciDevice              Input = Device.
 | 
						|
  @param  RoutingTable           The platform specific routing table
 | 
						|
  @param  RoutingTableEntries    Number of entries in table
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            At base bus.
 | 
						|
  @retval EFI_NOT_FOUND          Behind a bridge.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetBaseBus (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE        *Private,
 | 
						|
  IN UINTN                        PciBus,
 | 
						|
  IN UINTN                        PciDevice,
 | 
						|
  IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,
 | 
						|
  IN UINTN                        RoutingTableEntries
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Index;
 | 
						|
  for (Index = 0; Index < RoutingTableEntries; Index++) {
 | 
						|
    if ((RoutingTable[Index].Bus == PciBus) && (RoutingTable[Index].Device == (PciDevice << 3))) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Translate PIRQ through busses
 | 
						|
 | 
						|
  @param  Private              Legacy  BIOS Instance data
 | 
						|
  @param  PciBus               Input = Bus of device. Output = Translated Bus
 | 
						|
  @param  PciDevice            Input = Device. Output = Translated Device
 | 
						|
  @param  PciFunction          Input = Function. Output = Translated Function
 | 
						|
  @param  PirqIndex            Input = Original PIRQ index. If single function
 | 
						|
                                  device then 0, otherwise 0-3.
 | 
						|
                               Output = Translated Index
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          Pirq successfully translated.
 | 
						|
  @retval EFI_NOT_FOUND        The device is not behind any known bridge.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
TranslateBusPirq (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE            *Private,
 | 
						|
  IN OUT UINTN                        *PciBus,
 | 
						|
  IN OUT UINTN                        *PciDevice,
 | 
						|
  IN OUT UINTN                        *PciFunction,
 | 
						|
  IN OUT UINT8                        *PirqIndex
 | 
						|
  )
 | 
						|
{
 | 
						|
  /*
 | 
						|
  This routine traverses the PCI busses from base slot
 | 
						|
  and translates the PIRQ register to the appropriate one.
 | 
						|
 | 
						|
  Example:
 | 
						|
 | 
						|
  Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on.
 | 
						|
    Primary bus# = 0
 | 
						|
    Secondary bus # = 1
 | 
						|
    Subordinate bus # is highest bus # behind this bus
 | 
						|
       Bus 1, Device 0 is Slot 0 and is not a bridge.
 | 
						|
       Bus 1, Device 1 is Slot 1 and is a bridge.
 | 
						|
         Slot PIRQ routing is A,B,C,D.
 | 
						|
         Primary bus # = 1
 | 
						|
         Secondary bus # = 2
 | 
						|
         Subordinate bus # = 5
 | 
						|
            Bus 2, Device 6 is a bridge. It has no bridges behind it.
 | 
						|
              Primary bus # = 2
 | 
						|
              Secondary bus # = 3
 | 
						|
              Subordinate bus # = 3
 | 
						|
              Bridge PIRQ routing is C,D,A,B
 | 
						|
            Bus 2, Device 7 is a bridge. It has 1 bridge behind it.
 | 
						|
              Primary bus # = 2
 | 
						|
              Secondary bus = 4   Device 6 takes bus 2.
 | 
						|
              Subordinate bus = 5.
 | 
						|
              Bridge PIRQ routing is D,A,B,C
 | 
						|
                 Bus 4, Device 2 is a bridge. It has no bridges behind it.
 | 
						|
                   Primary bus # = 4
 | 
						|
                   Secondary bus # = 5
 | 
						|
                   Subordinate bus = 5
 | 
						|
                   Bridge PIRQ routing is B,C,D,A
 | 
						|
                      Bus 5, Device 1 is to be programmed.
 | 
						|
                         Device PIRQ routing is C,D,A,B
 | 
						|
 | 
						|
 | 
						|
Search busses starting from slot bus for final bus >= Secondary bus and
 | 
						|
final bus <= Suborninate bus. Assumption is bus entries increase in bus
 | 
						|
number.
 | 
						|
Starting PIRQ is A,B,C,D.
 | 
						|
Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device
 | 
						|
  7 modulo 4 giving (D,A,B,C).
 | 
						|
Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 giving
 | 
						|
  (B,C,D,A).
 | 
						|
No other busses match criteria. Device to be programmed is Bus 5, Device 1.
 | 
						|
Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C.
 | 
						|
 | 
						|
*/
 | 
						|
  UINTN LocalBus;
 | 
						|
  UINTN LocalDevice;
 | 
						|
  UINTN BaseBus;
 | 
						|
  UINTN BaseDevice;
 | 
						|
  UINTN BaseFunction;
 | 
						|
  UINT8 LocalPirqIndex;
 | 
						|
  BOOLEAN BaseIndexFlag;
 | 
						|
  UINTN BridgeIndex;
 | 
						|
  UINTN SBridgeIndex;
 | 
						|
  BaseIndexFlag   = FALSE;
 | 
						|
  BridgeIndex     = 0x00;
 | 
						|
 | 
						|
  LocalPirqIndex  = *PirqIndex;
 | 
						|
  LocalBus        = *PciBus;
 | 
						|
  LocalDevice     = *PciDevice;
 | 
						|
  BaseBus         = *PciBus;
 | 
						|
  BaseDevice      = *PciDevice;
 | 
						|
  BaseFunction    = *PciFunction;
 | 
						|
 | 
						|
  //
 | 
						|
  // LocalPirqIndex list PIRQs in rotated fashion
 | 
						|
  // = 0  A,B,C,D
 | 
						|
  // = 1  B,C,D,A
 | 
						|
  // = 2  C,D,A,B
 | 
						|
  // = 3  D,A,B,C
 | 
						|
  //
 | 
						|
 | 
						|
  for (BridgeIndex = 0; BridgeIndex < NumberOfBridges; BridgeIndex++) {
 | 
						|
    SBridgeIndex = SortedBridgeIndex[BridgeIndex];
 | 
						|
    //
 | 
						|
    // Check if device behind this bridge
 | 
						|
    //
 | 
						|
    if ((LocalBus >= Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= Bridges[SBridgeIndex].SubordinateBus)) {
 | 
						|
      //
 | 
						|
      // If BaseIndexFlag = FALSE then have found base bridge, i.e
 | 
						|
      // bridge in slot. Save info for use by IRQ routing table.
 | 
						|
      //
 | 
						|
      if (!BaseIndexFlag) {
 | 
						|
        BaseBus       = Bridges[SBridgeIndex].PciBus;
 | 
						|
        BaseDevice    = Bridges[SBridgeIndex].PciDevice;
 | 
						|
        BaseFunction  = Bridges[SBridgeIndex].PciFunction;
 | 
						|
        BaseIndexFlag = TRUE;
 | 
						|
      } else {
 | 
						|
        LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBridgeIndex].PciDevice)%4);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Check if at device. If not get new PCI location & PIRQ
 | 
						|
      //
 | 
						|
      if (Bridges[SBridgeIndex].SecondaryBus == (UINT8) LocalBus) {
 | 
						|
        //
 | 
						|
        // Translate PIRQ
 | 
						|
        //
 | 
						|
        LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice)) % 4);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // In case we fail to find the Bridge just above us, this is some potential error and we want to warn the user
 | 
						|
  //
 | 
						|
  if(BridgeIndex >= NumberOfBridges){
 | 
						|
    DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, Function %d\n", *PciBus, *PciDevice, *PciFunction));
 | 
						|
  }
 | 
						|
 | 
						|
  *PirqIndex    = LocalPirqIndex;
 | 
						|
  *PciBus       = BaseBus;
 | 
						|
  *PciDevice    = BaseDevice;
 | 
						|
  *PciFunction  = BaseFunction;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Copy the $PIR table as required.
 | 
						|
 | 
						|
  @param  Private                Legacy  BIOS Instance data
 | 
						|
  @param  RoutingTable           Pointer to IRQ routing table
 | 
						|
  @param  RoutingTableEntries    IRQ routing table entries
 | 
						|
  @param  PirqTable              Pointer to $PIR table
 | 
						|
  @param  PirqTableSize          Length of table
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CopyPirqTable (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE                *Private,
 | 
						|
  IN EFI_LEGACY_IRQ_ROUTING_ENTRY         *RoutingTable,
 | 
						|
  IN UINTN                                RoutingTableEntries,
 | 
						|
  IN EFI_LEGACY_PIRQ_TABLE_HEADER         *PirqTable,
 | 
						|
  IN UINTN                                PirqTableSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IA32_REGISTER_SET Regs;
 | 
						|
  UINT32                Granularity;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy $PIR table, if it exists.
 | 
						|
  //
 | 
						|
  if (PirqTable != NULL) {
 | 
						|
    Private->LegacyRegion->UnLock (
 | 
						|
                            Private->LegacyRegion,
 | 
						|
                            0xE0000,
 | 
						|
                            0x20000,
 | 
						|
                            &Granularity
 | 
						|
                            );
 | 
						|
 | 
						|
    Private->InternalIrqRoutingTable  = RoutingTable;
 | 
						|
    Private->NumberIrqRoutingEntries  = (UINT16) (RoutingTableEntries);
 | 
						|
    ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
 | 
						|
 | 
						|
    Regs.X.AX = Legacy16GetTableAddress;
 | 
						|
    Regs.X.CX = (UINT16) PirqTableSize;
 | 
						|
    //
 | 
						|
    // Allocate at F segment according to PCI IRQ Routing Table Specification
 | 
						|
    //
 | 
						|
    Regs.X.BX = (UINT16) 0x1;
 | 
						|
    //
 | 
						|
    // 16-byte boundary alignment requirement according to 
 | 
						|
    // PCI IRQ Routing Table Specification
 | 
						|
    //
 | 
						|
    Regs.X.DX = 0x10;
 | 
						|
    Private->LegacyBios.FarCall86 (
 | 
						|
      &Private->LegacyBios,
 | 
						|
      Private->Legacy16CallSegment,
 | 
						|
      Private->Legacy16CallOffset,
 | 
						|
      &Regs,
 | 
						|
      NULL,
 | 
						|
      0
 | 
						|
      );
 | 
						|
 | 
						|
    Private->Legacy16Table->IrqRoutingTablePointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);
 | 
						|
    if (Regs.X.AX != 0) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTableSize));
 | 
						|
    } else {
 | 
						|
      DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->Legacy16Table->IrqRoutingTablePointer));   
 | 
						|
      Private->Legacy16Table->IrqRoutingTableLength = (UINT32)PirqTableSize;
 | 
						|
      CopyMem (
 | 
						|
        (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer,
 | 
						|
        PirqTable,
 | 
						|
        PirqTableSize
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
 | 
						|
    Private->LegacyRegion->Lock (
 | 
						|
                             Private->LegacyRegion,
 | 
						|
                             0xE0000,
 | 
						|
                             0x20000,
 | 
						|
                             &Granularity
 | 
						|
                             );
 | 
						|
  }
 | 
						|
 | 
						|
  Private->PciInterruptLine = TRUE;
 | 
						|
  mHandleCount              = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information.
 | 
						|
 | 
						|
  @param  PciHandle               The pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
DumpPciHandle (
 | 
						|
  IN EFI_LEGACY_INSTALL_PCI_HANDLER  *PciHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG ((EFI_D_INFO, "PciBus             - %02x\n", (UINTN)PciHandle->PciBus));
 | 
						|
  DEBUG ((EFI_D_INFO, "PciDeviceFun       - %02x\n", (UINTN)PciHandle->PciDeviceFun));
 | 
						|
  DEBUG ((EFI_D_INFO, "PciSegment         - %02x\n", (UINTN)PciHandle->PciSegment));
 | 
						|
  DEBUG ((EFI_D_INFO, "PciClass           - %02x\n", (UINTN)PciHandle->PciClass));
 | 
						|
  DEBUG ((EFI_D_INFO, "PciSubclass        - %02x\n", (UINTN)PciHandle->PciSubclass));
 | 
						|
  DEBUG ((EFI_D_INFO, "PciInterface       - %02x\n", (UINTN)PciHandle->PciInterface));
 | 
						|
 | 
						|
  DEBUG ((EFI_D_INFO, "PrimaryIrq         - %02x\n", (UINTN)PciHandle->PrimaryIrq));
 | 
						|
  DEBUG ((EFI_D_INFO, "PrimaryReserved    - %02x\n", (UINTN)PciHandle->PrimaryReserved));
 | 
						|
  DEBUG ((EFI_D_INFO, "PrimaryControl     - %04x\n", (UINTN)PciHandle->PrimaryControl));
 | 
						|
  DEBUG ((EFI_D_INFO, "PrimaryBase        - %04x\n", (UINTN)PciHandle->PrimaryBase));
 | 
						|
  DEBUG ((EFI_D_INFO, "PrimaryBusMaster   - %04x\n", (UINTN)PciHandle->PrimaryBusMaster));
 | 
						|
 | 
						|
  DEBUG ((EFI_D_INFO, "SecondaryIrq       - %02x\n", (UINTN)PciHandle->SecondaryIrq));
 | 
						|
  DEBUG ((EFI_D_INFO, "SecondaryReserved  - %02x\n", (UINTN)PciHandle->SecondaryReserved));
 | 
						|
  DEBUG ((EFI_D_INFO, "SecondaryControl   - %04x\n", (UINTN)PciHandle->SecondaryControl));
 | 
						|
  DEBUG ((EFI_D_INFO, "SecondaryBase      - %04x\n", (UINTN)PciHandle->SecondaryBase));
 | 
						|
  DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->SecondaryBusMaster));
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy the $PIR table as required.
 | 
						|
 | 
						|
  @param  Private                Legacy  BIOS Instance data
 | 
						|
  @param  PciIo                  Pointer to PCI_IO protocol
 | 
						|
  @param  PciIrq                 Pci IRQ number
 | 
						|
  @param  PciConfigHeader        Type00 Pci configuration header
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
InstallLegacyIrqHandler (
 | 
						|
  IN LEGACY_BIOS_INSTANCE       *Private,
 | 
						|
  IN EFI_PCI_IO_PROTOCOL        *PciIo,
 | 
						|
  IN UINT8                      PciIrq,
 | 
						|
  IN PCI_TYPE00                 *PciConfigHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IA32_REGISTER_SET     Regs;
 | 
						|
  UINT16                    LegMask;
 | 
						|
  UINTN                     PciSegment;
 | 
						|
  UINTN                     PciBus;
 | 
						|
  UINTN                     PciDevice;
 | 
						|
  UINTN                     PciFunction;
 | 
						|
  EFI_LEGACY_8259_PROTOCOL  *Legacy8259;
 | 
						|
  UINT16                    PrimaryMaster;
 | 
						|
  UINT16                    SecondaryMaster;
 | 
						|
  UINTN                     TempData;
 | 
						|
  UINTN                     RegisterAddress;
 | 
						|
  UINT32                    Granularity;
 | 
						|
 | 
						|
  PrimaryMaster   = 0;
 | 
						|
  SecondaryMaster = 0;
 | 
						|
  Legacy8259      = Private->Legacy8259;
 | 
						|
  //
 | 
						|
  // Disable interrupt in PIC, in case shared, to prevent an
 | 
						|
  // interrupt from occuring.
 | 
						|
  //
 | 
						|
  Legacy8259->GetMask (
 | 
						|
                Legacy8259,
 | 
						|
                &LegMask,
 | 
						|
                NULL,
 | 
						|
                NULL,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
 | 
						|
  LegMask = (UINT16) (LegMask | (UINT16) (1 << PciIrq));
 | 
						|
 | 
						|
  Legacy8259->SetMask (
 | 
						|
                Legacy8259,
 | 
						|
                &LegMask,
 | 
						|
                NULL,
 | 
						|
                NULL,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
 | 
						|
  PciIo->GetLocation (
 | 
						|
          PciIo,
 | 
						|
          &PciSegment,
 | 
						|
          &PciBus,
 | 
						|
          &PciDevice,
 | 
						|
          &PciFunction
 | 
						|
          );
 | 
						|
  Private->IntThunk->PciHandler.PciBus              = (UINT8) PciBus;
 | 
						|
  Private->IntThunk->PciHandler.PciDeviceFun        = (UINT8) ((PciDevice << 3) + PciFunction);
 | 
						|
  Private->IntThunk->PciHandler.PciSegment          = (UINT8) PciSegment;
 | 
						|
  Private->IntThunk->PciHandler.PciClass            = PciConfigHeader->Hdr.ClassCode[2];
 | 
						|
  Private->IntThunk->PciHandler.PciSubclass         = PciConfigHeader->Hdr.ClassCode[1];
 | 
						|
  Private->IntThunk->PciHandler.PciInterface        = PciConfigHeader->Hdr.ClassCode[0];
 | 
						|
 | 
						|
  //
 | 
						|
  // Use native mode base address registers in two cases:
 | 
						|
  // 1. Programming Interface (PI) register indicates Primary Controller is
 | 
						|
  // in native mode OR
 | 
						|
  // 2. PCI device Sub Class Code is not IDE
 | 
						|
  //
 | 
						|
  Private->IntThunk->PciHandler.PrimaryBusMaster  = (UINT16)(PciConfigHeader->Device.Bar[4] & 0xfffc);
 | 
						|
  if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {
 | 
						|
    Private->IntThunk->PciHandler.PrimaryIrq      = PciIrq;
 | 
						|
    Private->IntThunk->PciHandler.PrimaryBase     = (UINT16) (PciConfigHeader->Device.Bar[0] & 0xfffc);
 | 
						|
    Private->IntThunk->PciHandler.PrimaryControl  = (UINT16) ((PciConfigHeader->Device.Bar[1] & 0xfffc) + 2);
 | 
						|
  } else {
 | 
						|
    Private->IntThunk->PciHandler.PrimaryIrq      = 14;
 | 
						|
    Private->IntThunk->PciHandler.PrimaryBase     = 0x1f0;
 | 
						|
    Private->IntThunk->PciHandler.PrimaryControl  = 0x3f6;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Secondary controller data
 | 
						|
  //
 | 
						|
  if (Private->IntThunk->PciHandler.PrimaryBusMaster != 0) {
 | 
						|
    Private->IntThunk->PciHandler.SecondaryBusMaster  = (UINT16) ((PciConfigHeader->Device.Bar[4] & 0xfffc) + 8);
 | 
						|
    PrimaryMaster = (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMaster + 2);
 | 
						|
    SecondaryMaster = (UINT16) (Private->IntThunk->PciHandler.SecondaryBusMaster + 2);
 | 
						|
 | 
						|
    //
 | 
						|
    // Clear pending interrupts in Bus Master registers
 | 
						|
    //
 | 
						|
    IoWrite16 (PrimaryMaster, 0x04);
 | 
						|
    IoWrite16 (SecondaryMaster, 0x04);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Use native mode base address registers in two cases:
 | 
						|
  // 1. Programming Interface (PI) register indicates Secondary Controller is
 | 
						|
  // in native mode OR
 | 
						|
  // 2. PCI device Sub Class Code is not IDE
 | 
						|
  //
 | 
						|
  if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {
 | 
						|
    Private->IntThunk->PciHandler.SecondaryIrq      = PciIrq;
 | 
						|
    Private->IntThunk->PciHandler.SecondaryBase     = (UINT16) (PciConfigHeader->Device.Bar[2] & 0xfffc);
 | 
						|
    Private->IntThunk->PciHandler.SecondaryControl  = (UINT16) ((PciConfigHeader->Device.Bar[3] & 0xfffc) + 2);
 | 
						|
  } else {
 | 
						|
 | 
						|
    Private->IntThunk->PciHandler.SecondaryIrq      = 15;
 | 
						|
    Private->IntThunk->PciHandler.SecondaryBase     = 0x170;
 | 
						|
    Private->IntThunk->PciHandler.SecondaryControl  = 0x376;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear pending interrupts in IDE Command Block Status reg before we
 | 
						|
  // Thunk to CSM16 below.  Don't want a pending Interrupt before we
 | 
						|
  // install the handlers as wierd corruption would occur and hang system.
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // Read IDE CMD blk status reg to clear out any pending interrupts.
 | 
						|
  // Do here for Primary and Secondary IDE channels
 | 
						|
  //
 | 
						|
  RegisterAddress = (UINT16)Private->IntThunk->PciHandler.PrimaryBase + 0x07;
 | 
						|
  IoRead8 (RegisterAddress);
 | 
						|
  RegisterAddress = (UINT16)Private->IntThunk->PciHandler.SecondaryBase + 0x07;
 | 
						|
  IoRead8 (RegisterAddress);
 | 
						|
 | 
						|
  Private->IntThunk->PciHandler.PrimaryReserved   = 0;
 | 
						|
  Private->IntThunk->PciHandler.SecondaryReserved = 0;
 | 
						|
  Private->LegacyRegion->UnLock (
 | 
						|
                           Private->LegacyRegion,
 | 
						|
                           0xE0000,
 | 
						|
                           0x20000,
 | 
						|
                           &Granularity
 | 
						|
                           );
 | 
						|
 | 
						|
  Regs.X.AX = Legacy16InstallPciHandler;
 | 
						|
  TempData  = (UINTN) &Private->IntThunk->PciHandler;
 | 
						|
  Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);
 | 
						|
  Regs.X.BX = EFI_OFFSET ((UINT32) TempData);
 | 
						|
 | 
						|
  DumpPciHandle (&Private->IntThunk->PciHandler);
 | 
						|
 | 
						|
  Private->LegacyBios.FarCall86 (
 | 
						|
    &Private->LegacyBios,
 | 
						|
    Private->Legacy16CallSegment,
 | 
						|
    Private->Legacy16CallOffset,
 | 
						|
    &Regs,
 | 
						|
    NULL,
 | 
						|
    0
 | 
						|
    );
 | 
						|
 | 
						|
  Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
 | 
						|
  Private->LegacyRegion->Lock (
 | 
						|
                           Private->LegacyRegion,
 | 
						|
                           0xE0000,
 | 
						|
                           0x20000,
 | 
						|
                           &Granularity
 | 
						|
                           );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Program the interrupt routing register in all the PCI devices. On a PC AT system
 | 
						|
  this register contains the 8259 IRQ vector that matches it's PCI interrupt.
 | 
						|
 | 
						|
  @param  Private                Legacy  BIOS Instance data
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Succeed.
 | 
						|
  @retval EFI_ALREADY_STARTED    All PCI devices have been processed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PciProgramAllInterruptLineRegisters (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE      *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL               *PciIo;
 | 
						|
  EFI_LEGACY_8259_PROTOCOL          *Legacy8259;
 | 
						|
  EFI_LEGACY_INTERRUPT_PROTOCOL     *LegacyInterrupt;
 | 
						|
  EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;
 | 
						|
  UINT8                             InterruptPin;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             HandleCount;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  UINTN                             MassStorageHandleCount;
 | 
						|
  EFI_HANDLE                        *MassStorageHandleBuffer;
 | 
						|
  UINTN                             MassStorageHandleIndex;
 | 
						|
  UINT8                             PciIrq;
 | 
						|
  UINT16                            Command;
 | 
						|
  UINTN                             PciSegment;
 | 
						|
  UINTN                             PciBus;
 | 
						|
  UINTN                             PciDevice;
 | 
						|
  UINTN                             PciFunction;
 | 
						|
  EFI_LEGACY_IRQ_ROUTING_ENTRY      *RoutingTable;
 | 
						|
  UINTN                             RoutingTableEntries;
 | 
						|
  UINT16                            LegMask;
 | 
						|
  UINT16                            LegEdgeLevel;
 | 
						|
  PCI_TYPE00                        PciConfigHeader;
 | 
						|
  EFI_LEGACY_PIRQ_TABLE_HEADER      *PirqTable;
 | 
						|
  UINTN                             PirqTableSize;
 | 
						|
  UINTN                             Flags;
 | 
						|
  HDD_INFO                          *HddInfo;
 | 
						|
  UINT64                            Supports;
 | 
						|
 | 
						|
  //
 | 
						|
  // Note - This routine use to return immediately if Private->PciInterruptLine
 | 
						|
  //        was true. Routine changed since resets etc can cause not all
 | 
						|
  //        PciIo protocols to be registered the first time through.
 | 
						|
  // New algorithm is to do the copy $PIR table on first pass and save
 | 
						|
  // HandleCount on first pass. If subsequent passes LocateHandleBuffer gives
 | 
						|
  // a larger handle count then proceed with body of function else return
 | 
						|
  // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != 0.
 | 
						|
  // If zero then function unprogrammed else skip function.
 | 
						|
  //
 | 
						|
  Legacy8259          = Private->Legacy8259;
 | 
						|
  LegacyInterrupt     = Private->LegacyInterrupt;
 | 
						|
  LegacyBiosPlatform  = Private->LegacyBiosPlatform;
 | 
						|
 | 
						|
  LegacyBiosPlatform->GetRoutingTable (
 | 
						|
                        Private->LegacyBiosPlatform,
 | 
						|
                        (VOID *) &RoutingTable,
 | 
						|
                        &RoutingTableEntries,
 | 
						|
                        (VOID *) &PirqTable,
 | 
						|
                        &PirqTableSize,
 | 
						|
                        NULL,
 | 
						|
                        NULL
 | 
						|
                        );
 | 
						|
  CreateBridgeTable (RoutingTable, RoutingTableEntries);
 | 
						|
 | 
						|
  if (!Private->PciInterruptLine) {
 | 
						|
    CopyPirqTable (
 | 
						|
      Private,
 | 
						|
      RoutingTable,
 | 
						|
      RoutingTableEntries,
 | 
						|
      PirqTable,
 | 
						|
      PirqTableSize
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  if (HandleCount == mHandleCount) {
 | 
						|
    FreePool (HandleBuffer);
 | 
						|
    return EFI_ALREADY_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mHandleCount == 0x00) {
 | 
						|
    mHandleCount = HandleCount;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
    //
 | 
						|
    // If VGA then only do VGA to allow drives fore time to spin up
 | 
						|
    // otherwise assign PCI IRQs to all potential devices.
 | 
						|
    //
 | 
						|
    if ((mVgaInstallationInProgress) && (HandleBuffer[Index] != mVgaHandle)) {
 | 
						|
      continue;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Force code to go through all handles next time called if video.
 | 
						|
      // This will catch case where HandleCount doesn't change but want
 | 
						|
      //  to get drive info etc.
 | 
						|
      //
 | 
						|
      mHandleCount = 0x00;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Test whether the device can be enabled or not.
 | 
						|
    // If it can't be enabled, then just skip it to avoid further operation.
 | 
						|
    //
 | 
						|
    PciIo->Pci.Read (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint32,
 | 
						|
                 0,
 | 
						|
                 sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
                 &PciConfigHeader
 | 
						|
                 );
 | 
						|
    Command = PciConfigHeader.Hdr.Command;
 | 
						|
 | 
						|
    //
 | 
						|
    // Note PciIo->Attributes does not program the PCI command register
 | 
						|
    //
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationSupported,
 | 
						|
                      0,
 | 
						|
                      &Supports
 | 
						|
                      );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | 
						|
      Status = PciIo->Attributes (
 | 
						|
                        PciIo,
 | 
						|
                        EfiPciIoAttributeOperationEnable,
 | 
						|
                        Supports,
 | 
						|
                        NULL
 | 
						|
                        );
 | 
						|
    }
 | 
						|
    PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command);
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    InterruptPin = PciConfigHeader.Device.InterruptPin;
 | 
						|
 | 
						|
    if ((InterruptPin != 0) && (PciConfigHeader.Device.InterruptLine == PCI_INT_LINE_UNKNOWN)) {
 | 
						|
      PciIo->GetLocation (
 | 
						|
               PciIo,
 | 
						|
               &PciSegment,
 | 
						|
               &PciBus,
 | 
						|
               &PciDevice,
 | 
						|
               &PciFunction
 | 
						|
               );
 | 
						|
      //
 | 
						|
      // Translate PIRQ index back thru busses to slot bus with InterruptPin
 | 
						|
      // zero based
 | 
						|
      //
 | 
						|
      InterruptPin -= 1;
 | 
						|
 | 
						|
      Status = GetBaseBus (
 | 
						|
                 Private,
 | 
						|
                 PciBus,
 | 
						|
                 PciDevice,
 | 
						|
                 RoutingTable,
 | 
						|
                 RoutingTableEntries
 | 
						|
                 );
 | 
						|
 | 
						|
      if (Status == EFI_NOT_FOUND) {
 | 
						|
        TranslateBusPirq (
 | 
						|
          Private,
 | 
						|
          &PciBus,
 | 
						|
          &PciDevice,
 | 
						|
          &PciFunction,
 | 
						|
          &InterruptPin
 | 
						|
          );
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Translate InterruptPin(0-3) into PIRQ
 | 
						|
      //
 | 
						|
      Status = LegacyBiosPlatform->TranslatePirq (
 | 
						|
                                     LegacyBiosPlatform,
 | 
						|
                                     PciBus,
 | 
						|
                                     (PciDevice << 3),
 | 
						|
                                     PciFunction,
 | 
						|
                                     &InterruptPin,
 | 
						|
                                     &PciIrq
 | 
						|
                                     );
 | 
						|
      //
 | 
						|
      // TranslatePirq() should never fail or we are in trouble
 | 
						|
      // If it does return failure status, check your PIRQ routing table to see if some item is missing or incorrect
 | 
						|
      //
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status = %r\n ", Status));
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      LegacyInterrupt->WritePirq (
 | 
						|
                         LegacyInterrupt,
 | 
						|
                         InterruptPin,
 | 
						|
                         PciIrq
 | 
						|
                         );
 | 
						|
 | 
						|
      //
 | 
						|
      // Check if device has an OPROM associated with it.
 | 
						|
      // If not invoke special 16-bit function, to allow 16-bit
 | 
						|
      // code to install an interrupt handler.
 | 
						|
      //
 | 
						|
      Status = LegacyBiosCheckPciRom (
 | 
						|
                 &Private->LegacyBios,
 | 
						|
                 HandleBuffer[Index],
 | 
						|
                 NULL,
 | 
						|
                 NULL,
 | 
						|
                 &Flags
 | 
						|
                 );
 | 
						|
      if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE)) {
 | 
						|
        //
 | 
						|
        // Device has no OPROM associated with it and is a mass storage
 | 
						|
        // device. It needs to have an PCI IRQ handler installed. To
 | 
						|
        // correctly install the handler we need to insure device is
 | 
						|
        // connected. The device may just have register itself but not
 | 
						|
        // been connected. Re-read PCI config space after as it can
 | 
						|
        // change
 | 
						|
        //
 | 
						|
        //
 | 
						|
        // Get IDE Handle. If matches handle then skip ConnectController
 | 
						|
        // since ConnectController may force native mode and we don't
 | 
						|
        // want that for primary IDE controller
 | 
						|
        //
 | 
						|
        MassStorageHandleCount = 0;
 | 
						|
        MassStorageHandleBuffer = NULL;
 | 
						|
        LegacyBiosPlatform->GetPlatformHandle (
 | 
						|
                              Private->LegacyBiosPlatform,
 | 
						|
                              EfiGetPlatformIdeHandle,
 | 
						|
                              0,
 | 
						|
                              &MassStorageHandleBuffer,
 | 
						|
                              &MassStorageHandleCount,
 | 
						|
                              NULL
 | 
						|
                              );
 | 
						|
 | 
						|
        HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
 | 
						|
 | 
						|
        LegacyBiosBuildIdeData (Private, &HddInfo, 0);
 | 
						|
        PciIo->Pci.Read (
 | 
						|
                     PciIo,
 | 
						|
                     EfiPciIoWidthUint32,
 | 
						|
                     0,
 | 
						|
                     sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
                     &PciConfigHeader
 | 
						|
                     );
 | 
						|
 | 
						|
        for (MassStorageHandleIndex = 0; MassStorageHandleIndex < MassStorageHandleCount; MassStorageHandleIndex++) {
 | 
						|
          if (MassStorageHandleBuffer[MassStorageHandleIndex] == HandleBuffer[Index]) {
 | 
						|
            //
 | 
						|
            // InstallLegacyIrqHandler according to Platform requirement
 | 
						|
            //
 | 
						|
            InstallLegacyIrqHandler (
 | 
						|
              Private,
 | 
						|
              PciIo,
 | 
						|
              PciIrq,
 | 
						|
              &PciConfigHeader
 | 
						|
              );
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Write InterruptPin and enable 8259.
 | 
						|
      //
 | 
						|
      PciIo->Pci.Write (
 | 
						|
                   PciIo,
 | 
						|
                   EfiPciIoWidthUint8,
 | 
						|
                   0x3c,
 | 
						|
                   1,
 | 
						|
                   &PciIrq
 | 
						|
                   );
 | 
						|
      Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask = (UINT16) (Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq));
 | 
						|
 | 
						|
      Legacy8259->GetMask (
 | 
						|
                    Legacy8259,
 | 
						|
                    &LegMask,
 | 
						|
                    &LegEdgeLevel,
 | 
						|
                    NULL,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
 | 
						|
      LegMask       = (UINT16) (LegMask & (UINT16)~(1 << PciIrq));
 | 
						|
      LegEdgeLevel  = (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq));
 | 
						|
      Legacy8259->SetMask (
 | 
						|
                    Legacy8259,
 | 
						|
                    &LegMask,
 | 
						|
                    &LegEdgeLevel,
 | 
						|
                    NULL,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    }
 | 
						|
  }
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Find & verify PnP Expansion header in ROM image
 | 
						|
 | 
						|
  @param  Private                Protocol instance pointer.
 | 
						|
  @param  FirstHeader            1 = Find first header, 0 = Find successive headers
 | 
						|
  @param  PnpPtr                 Input Rom start if FirstHeader =1, Current Header
 | 
						|
                                 otherwise Output Next header, if it exists
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Next Header found at BasePnpPtr
 | 
						|
  @retval EFI_NOT_FOUND          No more headers
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FindNextPnpExpansionHeader (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE             *Private,
 | 
						|
  IN BOOLEAN                           FirstHeader,
 | 
						|
  IN OUT LEGACY_PNP_EXPANSION_HEADER   **PnpPtr
 | 
						|
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       TempData;
 | 
						|
  LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr;
 | 
						|
  LocalPnpPtr = *PnpPtr;
 | 
						|
  if (FirstHeader == FIRST_INSTANCE) {
 | 
						|
    mBasePnpPtr     = LocalPnpPtr;
 | 
						|
    mBbsRomSegment  = (UINT16) ((UINTN) mBasePnpPtr >> 4);
 | 
						|
    //
 | 
						|
    // Offset 0x1a gives offset to PnP expansion header for the first
 | 
						|
    // instance, there after the structure gives the offset to the next
 | 
						|
    // structure
 | 
						|
    //
 | 
						|
    LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr + 0x1a);
 | 
						|
    TempData    = (*((UINT16 *) LocalPnpPtr));
 | 
						|
  } else {
 | 
						|
    TempData = (UINT16) LocalPnpPtr->NextHeader;
 | 
						|
  }
 | 
						|
 | 
						|
  LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr + TempData));
 | 
						|
 | 
						|
  //
 | 
						|
  // Search for PnP table in Shadowed ROM
 | 
						|
  //
 | 
						|
  *PnpPtr = LocalPnpPtr;
 | 
						|
  if (*(UINT32 *) LocalPnpPtr == SIGNATURE_32 ('$', 'P', 'n', 'P')) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Update list of Bev or BCV table entries.
 | 
						|
 | 
						|
  @param  Private                Protocol instance pointer.
 | 
						|
  @param  RomStart               Table of ROM start address in RAM/ROM. PciIo  _
 | 
						|
                                 Handle to PCI IO for this device
 | 
						|
  @param  PciIo                  Instance of PCI I/O Protocol
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Always should succeed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
UpdateBevBcvTable (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE             *Private,
 | 
						|
  IN  EFI_LEGACY_EXPANSION_ROM_HEADER  *RomStart,
 | 
						|
  IN  EFI_PCI_IO_PROTOCOL              *PciIo
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID                            *RomEnd;
 | 
						|
  BBS_TABLE                       *BbsTable;
 | 
						|
  UINTN                           BbsIndex;
 | 
						|
  EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr;
 | 
						|
  LEGACY_PNP_EXPANSION_HEADER     *PnpPtr;
 | 
						|
  BOOLEAN                         Instance;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  UINTN                           Segment;
 | 
						|
  UINTN                           Bus;
 | 
						|
  UINTN                           Device;
 | 
						|
  UINTN                           Function;
 | 
						|
  UINT8                           Class;
 | 
						|
  UINT16                          DeviceType;
 | 
						|
  Segment     = 0;
 | 
						|
  Bus         = 0;
 | 
						|
  Device      = 0;
 | 
						|
  Function    = 0;
 | 
						|
  Class       = 0;
 | 
						|
  DeviceType  = BBS_UNKNOWN;
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip floppy and 2*onboard IDE controller entries(Master/Slave per
 | 
						|
  // controller).
 | 
						|
  //
 | 
						|
  BbsIndex  = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
 | 
						|
 | 
						|
  BbsTable  = (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTable.BbsTable;
 | 
						|
  PnpPtr    = (LEGACY_PNP_EXPANSION_HEADER *) RomStart;
 | 
						|
  PciPtr    = (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart;
 | 
						|
 | 
						|
  RomEnd    = (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr);
 | 
						|
  Instance  = FIRST_INSTANCE;
 | 
						|
  //
 | 
						|
  // OPROMs like PXE may not be tied to a piece of hardware and thus
 | 
						|
  // don't have a PciIo associated with them
 | 
						|
  //
 | 
						|
  if (PciIo != NULL) {
 | 
						|
    PciIo->GetLocation (
 | 
						|
             PciIo,
 | 
						|
             &Segment,
 | 
						|
             &Bus,
 | 
						|
             &Device,
 | 
						|
             &Function
 | 
						|
             );
 | 
						|
    PciIo->Pci.Read (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint8,
 | 
						|
                 0x0b,
 | 
						|
                 1,
 | 
						|
                 &Class
 | 
						|
                 );
 | 
						|
 | 
						|
    if (Class == PCI_CLASS_MASS_STORAGE) {
 | 
						|
      DeviceType = BBS_HARDDISK;
 | 
						|
    } else {
 | 
						|
      if (Class == PCI_CLASS_NETWORK) {
 | 
						|
        DeviceType = BBS_EMBED_NETWORK;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    Status    = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr);
 | 
						|
    Instance  = NOT_FIRST_INSTANCE;
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // There can be additional $PnP headers within the OPROM.
 | 
						|
    // Example: SCSI can have one per drive.
 | 
						|
    //
 | 
						|
    BbsTable[BbsIndex].BootPriority             = BBS_UNPRIORITIZED_ENTRY;
 | 
						|
    BbsTable[BbsIndex].DeviceType               = DeviceType;
 | 
						|
    BbsTable[BbsIndex].Bus                      = (UINT32) Bus;
 | 
						|
    BbsTable[BbsIndex].Device                   = (UINT32) Device;
 | 
						|
    BbsTable[BbsIndex].Function                 = (UINT32) Function;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.OldPosition  = 0;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.Reserved1    = 0;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.Enabled      = 0;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.Failed       = 0;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;
 | 
						|
    BbsTable[BbsIndex].StatusFlags.Reserved2    = 0;
 | 
						|
    BbsTable[BbsIndex].Class                    = PnpPtr->Class;
 | 
						|
    BbsTable[BbsIndex].SubClass                 = PnpPtr->SubClass;
 | 
						|
    BbsTable[BbsIndex].DescStringOffset         = PnpPtr->ProductNamePointer;
 | 
						|
    BbsTable[BbsIndex].DescStringSegment        = mBbsRomSegment;
 | 
						|
    BbsTable[BbsIndex].MfgStringOffset          = PnpPtr->MfgPointer;
 | 
						|
    BbsTable[BbsIndex].MfgStringSegment         = mBbsRomSegment;
 | 
						|
    BbsTable[BbsIndex].BootHandlerSegment       = mBbsRomSegment;
 | 
						|
 | 
						|
    //
 | 
						|
    // Have seen case where PXE base code have PnP expansion ROM
 | 
						|
    // header but no Bcv or Bev vectors.
 | 
						|
    //
 | 
						|
    if (PnpPtr->Bcv != 0) {
 | 
						|
      BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv;
 | 
						|
      ++BbsIndex;
 | 
						|
    }
 | 
						|
 | 
						|
    if (PnpPtr->Bev != 0) {
 | 
						|
      BbsTable[BbsIndex].BootHandlerOffset  = PnpPtr->Bev;
 | 
						|
      BbsTable[BbsIndex].DeviceType         = BBS_BEV_DEVICE;
 | 
						|
      ++BbsIndex;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  BbsTable[BbsIndex].BootPriority = BBS_IGNORE_ENTRY;
 | 
						|
  Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT32) BbsIndex;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol
 | 
						|
  to chose the order. Skip any devices that have already have legacy
 | 
						|
  BIOS run.
 | 
						|
 | 
						|
  @param  Private                Protocol instance pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Succeed.
 | 
						|
  @retval EFI_UNSUPPORTED        Cannot get VGA device handle.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PciShadowRoms (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE      *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_PCI_IO_PROTOCOL               *PciIo;
 | 
						|
  PCI_TYPE00                        Pci;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             HandleCount;
 | 
						|
  EFI_HANDLE                        *HandleBuffer;
 | 
						|
  EFI_HANDLE                        VgaHandle;
 | 
						|
  EFI_HANDLE                        FirstHandle;
 | 
						|
  VOID                              **RomStart;
 | 
						|
  UINTN                             Flags;
 | 
						|
  PCI_TYPE00                        PciConfigHeader;
 | 
						|
  UINT16                            *Command;
 | 
						|
  UINT64                            Supports;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make the VGA device first
 | 
						|
  //
 | 
						|
  Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 | 
						|
                                          Private->LegacyBiosPlatform,
 | 
						|
                                          EfiGetPlatformVgaHandle,
 | 
						|
                                          0,
 | 
						|
                                          &HandleBuffer,
 | 
						|
                                          &HandleCount,
 | 
						|
                                          NULL
 | 
						|
                                          ); 
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  
 | 
						|
  VgaHandle = HandleBuffer[0];
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Place the VGA handle as first.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
    if (HandleBuffer[Index] == VgaHandle) {
 | 
						|
      FirstHandle         = HandleBuffer[0];
 | 
						|
      HandleBuffer[0]     = HandleBuffer[Index];
 | 
						|
      HandleBuffer[Index] = FirstHandle;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate memory to save Command WORD from each device. We do this
 | 
						|
  // to restore devices to same state as EFI after switching to legacy.
 | 
						|
  //
 | 
						|
  Command = (UINT16 *) AllocatePool (
 | 
						|
                         sizeof (UINT16) * (HandleCount + 1)
 | 
						|
                         );
 | 
						|
  if (NULL == Command) {
 | 
						|
    FreePool (HandleBuffer);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Disconnect all EFI devices first. This covers cases where alegacy BIOS
 | 
						|
  // may control multiple PCI devices.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Save command register for "connect" loop
 | 
						|
    //
 | 
						|
    PciIo->Pci.Read (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint32,
 | 
						|
                 0,
 | 
						|
                 sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
                 &PciConfigHeader
 | 
						|
                 );
 | 
						|
    Command[Index] = PciConfigHeader.Hdr.Command;
 | 
						|
    //
 | 
						|
    // Skip any device that already has a legacy ROM run
 | 
						|
    //
 | 
						|
    Status = IsLegacyRom (HandleBuffer[Index]);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Stop EFI Drivers with oprom.
 | 
						|
    //
 | 
						|
    gBS->DisconnectController (
 | 
						|
           HandleBuffer[Index],
 | 
						|
           NULL,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // For every device that has not had a legacy ROM started. Start a legacy ROM.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
    //
 | 
						|
    // Here make sure if one VGA have been shadowed,
 | 
						|
    // then wil not shadowed another one.
 | 
						|
    //
 | 
						|
    PciIo->Pci.Read (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint32,
 | 
						|
                 0,
 | 
						|
                 sizeof (Pci) / sizeof (UINT32),
 | 
						|
                 &Pci
 | 
						|
                 );
 | 
						|
    
 | 
						|
    //
 | 
						|
    // Only one Video OPROM can be given control in BIOS phase. If there are multiple Video devices, 
 | 
						|
    // one will work in legacy mode (OPROM will be given control) and 
 | 
						|
    // other Video devices will work in native mode (OS driver will handle these devices).
 | 
						|
    // 
 | 
						|
    if (IS_PCI_DISPLAY (&Pci) && Index != 0) {    
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Skip any device that already has a legacy ROM run
 | 
						|
    //
 | 
						|
    Status = IsLegacyRom (HandleBuffer[Index]);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // If legacy VBIOS Oprom has not been dispatched before, install legacy VBIOS here.
 | 
						|
    //
 | 
						|
    if (IS_PCI_DISPLAY (&Pci) && Index == 0) {    
 | 
						|
      Status = LegacyBiosInstallVgaRom (Private);
 | 
						|
      //
 | 
						|
      // A return status of EFI_NOT_FOUND is considered valid (No EFI
 | 
						|
      // driver is controlling video).
 | 
						|
      //
 | 
						|
      ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Install legacy ROM
 | 
						|
    //
 | 
						|
    Status = LegacyBiosInstallPciRom (
 | 
						|
               &Private->LegacyBios,
 | 
						|
               HandleBuffer[Index],
 | 
						|
               NULL,
 | 
						|
               &Flags,
 | 
						|
               NULL,
 | 
						|
               NULL,
 | 
						|
               (VOID **) &RomStart,
 | 
						|
               NULL
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      if (!((Status == EFI_UNSUPPORTED) && (Flags == NO_ROM))) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Restore Command register so legacy has same devices enabled or disabled
 | 
						|
    // as EFI.
 | 
						|
    // If Flags = NO_ROM use command register as is. This covers the
 | 
						|
    //            following cases:
 | 
						|
    //              Device has no ROMs associated with it.
 | 
						|
    //              Device has ROM associated with it but was already
 | 
						|
    //              installed.
 | 
						|
    //          = ROM_FOUND but not VALID_LEGACY_ROM, disable it.
 | 
						|
    //          = ROM_FOUND and VALID_LEGACY_ROM, enable it.
 | 
						|
    //
 | 
						|
    if ((Flags & ROM_FOUND) == ROM_FOUND) {
 | 
						|
      if ((Flags & VALID_LEGACY_ROM) == 0) {
 | 
						|
        Command[Index] = 0;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // For several VGAs, only one of them can be enabled.
 | 
						|
        //
 | 
						|
        Status = PciIo->Attributes (
 | 
						|
                          PciIo,
 | 
						|
                          EfiPciIoAttributeOperationSupported,
 | 
						|
                          0,
 | 
						|
                          &Supports
 | 
						|
                          );
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
 | 
						|
          Status = PciIo->Attributes (
 | 
						|
                            PciIo,
 | 
						|
                            EfiPciIoAttributeOperationEnable,
 | 
						|
                            Supports,
 | 
						|
                            NULL
 | 
						|
                            );
 | 
						|
        }
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          Command[Index] = 0x1f;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    PciIo->Pci.Write (
 | 
						|
                 PciIo,
 | 
						|
                 EfiPciIoWidthUint16,
 | 
						|
                 0x04,
 | 
						|
                 1,
 | 
						|
                 &Command[Index]
 | 
						|
                 );
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Command);
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Test to see if a legacy PCI ROM exists for this device. Optionally return
 | 
						|
  the Legacy ROM instance for this PCI device.
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  PciHandle              The PCI PC-AT OPROM from this devices ROM BAR will
 | 
						|
                                 be loaded
 | 
						|
  @param  RomImage               Return the legacy PCI ROM for this device
 | 
						|
  @param  RomSize                Size of ROM Image
 | 
						|
  @param  Flags                  Indicates if ROM found and if PC-AT.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Legacy Option ROM available for this device
 | 
						|
  @retval EFI_UNSUPPORTED        Legacy Option ROM not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
LegacyBiosCheckPciRom (
 | 
						|
  IN EFI_LEGACY_BIOS_PROTOCOL           *This,
 | 
						|
  IN  EFI_HANDLE                        PciHandle,
 | 
						|
  OUT VOID                              **RomImage, OPTIONAL
 | 
						|
  OUT UINTN                             *RomSize, OPTIONAL
 | 
						|
  OUT UINTN                             *Flags
 | 
						|
  )
 | 
						|
{
 | 
						|
  return LegacyBiosCheckPciRomEx (
 | 
						|
           This,
 | 
						|
           PciHandle,
 | 
						|
           RomImage,
 | 
						|
           RomSize,
 | 
						|
           NULL,
 | 
						|
           Flags,
 | 
						|
           NULL,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
    Test to see if a legacy PCI ROM exists for this device. Optionally return
 | 
						|
    the Legacy ROM instance for this PCI device.
 | 
						|
 | 
						|
    @param[in] This          Protocol instance pointer.
 | 
						|
    @param[in] PciHandle               The PCI PC-AT OPROM from this devices ROM BAR will be loaded
 | 
						|
    @param[out] RomImage               Return the legacy PCI ROM for this device
 | 
						|
    @param[out] RomSize                Size of ROM Image
 | 
						|
    @param[out] RuntimeImageLength     Runtime size of ROM Image
 | 
						|
    @param[out] Flags                  Indicates if ROM found and if PC-AT.
 | 
						|
    @param[out] OpromRevision          Revision of the PCI Rom
 | 
						|
    @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header
 | 
						|
 | 
						|
    @return EFI_SUCCESS            Legacy Option ROM available for this device
 | 
						|
    @return EFI_ALREADY_STARTED    This device is already managed by its Oprom
 | 
						|
    @return EFI_UNSUPPORTED        Legacy Option ROM not supported.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
LegacyBiosCheckPciRomEx (
 | 
						|
  IN EFI_LEGACY_BIOS_PROTOCOL           *This,
 | 
						|
  IN  EFI_HANDLE                        PciHandle,
 | 
						|
  OUT VOID                              **RomImage, OPTIONAL
 | 
						|
  OUT UINTN                             *RomSize, OPTIONAL
 | 
						|
  OUT UINTN                             *RuntimeImageLength, OPTIONAL
 | 
						|
  OUT UINTN                             *Flags, OPTIONAL
 | 
						|
  OUT UINT8                             *OpromRevision, OPTIONAL
 | 
						|
  OUT VOID                              **ConfigUtilityCodeHeader OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  LEGACY_BIOS_INSTANCE            *Private;
 | 
						|
  EFI_PCI_IO_PROTOCOL             *PciIo;
 | 
						|
  UINTN                           LocalRomSize;
 | 
						|
  VOID                            *LocalRomImage;
 | 
						|
  PCI_TYPE00                      PciConfigHeader;
 | 
						|
  VOID                            *LocalConfigUtilityCodeHeader;
 | 
						|
 | 
						|
  LocalConfigUtilityCodeHeader = NULL;
 | 
						|
  *Flags = NO_ROM;
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  PciHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // See if the option ROM for PciHandle has already been executed
 | 
						|
  //
 | 
						|
  Status = IsLegacyRom (PciHandle);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check for PCI ROM Bar
 | 
						|
  //
 | 
						|
  LocalRomSize  = (UINTN) PciIo->RomSize;
 | 
						|
  LocalRomImage = PciIo->RomImage;
 | 
						|
  if (LocalRomSize != 0) {
 | 
						|
    *Flags |= ROM_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // PCI specification states you should check VendorId and Device Id.
 | 
						|
  //
 | 
						|
  PciIo->Pci.Read (
 | 
						|
               PciIo,
 | 
						|
               EfiPciIoWidthUint32,
 | 
						|
               0,
 | 
						|
               sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
               &PciConfigHeader
 | 
						|
               );
 | 
						|
 | 
						|
  Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | 
						|
  Status = GetPciLegacyRom (
 | 
						|
             Private->Csm16PciInterfaceVersion,
 | 
						|
             PciConfigHeader.Hdr.VendorId,
 | 
						|
             PciConfigHeader.Hdr.DeviceId,
 | 
						|
             &LocalRomImage,
 | 
						|
             &LocalRomSize,
 | 
						|
             RuntimeImageLength,
 | 
						|
             OpromRevision,
 | 
						|
             &LocalConfigUtilityCodeHeader
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  *Flags |= VALID_LEGACY_ROM;
 | 
						|
 | 
						|
  //
 | 
						|
  // See if Configuration Utility Code Header valid
 | 
						|
  //
 | 
						|
  if (LocalConfigUtilityCodeHeader != NULL) {
 | 
						|
    *Flags |= ROM_WITH_CONFIG;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ConfigUtilityCodeHeader != NULL) {
 | 
						|
    *ConfigUtilityCodeHeader = LocalConfigUtilityCodeHeader;
 | 
						|
  }
 | 
						|
 | 
						|
  if (RomImage != NULL) {
 | 
						|
    *RomImage = LocalRomImage;
 | 
						|
  }
 | 
						|
 | 
						|
  if (RomSize != NULL) {
 | 
						|
    *RomSize = LocalRomSize;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Load a legacy PC-AT OPROM on the PciHandle device. Return information
 | 
						|
  about how many disks were added by the OPROM and the shadow address and
 | 
						|
  size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   Legacy ROM loaded for this device
 | 
						|
  @retval EFI_NOT_FOUND No PS2 Keyboard found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EnablePs2Keyboard (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_HANDLE                          *HandleBuffer;
 | 
						|
  UINTN                               HandleCount;
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
  UINTN                               Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get SimpleTextIn and find PS2 controller
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiSimpleTextInProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
    //
 | 
						|
    // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    &gEfiIsaIoProtocolGuid,
 | 
						|
                    (VOID **) &IsaIo,
 | 
						|
                    NULL,
 | 
						|
                    HandleBuffer[Index],
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
 | 
						|
                    );
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Use the ISA I/O Protocol to see if Controller is the Keyboard
 | 
						|
      // controller
 | 
						|
      //
 | 
						|
      if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
 | 
						|
        Status = EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      gBS->CloseProtocol (
 | 
						|
             HandleBuffer[Index],
 | 
						|
             &gEfiIsaIoProtocolGuid,
 | 
						|
             NULL,
 | 
						|
             HandleBuffer[Index]
 | 
						|
             );
 | 
						|
    }
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Load a legacy PC-AT OpROM for VGA controller.
 | 
						|
 | 
						|
  @param  Private                Driver private data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Legacy ROM successfully installed for this device.
 | 
						|
  @retval EFI_DEVICE_ERROR       No VGA device handle found, or native EFI video
 | 
						|
                                 driver cannot be successfully disconnected, or VGA
 | 
						|
                                 thunk driver cannot be successfully connected.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
LegacyBiosInstallVgaRom (
 | 
						|
  IN  LEGACY_BIOS_INSTANCE            *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
  EFI_HANDLE                           VgaHandle;
 | 
						|
  UINTN                                HandleCount;
 | 
						|
  EFI_HANDLE                           *HandleBuffer;
 | 
						|
  EFI_HANDLE                           *ConnectHandleBuffer;
 | 
						|
  EFI_PCI_IO_PROTOCOL                  *PciIo;
 | 
						|
  PCI_TYPE00                           PciConfigHeader;
 | 
						|
  UINT64                               Supports;
 | 
						|
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;
 | 
						|
  UINTN                                EntryCount;
 | 
						|
  UINTN                                Index;
 | 
						|
  VOID                                 *Interface;
 | 
						|
 | 
						|
  //
 | 
						|
  // EfiLegacyBiosGuild attached to a device implies that there is a legacy
 | 
						|
  // BIOS associated with that device.
 | 
						|
  //
 | 
						|
  // There are 3 cases to consider.
 | 
						|
  //   Case 1: No EFI driver is controlling the video.
 | 
						|
  //     Action: Return EFI_SUCCESS from DisconnectController, search
 | 
						|
  //             video thunk driver, and connect it.
 | 
						|
  //   Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is
 | 
						|
  //           not on the image handle.
 | 
						|
  //     Action: Disconnect EFI driver.
 | 
						|
  //             ConnectController for video thunk
 | 
						|
  //   Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is
 | 
						|
  //           on the image handle.
 | 
						|
  //     Action: Do nothing and set Private->VgaInstalled = TRUE.
 | 
						|
  //             Then this routine is not called any more.
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // Get the VGA device.
 | 
						|
  //
 | 
						|
  Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 | 
						|
                                          Private->LegacyBiosPlatform,
 | 
						|
                                          EfiGetPlatformVgaHandle,
 | 
						|
                                          0,
 | 
						|
                                          &HandleBuffer,
 | 
						|
                                          &HandleCount,
 | 
						|
                                          NULL
 | 
						|
                                          );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  VgaHandle = HandleBuffer[0];
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether video thunk driver already starts.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocolInformation (
 | 
						|
                  VgaHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  &OpenInfoBuffer,
 | 
						|
                  &EntryCount
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  
 | 
						|
  for (Index = 0; Index < EntryCount; Index++) {
 | 
						|
    if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
 | 
						|
      Status = gBS->HandleProtocol (
 | 
						|
                      OpenInfoBuffer[Index].AgentHandle,
 | 
						|
                      &gEfiLegacyBiosGuid,
 | 
						|
                      (VOID **) &Interface
 | 
						|
                      );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // This should be video thunk driver which is managing video device
 | 
						|
        // So it need not start again
 | 
						|
        //
 | 
						|
        DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n"));
 | 
						|
        Private->VgaInstalled = TRUE;
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Kick off the native EFI driver
 | 
						|
  //
 | 
						|
  Status = gBS->DisconnectController (
 | 
						|
                  VgaHandle,
 | 
						|
                  NULL,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (Status != EFI_NOT_FOUND) {
 | 
						|
      return EFI_DEVICE_ERROR;
 | 
						|
    } else {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Find all the Thunk Driver
 | 
						|
  //
 | 
						|
  HandleBuffer = NULL;
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiLegacyBiosGuid,
 | 
						|
                  NULL,
 | 
						|
                  &HandleCount,
 | 
						|
                  &HandleBuffer
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  ConnectHandleBuffer = (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE) * (HandleCount + 1));
 | 
						|
  ASSERT (ConnectHandleBuffer != NULL);
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    ConnectHandleBuffer,
 | 
						|
    HandleBuffer,
 | 
						|
    sizeof (EFI_HANDLE) * HandleCount
 | 
						|
    );
 | 
						|
  ConnectHandleBuffer[HandleCount] = NULL;
 | 
						|
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
 | 
						|
  //
 | 
						|
  // Enable the device and make sure VGA cycles are being forwarded to this VGA device
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  VgaHandle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  PciIo->Pci.Read (
 | 
						|
               PciIo,
 | 
						|
               EfiPciIoWidthUint32,
 | 
						|
               0,
 | 
						|
               sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
               &PciConfigHeader
 | 
						|
               );
 | 
						|
 | 
						|
  Status = PciIo->Attributes (
 | 
						|
                    PciIo,
 | 
						|
                    EfiPciIoAttributeOperationSupported,
 | 
						|
                    0,
 | 
						|
                    &Supports
 | 
						|
                    );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \
 | 
						|
                         EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationEnable,
 | 
						|
                      Supports,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    Private->VgaInstalled = TRUE;
 | 
						|
 | 
						|
    //
 | 
						|
    // Attach the VGA thunk driver.
 | 
						|
    // Assume the video is installed. This prevents potential of infinite recursion.
 | 
						|
    //
 | 
						|
    Status = gBS->ConnectController (
 | 
						|
                    VgaHandle,
 | 
						|
                    ConnectHandleBuffer,
 | 
						|
                    NULL,
 | 
						|
                    TRUE
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (ConnectHandleBuffer);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
 | 
						|
    Private->VgaInstalled = FALSE;
 | 
						|
 | 
						|
    //
 | 
						|
    // Reconnect the EFI VGA driver.
 | 
						|
    //
 | 
						|
    gBS->ConnectController (VgaHandle, NULL, NULL, TRUE);
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Load a legacy PC-AT OpROM.
 | 
						|
 | 
						|
  @param  This                              Protocol instance pointer.
 | 
						|
  @param  Private                          Driver's private data.
 | 
						|
  @param  PciHandle                      The EFI handle for the PCI device. It could be
 | 
						|
                                                    NULL if the  OpROM image is not associated with
 | 
						|
                                                    any device.
 | 
						|
  @param  OpromRevision              The revision of PCI PC-AT ROM image.
 | 
						|
  @param  RomImage                    Pointer to PCI PC-AT ROM image header. It must not
 | 
						|
                                                    be NULL.
 | 
						|
  @param  ImageSize                     Size of the PCI PC-AT ROM image.
 | 
						|
  @param  RuntimeImageLength      On input is the max runtime image length indicated by the PCIR structure
 | 
						|
                                                    On output is the actual runtime image length
 | 
						|
  @param  DiskStart                       Disk number of first device hooked by the ROM. If
 | 
						|
                                                    DiskStart is the same as DiskEnd no disked were
 | 
						|
                                                    hooked.
 | 
						|
  @param  DiskEnd                         Disk number of the last device hooked by the ROM.
 | 
						|
  @param  RomShadowAddress       Shadow address of PC-AT ROM
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Legacy ROM loaded for this device
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No more space for this ROM
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
LegacyBiosInstallRom (
 | 
						|
  IN EFI_LEGACY_BIOS_PROTOCOL           *This,
 | 
						|
  IN LEGACY_BIOS_INSTANCE               *Private,
 | 
						|
  IN EFI_HANDLE                         PciHandle,
 | 
						|
  IN UINT8                              OpromRevision,
 | 
						|
  IN VOID                               *RomImage,
 | 
						|
  IN UINTN                              ImageSize,
 | 
						|
  IN OUT UINTN                          *RuntimeImageLength,
 | 
						|
  OUT UINT8                             *DiskStart, OPTIONAL
 | 
						|
  OUT UINT8                             *DiskEnd, OPTIONAL
 | 
						|
  OUT VOID                              **RomShadowAddress OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_STATUS            PciEnableStatus;
 | 
						|
  EFI_PCI_IO_PROTOCOL   *PciIo;
 | 
						|
  UINT8                 LocalDiskStart;
 | 
						|
  UINT8                 LocalDiskEnd;
 | 
						|
  UINTN                 Segment;
 | 
						|
  UINTN                 Bus;
 | 
						|
  UINTN                 Device;
 | 
						|
  UINTN                 Function;
 | 
						|
  EFI_IA32_REGISTER_SET Regs;
 | 
						|
  UINT8                 VideoMode;
 | 
						|
  EFI_TIME              BootTime;
 | 
						|
  UINT32                *BdaPtr;
 | 
						|
  UINT32                LocalTime;
 | 
						|
  UINT32                StartBbsIndex;
 | 
						|
  UINT32                EndBbsIndex;
 | 
						|
  UINT32                MaxRomAddr;
 | 
						|
  UINTN                 TempData;
 | 
						|
  UINTN                 InitAddress;
 | 
						|
  UINTN                 RuntimeAddress;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
 | 
						|
  UINT32                Granularity;
 | 
						|
 | 
						|
  PciIo           = NULL;
 | 
						|
  LocalDiskStart  = 0;
 | 
						|
  LocalDiskEnd    = 0;
 | 
						|
  Segment         = 0;
 | 
						|
  Bus             = 0;
 | 
						|
  Device          = 0;
 | 
						|
  Function        = 0;
 | 
						|
  VideoMode       = 0;
 | 
						|
  PhysicalAddress = 0;
 | 
						|
  MaxRomAddr      = PcdGet32 (PcdEndOpromShadowAddress);
 | 
						|
 | 
						|
  if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) &&
 | 
						|
      (Private->Legacy16Table->UmaAddress != 0) && 
 | 
						|
      (Private->Legacy16Table->UmaSize != 0) &&
 | 
						|
      (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) {
 | 
						|
    MaxRomAddr = Private->Legacy16Table->UmaAddress;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  PciProgramAllInterruptLineRegisters (Private);
 | 
						|
 | 
						|
  if ((OpromRevision >= 3) && (Private->Csm16PciInterfaceVersion >= 0x0300)) {
 | 
						|
    //
 | 
						|
    // CSM16 3.0 meets PCI 3.0 OpROM
 | 
						|
    //   first test if there is enough space for its INIT code
 | 
						|
    //
 | 
						|
    PhysicalAddress = CONVENTIONAL_MEMORY_TOP;
 | 
						|
    Status = gBS->AllocatePages (
 | 
						|
                    AllocateMaxAddress,
 | 
						|
                    EfiBootServicesCode,
 | 
						|
                    EFI_SIZE_TO_PAGES (ImageSize),
 | 
						|
                    &PhysicalAddress
 | 
						|
                    );
 | 
						|
        
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
 | 
						|
      //
 | 
						|
      // Report Status Code to indicate that there is no enough space for OpROM
 | 
						|
      //
 | 
						|
      REPORT_STATUS_CODE (
 | 
						|
        EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
 | 
						|
        );
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    InitAddress = (UINTN) PhysicalAddress;
 | 
						|
    //
 | 
						|
    //   then test if there is enough space for its RT code
 | 
						|
    //
 | 
						|
    RuntimeAddress = Private->OptionRom;
 | 
						|
    if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
 | 
						|
      gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));
 | 
						|
      //
 | 
						|
      // Report Status Code to indicate that there is no enough space for OpROM
 | 
						|
      //
 | 
						|
      REPORT_STATUS_CODE (
 | 
						|
        EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
 | 
						|
        );
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // CSM16 3.0 meets PCI 2.x OpROM
 | 
						|
    // CSM16 2.x meets PCI 2.x/3.0 OpROM
 | 
						|
    //   test if there is enough space for its INIT code
 | 
						|
    //
 | 
						|
    InitAddress    = PCI_START_ADDRESS (Private->OptionRom);
 | 
						|
    if (InitAddress + ImageSize > MaxRomAddr) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
 | 
						|
      //
 | 
						|
      // Report Status Code to indicate that there is no enough space for OpROM
 | 
						|
      //
 | 
						|
      REPORT_STATUS_CODE (
 | 
						|
        EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
        (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
 | 
						|
        );
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    RuntimeAddress = InitAddress;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->LegacyRegion->UnLock (
 | 
						|
                           Private->LegacyRegion,
 | 
						|
                           0xE0000,
 | 
						|
                           0x20000,
 | 
						|
                           &Granularity
 | 
						|
                           );
 | 
						|
 | 
						|
  Private->LegacyRegion->UnLock (
 | 
						|
                           Private->LegacyRegion,
 | 
						|
                           (UINT32) RuntimeAddress,
 | 
						|
                           (UINT32) ImageSize,
 | 
						|
                           &Granularity
 | 
						|
                           );
 | 
						|
    
 | 
						|
  DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize = %x/%x/%x\n", InitAddress, RuntimeAddress, ImageSize));
 | 
						|
 | 
						|
  CopyMem ((VOID *) InitAddress, RomImage, ImageSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Read the highest disk number "installed: and assume a new disk will
 | 
						|
  // show up on the first drive past the current value.
 | 
						|
  // There are several considerations here:
 | 
						|
  // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo
 | 
						|
  //    the change until boot selection time frame.
 | 
						|
  // 2. BBS compliants drives will not change 40:75 until boot time.
 | 
						|
  // 3. Onboard IDE controllers will change 40:75
 | 
						|
  //
 | 
						|
  LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
 | 
						|
  if ((Private->Disk4075 + 0x80) < LocalDiskStart) {
 | 
						|
    //
 | 
						|
    // Update table since onboard IDE drives found
 | 
						|
    //
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment        = 0xff;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus            = 0xff;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice         = 0xff;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction       = 0xff;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber  = (UINT8) (Private->Disk4075 + 0x80);
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber    = LocalDiskStart;
 | 
						|
    Private->LegacyEfiHddTableIndex ++;
 | 
						|
    Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f);
 | 
						|
    Private->DiskEnd  = LocalDiskStart;
 | 
						|
  }
 | 
						|
 | 
						|
  if (PciHandle != mVgaHandle) {
 | 
						|
 | 
						|
    EnablePs2Keyboard ();
 | 
						|
 | 
						|
    //
 | 
						|
    // Store current mode settings since PrepareToScanRom may change mode.
 | 
						|
    //
 | 
						|
    VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Notify the platform that we are about to scan the ROM
 | 
						|
  //
 | 
						|
  Status = Private->LegacyBiosPlatform->PlatformHooks (
 | 
						|
                                          Private->LegacyBiosPlatform,
 | 
						|
                                          EfiPlatformHookPrepareToScanRom,
 | 
						|
                                          0,
 | 
						|
                                          PciHandle,
 | 
						|
                                          &InitAddress,
 | 
						|
                                          NULL,
 | 
						|
                                          NULL
 | 
						|
                                          );
 | 
						|
 | 
						|
  //
 | 
						|
  // If Status returned is EFI_UNSUPPORTED then abort due to platform
 | 
						|
  // policy.
 | 
						|
  //
 | 
						|
  if (Status == EFI_UNSUPPORTED) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Report corresponding status code
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT)
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Generate number of ticks since midnight for BDA. Some OPROMs require
 | 
						|
  // this. Place result in 40:6C-6F
 | 
						|
  //
 | 
						|
  gRT->GetTime (&BootTime, NULL);
 | 
						|
  LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Multiply result by 18.2 for number of ticks since midnight.
 | 
						|
  // Use 182/10 to avoid floating point math.
 | 
						|
  //
 | 
						|
  LocalTime = (LocalTime * 182) / 10;
 | 
						|
  BdaPtr    = (UINT32 *) ((UINTN) 0x46C);
 | 
						|
  *BdaPtr   = LocalTime;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Pass in handoff data
 | 
						|
  //
 | 
						|
  PciEnableStatus = EFI_UNSUPPORTED;
 | 
						|
  ZeroMem (&Regs, sizeof (Regs));
 | 
						|
  if (PciHandle != NULL) {
 | 
						|
  
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    PciHandle,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Enable command register.
 | 
						|
    //
 | 
						|
    PciEnableStatus = PciIo->Attributes (
 | 
						|
                               PciIo,
 | 
						|
                               EfiPciIoAttributeOperationEnable,
 | 
						|
                               EFI_PCI_DEVICE_ENABLE,
 | 
						|
                               NULL
 | 
						|
                               );
 | 
						|
  
 | 
						|
    PciIo->GetLocation (
 | 
						|
             PciIo,
 | 
						|
             &Segment,
 | 
						|
             &Bus,
 | 
						|
             &Device,
 | 
						|
             &Function
 | 
						|
             );
 | 
						|
    DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bus, Device, Function));
 | 
						|
  }
 | 
						|
  
 | 
						|
  mIgnoreBbsUpdateFlag  = FALSE;
 | 
						|
  Regs.X.AX             = Legacy16DispatchOprom;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Generate DispatchOpRomTable data
 | 
						|
  //
 | 
						|
  Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment = Private->Legacy16Table->PnPInstallationCheckSegment;
 | 
						|
  Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset  = Private->Legacy16Table->PnPInstallationCheckOffset;
 | 
						|
  Private->IntThunk->DispatchOpromTable.OpromSegment                = (UINT16) (InitAddress >> 4);
 | 
						|
  Private->IntThunk->DispatchOpromTable.PciBus                      = (UINT8) Bus;
 | 
						|
  Private->IntThunk->DispatchOpromTable.PciDeviceFunction           = (UINT8) ((Device << 3) | Function);
 | 
						|
  Private->IntThunk->DispatchOpromTable.NumberBbsEntries            = (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
 | 
						|
  Private->IntThunk->DispatchOpromTable.BbsTablePointer             = (UINT32) (UINTN) Private->BbsTablePtr;
 | 
						|
  Private->IntThunk->DispatchOpromTable.RuntimeSegment              = (UINT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4));
 | 
						|
  TempData = (UINTN) &Private->IntThunk->DispatchOpromTable;
 | 
						|
  Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);
 | 
						|
  Regs.X.BX = EFI_OFFSET ((UINT32) TempData);
 | 
						|
  //
 | 
						|
  // Skip dispatching ROM for those PCI devices that can not be enabled by PciIo->Attributes
 | 
						|
  // Otherwise, it may cause the system to hang in some cases
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (PciEnableStatus)) {
 | 
						|
    DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, Device, Function));
 | 
						|
    Private->LegacyBios.FarCall86 (
 | 
						|
      &Private->LegacyBios,
 | 
						|
      Private->Legacy16CallSegment,
 | 
						|
      Private->Legacy16CallOffset,
 | 
						|
      &Regs,
 | 
						|
      NULL,
 | 
						|
      0
 | 
						|
      );
 | 
						|
  } else {
 | 
						|
    Regs.X.BX = 0;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries != (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) {
 | 
						|
    Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries  = (UINT8) Private->IntThunk->DispatchOpromTable.NumberBbsEntries;
 | 
						|
    mIgnoreBbsUpdateFlag = TRUE;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if non-BBS compliant drives found
 | 
						|
  //
 | 
						|
  if (Regs.X.BX != 0) {
 | 
						|
    LocalDiskEnd  = (UINT8) (LocalDiskStart + Regs.H.BL);
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment        = (UINT8) Segment;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus            = (UINT8) Bus;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice         = (UINT8) Device;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction       = (UINT8) Function;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber  = Private->DiskEnd;
 | 
						|
    Private->DiskEnd = LocalDiskEnd;
 | 
						|
    Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;
 | 
						|
    Private->LegacyEfiHddTableIndex += 1;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Skip video mode set, if installing VGA
 | 
						|
  //
 | 
						|
  if (PciHandle != mVgaHandle) {
 | 
						|
    //
 | 
						|
    // Set mode settings since PrepareToScanRom may change mode
 | 
						|
    //
 | 
						|
    if (VideoMode != *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE))) {
 | 
						|
      //
 | 
						|
      // The active video mode is changed, restore it to original mode.
 | 
						|
      //
 | 
						|
      Regs.H.AH = 0x00;
 | 
						|
      Regs.H.AL = VideoMode;
 | 
						|
      Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Regs.X.AX from the adapter initializion is ignored since some adapters
 | 
						|
  // do not follow the standard of setting AX = 0 on success.
 | 
						|
  //
 | 
						|
  //
 | 
						|
  // The ROM could have updated it's size so we need to read again.
 | 
						|
  //
 | 
						|
  if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
 | 
						|
    //
 | 
						|
    // Now we check the signature (0xaa55) to judge whether the run-time code is truly generated by INIT function.
 | 
						|
    // If signature is not valid, that means the INIT function didn't copy the run-time code to RuntimeAddress.
 | 
						|
    //
 | 
						|
    *RuntimeImageLength = 0;
 | 
						|
  } else {
 | 
						|
    *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Size512 * 512;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength));
 | 
						|
 | 
						|
  //
 | 
						|
  // If OpROM runs in 2.0 mode
 | 
						|
  //
 | 
						|
  if (PhysicalAddress == 0) {
 | 
						|
    if (*RuntimeImageLength < ImageSize) {
 | 
						|
      //
 | 
						|
      // Make area from end of shadowed rom to end of original rom all ffs
 | 
						|
      //
 | 
						|
      gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize - *RuntimeImageLength, 0xff);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Allow platform to perform any required actions after the
 | 
						|
  // OPROM has been initialized.
 | 
						|
  //
 | 
						|
  Status = Private->LegacyBiosPlatform->PlatformHooks (
 | 
						|
                                          Private->LegacyBiosPlatform,
 | 
						|
                                          EfiPlatformHookAfterRomInit,
 | 
						|
                                          0,
 | 
						|
                                          PciHandle,
 | 
						|
                                          &RuntimeAddress,
 | 
						|
                                          NULL,
 | 
						|
                                          NULL
 | 
						|
                                          );
 | 
						|
  if (PciHandle != NULL) {
 | 
						|
    //
 | 
						|
    // If no PCI Handle then no header or Bevs.
 | 
						|
    //
 | 
						|
    if ((*RuntimeImageLength != 0) && (!mIgnoreBbsUpdateFlag)) {
 | 
						|
      StartBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
 | 
						|
      TempData      = RuntimeAddress;
 | 
						|
      UpdateBevBcvTable (
 | 
						|
        Private,
 | 
						|
        (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData,
 | 
						|
        PciIo
 | 
						|
        );
 | 
						|
      EndBbsIndex   = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
 | 
						|
      LocalDiskEnd  = (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - StartBbsIndex));
 | 
						|
      if (LocalDiskEnd != LocalDiskStart) {
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment        = (UINT8) Segment;
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus            = (UINT8) Bus;
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice         = (UINT8) Device;
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction       = (UINT8) Function;
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber  = Private->DiskEnd;
 | 
						|
        Private->DiskEnd = LocalDiskEnd;
 | 
						|
        Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;
 | 
						|
        Private->LegacyEfiHddTableIndex += 1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Mark PCI device as having a legacy BIOS ROM loaded.
 | 
						|
    //
 | 
						|
    RomShadow (
 | 
						|
      PciHandle,
 | 
						|
      (UINT32) RuntimeAddress,
 | 
						|
      (UINT32) *RuntimeImageLength,
 | 
						|
      LocalDiskStart,
 | 
						|
      LocalDiskEnd
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Stuff caller's OPTIONAL return parameters.
 | 
						|
  //
 | 
						|
  if (RomShadowAddress != NULL) {
 | 
						|
    *RomShadowAddress = (VOID *) RuntimeAddress;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DiskStart != NULL) {
 | 
						|
    *DiskStart = LocalDiskStart;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DiskEnd != NULL) {
 | 
						|
    *DiskEnd = LocalDiskEnd;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->OptionRom = (UINT32) (RuntimeAddress + *RuntimeImageLength);
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
   
 | 
						|
Done:
 | 
						|
  if (PhysicalAddress != 0) {
 | 
						|
    //
 | 
						|
    // Free pages when OpROM is 3.0
 | 
						|
    //
 | 
						|
    gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Insure all shadowed  areas are locked
 | 
						|
  //
 | 
						|
  Private->LegacyRegion->Lock (
 | 
						|
                           Private->LegacyRegion,
 | 
						|
                           0xC0000,
 | 
						|
                           0x40000,
 | 
						|
                           &Granularity
 | 
						|
                           );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Load a legacy PC-AT OPROM on the PciHandle device. Return information
 | 
						|
  about how many disks were added by the OPROM and the shadow address and
 | 
						|
  size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:
 | 
						|
 | 
						|
  @param  This                   Protocol instance pointer.
 | 
						|
  @param  PciHandle              The PCI PC-AT OPROM from this devices ROM BAR will
 | 
						|
                                 be loaded. This value is NULL if RomImage is
 | 
						|
                                 non-NULL. This is the normal case.
 | 
						|
  @param  RomImage               A PCI PC-AT ROM image. This argument is non-NULL
 | 
						|
                                 if there is no hardware associated with the ROM
 | 
						|
                                 and thus no PciHandle, otherwise is must be NULL.
 | 
						|
                                 Example is PXE base code.
 | 
						|
  @param  Flags                  Indicates if ROM found and if PC-AT.
 | 
						|
  @param  DiskStart              Disk number of first device hooked by the ROM. If
 | 
						|
                                 DiskStart is the same as DiskEnd no disked were
 | 
						|
                                 hooked.
 | 
						|
  @param  DiskEnd                Disk number of the last device hooked by the ROM.
 | 
						|
  @param  RomShadowAddress       Shadow address of PC-AT ROM
 | 
						|
  @param  RomShadowedSize        Size of RomShadowAddress in bytes
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Legacy ROM loaded for this device
 | 
						|
  @retval EFI_INVALID_PARAMETER  PciHandle not found
 | 
						|
  @retval EFI_UNSUPPORTED        There is no PCI ROM in the ROM BAR or no onboard
 | 
						|
                                 ROM
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
LegacyBiosInstallPciRom (
 | 
						|
  IN EFI_LEGACY_BIOS_PROTOCOL           * This,
 | 
						|
  IN  EFI_HANDLE                        PciHandle,
 | 
						|
  IN  VOID                              **RomImage,
 | 
						|
  OUT UINTN                             *Flags,
 | 
						|
  OUT UINT8                             *DiskStart, OPTIONAL
 | 
						|
  OUT UINT8                             *DiskEnd, OPTIONAL
 | 
						|
  OUT VOID                              **RomShadowAddress, OPTIONAL
 | 
						|
  OUT UINT32                            *RomShadowedSize OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  LEGACY_BIOS_INSTANCE            *Private;
 | 
						|
  VOID                            *LocalRomImage;
 | 
						|
  UINTN                           ImageSize;
 | 
						|
  UINTN                           RuntimeImageLength;
 | 
						|
  EFI_PCI_IO_PROTOCOL             *PciIo;
 | 
						|
  PCI_TYPE01                      PciConfigHeader;
 | 
						|
  UINTN                           HandleCount;
 | 
						|
  EFI_HANDLE                      *HandleBuffer;
 | 
						|
  UINTN                           PciSegment;
 | 
						|
  UINTN                           PciBus;
 | 
						|
  UINTN                           PciDevice;
 | 
						|
  UINTN                           PciFunction;
 | 
						|
  UINTN                           LastBus;
 | 
						|
  UINTN                           Index;
 | 
						|
  UINT8                           OpromRevision;
 | 
						|
  UINT32                          Granularity;
 | 
						|
  PCI_3_0_DATA_STRUCTURE          *Pcir;
 | 
						|
 | 
						|
  OpromRevision = 0;
 | 
						|
 | 
						|
  Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
 | 
						|
  if (Private->Legacy16Table->LastPciBus == 0) {
 | 
						|
    //
 | 
						|
    // Get last bus number if not already found
 | 
						|
    //
 | 
						|
    Status = gBS->LocateHandleBuffer (
 | 
						|
                    ByProtocol,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    NULL,
 | 
						|
                    &HandleCount,
 | 
						|
                    &HandleBuffer
 | 
						|
                    );
 | 
						|
 | 
						|
    LastBus = 0;
 | 
						|
    for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
      Status = gBS->HandleProtocol (
 | 
						|
                      HandleBuffer[Index],
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      (VOID **) &PciIo
 | 
						|
                      );
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = PciIo->GetLocation (
 | 
						|
                        PciIo,
 | 
						|
                        &PciSegment,
 | 
						|
                        &PciBus,
 | 
						|
                        &PciDevice,
 | 
						|
                        &PciFunction
 | 
						|
                        );
 | 
						|
      if (PciBus > LastBus) {
 | 
						|
        LastBus = PciBus;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Private->LegacyRegion->UnLock (
 | 
						|
                             Private->LegacyRegion,
 | 
						|
                             0xE0000,
 | 
						|
                             0x20000,
 | 
						|
                             &Granularity
 | 
						|
                             );
 | 
						|
    Private->Legacy16Table->LastPciBus = (UINT8) LastBus;
 | 
						|
    Private->LegacyRegion->Lock (
 | 
						|
                             Private->LegacyRegion,
 | 
						|
                             0xE0000,
 | 
						|
                             0x20000,
 | 
						|
                             &Granularity
 | 
						|
                             );
 | 
						|
  }
 | 
						|
 | 
						|
  *Flags = 0;
 | 
						|
  if ((PciHandle != NULL) && (RomImage == NULL)) {
 | 
						|
    //
 | 
						|
    // If PciHandle has OpRom to Execute 
 | 
						|
    // and OpRom are all associated with Hardware
 | 
						|
    //
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    PciHandle,
 | 
						|
                    &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID **) &PciIo
 | 
						|
                    );
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      PciIo->Pci.Read (
 | 
						|
                   PciIo,
 | 
						|
                   EfiPciIoWidthUint32,
 | 
						|
                   0,
 | 
						|
                   sizeof (PciConfigHeader) / sizeof (UINT32),
 | 
						|
                   &PciConfigHeader
 | 
						|
                   );
 | 
						|
 | 
						|
      //
 | 
						|
      // if video installed & OPROM is video return
 | 
						|
      //
 | 
						|
      if (
 | 
						|
          (
 | 
						|
           ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_OLD) &&
 | 
						|
            (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA))
 | 
						|
           ||
 | 
						|
           ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY) &&
 | 
						|
            (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA))
 | 
						|
          )
 | 
						|
          &&
 | 
						|
          (!Private->VgaInstalled)
 | 
						|
         ) {
 | 
						|
        mVgaInstallationInProgress = TRUE;
 | 
						|
 | 
						|
        //
 | 
						|
        //      return EFI_UNSUPPORTED;
 | 
						|
        //
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // To run any legacy image, the VGA needs to be installed first.
 | 
						|
    // if installing the video, then don't need the thunk as already installed.
 | 
						|
    //
 | 
						|
    Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 | 
						|
                                            Private->LegacyBiosPlatform,
 | 
						|
                                            EfiGetPlatformVgaHandle,
 | 
						|
                                            0,
 | 
						|
                                            &HandleBuffer,
 | 
						|
                                            &HandleCount,
 | 
						|
                                            NULL
 | 
						|
                                            );
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      mVgaHandle = HandleBuffer[0];
 | 
						|
      if ((!Private->VgaInstalled) && (PciHandle != mVgaHandle)) {
 | 
						|
        //
 | 
						|
        // A return status of EFI_NOT_FOUND is considered valid (No EFI
 | 
						|
        // driver is controlling video.
 | 
						|
        //
 | 
						|
        mVgaInstallationInProgress  = TRUE;
 | 
						|
        Status                      = LegacyBiosInstallVgaRom (Private);
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          if (Status != EFI_NOT_FOUND) {
 | 
						|
            mVgaInstallationInProgress = FALSE;
 | 
						|
            return Status;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          mVgaInstallationInProgress = FALSE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // See if the option ROM for PciHandle has already been executed
 | 
						|
    //
 | 
						|
    Status = IsLegacyRom (PciHandle);
 | 
						|
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      mVgaInstallationInProgress = FALSE;
 | 
						|
      GetShadowedRomParameters (
 | 
						|
        PciHandle,
 | 
						|
        DiskStart,
 | 
						|
        DiskEnd,
 | 
						|
        RomShadowAddress,
 | 
						|
        (UINTN *) RomShadowedSize
 | 
						|
        );
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = LegacyBiosCheckPciRomEx (
 | 
						|
               &Private->LegacyBios,
 | 
						|
               PciHandle,
 | 
						|
               &LocalRomImage,
 | 
						|
               &ImageSize,
 | 
						|
               &RuntimeImageLength,
 | 
						|
               Flags,
 | 
						|
               &OpromRevision,
 | 
						|
               NULL
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // There is no PCI ROM in the ROM BAR or no onboard ROM
 | 
						|
      //
 | 
						|
      mVgaInstallationInProgress = FALSE;
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if ((RomImage == NULL) || (*RomImage == NULL)) {
 | 
						|
      //
 | 
						|
      // If PciHandle is NULL, and no OpRom is to be associated
 | 
						|
      //
 | 
						|
      mVgaInstallationInProgress = FALSE;
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = Private->LegacyBiosPlatform->GetPlatformHandle (
 | 
						|
                                            Private->LegacyBiosPlatform,
 | 
						|
                                            EfiGetPlatformVgaHandle,
 | 
						|
                                            0,
 | 
						|
                                            &HandleBuffer,
 | 
						|
                                            &HandleCount,
 | 
						|
                                            NULL
 | 
						|
                                            );
 | 
						|
    if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) {
 | 
						|
      //
 | 
						|
      // A return status of EFI_NOT_FOUND is considered valid (No EFI
 | 
						|
      // driver is controlling video.
 | 
						|
      //
 | 
						|
      mVgaInstallationInProgress  = TRUE;
 | 
						|
      Status                      = LegacyBiosInstallVgaRom (Private);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        if (Status != EFI_NOT_FOUND) {
 | 
						|
          mVgaInstallationInProgress = FALSE;
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        mVgaInstallationInProgress = FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    LocalRomImage = *RomImage;
 | 
						|
    if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE ||
 | 
						|
        ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset == 0 ||
 | 
						|
        (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != 0) {
 | 
						|
      mVgaInstallationInProgress = FALSE;
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
    
 | 
						|
    Pcir = (PCI_3_0_DATA_STRUCTURE *)
 | 
						|
           ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset);
 | 
						|
 | 
						|
    if ((Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->CodeType != PCI_CODE_TYPE_PCAT_IMAGE)) {
 | 
						|
      mVgaInstallationInProgress = FALSE;
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageSize = Pcir->ImageLength * 512;
 | 
						|
    if (Pcir->Length >= 0x1C) {
 | 
						|
      OpromRevision = Pcir->Revision;
 | 
						|
    } else {
 | 
						|
      OpromRevision = 0;
 | 
						|
    }
 | 
						|
    if (Pcir->Revision < 3) {
 | 
						|
      RuntimeImageLength = 0;
 | 
						|
    } else {
 | 
						|
      RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Shadow and initialize the OpROM.
 | 
						|
  //
 | 
						|
  ASSERT (Private->TraceIndex < 0x200);
 | 
						|
  Private->Trace[Private->TraceIndex] = LEGACY_PCI_TRACE_000;
 | 
						|
  Private->TraceIndex ++;
 | 
						|
  Private->TraceIndex = (UINT16) (Private->TraceIndex % 0x200);
 | 
						|
  Status = LegacyBiosInstallRom (
 | 
						|
             This,
 | 
						|
             Private,
 | 
						|
             PciHandle,
 | 
						|
             OpromRevision,
 | 
						|
             LocalRomImage,
 | 
						|
             ImageSize,
 | 
						|
             &RuntimeImageLength,
 | 
						|
             DiskStart,
 | 
						|
             DiskEnd,
 | 
						|
             RomShadowAddress
 | 
						|
             );
 | 
						|
  if (RomShadowedSize != NULL) {
 | 
						|
    *RomShadowedSize = (UINT32) RuntimeImageLength;
 | 
						|
  }
 | 
						|
 | 
						|
  mVgaInstallationInProgress = FALSE;
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 |