示例#1
0
EFI_STATUS
PciIoVerifyConfigAccess (
  PCI_IO_DEVICE                 *PciIoDevice,
  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,
  IN UINTN                      Count,
  IN UINT64                     *Offset
  )
/*++

Routine Description:

  Verifies access to a PCI Config Header

Arguments:

Returns:

  None

--*/
{
  UINT64  ExtendOffset;

  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
  //
  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);

  if (PciIoDevice->IsPciExp) {
    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
      return EFI_UNSUPPORTED;
    }

    ExtendOffset  = LShiftU64 (*Offset, 32);
    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
    *Offset       = (*Offset) | ExtendOffset;

  } else {
    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
      return EFI_UNSUPPORTED;
    }

    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
  }

  return EFI_SUCCESS;
}
EFI_STATUS
PciDevicePresent (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
  PCI_TYPE00                          *Pci,
  UINT8                               Bus,
  UINT8                               Device,
  UINT8                               Func
  )
/*++

Routine Description:

  This routine is used to check whether the pci device is present

Arguments:

Returns:

  None

--*/
{
  UINT64      Address;
  EFI_STATUS  Status;

  //
  // Create PCI address map in terms of Bus, Device and Func
  //
  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

  //
  // Read the Vendor Id register
  //
  Status = PciRootBridgeIo->Pci.Read (
                                  PciRootBridgeIo,
                                  EfiPciWidthUint32,
                                  Address,
                                  1,
                                  Pci
                                  );

  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {

    //
    // Read the entire config header for the device
    //

    /*Status = */PciRootBridgeIo->Pci.Read (
                                    PciRootBridgeIo,
                                    EfiPciWidthUint32,
                                    Address,
                                    sizeof (PCI_TYPE00) / sizeof (UINT32),
                                    Pci
                                    );

    return EFI_SUCCESS;
  }

  return EFI_NOT_FOUND;
}
示例#3
0
文件: efi_pci.c 项目: grze/ipxe
static unsigned long efipci_address ( struct pci_device *pci,
				      unsigned long location ) {
	return EFI_PCI_ADDRESS ( PCI_BUS ( pci->busdevfn ),
				 PCI_SLOT ( pci->busdevfn ),
				 PCI_FUNC ( pci->busdevfn ),
				 EFIPCI_OFFSET ( location ) );
}
示例#4
0
VOID
RestoreCommandRegister (
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
  UINT16                           MinBus,
  UINT16                           MaxBus,
  UINT16                           MinDevice,
  UINT16                           MaxDevice,
  UINT16                           MinFunc,
  UINT16                           MaxFunc,
  UINT16                           Bus,
  UINT16                           Device,
  UINT16                           Func,
  IN VOID                          *VoidContext
  )

{
  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
  UINT64                                     Address;
  UINTN                                      Index;

  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);
}
示例#5
0
VOID
SaveCommandRegister (
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
  UINT16                           MinBus,
  UINT16                           MaxBus,
  UINT16                           MinDevice,
  UINT16                           MaxDevice,
  UINT16                           MinFunc,
  UINT16                           MaxFunc,
  UINT16                           Bus,
  UINT16                           Device,
  UINT16                           Func,
  IN VOID                          *VoidContext
  )

{
  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
  UINT64  Address;
  UINTN   Index;
  UINT16  Command;

  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

  IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);

  //
  // Clear the memory enable bit
  //
  Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));

  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);
}
示例#6
0
EFI_STATUS
GetOpRomInfo (
  IN PCI_IO_DEVICE    *PciIoDevice
  )
/*++

Routine Description:

Arguments:

Returns:

--*/
{
  UINT8                           RomBarIndex;
  UINT32                          AllOnes;
  UINT64                          Address;
  EFI_STATUS                      Status;
  UINT8                           Bus;
  UINT8                           Device;
  UINT8                           Function;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

  Bus             = PciIoDevice->BusNumber;
  Device          = PciIoDevice->DeviceNumber;
  Function        = PciIoDevice->FunctionNumber;

  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;

  //
  // offset is 0x30 if is not ppb
  //

  //
  // 0x30
  //
  RomBarIndex = PCI_EXPANSION_ROM_BASE;

  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
    //
    // if is ppb
    //

    //
    // 0x38
    //
    RomBarIndex = PCI_BRIDGE_ROMBAR;
  }
  //
  // the bit0 is 0 to prevent the enabling of the Rom address decoder
  //
  AllOnes = 0xfffffffe;
  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);

  Status = PciRootBridgeIo->Pci.Write (
                                  PciRootBridgeIo,
                                  EfiPciWidthUint32,
                                  Address,
                                  1,
                                  &AllOnes
                                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  
  //
  // read back
  //
  Status = PciRootBridgeIo->Pci.Read (
                                  PciRootBridgeIo,
                                  EfiPciWidthUint32,
                                  Address,
                                  1,
                                  &AllOnes
                                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Bits [1, 10] are reserved
  //
  AllOnes &= 0xFFFFF800;
  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {
    return EFI_NOT_FOUND;
  }
  
  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));
  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));

  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
  return EFI_SUCCESS;
}
示例#7
0
EFI_STATUS
RomDecode (
  IN PCI_IO_DEVICE   *PciDevice,
  IN UINT8           RomBarIndex,
  IN UINT32          RomBar,
  IN BOOLEAN         Enable
  )
