// Implementation\r
//\r
\r
+/**\r
+ Allocate and initialize a root bridge.\r
+\r
+ param[in] RootBusNumber The bus number of the root bus (root bridge) to\r
+ create.\r
+ RootBusNumber is expected to fall into the valid\r
+ offset range of mResAperture.\r
+\r
+ param[in] HostBridgeHandle The EFI_HANDLE corresponding to the host bridge\r
+ that is the parent of the root bridge to create.\r
+ HostBridgeHandle is expected to have\r
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
+ installed on it.\r
+\r
+ param[out] RootBus The private PCI_ROOT_BRIDGE_INSTANCE that has\r
+ been created as the result of the function call.\r
+\r
+ @retval EFI_SUCCESS Initialization successful. A new\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL has been\r
+ created as the child of HostBridgeHandle. A\r
+ device path consisting of an ACPI device path\r
+ node, with UID = RootBusNumber, has been\r
+ installed on the same new handle.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+\r
+ @return Error codes from\r
+ gBS->InstallMultipleProtocolInterfaces().\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+InitRootBridge (\r
+ IN UINT8 RootBusNumber,\r
+ IN EFI_HANDLE HostBridgeHandle,\r
+ OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus\r
+ )\r
+{\r
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ EFI_STATUS Status;\r
+\r
+ PrivateData = AllocateZeroPool (sizeof *PrivateData);\r
+ if (PrivateData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
+\r
+ CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,\r
+ sizeof mRootBridgeDevicePathTemplate);\r
+ PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;\r
+\r
+ //\r
+ // The function call below allocates no resources and performs no actions\r
+ // that have to be rolled back on later failure. It always succeeds.\r
+ //\r
+ Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,\r
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,\r
+ &mResAperture[RootBusNumber]);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,\r
+ &gEfiDevicePathProtocolGuid, &PrivateData->DevicePath,\r
+ &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,\r
+ NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreePrivateData;\r
+ }\r
+\r
+ *RootBus = PrivateData;\r
+ return EFI_SUCCESS;\r
+\r
+FreePrivateData:\r
+ FreePool (PrivateData);\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Entry point of this driver\r
\r
)\r
{\r
EFI_STATUS Status;\r
- UINTN Loop2;\r
+ UINTN RootBridgeNumber;\r
PCI_HOST_BRIDGE_INSTANCE *HostBridge;\r
- PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
+ PCI_ROOT_BRIDGE_INSTANCE *RootBus;\r
\r
mDriverImageHandle = ImageHandle;\r
\r
return EFI_DEVICE_ERROR;\r
}\r
\r
- //\r
- // Create Root Bridge Device Handle in this Host Bridge\r
- //\r
-\r
- for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {\r
- PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));\r
- if (PrivateData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;\r
-\r
- CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,\r
- sizeof mRootBridgeDevicePathTemplate);\r
- PrivateData->DevicePath.AcpiDevicePath.UID = Loop2;\r
-\r
- RootBridgeConstructor (\r
- &PrivateData->Io,\r
- HostBridge->HostBridgeHandle,\r
- EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM,\r
- &mResAperture[Loop2]\r
- );\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces(\r
- &PrivateData->Handle,\r
- &gEfiDevicePathProtocolGuid,\r
- &PrivateData->DevicePath,\r
- &gEfiPciRootBridgeIoProtocolGuid,\r
- &PrivateData->Io,\r
- NULL\r
- );\r
+ for (RootBridgeNumber = 0;\r
+ RootBridgeNumber < HostBridge->RootBridgeNumber;\r
+ ++RootBridgeNumber) {\r
+ Status = InitRootBridge (\r
+ (UINT8)RootBridgeNumber,\r
+ HostBridge->HostBridgeHandle,\r
+ &RootBus\r
+ );\r
if (EFI_ERROR (Status)) {\r
- FreePool(PrivateData);\r
- return EFI_DEVICE_ERROR;\r
+ return Status;\r
}\r
-\r
- InsertTailList (&HostBridge->Head, &PrivateData->Link);\r
+ InsertTailList (&HostBridge->Head, &RootBus->Link);\r
}\r
\r
return EFI_SUCCESS;\r