/** Get the NIC's PCI location and return it accroding to the composited format defined in iSCSI Boot Firmware Table. @param[in] Controller The handle of the controller. @return UINT16 The composited representation of the NIC PCI location. @retval 0 Other errors as indicated. **/ UINT16 IScsiGetNICPciLocation ( IN EFI_HANDLE Controller ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_HANDLE PciIoHandle; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; Status = gBS->HandleProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &DevicePath, &PciIoHandle ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo); if (EFI_ERROR (Status)) { return 0; } Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); if (EFI_ERROR (Status)) { return 0; } return (UINT16) ((Bus << 8) | (Device << 3) | Function); }
STATIC UINT16 IScsiGetNICPciLocation ( IN EFI_HANDLE Controller ) /*++ Routine Description: Get the NIC's PCI location and return it accroding to the composited format defined in iSCSI Boot Firmware Table. Arguments: Controller - The handle of the controller. Returns: UINT16 - The composited representation of the NIC PCI location. --*/ { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_HANDLE PciIoHandle; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; Status = gBS->HandleProtocol ( Controller, &gEfiDevicePathProtocolGuid, &DevicePath ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &DevicePath, &PciIoHandle ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo); if (EFI_ERROR (Status)) { return 0; } Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); if (EFI_ERROR (Status)) { return 0; } return (UINT16) ((Bus << 8) | (Device << 3) | Function); }
/** Complete build of BBS TABLE. @param Private Legacy BIOS Instance data @param BbsTable BBS Table passed to 16-bit code @retval EFI_SUCCESS Removable media not present **/ EFI_STATUS LegacyBiosBuildBbs ( IN LEGACY_BIOS_INSTANCE *Private, IN BBS_TABLE *BbsTable ) { UINTN BbsIndex; HDD_INFO *HddInfo; UINTN HddIndex; UINTN Index; // // First entry is floppy. // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. // Next n entries are filled in after each ROM is dispatched. // Entry filled in if follow BBS spec. See LegacyPci.c // Next entries are for non-BBS compliant ROMS. They are filled in by // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority // occurs after that invocation. // // Floppy // Set default state. // IsHaveMediaInFloppy = HasMediaInFloppy (); if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) { BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY; } else { if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) { BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY; } else { BbsTable[0].BootPriority = BBS_IGNORE_ENTRY; } } BbsTable[0].Bus = 0xff; BbsTable[0].Device = 0xff; BbsTable[0].Function = 0xff; BbsTable[0].DeviceType = BBS_FLOPPY; BbsTable[0].Class = 01; BbsTable[0].SubClass = 02; BbsTable[0].StatusFlags.OldPosition = 0; BbsTable[0].StatusFlags.Reserved1 = 0; BbsTable[0].StatusFlags.Enabled = 0; BbsTable[0].StatusFlags.Failed = 0; BbsTable[0].StatusFlags.MediaPresent = 0; BbsTable[0].StatusFlags.Reserved2 = 0; // // Onboard HDD - Note Each HDD controller controls 2 drives // Master & Slave // HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; // // Get IDE Drive Info // LegacyBiosBuildIdeData (Private, &HddInfo, 0); for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { BbsIndex = HddIndex * 2 + 1; for (Index = 0; Index < 2; ++Index) { BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus; BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device; BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function; BbsTable[BbsIndex + Index].Class = 01; BbsTable[BbsIndex + Index].SubClass = 01; BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0; BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0; BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0; BbsTable[BbsIndex + Index].StatusFlags.Failed = 0; BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0; BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0; // // If no controller found or no device found set to ignore // else set to unprioritized and set device type // if (HddInfo[HddIndex].CommandBaseAddress == 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } else { if (Index == 0) { if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; } else { // // for ZIPDISK // BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } } else { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } } else { if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; } else { // // for ZIPDISK // BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } } else { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } } } } } // // add virtio-blk devices // { EFI_STATUS Status; UINTN NumPciIoHandles; EFI_HANDLE *PciIoHandles; BbsIndex = HddIndex * 2 + 1; // // scan all handles supporting the PCI IO protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &NumPciIoHandles, &PciIoHandles ); if (Status == EFI_SUCCESS) { UINTN CurPciIo; for (CurPciIo = 0; CurPciIo < NumPciIoHandles; ++CurPciIo) { EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *References; UINTN NumReferences; UINTN CurRef; // // on each handle supporting the PCI IO protocol, see which drivers // (agents) have a PCI IO protocol interface actually opened // Status = gBS->OpenProtocolInformation ( PciIoHandles[CurPciIo], &gEfiPciIoProtocolGuid, &References, &NumReferences ); if (EFI_ERROR (Status)) { continue; } for (CurRef = 0; CurRef < NumReferences; ++CurRef) { if (References[CurRef].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { EFI_COMPONENT_NAME2_PROTOCOL *ComponentName; CHAR16 *DriverName; // // OpenProtocol() enforced non-NULL AgentHandle for this case // ASSERT (References[CurRef].AgentHandle != NULL); // // Check if the agent owning the open protocol interface can // provide its name, and if so, whether it's VirtioBlkDxe. For this // check we don't want a persistent reference to the agent's // EFI_COMPONENT_NAME2_PROTOCOL instance, therefore we use // HandleProtocol() instead of OpenProtocol(). // Status = gBS->HandleProtocol ( References[CurRef].AgentHandle, &gEfiComponentName2ProtocolGuid, (VOID **) &ComponentName ); if (EFI_ERROR (Status)) { continue; } Status = ComponentName->GetDriverName ( ComponentName, "en", &DriverName ); if (Status == EFI_SUCCESS && StrCmp (DriverName, L"Virtio Block Driver") == 0) { break; } } } if (CurRef < NumReferences) { EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; // // reference by VirtioBlkDxe found, produce boot entry for device // Status = gBS->HandleProtocol ( PciIoHandles[CurPciIo], &gEfiPciIoProtocolGuid, (VOID **) &PciIo ); ASSERT (Status == EFI_SUCCESS); Status = PciIo->GetLocation ( PciIo, &Segment, &Bus, &Device, &Function ); ASSERT (Status == EFI_SUCCESS); if (Segment == 0) { BbsTable[BbsIndex].Bus = (UINT32) Bus; BbsTable[BbsIndex].Device = (UINT32) Device; BbsTable[BbsIndex].Function = (UINT32) Function; BbsTable[BbsIndex].Class = 1; BbsTable[BbsIndex].SubClass = 0x80; 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].DeviceType = BBS_HARDDISK; BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY; ++BbsIndex; } } FreePool (References); } FreePool (PciIoHandles); } } return EFI_SUCCESS; }
EFI_STATUS EFIAPI GetPciRom ( IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, IN EFI_HANDLE PciHandle, OUT VOID **RomImage, OUT UINTN *RomSize ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINT16 VendorId; UINT16 DeviceId; UINT16 DeviceClass; UINTN TableIndex; UINT8 Data8; BOOLEAN MfgMode; EFI_PLATFORM_SETUP_ID *BootModeBuffer; EFI_PEI_HOB_POINTERS GuidHob; MfgMode = FALSE; // // Check if system is in manufacturing mode. // GuidHob.Raw = GetHobList (); if (GuidHob.Raw == NULL) { return EFI_NOT_FOUND; } if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformBootModeGuid, GuidHob.Raw)) != NULL) { BootModeBuffer = GET_GUID_HOB_DATA (GuidHob.Guid); if (!CompareMem (&BootModeBuffer->SetupName, MANUFACTURE_SETUP_NAME, StrSize (MANUFACTURE_SETUP_NAME))) { // // System is in manufacturing mode. // MfgMode = TRUE; } } Status = gBS->HandleProtocol ( PciHandle, &gEfiPciIoProtocolGuid, (void **)&PciIo ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } Status = gBS->LocateProtocol ( &gEfiPciRootBridgeIoProtocolGuid, NULL, (void **)&PciRootBridgeIo ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass); PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId); // // WA for PCIe SATA card (SYBA SY-PEX400-40) // if ((VendorId == 0x1B21) && (DeviceId == 0x0612)) { Data8 = 0x07; PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 4, 1, &Data8); } // // Do not run RAID or AHCI Option ROM if IDE // if ( (DeviceClass == ((PCI_CLASS_MASS_STORAGE << 8 ) | PCI_CLASS_MASS_STORAGE_IDE)) ) { return EFI_NOT_FOUND; } // // Run PXE ROM only if Boot network is enabled and not in MFG mode // if (DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) { if (((mSystemConfiguration.BootNetwork == 0) && (MfgMode == FALSE )) || (mSystemConfiguration.FastBoot == 1)) { return EFI_NOT_FOUND; } } // // Loop through table of Onboard option rom descriptions // for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) { // // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable // if (VendorId != mPciOptionRomTable[TableIndex].VendorId || DeviceId != mPciOptionRomTable[TableIndex].DeviceId || ((DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) && (mPciOptionRomTable[TableIndex].Flag != mSystemConfiguration.BootNetwork)) ) { continue; } Status = GetRawImage( &mPciOptionRomTable[TableIndex].FileName, RomImage, RomSize ); if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_VLV_A0)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_VLV_A0; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_II)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_II; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_0BE4)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_0BE4; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_QS)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_QS; } if (EFI_ERROR (Status)) { continue; } return EFI_SUCCESS; } return EFI_NOT_FOUND; }
/** ControllerDriver Protocol Method @param This Driver Binding protocol instance pointer. @param Controller Handle of device to test. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI PcatIsaAcpiDriverBindingSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; UINTN SegmentNumber; UINTN BusNumber; UINTN DeviceNumber; UINTN FunctionNumber; // // Get PciIo protocol instance // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID**)&PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR(Status)) { return Status; } Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint32, 0, sizeof(Pci) / sizeof(UINT32), &Pci); if (!EFI_ERROR (Status)) { Status = EFI_UNSUPPORTED; if ((Pci.Hdr.Command & 0x03) == 0x03) { if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) { // // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code // if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) { Status = EFI_SUCCESS; } // // See if this is an Intel PCI to ISA bridge in Positive Decode Mode // if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE && Pci.Hdr.VendorId == 0x8086 ) { // // See if this is on Function #0 to avoid false positives on // PCI_CLASS_BRIDGE_OTHER that has the same value as // PCI_CLASS_BRIDGE_ISA_PDECODE // Status = PciIo->GetLocation ( PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber ); if (!EFI_ERROR (Status) && FunctionNumber == 0) { Status = EFI_SUCCESS; } else { Status = EFI_UNSUPPORTED; } } } } } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
VOID EFIAPI SEnvPciIo ( IN EFI_HANDLE h, IN VOID *Interface ) /*++ Routine Description: Arguments: h - An EFI handle Interface - The interface Returns: --*/ { EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINTN Index; PciIo = Interface; PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); // // Dump PciIo Info // Print (L"\n"); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_SEGMENT_2), HiiEnvHandle, Segment); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_BUS_2), HiiEnvHandle, Bus); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_NUMBER), HiiEnvHandle, Device); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_FUNCTION_NUMBER_2), HiiEnvHandle, Function); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ROM_SIZE_2), HiiEnvHandle, PciIo->RomSize); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ROM_LOCATION), HiiEnvHandle, PciIo->RomImage); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_VENDOR_ID), HiiEnvHandle, Pci.Hdr.VendorId); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_ID_2), HiiEnvHandle, Pci.Hdr.DeviceId); PrintToken ( STRING_TOKEN (STR_SHELLENV_DPROT_CLASS_CODE), HiiEnvHandle, Pci.Hdr.ClassCode[0], Pci.Hdr.ClassCode[1], Pci.Hdr.ClassCode[2] ); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_CONFIG_HEADER), HiiEnvHandle); for (Index = 0; Index < sizeof (Pci); Index++) { if ((Index % 0x10) == 0) { Print (L"\n "); } PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ONE_VAR_X), HiiEnvHandle, *((UINT8 *) (&Pci) + Index)); } Print (L"\n"); }
EFI_STATUS GetPciRom ( IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, IN EFI_HANDLE PciHandle, OUT VOID **RomImage, OUT UINTN *RomSize ) /*++ Routine Description: Return a PCI ROM image for the onboard device represented by PciHandle Arguments: This - Protocol instance pointer. PciHandle - PCI device to return the ROM image for. RomImage - PCI Rom Image for onboard device RomSize - Size of RomImage in bytes Returns: EFI_SUCCESS - RomImage is valid EFI_NOT_FOUND - No RomImage --*/ { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINT16 VendorId; UINT16 DeviceId; UINT16 DeviceClass; UINTN TableIndex; Status = gBS->HandleProtocol ( PciHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId); // // Loop through table of video option rom descriptions // for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) { // // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable // if (VendorId != mPciOptionRomTable[TableIndex].VendorId || DeviceId != mPciOptionRomTable[TableIndex].DeviceId || Segment != mPciOptionRomTable[TableIndex].Segment || Bus != mPciOptionRomTable[TableIndex].Bus || Device != mPciOptionRomTable[TableIndex].Device || Function != mPciOptionRomTable[TableIndex].Function) { continue; } Status = GetSectionFromFv ( &mPciOptionRomTable[TableIndex].FileName, EFI_SECTION_RAW, 0, RomImage, RomSize ); if (EFI_ERROR (Status)) { continue; } return EFI_SUCCESS; } return EFI_NOT_FOUND; }
VOID GetGpuVbiosImage ( IN AMD_CPM_DISPLAY_FEATURE_PROTOCOL *CpmDisplayFeatureProtocolPtr, IN UINT8 GpuType, OUT VOID **VBiosImage, OUT UINTN *VBiosImageSize ) { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINTN Index; EFI_PCI_IO_PROTOCOL *PciIo; BOOLEAN Found; BOOLEAN dGpVbiosBarStatus; AMD_CPM_ALL_PCI_IO_PROTOCOLS_INSTALLED_PROTOCOL *Tmp; UINT32 *VbiosInfo; UINTN Seg; UINTN Bus; UINTN Dev; UINTN Fnc; UINT8 GpuBus; EFI_HANDLE VgaHandle; UINT16 dGpVid; UINT32 dGpVbiosBar; CPM_DISPLAY_FEATURE_PRIVATE *DisplayFeatureDataPtr; UINT16 *TmpPtr; PCI_DATA_STRUCTURE *TmpPciDataStruct; UINT32 FrameBufferAddress; UINT32 RomAddress; UINT32 Temp; dGpVbiosBarStatus = FALSE; dGpVid = 0; Found = FALSE; PciIo = NULL; GpuBus = 0x00; Seg = 0x00; Bus = 0x00; Dev = 0x00; Fnc = 0x00; VgaHandle = NULL; DisplayFeatureDataPtr = &CpmDisplayFeatureProtocolPtr->DisplayFeatureData; // // A. Search Int or Ext GFX bridge and then get the SubBus information from this bridge // // Step 01. // Search handles that support the gEfiPciIoProtocolGuid protocol // gBS->LocateHandleBuffer returns an array of handles. Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer ); ASSERT_EFI_ERROR (Status); // //B. Search iGPU / dGPU device under bridge // *VBiosImage = NULL; *VBiosImageSize = 0; for (Index = 0; (Index < HandleCount) && (Found == FALSE); Index++) { Status = gBS->HandleProtocol ( HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID**)&PciIo ); if (EFI_ERROR (Status)) { continue; } // // Step 01. // See if this is a PCI Graphics Controller by looking at Class Code Register // PciIo->GetLocation ( PciIo, &Seg, &Bus, &Dev, &Fnc ); if (((UINTN)Bus == DisplayFeatureDataPtr->GfxDevicePfa[GpuType].Pfa.Bus) && ((UINTN)Dev == DisplayFeatureDataPtr->GfxDevicePfa[GpuType].Pfa.Device) && ((UINTN)Fnc == DisplayFeatureDataPtr->GfxDevicePfa[GpuType].Pfa.Function)) { Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET, //Start offset: 0x00 1, //Length of bytes &dGpVid ); Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint32, 0x30, //Start offset: 0x30 1, //Length of bytes &dGpVbiosBar ); if (dGpVid != 0xFFFF) { if (dGpVbiosBar) { Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint32, 0x10, //Start offset: 0x10 1, //Length of bytes &FrameBufferAddress ); RomAddress = FrameBufferAddress & 0xFFFFFFF0; if (RomAddress) { Temp = 0; Status = PciIo->Pci.Write ( PciIo, EfiPciIoWidthUint32, 0x10, //Start offset: 0x10 1, //Length of bytes &Temp ); Temp = RomAddress | 0x00000001; Status = PciIo->Pci.Write ( PciIo, EfiPciIoWidthUint32, 0x30, //Start offset: 0x30 1, //Length of bytes &Temp ); if (CpmDisplayFeatureProtocolPtr->TableProtocolPtr->CommonFunction.MmioRead16 (RomAddress) == 0xAA55) { dGpVbiosBarStatus = TRUE; } Status = PciIo->Pci.Write ( PciIo, EfiPciIoWidthUint32, 0x10, //Start offset: 0x10 1, //Length of bytes &FrameBufferAddress ); Status = PciIo->Pci.Write ( PciIo, EfiPciIoWidthUint32, 0x30, //Start offset: 0x30 1, //Length of bytes &dGpVbiosBar ); } } VgaHandle = HandleBuffer[Index]; *VBiosImage = PciIo->RomImage; *VBiosImageSize = (UINTN) PciIo->RomSize; } else { *VBiosImage = NULL; *VBiosImageSize = 0; } Found = TRUE; } } // // Check VBIOS ROM SIZE. if it is harger 64K bytes, it must be adjusted. // if (*VBiosImageSize > 0x10000) { // // Get a Pointer to PCI Data Structure from offset 0x18,0x19 // TmpPtr = (UINT16 *) ((UINT8 *) (*VBiosImage) + 0x18); // // Get actual VBios image size // TmpPciDataStruct = (PCI_DATA_STRUCTURE *) ((UINT8 *) (*VBiosImage) + (*TmpPtr)); *VBiosImageSize = (UINT16) (TmpPciDataStruct->ImageLength) * 512; } // //Step03. Save OpRom info. to an Array of AmdCpmAllPciIoProtocolsInstalledProtocolGuid // Status = gBS->AllocatePool ( EfiBootServicesData, 12, //(UINT32 = 4 bytes, 4 byte * 3 = 12 bytes) (VOID**)&VbiosInfo ); Status = gBS->LocateProtocol (&gAmdCpmAllPciIoProtocolsInstalledProtocolGuid, NULL, (VOID**)&Tmp); VbiosInfo[0] = (UINT32) (UINTN)*VBiosImage; VbiosInfo[1] = (UINT32) *VBiosImageSize; VbiosInfo[2] = (UINT32) (UINTN)VgaHandle; DisplayFeatureDataPtr->VBiosImage = (UINT32) (UINTN) *VBiosImage; DisplayFeatureDataPtr->VBiosImageSize = (UINT32) *VBiosImageSize; if (dGpVbiosBarStatus) { DisplayFeatureDataPtr->VBiosFlag = 1; } else { DisplayFeatureDataPtr->VBiosFlag = 0; } Tmp->Buffer = (VOID *)VbiosInfo; return; }
/** Finds the device path that should be used as the primary display adapter. @param VgaHandle - The handle of the video device **/ VOID GetSelectedVgaDeviceInfo ( OUT EFI_HANDLE *VgaHandle ) { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINTN Index; EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; UINT8 MinBus; UINT8 MaxBus; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINTN SelectedAddress; UINTN CurrentAddress; // // Initialize return to 'not found' state // *VgaHandle = NULL; // // Initialize variable states. Ths is important for selecting the VGA device // if multiple devices exist behind a single bridge. // HandleCount = 0; HandleBuffer = NULL; SelectedAddress = PCI_LIB_ADDRESS(0xff, 0x1f, 0x7, 0); // // The bus range to search for a VGA device in. // MinBus = MaxBus = 0; // // Start to check all the pci io to find all possible VGA device // HandleCount = 0; HandleBuffer = NULL; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { return; } for (Index = 0; Index < HandleCount; Index++) { Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID**)&PciIo); if (!EFI_ERROR (Status)) { // // Detemine if this is in the correct bus range. // Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); if (EFI_ERROR(Status) || (Bus < MinBus || Bus > MaxBus)) { continue; } // // Read device information. // Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci ); if (EFI_ERROR (Status)) { continue; } // // Make sure the device is a VGA device. // if (!IS_PCI_VGA (&Pci)) { continue; } DEBUG ((EFI_D_INFO, "PCI VGA: 0x%04x:0x%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId )); // // Currently we use the lowest numbered bus/device/function if multiple // devices are found in the target bus range. // CurrentAddress = PCI_LIB_ADDRESS(Bus, Device, Function, 0); if (CurrentAddress < SelectedAddress) { SelectedAddress = CurrentAddress; *VgaHandle = HandleBuffer[Index]; } } } FreePool (HandleBuffer); }