/** @file\r
Rewrite the BootOrder NvVar based on QEMU's "bootorder" fw_cfg file.\r
\r
- Copyright (C) 2012, Red Hat, Inc.\r
+ Copyright (C) 2012 - 2013, Red Hat, Inc.\r
\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
#include <Library/UefiRuntimeServicesTableLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/PrintLib.h>\r
-#include <Protocol/DevicePathToText.h>\r
+#include <Library/DevicePathLib.h>\r
#include <Guid/GlobalVariable.h>\r
\r
\r
\r
\r
/**\r
- Number of nodes in OpenFirmware device paths that is required and examined.\r
+ Numbers of nodes in OpenFirmware device paths that are required and examined.\r
**/\r
-#define FIXED_OFW_NODES 4\r
+#define REQUIRED_OFW_NODES 2\r
+#define EXAMINED_OFW_NODES 4\r
\r
\r
/**\r
++Chr;\r
}\r
\r
- return (Pos == Substring.Len && *Chr == '\0');\r
+ return (BOOLEAN)(Pos == Substring.Len && *Chr == '\0');\r
}\r
\r
\r
//\r
// Get PCI device and optional PCI function. Assume a single PCI root.\r
//\r
- if (NumNodes < FIXED_OFW_NODES ||\r
+ if (NumNodes < REQUIRED_OFW_NODES ||\r
!SubstringEq (OfwNode[0].DriverName, "pci")\r
) {\r
return RETURN_UNSUPPORTED;\r
return RETURN_UNSUPPORTED;\r
}\r
\r
- if (SubstringEq (OfwNode[1].DriverName, "ide") &&\r
+ if (NumNodes >= 4 &&\r
+ SubstringEq (OfwNode[1].DriverName, "ide") &&\r
SubstringEq (OfwNode[2].DriverName, "drive") &&\r
SubstringEq (OfwNode[3].DriverName, "disk")\r
) {\r
Secondary ? "Secondary" : "Primary",\r
Slave ? "Slave" : "Master"\r
);\r
- } else if (SubstringEq (OfwNode[1].DriverName, "isa") &&\r
+ } else if (NumNodes >= 4 &&\r
+ SubstringEq (OfwNode[1].DriverName, "isa") &&\r
SubstringEq (OfwNode[2].DriverName, "fdc") &&\r
SubstringEq (OfwNode[3].DriverName, "floppy")\r
) {\r
PciDevFun[1],\r
AcpiUid\r
);\r
- } else {\r
- return RETURN_UNSUPPORTED;\r
- }\r
+ } else if (NumNodes >= 3 &&\r
+ SubstringEq (OfwNode[1].DriverName, "scsi") &&\r
+ SubstringEq (OfwNode[2].DriverName, "disk")\r
+ ) {\r
+ //\r
+ // OpenFirmware device path (virtio-blk disk):\r
+ //\r
+ // /pci@i0cf8/scsi@6[,3]/disk@0,0\r
+ // ^ ^ ^ ^ ^\r
+ // | | | fixed\r
+ // | | PCI function corresponding to disk (optional)\r
+ // | PCI slot holding disk\r
+ // PCI root at system bus port, PIO\r
+ //\r
+ // UEFI device path prefix:\r
+ //\r
+ // PciRoot(0x0)/Pci(0x6,0x0)/HD( -- if PCI function is 0 or absent\r
+ // PciRoot(0x0)/Pci(0x6,0x3)/HD( -- if PCI function is present and nonzero\r
+ //\r
+ Written = UnicodeSPrintAsciiFormat (\r
+ Translated,\r
+ *TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
+ "PciRoot(0x0)/Pci(0x%x,0x%x)/HD(",\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
+ ) {\r
+ //\r
+ // OpenFirmware device path (virtio-scsi disk):\r
+ //\r
+ // /pci@i0cf8/scsi@7[,3]/channel@0/disk@2,3\r
+ // ^ ^ ^ ^ ^\r
+ // | | | | LUN\r
+ // | | | target\r
+ // | | channel (unused, fixed 0)\r
+ // | PCI slot[, function] holding SCSI controller\r
+ // PCI root at system bus port, PIO\r
+ //\r
+ // UEFI device path prefix:\r
+ //\r
+ // PciRoot(0x0)/Pci(0x7,0x0)/Scsi(0x2,0x3)\r
+ // -- if PCI function is 0 or absent\r
+ // PciRoot(0x0)/Pci(0x7,0x3)/Scsi(0x2,0x3)\r
+ // -- if PCI function is present and nonzero\r
+ //\r
+ UINT32 TargetLun[2];\r
+\r
+ TargetLun[1] = 0;\r
+ NumEntries = sizeof (TargetLun) / sizeof (TargetLun[0]);\r
+ if (ParseUnitAddressHexList (\r
+ OfwNode[3].UnitAddress,\r
+ TargetLun,\r
+ &NumEntries\r
+ ) != RETURN_SUCCESS\r
+ ) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ Written = UnicodeSPrintAsciiFormat (\r
+ Translated,\r
+ *TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
+ "PciRoot(0x0)/Pci(0x%x,0x%x)/Scsi(0x%x,0x%x)",\r
+ PciDevFun[0],\r
+ PciDevFun[1],\r
+ TargetLun[0],\r
+ TargetLun[1]\r
+ );\r
+ } else if (NumNodes >= 3 &&\r
+ SubstringEq (OfwNode[1].DriverName, "ethernet") &&\r
+ SubstringEq (OfwNode[2].DriverName, "ethernet-phy")\r
+ ) {\r
+ //\r
+ // OpenFirmware device path (Ethernet NIC):\r
+ //\r
+ // /pci@i0cf8/ethernet@3[,2]/ethernet-phy@0\r
+ // ^ ^ ^\r
+ // | | fixed\r
+ // | PCI slot[, function] holding Ethernet card\r
+ // PCI root at system bus port, PIO\r
+ //\r
+ // UEFI device path prefix (dependent on presence of nonzero PCI function):\r
+ //\r
+ // PciRoot(0x0)/Pci(0x3,0x0)/MAC(525400E15EEF,0x1)\r
+ // PciRoot(0x0)/Pci(0x3,0x2)/MAC(525400E15EEF,0x1)\r
+ // ^ ^\r
+ // MAC address IfType (1 == Ethernet)\r
+ //\r
+ // (Some UEFI NIC drivers don't set 0x1 for IfType.)\r
+ //\r
+ Written = UnicodeSPrintAsciiFormat (\r
+ Translated,\r
+ *TranslatedSize * sizeof (*Translated), // BufferSize in bytes\r
+ "PciRoot(0x0)/Pci(0x%x,0x%x)/MAC",\r
+ PciDevFun[0],\r
+ PciDevFun[1]\r
+ );\r
+ } else {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
\r
//\r
// There's no way to differentiate between "completely used up without\r
{\r
UINTN NumNodes;\r
RETURN_STATUS Status;\r
- OFW_NODE Node[FIXED_OFW_NODES];\r
+ OFW_NODE Node[EXAMINED_OFW_NODES];\r
BOOLEAN IsFinal;\r
OFW_NODE Skip;\r
\r
++NumNodes;\r
Status = ParseOfwNode (\r
Ptr,\r
- (NumNodes < FIXED_OFW_NODES) ? &Node[NumNodes] : &Skip,\r
+ (NumNodes < EXAMINED_OFW_NODES) ? &Node[NumNodes] : &Skip,\r
&IsFinal\r
);\r
}\r
\r
Status = TranslateOfwNodes (\r
Node,\r
- NumNodes < FIXED_OFW_NODES ? NumNodes : FIXED_OFW_NODES,\r
+ NumNodes < EXAMINED_OFW_NODES ? NumNodes : EXAMINED_OFW_NODES,\r
Translated,\r
TranslatedSize);\r
switch (Status) {\r
Match (\r
IN CONST CHAR16 *Translated,\r
IN UINTN TranslatedLength,\r
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN CONST EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
)\r
{\r
CHAR16 *Converted;\r
BOOLEAN Result;\r
\r
- Converted = DevPathToText->ConvertDevicePathToText (\r
- DevicePath,\r
- FALSE, // DisplayOnly\r
- FALSE // AllowShortcuts\r
- );\r
+ Converted = ConvertDevicePathToText (\r
+ DevicePath,\r
+ FALSE, // DisplayOnly\r
+ FALSE // AllowShortcuts\r
+ );\r
if (Converted == NULL) {\r
return FALSE;\r
}\r
//\r
// Is Translated a prefix of Converted?\r
//\r
- Result = (StrnCmp (Converted, Translated, TranslatedLength) == 0);\r
+ Result = (BOOLEAN)(StrnCmp (Converted, Translated, TranslatedLength) == 0);\r
DEBUG ((\r
DEBUG_VERBOSE,\r
"%a: against \"%s\": %a\n",\r
)\r
{\r
RETURN_STATUS Status;\r
-\r
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
-\r
FIRMWARE_CONFIG_ITEM FwCfgItem;\r
UINTN FwCfgSize;\r
CHAR8 *FwCfg;\r
UINTN TranslatedSize;\r
CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];\r
\r
- Status = gBS->LocateProtocol (\r
- &gEfiDevicePathToTextProtocolGuid,\r
- NULL, // optional registration key\r
- (VOID **) &DevPathToText\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- return Status;\r
- }\r
-\r
Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize);\r
if (Status != RETURN_SUCCESS) {\r
return Status;\r
Match (\r
Translated,\r
TranslatedSize, // contains length, not size, in CHAR16's here\r
- BootOption->DevicePath,\r
- DevPathToText\r
+ BootOption->DevicePath\r
)\r
) {\r
//\r