+/**\r
+ Connect devices based on the boot order retrieved from QEMU.\r
+\r
+ Attempt to retrieve the "bootorder" fw_cfg file from QEMU. Translate the\r
+ OpenFirmware device paths therein to UEFI device path fragments. Connect the\r
+ devices identified by the UEFI devpath prefixes as narrowly as possible, then\r
+ connect all their child devices, recursively.\r
+\r
+ If this function fails, then platform BDS should fall back to\r
+ EfiBootManagerConnectAll(), or some other method for connecting any expected\r
+ boot devices.\r
+\r
+ @retval RETURN_SUCCESS The "bootorder" fw_cfg file has been\r
+ parsed, and the referenced device-subtrees\r
+ have been connected.\r
+\r
+ @retval RETURN_UNSUPPORTED QEMU's fw_cfg is not supported.\r
+\r
+ @retval RETURN_NOT_FOUND Empty or nonexistent "bootorder" fw_cfg\r
+ file.\r
+\r
+ @retval RETURN_INVALID_PARAMETER Parse error in the "bootorder" fw_cfg file.\r
+\r
+ @retval RETURN_OUT_OF_RESOURCES Memory allocation failed.\r
+\r
+ @return Error statuses propagated from underlying\r
+ functions.\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+ConnectDevicesFromQemu (\r
+ VOID\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM FwCfgItem;\r
+ UINTN FwCfgSize;\r
+ CHAR8 *FwCfg;\r
+ EFI_STATUS EfiStatus;\r
+ EXTRA_ROOT_BUS_MAP *ExtraPciRoots;\r
+ CONST CHAR8 *FwCfgPtr;\r
+ UINTN NumConnected;\r
+ UINTN TranslatedSize;\r
+ CHAR16 Translated[TRANSLATION_OUTPUT_SIZE];\r
+\r
+ Status = QemuFwCfgFindFile ("bootorder", &FwCfgItem, &FwCfgSize);\r
+ if (RETURN_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (FwCfgSize == 0) {\r
+ return RETURN_NOT_FOUND;\r
+ }\r
+\r
+ FwCfg = AllocatePool (FwCfgSize);\r
+ if (FwCfg == NULL) {\r
+ return RETURN_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ QemuFwCfgSelectItem (FwCfgItem);\r
+ QemuFwCfgReadBytes (FwCfgSize, FwCfg);\r
+ if (FwCfg[FwCfgSize - 1] != '\0') {\r
+ Status = RETURN_INVALID_PARAMETER;\r
+ goto FreeFwCfg;\r
+ }\r
+ DEBUG ((DEBUG_VERBOSE, "%a: FwCfg:\n", __FUNCTION__));\r
+ DEBUG ((DEBUG_VERBOSE, "%a\n", FwCfg));\r
+ DEBUG ((DEBUG_VERBOSE, "%a: FwCfg: <end>\n", __FUNCTION__));\r
+\r
+ if (FeaturePcdGet (PcdQemuBootOrderPciTranslation)) {\r
+ EfiStatus = CreateExtraRootBusMap (&ExtraPciRoots);\r
+ if (EFI_ERROR (EfiStatus)) {\r
+ Status = (RETURN_STATUS)EfiStatus;\r
+ goto FreeFwCfg;\r
+ }\r
+ } else {\r
+ ExtraPciRoots = NULL;\r
+ }\r
+\r
+ //\r
+ // Translate each OpenFirmware path to a UEFI devpath prefix.\r
+ //\r
+ FwCfgPtr = FwCfg;\r
+ NumConnected = 0;\r
+ TranslatedSize = ARRAY_SIZE (Translated);\r
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,\r
+ &TranslatedSize);\r
+ while (!RETURN_ERROR (Status)) {\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ EFI_HANDLE Controller;\r
+\r
+ //\r
+ // Convert the UEFI devpath prefix to binary representation.\r
+ //\r
+ ASSERT (Translated[TranslatedSize] == L'\0');\r
+ DevicePath = ConvertTextToDevicePath (Translated);\r
+ if (DevicePath == NULL) {\r
+ Status = RETURN_OUT_OF_RESOURCES;\r
+ goto FreeExtraPciRoots;\r
+ }\r
+ //\r
+ // Advance along DevicePath, connecting the nodes individually, and asking\r
+ // drivers not to produce sibling nodes. Retrieve the controller handle\r
+ // associated with the full DevicePath -- this is the device that QEMU's\r
+ // OFW devpath refers to.\r
+ //\r
+ EfiStatus = EfiBootManagerConnectDevicePath (DevicePath, &Controller);\r
+ FreePool (DevicePath);\r
+ if (EFI_ERROR (EfiStatus)) {\r
+ Status = (RETURN_STATUS)EfiStatus;\r
+ goto FreeExtraPciRoots;\r
+ }\r
+ //\r
+ // Because QEMU's OFW devpaths have lesser expressive power than UEFI\r
+ // devpaths (i.e., DevicePath is considered a prefix), connect the tree\r
+ // rooted at Controller, recursively. If no children are produced\r
+ // (EFI_NOT_FOUND), that's OK.\r
+ //\r
+ EfiStatus = gBS->ConnectController (Controller, NULL, NULL, TRUE);\r
+ if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) {\r
+ Status = (RETURN_STATUS)EfiStatus;\r
+ goto FreeExtraPciRoots;\r
+ }\r
+ ++NumConnected;\r
+ //\r
+ // Move to the next OFW devpath.\r
+ //\r
+ TranslatedSize = ARRAY_SIZE (Translated);\r
+ Status = TranslateOfwPath (&FwCfgPtr, ExtraPciRoots, Translated,\r
+ &TranslatedSize);\r
+ }\r
+\r
+ if (Status == RETURN_NOT_FOUND && NumConnected > 0) {\r
+ DEBUG ((DEBUG_INFO, "%a: %Lu OpenFirmware device path(s) connected\n",\r
+ __FUNCTION__, (UINT64)NumConnected));\r
+ Status = RETURN_SUCCESS;\r
+ }\r
+\r
+FreeExtraPciRoots:\r
+ if (ExtraPciRoots != NULL) {\r
+ DestroyExtraRootBusMap (ExtraPciRoots);\r
+ }\r
+\r
+FreeFwCfg:\r
+ FreePool (FwCfg);\r
+\r
+ return Status;\r
+}\r
+\r
+\r