/*++

Routine Description:

Arguments:

Returns:

--*/
{
  UINT16                          CommandValue;
  UINT32                          Value32;
  UINT64                          Address;
  //EFI_STATUS                      Status;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  
  PciRootBridgeIo = PciDevice->PciRootBridgeIo;
  if (Enable) {
    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
    //
    // set the Rom base address: now is hardcode
    //
    PciRootBridgeIo->Pci.Write(
                               PciRootBridgeIo, 
                               EfiPciWidthUint32, 
                               Address, 
                               1, 
                               &RomBar);
  
    //
    // enable its decoder
    //
    Value32 = RomBar | 0x1;
    PciRootBridgeIo->Pci.Write(
                               PciRootBridgeIo, 
                               EfiPciWidthUint32, 
                               Address, 
                               1, 
                               &Value32);
    
    //
    //setting the memory space bit in the function's command register
    //
    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);
    PciRootBridgeIo->Pci.Read(
                              PciRootBridgeIo, 
                              EfiPciWidthUint16, 
                              Address, 
                              1, 
                              &CommandValue);
    
    CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003
    PciRootBridgeIo->Pci.Write(
                               PciRootBridgeIo, 
                               EfiPciWidthUint16, 
                               Address, 
                               1, 
                               &CommandValue);
  } else {
    //
    // disable rom decode
    //  
    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);
    Value32 = 0xfffffffe;
    PciRootBridgeIo->Pci.Write(
                               PciRootBridgeIo, 
                               EfiPciWidthUint32, 
                               Address, 
                               1, 
                               &Value32);
  }

  return EFI_SUCCESS;

}
EFI_STATUS
PcatPciRootBridgeParseBars (
  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,
  IN UINT16                         Command,
  IN UINTN                          Bus,
  IN UINTN                          Device,
  IN UINTN                          Function
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS  Status;
  UINT64      Address;
  UINT32      OriginalValue;
  UINT32      Value;
  UINT32      OriginalUpperValue;
  UINT32      UpperValue;
  UINT64      Mask;
  UINTN       Offset;
  UINT64      Base;
  UINT64      Length;
  UINT64      Limit;

  for (Offset = 0x10; Offset < 0x28; Offset += 4) {
    Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);
    Status = PcatPciRootBridgeBarExisted (
               PrivateData,
               Address,
               &OriginalValue,
               &Value
               );

    if (!EFI_ERROR (Status )) {
      if ( Value & 0x01 ) { 
        if (Command & 0x0001) {
          //
          //Device I/Os
          //
          Mask = 0xfffffffc;
          Base = OriginalValue & Mask;
          Length = ((~(Value & Mask)) & Mask) + 0x04;
          if (!(Value & 0xFFFF0000)){
            Length &= 0x0000FFFF;
          }
          Limit = Base + Length - 1;

          if (Base < Limit) {
            if (PrivateData->IoBase > Base) {
              PrivateData->IoBase = (UINT32)Base;
            }
            if (PrivateData->IoLimit < Limit) {
              PrivateData->IoLimit = (UINT32)Limit;
            }
          }
        }
   
      } else {

        if (Command & 0x0002) {

          Mask = 0xfffffff0;
          Base = OriginalValue & Mask;
          Length = Value & Mask;
 
          if ((Value & 0x07) != 0x04) {
            Length = ((~Length) + 1) & 0xffffffff;
          } else {
            Offset += 4; 
            Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);

            Status = PcatPciRootBridgeBarExisted (
                       PrivateData,
                       Address,
                       &OriginalUpperValue,
                       &UpperValue
                       );

            Base   = Base | LShiftU64((UINT64)OriginalUpperValue,32);
            Length = Length | LShiftU64((UINT64)UpperValue,32);
            Length = (~Length) + 1;
          }

          Limit = Base + Length - 1;

          if (Base < Limit) {
            if (PrivateData->MemBase > Base) {
              PrivateData->MemBase = Base;
            }
            if (PrivateData->MemLimit < Limit) {
              PrivateData->MemLimit = Limit;
            }

            switch (Value &0x07) {
            case 0x00: ////memory space; anywhere in 32 bit address space
              if (Value & 0x08) {
                if (PrivateData->Pmem32Base > Base) {
                  PrivateData->Pmem32Base = Base;
                }
                if (PrivateData->Pmem32Limit < Limit) {
                  PrivateData->Pmem32Limit = Limit;
                }
              } else {
                if (PrivateData->Mem32Base > Base) {
                  PrivateData->Mem32Base = Base;
                }
                if (PrivateData->Mem32Limit < Limit) {
                  PrivateData->Mem32Limit = Limit;
                }
              }
              break;
            case 0x04: //memory space; anywhere in 64 bit address space
              if (Value & 0x08) {
                if (PrivateData->Pmem64Base > Base) {
                  PrivateData->Pmem64Base = Base;
                }
                if (PrivateData->Pmem64Limit < Limit) {
                  PrivateData->Pmem64Limit = Limit;
                }
              } else {
                if (PrivateData->Mem64Base > Base) {
                  PrivateData->Mem64Base = Base;
                }
                if (PrivateData->Mem64Limit < Limit) {
                  PrivateData->Mem64Limit = Limit;
                }
              }
              break;
            }
          }
        }
      }
    }
  }
  return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
