**/\r
#define TRANSLATION_OUTPUT_SIZE 0x100\r
\r
+/**\r
+ Output buffer size for OpenFirmware to UEFI device path fragment translation,\r
+ in CHAR16's, for a sequence of PCI bridges.\r
+**/\r
+#define BRIDGE_TRANSLATION_OUTPUT_SIZE 0x40\r
\r
/**\r
Numbers of nodes in OpenFirmware device paths that are required and examined.\r
**/\r
#define REQUIRED_PCI_OFW_NODES 2\r
#define REQUIRED_MMIO_OFW_NODES 1\r
-#define EXAMINED_OFW_NODES 4\r
+#define EXAMINED_OFW_NODES 6\r
\r
\r
/**\r
IN OUT UINTN *TranslatedSize\r
)\r
{\r
+ UINTN FirstNonBridge;\r
+ CHAR16 Bridges[BRIDGE_TRANSLATION_OUTPUT_SIZE];\r
+ UINTN BridgesLen;\r
UINT64 PciDevFun[2];\r
UINTN NumEntries;\r
UINTN Written;\r
) {\r
return RETURN_UNSUPPORTED;\r
}\r
+\r
+ //\r
+ // Translate a sequence of PCI bridges. For each bridge, the OFW node is:\r
+ //\r
+ // pci-bridge@1e[,0]\r
+ // ^ ^\r
+ // PCI slot & function on the parent, holding the bridge\r
+ //\r
+ // and the UEFI device path node is:\r
+ //\r
+ // Pci(0x1E,0x0)\r
+ //\r
+ FirstNonBridge = 1;\r
+ Bridges[0] = L'\0';\r
+ BridgesLen = 0;\r
+ do {\r
+ UINT64 BridgeDevFun[2];\r
+ UINTN BridgesFreeBytes;\r
+\r
+ if (!SubstringEq (OfwNode[FirstNonBridge].DriverName, "pci-bridge")) {\r
+ break;\r
+ }\r
+\r
+ BridgeDevFun[1] = 0;\r
+ NumEntries = sizeof BridgeDevFun / sizeof BridgeDevFun[0];\r
+ if (ParseUnitAddressHexList (OfwNode[FirstNonBridge].UnitAddress,\r
+ BridgeDevFun, &NumEntries) != RETURN_SUCCESS) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ BridgesFreeBytes = sizeof Bridges - BridgesLen * sizeof Bridges[0];\r
+ Written = UnicodeSPrintAsciiFormat (Bridges + BridgesLen, BridgesFreeBytes,\r
+ "/Pci(0x%Lx,0x%Lx)", BridgeDevFun[0], BridgeDevFun[1]);\r
+ BridgesLen += Written;\r
+\r
+ //\r
+ // There's no way to differentiate between "completely used up without\r
+ // truncation" and "truncated", so treat the former as the latter.\r
+ //\r
+ if (BridgesLen + 1 == BRIDGE_TRANSLATION_OUTPUT_SIZE) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ ++FirstNonBridge;\r
+ } while (FirstNonBridge < NumNodes);\r
+\r
+ if (FirstNonBridge == NumNodes) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Parse the OFW nodes starting with the first non-bridge node.\r
+ //\r
PciDevFun[1] = 0;\r
NumEntries = sizeof (PciDevFun) / sizeof (PciDevFun[0]);\r
if (ParseUnitAddressHexList (\r
- OfwNode[1].UnitAddress,\r
+ OfwNode[FirstNonBridge].UnitAddress,\r
PciDevFun,\r
&NumEntries\r
) != RETURN_SUCCESS\r
return RETURN_UNSUPPORTED;\r
}\r
\r
- if (NumNodes >= 4 &&\r
- SubstringEq (OfwNode[1].DriverName, "ide") &&\r
- SubstringEq (OfwNode[2].DriverName, "drive") &&\r
- SubstringEq (OfwNode[3].DriverName, "disk")\r
+ if (NumNodes >= FirstNonBridge + 3 &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 0].DriverName, "ide") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 1].DriverName, "drive") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 2].DriverName, "disk")\r
) {\r
//\r
// OpenFirmware device path (IDE disk, IDE CD-ROM):\r
\r
NumEntries = 1;\r
if (ParseUnitAddressHexList (\r
- OfwNode[2].UnitAddress,\r
+ OfwNode[FirstNonBridge + 1].UnitAddress,\r
&Secondary,\r
&NumEntries\r
) != RETURN_SUCCESS ||\r
Secondary > 1 ||\r
ParseUnitAddressHexList (\r
- OfwNode[3].UnitAddress,\r
+ OfwNode[FirstNonBridge + 2].UnitAddress,\r
&Slave,\r
&NumEntries // reuse after previous single-element call\r
) != RETURN_SUCCESS ||\r
Written = UnicodeSPrintAsciiFormat (\r
Translated,\r
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
- "PciRoot(0x0)/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",\r
+ "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Ata(%a,%a,0x0)",\r
+ Bridges,\r
PciDevFun[0],\r
PciDevFun[1],\r
Secondary ? "Secondary" : "Primary",\r
Slave ? "Slave" : "Master"\r
);\r
- } else if (NumNodes >= 4 &&\r
- SubstringEq (OfwNode[1].DriverName, "isa") &&\r
- SubstringEq (OfwNode[2].DriverName, "fdc") &&\r
- SubstringEq (OfwNode[3].DriverName, "floppy")\r
+ } else if (NumNodes >= FirstNonBridge + 3 &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 0].DriverName, "isa") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 1].DriverName, "fdc") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 2].DriverName, "floppy")\r
) {\r
//\r
// OpenFirmware device path (floppy disk):\r
\r
NumEntries = 1;\r
if (ParseUnitAddressHexList (\r
- OfwNode[3].UnitAddress,\r
+ OfwNode[FirstNonBridge + 2].UnitAddress,\r
&AcpiUid,\r
&NumEntries\r
) != RETURN_SUCCESS ||\r
Written = UnicodeSPrintAsciiFormat (\r
Translated,\r
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
- "PciRoot(0x0)/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",\r
+ "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Floppy(0x%Lx)",\r
+ Bridges,\r
PciDevFun[0],\r
PciDevFun[1],\r
AcpiUid\r
);\r
- } else if (NumNodes >= 3 &&\r
- SubstringEq (OfwNode[1].DriverName, "scsi") &&\r
- SubstringEq (OfwNode[2].DriverName, "disk")\r
+ } else if (NumNodes >= FirstNonBridge + 2 &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 0].DriverName, "scsi") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 1].DriverName, "disk")\r
) {\r
//\r
// OpenFirmware device path (virtio-blk disk):\r
Written = UnicodeSPrintAsciiFormat (\r
Translated,\r
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
- "PciRoot(0x0)/Pci(0x%Lx,0x%Lx)/HD(",\r
+ "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/HD(",\r
+ Bridges,\r
PciDevFun[0],\r
PciDevFun[1]\r
);\r
- } else if (NumNodes >= 4 &&\r
- SubstringEq (OfwNode[1].DriverName, "scsi") &&\r
- SubstringEq (OfwNode[2].DriverName, "channel") &&\r
- SubstringEq (OfwNode[3].DriverName, "disk")\r
+ } else if (NumNodes >= FirstNonBridge + 3 &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 0].DriverName, "scsi") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 1].DriverName, "channel") &&\r
+ SubstringEq (OfwNode[FirstNonBridge + 2].DriverName, "disk")\r
) {\r
//\r
// OpenFirmware device path (virtio-scsi disk):\r
TargetLun[1] = 0;\r
NumEntries = sizeof (TargetLun) / sizeof (TargetLun[0]);\r
if (ParseUnitAddressHexList (\r
- OfwNode[3].UnitAddress,\r
+ OfwNode[FirstNonBridge + 2].UnitAddress,\r
TargetLun,\r
&NumEntries\r
) != RETURN_SUCCESS\r
Written = UnicodeSPrintAsciiFormat (\r
Translated,\r
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
- "PciRoot(0x0)/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",\r
+ "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)/Scsi(0x%Lx,0x%Lx)",\r
+ Bridges,\r
PciDevFun[0],\r
PciDevFun[1],\r
TargetLun[0],\r
Written = UnicodeSPrintAsciiFormat (\r
Translated,\r
*TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
- "PciRoot(0x0)/Pci(0x%Lx,0x%Lx)",\r
+ "PciRoot(0x0)%s/Pci(0x%Lx,0x%Lx)",\r
+ Bridges,\r
PciDevFun[0],\r
PciDevFun[1]\r
);\r