diff options
Diffstat (limited to 'IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c')
-rw-r--r-- | IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c | 3083 |
1 files changed, 0 insertions, 3083 deletions
diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c deleted file mode 100644 index dc1f760876..0000000000 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyPci.c +++ /dev/null @@ -1,3083 +0,0 @@ -/** @file
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#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];
-EDKII_IOMMU_PROTOCOL *mIoMmu;
-
-/**
- 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 - (UINTN)*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;
- UINT8 OldVideoMode;
- 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;
- OldVideoMode = 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
- //
- ACCESS_PAGE0_CODE (
- 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.
- //
- ACCESS_PAGE0_CODE (
- 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
- //
- ACCESS_PAGE0_CODE ({
- OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
- });
-
- if (VideoMode != OldVideoMode) {
- //
- // 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);
- }
- }
-
- ACCESS_PAGE0_CODE (
- 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;
-}
-
-/**
- Let IOMMU grant DMA access for the PCI device.
-
- @param PciHandle The EFI handle for the PCI device.
- @param HostAddress The system memory address to map to the PCI controller.
- @param NumberOfBytes The number of bytes to map.
-
- @retval EFI_SUCCESS The DMA access is granted.
-**/
-EFI_STATUS
-IoMmuGrantAccess (
- IN EFI_HANDLE PciHandle,
- IN EFI_PHYSICAL_ADDRESS HostAddress,
- IN UINTN NumberOfBytes
- )
-{
- EFI_PHYSICAL_ADDRESS DeviceAddress;
- VOID *Mapping;
- EFI_STATUS Status;
-
- if (PciHandle == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- Status = EFI_SUCCESS;
- if (mIoMmu == NULL) {
- gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);
- }
- if (mIoMmu != NULL) {
- Status = mIoMmu->Map (
- mIoMmu,
- EdkiiIoMmuOperationBusMasterCommonBuffer,
- (VOID *)(UINTN)HostAddress,
- &NumberOfBytes,
- &DeviceAddress,
- &Mapping
- );
- if (EFI_ERROR(Status)) {
- DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuMap - %r\n", Status));
- } else {
- ASSERT (DeviceAddress == HostAddress);
- Status = mIoMmu->SetAttribute (
- mIoMmu,
- PciHandle,
- Mapping,
- EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
- );
- if (EFI_ERROR(Status)) {
- DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuSetAttribute - %r\n", Status));
- }
- }
- }
- 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;
- }
- }
-
- //
- // Grant access for below 1M
- // BDA/EBDA/LowPMM and scratch memory for OPROM.
- //
- IoMmuGrantAccess (PciHandle, 0, SIZE_1MB);
- //
- // Grant access for HiPmm
- //
- IoMmuGrantAccess (
- PciHandle,
- Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemory,
- Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemorySizeInBytes
- );
-
- //
- // 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;
-}
-
|