InitializePcatPciRootBridge (
  IN EFI_HANDLE       ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
/*++

Routine Description:
  Initializes the PCI Root Bridge Controller

Arguments:
  ImageHandle -
  SystemTable -
    
Returns:
    None

--*/
{
  EFI_STATUS                     Status;
  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
  UINTN                          PciSegmentIndex;
  UINTN                          PciRootBridgeIndex;
  UINTN                          PrimaryBusIndex;
  UINTN                          NumberOfPciRootBridges;
  UINTN                          NumberOfPciDevices;
  UINTN                          Device;
  UINTN                          Function;
  UINT16                         VendorId;
  PCI_TYPE02                     PciConfigurationHeader;
  UINT64                         Address;
  UINT64                         Value;
  UINT64                         Base;
  UINT64                         Limit;

  //
  // Initialize gCpuIo now since the chipset init code requires it.
  //
  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo);
  ASSERT_EFI_ERROR (Status);

  //
  // Initialize variables required to search all PCI segments for PCI devices
  //
  PciSegmentIndex        = 0;
  PciRootBridgeIndex     = 0;
  NumberOfPciRootBridges = 0;
  PrimaryBusIndex        = 0;

  while (PciSegmentIndex <= PCI_MAX_SEGMENT) {

    PrivateData = NULL;
    Status = gBS->AllocatePool(
                    EfiBootServicesData,
                    sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),
                    (VOID **)&PrivateData
                    );
    if (EFI_ERROR (Status)) {
      goto Done;
    }

    ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));

    //
    // Initialize the signature of the private data structure
    //
    PrivateData->Signature  = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;
    PrivateData->Handle     = NULL;
    PrivateData->DevicePath = NULL;
    InitializeListHead (&PrivateData->MapInfo);

    //
    // Initialize the PCI root bridge number and the bus range for that root bridge
    //
    PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;
    PrivateData->PrimaryBus       = (UINT32)PrimaryBusIndex;
    PrivateData->SubordinateBus   = (UINT32)PrimaryBusIndex;

    PrivateData->IoBase      = 0xffffffff;
    PrivateData->MemBase     = 0xffffffff;
    PrivateData->Mem32Base   = 0xffffffffffffffffULL;
    PrivateData->Pmem32Base  = 0xffffffffffffffffULL;
    PrivateData->Mem64Base   = 0xffffffffffffffffULL;
    PrivateData->Pmem64Base  = 0xffffffffffffffffULL;

    //
    // The default mechanism for performing PCI Configuration cycles is to 
    // use the I/O ports at 0xCF8 and 0xCFC.  This is only used for IA-32.
    // IPF uses SAL calls to perform PCI COnfiguration cycles
    //
    PrivateData->PciAddress  = 0xCF8;
    PrivateData->PciData     = 0xCFC;

    //
    // Get the physical I/O base for performing PCI I/O cycles
    // For IA-32, this is always 0, because IA-32 has IN and OUT instructions
    // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles
    //
    Status = PcatRootBridgeIoGetIoPortMapping (
               &PrivateData->PhysicalIoBase, 
               &PrivateData->PhysicalMemoryBase
               );
    if (EFI_ERROR (Status)) {
      goto Done;
    }

    //
    // Get PCI Express Base Address
    //
    PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);
 /*   if (PrivateData->PciExpressBaseAddress != 0) {
      DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));
    }
*/
    //
    // Create a lock for performing PCI Configuration cycles
    //
    EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);

    //
    // Initialize the attributes for this PCI root bridge
    //
    PrivateData->Attributes  = 0;

    //
    // Build the EFI Device Path Protocol instance for this PCI Root Bridge
    //
    Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE));
    if (EFI_ERROR (Status)) {
      goto Done;
    }

    //
    // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge
    //
    Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);
    if (EFI_ERROR (Status)) {
      goto Done;
    }
    
    //
    // Scan all the PCI devices on the primary bus of the PCI root bridge
    //
    for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
    
      for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {

        //
        // Compute the PCI configuration address of the PCI device to probe
        //
        Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);

        //
        // Read the Vendor ID from the PCI Configuration Header
        //
        Status = PrivateData->Io.Pci.Read (
                                       &PrivateData->Io, 
                                       EfiPciWidthUint16, 
                                       Address, 
                                       sizeof (VendorId) / sizeof (UINT16), 
                                       &VendorId
                                       );
        if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {
          //
          // If the PCI Configuration Read fails, or a PCI device does not exist, then 
          // skip this entire PCI device
          //
          break;
        }
        if (VendorId == 0xffff) {
          //
          // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.
          //
          continue;
        }

        //
        // Read the entire PCI Configuration Header
        //
        Status = PrivateData->Io.Pci.Read (
                                       &PrivateData->Io, 
                                       EfiPciWidthUint16, 
                                       Address, 
                                       sizeof (PciConfigurationHeader) / sizeof (UINT16), 
                                       &PciConfigurationHeader
                                       );
        if (EFI_ERROR (Status)) {
          //
          // If the entire PCI Configuration Header can not be read, then skip this entire PCI device
          //
          break;
        }


        //
        // Increment the number of PCI device found on the primary bus of the PCI root bridge
        //
        NumberOfPciDevices++;

        //
        // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
        //
        if (PciConfigurationHeader.Hdr.Command & 0x20) {
          PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
        }

        //
        // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
        //
        if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
          //
          // Get the Bus range that the PPB is decoding
          //
          if (PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus > PrivateData->SubordinateBus) {
            //
            // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
            // current subordinate bus number, then update the PCI root bridge's subordinate bus number 
            //
            PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.P2PBridge.SubordinateBus;
          }

          //
          // Get the I/O range that the PPB is decoding
          //
          Value = PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0x0f;
          Base  = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBase & 0xf0) << 8;
          Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimit & 0xf0) << 8) | 0x0fff;
          if (Value == 0x01) {
            Base  |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoBaseUpper16 << 16);
            Limit |= ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.IoLimitUpper16 << 16);
          }
          if (Base < Limit) {
            if (PrivateData->IoBase > Base) {
              PrivateData->IoBase = Base;
            }
            if (PrivateData->IoLimit < Limit) {
              PrivateData->IoLimit = Limit;
            }
          }

          //
          // Get the Memory range that the PPB is decoding
          //
          Base  = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryBase & 0xfff0) << 16;
          Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
          if (Base < Limit) {
            if (PrivateData->MemBase > Base) {
              PrivateData->MemBase = Base;
            }
            if (PrivateData->MemLimit < Limit) {
              PrivateData->MemLimit = Limit;
            }
            if (PrivateData->Mem32Base > Base) {
              PrivateData->Mem32Base = Base;
            }
            if (PrivateData->Mem32Limit < Limit) {
              PrivateData->Mem32Limit = Limit;
            }
          }

          //
          // Get the Prefetchable Memory range that the PPB is decoding
          //
          Value = PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0x0f;
          Base  = ((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryBase & 0xfff0) << 16;
          Limit = (((UINT32)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;
          if (Value == 0x01) {
            Base  |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableBaseUpper32,32);
            Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.P2PBridge.PrefetchableLimitUpper32,32);
          }
          if (Base < Limit) {
            if (PrivateData->MemBase > Base) {
              PrivateData->MemBase = Base;
            }
            if (PrivateData->MemLimit < Limit) {
              PrivateData->MemLimit = Limit;
            }
            if (Value == 0x00) {
              if (PrivateData->Pmem32Base > Base) {
                PrivateData->Pmem32Base = Base;
              }
              if (PrivateData->Pmem32Limit < Limit) {
                PrivateData->Pmem32Limit = Limit;
              }
            }
            if (Value == 0x01) {
              if (PrivateData->Pmem64Base > Base) {
                PrivateData->Pmem64Base = Base;
              }
              if (PrivateData->Pmem64Limit < Limit) {
                PrivateData->Pmem64Limit = Limit;
              }
            }
          }

          //
          // Look at the PPB Configuration for legacy decoding attributes
          //
          if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x04) {
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
          }
          if (PciConfigurationHeader.Bridge.P2PBridge.BridgeControl & 0x08) {
           // PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
          }

        } else if (IS_CARDBUS_BRIDGE(&PciConfigurationHeader)) {
          //
          // Get the Bus range that the PPB is decoding
          //
          if (PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber > PrivateData->SubordinateBus) {
            //
            // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's
            // current subordinate bus number, then update the PCI root bridge's subordinate bus number 
            //
            PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.CardBridge.SubordinateBusNumber;
          }
          
          //
          // Get the I/O range that the PPB is decoding
          //
          Base  = PciConfigurationHeader.Bridge.CardBridge.IoBase0;
          Limit = PciConfigurationHeader.Bridge.CardBridge.IoLimit0;
          if (Base < Limit) {
            if (PrivateData->IoBase > Base) {
              PrivateData->IoBase = Base;
            }
            if (PrivateData->IoLimit < Limit) {
              PrivateData->IoLimit = Limit;
            }
          }
          
          //
          // Get the Memory range that the PPB is decoding
          //
          Base  = PciConfigurationHeader.Bridge.CardBridge.MemoryBase0;
          Limit = PciConfigurationHeader.Bridge.CardBridge.MemoryLimit0;
          if (Base < Limit) {
            if (PrivateData->MemBase > Base) {
              PrivateData->MemBase = Base;
            }
            if (PrivateData->MemLimit < Limit) {
              PrivateData->MemLimit = Limit;
            }
            if (PrivateData->Mem32Base > Base) {
              PrivateData->Mem32Base = Base;
            }
            if (PrivateData->Mem32Limit < Limit) {
              PrivateData->Mem32Limit = Limit;
            }
          }
          
        } else 
          {
          //
          // Parse the BARs of the PCI device to determine what I/O Ranges,
          // Memory Ranges, and Prefetchable Memory Ranges the device is decoding
          //
          if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
            Status = PcatPciRootBridgeParseBars (
                       PrivateData, 
                       PciConfigurationHeader.Hdr.Command,
                       PrimaryBusIndex, 
                       Device, 
                       Function
                       );
          }

          //
          // See if the PCI device is an IDE controller
          //
          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
            }
            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
            }
            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
            }
          }

          //
          // See if the PCI device is a legacy VGA controller
          //
          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
          }

          //
          // See if the PCI device is a standard VGA controller
          //
          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
              PciConfigurationHeader.Hdr.ClassCode[1] == 0x00    ) {
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
          }

          //
          // See if the PCI Device is a PCI - ISA or PCI - EISA 
          // or ISA_POSITIVIE_DECODE Bridge device
          //
          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {
            if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||
                PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || 
                PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;

              if (PrivateData->MemBase > 0xa0000) {
                PrivateData->MemBase = 0xa0000;
              }
              if (PrivateData->MemLimit < 0xbffff) {
               PrivateData->MemLimit = 0xbffff;
             }
            }
          }
        }

        //
        // If this device is not a multi function device, then skip the rest of this PCI device
        //
        if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {
          break;
        }
      }
    }

    //
    // After scanning all the PCI devices on the PCI root bridge's primary bus, update the 
    // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate
    // bus number + 1.
    //
    PrimaryBusIndex = PrivateData->SubordinateBus + 1;

    //
    // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge
    // exists.
    //
    if (NumberOfPciDevices > 0) {

      //
      // Adjust the I/O range used for bounds checking for the legacy decoding attributed
      //
      if (PrivateData->Attributes & 0x7f) {
        PrivateData->IoBase = 0;
        if (PrivateData->IoLimit < 0xffff) {
          PrivateData->IoLimit = 0xffff;
        }
      }

      //
      // Adjust the Memory range used for bounds checking for the legacy decoding attributed
      //
      if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {
        if (PrivateData->MemBase > 0xa0000) {
          PrivateData->MemBase = 0xa0000;
        }
        if (PrivateData->MemLimit < 0xbffff) {
          PrivateData->MemLimit = 0xbffff;
        }
      }

      //
      // Build ACPI descriptors for the resources on the PCI Root Bridge
      //
      Status = ConstructConfiguration(PrivateData);
      ASSERT_EFI_ERROR (Status);

      //
      // Create the handle for this PCI Root Bridge 
      //
      Status = gBS->InstallMultipleProtocolInterfaces (
                     &PrivateData->Handle,              
                     &gEfiDevicePathProtocolGuid,
                     PrivateData->DevicePath,
                     &gEfiPciRootBridgeIoProtocolGuid,
                     &PrivateData->Io,
                     NULL
                     );
      ASSERT_EFI_ERROR (Status);

      //
      // Contruct DeviceIoProtocol
      //
      Status = DeviceIoConstructor (
                 PrivateData->Handle,
                 &PrivateData->Io,
                 PrivateData->DevicePath,
                 (UINT16)PrivateData->PrimaryBus,
                 (UINT16)PrivateData->SubordinateBus
                 );
      ASSERT_EFI_ERROR (Status);
#if 0 //patch by nms42
      //
      // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table
      //
      Status = ScanPciRootBridgeForRoms(&PrivateData->Io);
#endif
      //
      // Increment the index for the next PCI Root Bridge
      //
      PciRootBridgeIndex++;

    } else {

      //
      // If no PCI Root Bridges were found on the current PCI segment, then exit
      //
      if (NumberOfPciRootBridges == 0) {
        Status = EFI_SUCCESS;
        goto Done;
      }

    }

    //
    // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then
    // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0
    // Otherwise, the search is continued on the next PCI Root Bridge
    //
    if (PrimaryBusIndex > PCI_MAX_BUS) {
      PciSegmentIndex++;
      NumberOfPciRootBridges = 0;
      PrimaryBusIndex = 0;
    } else {
      NumberOfPciRootBridges++;
    }

  }

  return EFI_SUCCESS;

