Exemple #1
0
/**
  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);
}
Exemple #2
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
/**
  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;
}
Exemple #6
0
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;
}
Exemple #9
0
/**
  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);
}