Questions about unusual PCI location when using EFI_PCI_IO_PROTOCOL in ARM system


gustavo.marcello@...
 

Hello,

I am learning about PCI and trying to write an application that lists PCI controllers in UEFI environment, using EFI_PCI_IO_PROTOCOL and EDK2. I want to list some information from Configuration Space Header and the Bus/Device/Function location for each instance.

The system that I am executing the application is an ARM, which has a Qualcomm
Snapdragon SoC. The code simply locates all handles for EFI_PCI_IO_PROTOCOL and reads some information from each one, as shown in this code snippet:

EFI_GUID gPciIo = EFI_PCI_IO_PROTOCOL_GUID;
EFI_PCI_IO_PROTOCOL *PciIo;
...

// Locate all handles with PciIo protocol
gBS->LocateHandleBuffer(ByProtocol, &gPciIo, NULL, &NoHandles, &Buffer);

// Scan all found handles
for (Index = 0, Count = 0; Index < NoHandles; Index++) {
// Get PciIo protocol for current handle
gBS->HandleProtocol (Buffer[Index], &gPciIo, (VOID**) &PciIo);
// Get some PCI information
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x00, 2, &VendorId);
...
// Check if VendorId is different from 0xFFFF
...

// Get location
PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);

// Show PCI information
...
}

The information retrieved from EFI_PCI_IO_PROTOCOL seems to be OK, except the information from GetLocation that some USB controller handles are returning, as follows:

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x80
Function: 0x00

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x81
Function: 0x00

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x82
Function: 0x00

My questions are:

1 - I am not familiar with PCI, but, as far as I know, maximum device number is 32, since it comes from a 5 bits field, am I correct? If so, how can it be 0x80, 0x81 or 0x82, maybe a bug in EFI_PCI_IO_PROTOCOL code or am I missing something?

2 - Usually , the bus numbering use sequential numbers starting from 0 (afaik again), and since it's a simple small system with few PCI components (it does not have 255 buses), what does the number 0xFF for Bus indicates?

PS: "pci" command in UEFI Shell do not show these USB controllers but "devtree" command shows these USB contollers with the same Device/Funcion numbers.

Thanks so much!


Laszlo Ersek
 

On 02/16/21 14:41, gustavo.marcello via groups.io wrote:
Hello,

I am learning about PCI and trying to write an application that lists PCI controllers in UEFI environment, using EFI_PCI_IO_PROTOCOL and EDK2. I want to list some information from Configuration Space Header and the Bus/Device/Function location for each instance.

The system that I am executing the application is an ARM, which has a Qualcomm
Snapdragon SoC. The code simply locates all handles for EFI_PCI_IO_PROTOCOL and reads some information from each one, as shown in this code snippet:

EFI_GUID gPciIo = EFI_PCI_IO_PROTOCOL_GUID;
EFI_PCI_IO_PROTOCOL *PciIo;
...

// Locate all handles with PciIo protocol
gBS->LocateHandleBuffer(ByProtocol, &gPciIo, NULL, &NoHandles, &Buffer);
Style comment: you should remove "gPciIo", and use the auto-generated
"gEfiPciIoProtocolGuid" variable instead.


// Scan all found handles
for (Index = 0, Count = 0; Index < NoHandles; Index++) {
// Get PciIo protocol for current handle
gBS->HandleProtocol (Buffer[Index], &gPciIo, (VOID**) &PciIo);
// Get some PCI information
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x00, 2, &VendorId);
Why not read it with a single EfiPciIoWidthUint16 operation?

Also, for the offset, PCI_VENDOR_ID_OFFSET would be more idiomatic.

...
// Check if VendorId is different from 0xFFFF
...

// Get location
PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);

// Show PCI information
...
}

The information retrieved from EFI_PCI_IO_PROTOCOL seems to be OK, except the information from GetLocation that some USB controller handles are returning, as follows:

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x80
Function: 0x00

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x81
Function: 0x00

Class: Serial Bus Controller
Subclass: USB Controller
Bus: 0xFF
Device: 0x82
Function: 0x00

My questions are:

1 - I am not familiar with PCI, but, as far as I know, maximum device number is 32, since it comes from a 5 bits field, am I correct? If so, how can it be 0x80, 0x81 or 0x82, maybe a bug in EFI_PCI_IO_PROTOCOL code or am I missing something?
Yes, I would hazard that this is a bug in your platform's PCI host
bridge driver. (I assume they use the PCI bus driver from edk2 without
any modifications.)

Or maybe the MMCONFIG range is misconfigured somehow; not sure.

(I'm reminded of ARI too, which I don't have any practical experience
with, however. ARI seems to permit up to 256 functions, combining the 5
bits from the device number with the 3 bits from the function number.
But a *device* number as high as 0x80 -- and not a function number that
high -- looks a bit fishy still. ARI seems to eliminate the device
number completely.)


2 - Usually , the bus numbering use sequential numbers starting from 0 (afaik again), and since it's a simple small system with few PCI components (it does not have 255 buses), what does the number 0xFF for Bus indicates?
Assuming the bus number refers to a root bridge (and not a bridge behind
a root port, or the downstream port of a switch), the bus number is not
assigned by the PCI bus driver. It's just a platform trait. I don't
think it's necessarily a bug.

Hope this helps; I could only make some guesses.
Laszlo



PS: "pci" command in UEFI Shell do not show these USB controllers but "devtree" command shows these USB contollers with the same Device/Funcion numbers.

Thanks so much!





gustavo.marcello@...
 

Hi Laszlo Ersek,
Thanks for the style comments, I appreciate it, I will do these changes.

And, for the questions, I agree, for the first question, that seems to be a platform driver bug and, for the second one, it seems something related to the platform as you said. I will try to contact the manufacturer to clarify if it's correct.

Thanks so much for your reply, it was very helpful!