Done:
  //
  // Clean up memory allocated for the PCI Root Bridge that was searched but not created.
  //
  if (PrivateData) {
    if (PrivateData->DevicePath) {
      gBS->FreePool(PrivateData->DevicePath);
    }
    gBS->FreePool (PrivateData);
  }

  //
  // If no PCI Root Bridges were discovered, then return the error condition from scanning the
  // first PCI Root Bridge
  //
  if (PciRootBridgeIndex == 0) {
    return Status;
  }

  return EFI_SUCCESS;
}
示例#10
0
VOID
CheckForRom (
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
  UINT16                           MinBus,
  UINT16                           MaxBus,
  UINT16                           MinDevice,
  UINT16                           MaxDevice,
  UINT16                           MinFunc,
  UINT16                           MaxFunc,
  UINT16                           Bus,
  UINT16                           Device,
  UINT16                           Func,
  IN VOID                          *VoidContext
  )
{
  EFI_STATUS                                 Status;
  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;
  UINT64                                     Address;
  PCI_TYPE00                                 PciHeader;
  PCI_TYPE01                                 *PciBridgeHeader;
  UINT32                                     Register;
  UINT32                                     RomBar;
  UINT32                                     RomBarSize;
  EFI_PHYSICAL_ADDRESS                       RomBuffer;
  UINT32                                     MaxRomSize;
  EFI_PCI_EXPANSION_ROM_HEADER               EfiRomHeader;
  PCI_DATA_STRUCTURE                         Pcir;
  EFI_PCI_OPTION_ROM_DESCRIPTOR              *TempPciOptionRomDescriptors;
  BOOLEAN                                    LastImage;

  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

  //
  // Save the contents of the PCI Configuration Header
  //
  IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);

  if (IS_PCI_BRIDGE(&PciHeader)) {

    PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);

    //
    // See if the PCI-PCI Bridge has its secondary interface enabled.
    //
    if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {

      //
      // Disable the Prefetchable Memory Window
      //
      Register = 0x00000000;
      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);
      IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);
      Register = 0xffffffff;
      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);
      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);

      //
      // Program Memory Window to the PCI Root Bridge Memory Window
      //
      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);

      //
      // Enable the Memory decode for the PCI-PCI Bridge
      //
      IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
      Register |= 0x02;
      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

      //
      // Recurse on the Secondary Bus Number
      //
      ScanPciBus(
        IoDev,
        PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, 
        0, PCI_MAX_DEVICE, 
        0, PCI_MAX_FUNC, 
        CheckForRom, Context
        );
    }
  } else {

    //
    // Check if an Option ROM Register is present and save the Option ROM Window Register
    //
    RomBar = 0xffffffff;
    IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
    IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

    RomBarSize = (~(RomBar & 0xfffff800)) + 1;

    //
    // Make sure the size of the ROM is between 0 and 16 MB
    //
    if (RomBarSize > 0 && RomBarSize <= 0x01000000) {

      //
      // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window
      //
      RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;
      RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;
      if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {
        MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;
        RomBar = RomBar + 1;
        IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
        IoDev->Pci.Read  (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);
        RomBar = RomBar - 1;

        //
        // Enable the Memory decode for the PCI Device
        //
        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
        Register |= 0x02;
        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

        //
        // Follow the chain of images to determine the size of the Option ROM present
        // Keep going until the last image is found by looking at the Indicator field
        // or the size of an image is 0, or the size of all the images is bigger than the
        // size of the window programmed into the PPB.
        //
        RomBarSize = 0;
        do {

          LastImage = TRUE;

          ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));
          IoDev->Mem.Read (
            IoDev, 
            EfiPciWidthUint8, 
            RomBar + RomBarSize, 
            sizeof(EfiRomHeader),
            &EfiRomHeader
            );

          Pcir.ImageLength = 0;

          if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&
              EfiRomHeader.PcirOffset != 0 &&
              (EfiRomHeader.PcirOffset & 3) == 0 &&
              RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {
            ZeroMem (&Pcir, sizeof(Pcir));
            IoDev->Mem.Read (
              IoDev, 
              EfiPciWidthUint8, 
              RomBar + RomBarSize + EfiRomHeader.PcirOffset, 
              sizeof(Pcir),
              &Pcir
              );

            if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
              break;
            }
            if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {
              break;
            }
            if ((Pcir.Indicator & 0x80) == 0x00) {
              LastImage = FALSE;
            }

            RomBarSize += Pcir.ImageLength * 512;
          }
        } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);

        if (RomBarSize > 0) {

          //
          // Allocate a memory buffer for the Option ROM contents.
          //
          Status = gBS->AllocatePages(
                          AllocateAnyPages,
                          EfiBootServicesData,
                          EFI_SIZE_TO_PAGES(RomBarSize),
                          &RomBuffer
                          );

          if (!EFI_ERROR (Status)) {

            //
            // Copy the contents of the Option ROM to the memory buffer
            //
            IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);

            Status = gBS->AllocatePool(
                            EfiBootServicesData,
                            ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),
                            (VOID*)&TempPciOptionRomDescriptors
                            );
            if (mPciOptionRomTable.PciOptionRomCount > 0) {
              CopyMem(
                TempPciOptionRomDescriptors, 
                mPciOptionRomTable.PciOptionRomDescriptors, 
                (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)
                );

              gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);
            }

            mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; 

            TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);

            TempPciOptionRomDescriptors->RomAddress              = RomBuffer;
            TempPciOptionRomDescriptors->MemoryType              = EfiBootServicesData;
            TempPciOptionRomDescriptors->RomLength               = RomBarSize;
            TempPciOptionRomDescriptors->Seg                     = (UINT32)IoDev->SegmentNumber;
            TempPciOptionRomDescriptors->Bus                     = (UINT8)Bus;
            TempPciOptionRomDescriptors->Dev                     = (UINT8)Device;
            TempPciOptionRomDescriptors->Func                    = (UINT8)Func;
            TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;
            TempPciOptionRomDescriptors->DontLoadEfiRom          = FALSE;

            mPciOptionRomTable.PciOptionRomCount++;
          }
        }

        //
        // Disable the Memory decode for the PCI-PCI Bridge
        //
        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
        Register &= (~0x02);
        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);
      }
    }
  }

  //
  // Restore the PCI Configuration Header 
  //
  IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);
}
示例#11
0
VOID
ScanPciBus(
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,
  UINT16                           MinBus,
  UINT16                           MaxBus,
  UINT16                           MinDevice,
  UINT16                           MaxDevice,
  UINT16                           MinFunc,
  UINT16                           MaxFunc,
  EFI_PCI_BUS_SCAN_CALLBACK        Callback,
  VOID                             *Context
  )
  
