}\r
\r
\r
+/**\r
+ Uninitialize and free a root bridge set up with InitRootBridge().\r
+\r
+ On return, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance and the device path\r
+ will have been released, freeing RootBus->Handle as well.\r
+\r
+ param[in] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has been created\r
+ with InitRootBridge(), and should be released.\r
+**/\r
+STATIC\r
+VOID\r
+UninitRootBridge (\r
+ IN PCI_ROOT_BRIDGE_INSTANCE *RootBus\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (RootBus->Handle,\r
+ &gEfiDevicePathProtocolGuid, &RootBus->DevicePath,\r
+ &gEfiPciRootBridgeIoProtocolGuid, &RootBus->Io,\r
+ NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePool (RootBus);\r
+}\r
+\r
+\r
/**\r
Entry point of this driver\r
\r
UINTN RootBridgeNumber;\r
PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
PCI_ROOT_BRIDGE_INSTANCE *RootBus;\r
+ EFI_STATUS UninstallStatus;\r
\r
mDriverImageHandle = ImageHandle;\r
\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (HostBridge);\r
- return EFI_DEVICE_ERROR;\r
+ goto FreeHostBridge;\r
}\r
\r
for (RootBridgeNumber = 0;\r
&RootBus\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto RollbackProtocols;\r
}\r
InsertTailList (&HostBridge->Head, &RootBus->Link);\r
}\r
\r
return EFI_SUCCESS;\r
+\r
+RollbackProtocols:\r
+ while (!IsListEmpty (&HostBridge->Head)) {\r
+ LIST_ENTRY *Entry;\r
+\r
+ Entry = GetFirstNode (&HostBridge->Head);\r
+ RemoveEntryList (Entry);\r
+ RootBus = DRIVER_INSTANCE_FROM_LIST_ENTRY (Entry);\r
+ UninitRootBridge (RootBus);\r
+ }\r
+ UninstallStatus = gBS->UninstallMultipleProtocolInterfaces (\r
+ HostBridge->HostBridgeHandle,\r
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,\r
+ &HostBridge->ResAlloc,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (UninstallStatus);\r
+\r
+FreeHostBridge:\r
+ FreePool (HostBridge);\r
+\r
+ return Status;\r
}\r
\r
\r