{
  UINT16      Bus;
  UINT16      Device;
  UINT16      Func;
  UINT64      Address;
  PCI_TYPE00  PciHeader;

  //
  // Loop through all busses
  //
  for (Bus = MinBus; Bus <= MaxBus; Bus++) {
    //  
    // Loop 32 devices per bus
    //
    for (Device = MinDevice; Device <= MaxDevice; Device++) {
      //
      // Loop through 8 functions per device
      //
      for (Func = MinFunc; Func <= MaxFunc; Func++) {

        //
        // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device
        //
        Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

        //
        // Read the VendorID from this PCI Device's Confioguration Header
        //
        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);
    
        //
        // If VendorId = 0xffff, there does not exist a device at this 
        // location. For each device, if there is any function on it, 
        // there must be 1 function at Function 0. So if Func = 0, there
        // will be no more functions in the same device, so we can break
        // loop to deal with the next device.
        //  
        if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {
          break;
        }
        
        if (PciHeader.Hdr.VendorId != 0xffff) {

          //
          // Read the HeaderType to determine if this is a multi-function device
          //
          IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);

          //
          // Call the callback function for the device that was found
          //
          Callback(
            IoDev, 
            MinBus, MaxBus,
            MinDevice, MaxDevice,
            MinFunc, MaxFunc,
            Bus,
            Device,
            Func,
            Context
            );

          //
          // If this is not a multi-function device, we can leave the loop 
          // to deal with the next device.
          //
          if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {
            break;
          }
        }  
      }
    }
  }
}
示例#12
0
/**
 *---------------------------------------------------------------------------------------
 *
 *  AddApeiTables
 *
 *  Description:
 *     Event Callback that adds the APEI Tables to OS.
 *
 *  Parameters:
 *    @param[in]     Event
 *    @param[in]     *Context
 *
 *    @retval         EFI_SUCCESS   Error record has been added to BERT table
 *                    EFI_UNSUPPORTED   ErrorType passed in is unsupported
 *                    EFI_OUT_OF_RESOURCES  Could not allocate memory
 *                    EFI_VOLUME_FULL   Cannot add one more error record
 *
 *---------------------------------------------------------------------------------------
 **/
VOID
AddApeiTables (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  EFI_STATUS  Status = EFI_SUCCESS;
  EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupportProtocol = NULL;
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo = NULL;
  UINTN BertTblHandle;
  UINTN EinjTblHandle;
  UINT32  Value32;
  // UINTN  ErstTblHandle;

  BertTblHandle = 0;
  EinjTblHandle = 0;
  //ErstTblHandle = 0;


  // Local ACPI Protocol
  Status = gBS->LocateProtocol (
                                &gAcpiSupportGuid,
                                NULL,
                                &AcpiSupportProtocol
                                );
  if (EFI_ERROR (Status)) {
    return;
  }

  //Add BERT table to the ACPI aware OS
  Status = AcpiSupportProtocol->SetAcpiTable (
                                              AcpiSupportProtocol,                       // IN EFI_ACPI_SUPPORT_PROTOCOL *This
                                              mApeiInterface->ApeiPrivData->ApeiBertTbl, // IN VOID *Table OPTIONAL
                                              TRUE,                                      // IN BOOLEAN Checksum
                                              EFI_ACPI_TABLE_VERSION_ALL,                // IN EFI_ACPI_TABLE_VERSION Version
                                              &BertTblHandle                             // IN OUT UINTN *TableHandle
                                              );
  ASSERT_EFI_ERROR (Status);

  // Locate PCI Root Bridge Protocol
  Status = gBS->LocateProtocol (
                                &gEfiPciRootBridgeIoProtocolGuid,
                                NULL,
                                (VOID**) &PciRootBridgeIo
                                );
  if (EFI_ERROR (Status)) {
    return;
  }

  // Check to see if ECC is enabled before adding EINJ table
  PciRootBridgeIo->Pci.Read (
                             PciRootBridgeIo,
                             EfiPciWidthUint32,
                             EFI_PCI_ADDRESS (0, 0x18, 0x3, 0x44),
                             1,
                             &Value32
                             );

  if (Value32 & (1 << 22)) {
    //
    //Add EINJ table to the ACPI aware OS
    //
    Status = AcpiSupportProtocol->SetAcpiTable (
                                                AcpiSupportProtocol,                        // IN EFI_ACPI_SUPPORT_PROTOCOL *This
                                                mApeiInterface->ApeiPrivData->ApeiEinjTbl,  // IN VOID  *Table OPTIONAL
                                                TRUE,                                       // IN BOOLEAN Checksum
                                                EFI_ACPI_TABLE_VERSION_ALL,                 // IN EFI_ACPI_TABLE_VERSION Version
                                                &EinjTblHandle                              // IN OUT UINTN *TableHandle
                                                );
    ASSERT_EFI_ERROR (Status);
  }

  // Uncomment code below to publish ERST Table to OS
  //Add ERST table
  //Status = AcpiSupportProtocol->SetAcpiTable (
  //                                            AcpiSupportProtocol,                       // IN EFI_ACPI_SUPPORT_PROTOCOL *This
  //                                            mApeiInterface->ApeiPrivData->ApeiErstTbl, // IN VOID *Table OPTIONAL
  //                                            TRUE,                                      // IN BOOLEAN Checksum
  //                                            EFI_ACPI_TABLE_VERSION_ALL,                // IN EFI_ACPI_TABLE_VERSION Version
  //                                            &ErstTblHandle                             // IN OUT UINTN *TableHandle
  //                                            );
  //
  //ASSERT_EFI_ERROR (Status);

  // Close the APEI ready2boot event
  gBS->CloseEvent (mEvtApeiReadyToBoot);
  return;
}
示例#13
0
/**
  Graphics OpRegion / Software SCI driver installation function.

  @param ImageHandle     Handle for this drivers loaded image protocol.
  @param SystemTable     EFI system table.

  @retval EFI_SUCCESS    The driver installed without error.
  @retval EFI_ABORTED    The driver encountered an error and could not complete
                         installation of the ACPI tables.

**/
EFI_STATUS
IgdOpRegionInit (
    void
)
{
    EFI_HANDLE                    Handle;
    EFI_STATUS                    Status;
    EFI_GLOBAL_NVS_AREA_PROTOCOL  *GlobalNvsArea;
    UINT32                        DwordData;
    EFI_CPU_IO_PROTOCOL           *CpuIo;
    UINT16                        Data16;
    UINT16                        AcpiBase;
    VOID                          *gConOutNotifyReg;


    //
    //  Locate the Global NVS Protocol.
    //
    Status = gBS->LocateProtocol (
                 &gEfiGlobalNvsAreaProtocolGuid,
                 NULL,
                 (void **)&GlobalNvsArea
             );
    ASSERT_EFI_ERROR (Status);

    //
    // Allocate an ACPI NVS memory buffer as the IGD OpRegion, zero initialize
    // the first 1K, and set the IGD OpRegion pointer in the Global NVS
    // area structure.
    //
    Status = (gBS->AllocatePool) (
                 EfiACPIMemoryNVS,
                 sizeof (IGD_OPREGION_STRUC),
                 (void **)&mIgdOpRegion.OpRegion
             );
    ASSERT_EFI_ERROR (Status);
    (gBS->SetMem) (
        mIgdOpRegion.OpRegion,
        sizeof (IGD_OPREGION_STRUC),
        0
    );
    GlobalNvsArea->Area->IgdOpRegionAddress = (UINT32)(UINTN)(mIgdOpRegion.OpRegion);

    //
    // If IGD is disabled return
    //
    if (IgdMmPci32 (0) == 0xFFFFFFFF) {
        return EFI_SUCCESS;
    }

    //
    // Initialize OpRegion Header
    //

    (gBS->CopyMem) (
        mIgdOpRegion.OpRegion->Header.SIGN,
        HEADER_SIGNATURE,
        sizeof(HEADER_SIGNATURE)
    );


    //
    // Set OpRegion Size in KBs
    //
    mIgdOpRegion.OpRegion->Header.SIZE = HEADER_SIZE/1024;

    //
    // FIXME: Need to check Header OVER Field and the supported version.
    //
    mIgdOpRegion.OpRegion->Header.OVER = (UINT32) (LShiftU64 (HEADER_OPREGION_VER, 16) + LShiftU64 (HEADER_OPREGION_REV, 8));
#ifdef ECP_FLAG
    CopyMem(mIgdOpRegion.OpRegion->Header.SVER, gSVER, sizeof(gSVER));
#else
    gBS->CopyMem(
        mIgdOpRegion.OpRegion->Header.SVER,
        gSVER,
        sizeof(gSVER)
    );
#endif
    DEBUG ((EFI_D_ERROR, "System BIOS ID is %a\n", mIgdOpRegion.OpRegion->Header.SVER));


    mIgdOpRegion.OpRegion->Header.MBOX = HEADER_MBOX_SUPPORT;

    if( 1 == DxePlatformSaPolicy->IdleReserve) {
        mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | BIT1;
    } else {
        mIgdOpRegion.OpRegion->Header.PCON = (mIgdOpRegion.OpRegion->Header.PCON & 0xFFFC) | (BIT1 | BIT0);
    }

    //
    //For graphics driver to identify if LPE Audio/HD Audio is enabled on the platform
    //
    mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_SUPPORT_MASK;
    mIgdOpRegion.OpRegion->Header.PCON &= AUDIO_TYPE_FIELD_MASK;
    if ( 1 == DxePlatformSaPolicy->AudioTypeSupport ) {
        mIgdOpRegion.OpRegion->Header.PCON = HD_AUDIO_SUPPORT;
        mIgdOpRegion.OpRegion->Header.PCON |= AUDIO_TYPE_FIELD_VALID;
    }

    //
    // Initialize OpRegion Mailbox 1 (Public ACPI Methods).
    //
    //<TODO> The initial setting of mailbox 1 fields is implementation specific.
    // Adjust them as needed many even coming from user setting in setup.
    //
    //Workaround to solve LVDS is off after entering OS in desktop platform
    //
    mIgdOpRegion.OpRegion->MBox1.CLID = DxePlatformSaPolicy->IgdPanelFeatures.LidStatus;

    //
    // Initialize OpRegion Mailbox 3 (ASLE Interrupt and Power Conservation).
    //
    //<TODO> The initial setting of mailbox 3 fields is implementation specific.
    // Adjust them as needed many even coming from user setting in setup.
    //

    //
    // Do not initialize TCHE. This field is written by the graphics driver only.
    //

    //
    // The ALSI field is generally initialized by ASL code by reading the embedded controller.
    //

    mIgdOpRegion.OpRegion->MBox3.BCLP = BACKLIGHT_BRIGHTNESS;

    mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);
    if ( DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 2) {
        //
        // Center
        //
        mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_CENTER);
    } else if (DxePlatformSaPolicy->IgdPanelFeatures.PFITStatus == 1) {
        //
        // Stretch
        //
        mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_STRETCH);
    } else {
        //
        // Auto
        //
        mIgdOpRegion.OpRegion->MBox3.PFIT = (FIELD_VALID_BIT | PFIT_SETUP_AUTO);
    }

    //
    // Set Initial current Brightness
    //
    mIgdOpRegion.OpRegion->MBox3.CBLV = (INIT_BRIGHT_LEVEL | FIELD_VALID_BIT);

    //
    // <EXAMPLE> Create a static Backlight Brightness Level Duty cycle Mapping Table
    // Possible 20 entries (example used 10), each 16 bits as follows:
    // [15] = Field Valid bit, [14:08] = Level in Percentage (0-64h), [07:00] = Desired duty cycle (0 - FFh).
    //
    //                                             %            Brightness
    mIgdOpRegion.OpRegion->MBox3.BCLM[0]   = ( (  0 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[1]   = ( (  1 << 8 ) + ( 0xFF - 0xFC ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[2]   = ( ( 10 << 8 ) + ( 0xFF - 0xE5 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[3]   = ( ( 19 << 8 ) + ( 0xFF - 0xCE ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[4]   = ( ( 28 << 8 ) + ( 0xFF - 0xB7 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[5]   = ( ( 37 << 8 ) + ( 0xFF - 0xA0 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[6]   = ( ( 46 << 8 ) + ( 0xFF - 0x89 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[7]   = ( ( 55 << 8 ) + ( 0xFF - 0x72 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[8]   = ( ( 64 << 8 ) + ( 0xFF - 0x5B ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[9]   = ( ( 73 << 8 ) + ( 0xFF - 0x44 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[10]  = ( ( 82 << 8 ) + ( 0xFF - 0x2D ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[11]  = ( ( 91 << 8 ) + ( 0xFF - 0x16 ) + WORD_FIELD_VALID_BIT);
    mIgdOpRegion.OpRegion->MBox3.BCLM[12]  = ( (100 << 8 ) + ( 0xFF - 0x00 ) + WORD_FIELD_VALID_BIT);

    mIgdOpRegion.OpRegion->MBox3.PCFT = ((UINT32) GlobalNvsArea->Area->IgdPowerConservation) | BIT31;
    //
    // Create the notification and register callback function on the PciIo installation,
    //
    //
    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_CALLBACK,
                 (EFI_EVENT_NOTIFY)GetVBiosVbtCallback,
                 NULL,
                 &mConOutEvent
             );

    ASSERT_EFI_ERROR (Status);
    if (EFI_ERROR (Status)) {
        return Status;

    }

    Status = gBS->RegisterProtocolNotify (
#ifdef ECP_FLAG
                 &gExitPmAuthProtocolGuid,
#else
                 &gEfiDxeSmmReadyToLockProtocolGuid,
#endif
                 mConOutEvent,
                 &gConOutNotifyReg
             );

    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_CALLBACK,
                 (EFI_EVENT_NOTIFY)SetGOPVersionCallback,
                 NULL,
                 &mSetGOPverEvent
             );

    ASSERT_EFI_ERROR (Status);
    if (EFI_ERROR (Status)) {
        return Status;
    }

    Status = gBS->RegisterProtocolNotify (
                 &gEfiGraphicsOutputProtocolGuid,
                 mSetGOPverEvent,
                 &gConOutNotifyReg
             );


    //
    // Initialize hardware state:
    //   Set ASLS Register to the OpRegion physical memory address.
    //   Set SWSCI register bit 15 to a "1" to activate SCI interrupts.
    //

    IgdMmPci32 (IGD_ASLS_OFFSET) = (UINT32)(UINTN)(mIgdOpRegion.OpRegion);
    IgdMmPci16AndThenOr (IGD_SWSCI_OFFSET, ~(BIT0), BIT15);

    DwordData = IgdMmPci32 (IGD_ASLS_OFFSET);
    S3BootScriptSavePciCfgWrite (
        S3BootScriptWidthUint32,
        (UINTN) (EFI_PCI_ADDRESS  (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_ASLS_OFFSET)),
        1,
        &DwordData
    );


    DwordData = IgdMmPci32 (IGD_SWSCI_OFFSET);
    S3BootScriptSavePciCfgWrite (
        S3BootScriptWidthUint32,
        (UINTN) (EFI_PCI_ADDRESS  (IGD_BUS, IGD_DEV, IGD_FUN_0, IGD_SWSCI_OFFSET)),
        1,
        &DwordData
    );

    AcpiBase =  MmPci16 (
                    0,
                    DEFAULT_PCI_BUS_NUMBER_PCH,
                    PCI_DEVICE_NUMBER_PCH_LPC,
                    PCI_FUNCTION_NUMBER_PCH_LPC,
                    R_PCH_LPC_ACPI_BASE
                ) & B_PCH_LPC_ACPI_BASE_BAR;

    //
    // Find the CPU I/O Protocol.  ASSERT if not found.
    //
    Status = gBS->LocateProtocol (
                 &gEfiCpuIoProtocolGuid,
                 NULL,
                 (void **)&CpuIo
             );
    ASSERT_EFI_ERROR (Status);

    CpuIo->Io.Read (
        CpuIo,
        EfiCpuIoWidthUint16,
        AcpiBase + R_PCH_ACPI_GPE0a_STS,
        1,
        &Data16
    );
    //
    // Clear the B_PCH_ACPI_GPE0a_STS_GUNIT_SCI bit in R_PCH_ACPI_GPE0a_STS by writing a '1'.
    //
    Data16 |= B_PCH_ACPI_GPE0a_STS_GUNIT_SCI;

    CpuIo->Io.Write (
        CpuIo,
        EfiCpuIoWidthUint16,
        AcpiBase + R_PCH_ACPI_GPE0a_STS,
        1,
        &Data16
    );

    //
    // Install OpRegion / Software SCI protocol
    //
    Handle = NULL;
    Status = gBS->InstallMultipleProtocolInterfaces (
                 &Handle,
                 &gIgdOpRegionProtocolGuid,
                 &mIgdOpRegion,
                 NULL
             );
    ASSERT_EFI_ERROR (Status);

    //
    // Return final status
    //
    return EFI_SUCCESS;
}