\r
#include <DxeMain.h>\r
\r
+BOOLEAN mRepairLoadedImage = FALSE;\r
\r
-\r
-STATIC\r
+//\r
+// Driver Support Function Prototypes\r
+//\r
EFI_STATUS\r
GetHandleFromDriverBinding (\r
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,\r
OUT EFI_HANDLE *Handle \r
);\r
\r
-\r
-//\r
-// Driver Support Function Prototypes\r
-//\r
-STATIC\r
EFI_STATUS \r
CoreConnectSingleController (\r
IN EFI_HANDLE ControllerHandle,\r
//\r
// Driver Support Functions\r
//\r
-\r
-\r
EFI_STATUS \r
EFIAPI\r
CoreConnectController (\r
LIST_ENTRY *ProtLink;\r
OPEN_PROTOCOL_DATA *OpenData;\r
EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+ UINTN ChildHandleCount;\r
+ UINTN Index;\r
+ EFI_HANDLE *LoadedImageHandleBuffer;\r
+ UINTN LoadedImageHandleCount;\r
+ LOADED_IMAGE_PRIVATE_DATA *Image;\r
+ EFI_HANDLE DeviceHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
\r
//\r
// Make sure ControllerHandle is valid\r
Handle = ControllerHandle;\r
\r
//\r
- // Connect all drivers to ControllerHandle \r
+ // Make a copy of RemainingDevicePath to guanatee it is aligned\r
//\r
AlignedRemainingDevicePath = NULL;\r
if (RemainingDevicePath != NULL) {\r
AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);\r
}\r
- ReturnStatus = CoreConnectSingleController (\r
- ControllerHandle,\r
- DriverImageHandle,\r
- AlignedRemainingDevicePath\r
- );\r
- if (AlignedRemainingDevicePath != NULL) {\r
- CoreFreePool (AlignedRemainingDevicePath);\r
- }\r
\r
//\r
- // If not recursive, then just return after connecting drivers to ControllerHandle\r
+ // Connect all drivers to ControllerHandle\r
+ // If CoreConnectSingleController returns EFI_NOT_READY, then the number of\r
+ // Driver Binding Protocols in the handle database has increased during the call\r
+ // so the connect operation must be restarted\r
//\r
- if (!Recursive) {\r
- return ReturnStatus;\r
+ do {\r
+ ReturnStatus = CoreConnectSingleController (\r
+ ControllerHandle,\r
+ DriverImageHandle,\r
+ AlignedRemainingDevicePath\r
+ );\r
+ } while (ReturnStatus == EFI_NOT_READY);\r
+\r
+ //\r
+ // Free the aligned copy of RemainingDevicePath\r
+ //\r
+ if (AlignedRemainingDevicePath != NULL) {\r
+ CoreFreePool (AlignedRemainingDevicePath);\r
}\r
\r
//\r
// If recursive, then connect all drivers to all of ControllerHandle's children\r
//\r
- CoreAcquireProtocolLock ();\r
- for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
- Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
- for (ProtLink = Prot->OpenList.ForwardLink; \r
- ProtLink != &Prot->OpenList; \r
- ProtLink = ProtLink->ForwardLink) {\r
+ if (Recursive) {\r
+ //\r
+ // Acquire the protocol lock on the handle database so the child handles can be collected\r
+ //\r
+ CoreAcquireProtocolLock ();\r
+\r
+ //\r
+ // Make sure the DriverBindingHandle is valid\r
+ //\r
+ Status = CoreValidateHandle (ControllerHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Release the protocol lock on the handle database\r
+ //\r
+ CoreReleaseProtocolLock ();\r
+\r
+ return ReturnStatus;\r
+ }\r
+\r
+\r
+ //\r
+ // Count ControllerHandle's children\r
+ //\r
+ for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
+ for (ProtLink = Prot->OpenList.ForwardLink; \r
+ ProtLink != &Prot->OpenList; \r
+ ProtLink = ProtLink->ForwardLink) {\r
OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
- CoreReleaseProtocolLock ();\r
- Status = CoreConnectController (\r
- OpenData->ControllerHandle,\r
- NULL,\r
- NULL,\r
- TRUE\r
- ); \r
- CoreAcquireProtocolLock ();\r
+ ChildHandleCount++;\r
}\r
+ }\r
}\r
+\r
+ //\r
+ // Allocate a handle buffer for ControllerHandle's children\r
+ //\r
+ ChildHandleBuffer = CoreAllocateBootServicesPool (ChildHandleCount * sizeof(EFI_HANDLE));\r
+\r
+ //\r
+ // Fill in a handle buffer with ControllerHandle's children\r
+ //\r
+ for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
+ Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
+ for (ProtLink = Prot->OpenList.ForwardLink; \r
+ ProtLink != &Prot->OpenList; \r
+ ProtLink = ProtLink->ForwardLink) {\r
+ OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
+ ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;\r
+ ChildHandleCount++;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Release the protocol lock on the handle database\r
+ //\r
+ CoreReleaseProtocolLock ();\r
+\r
+ //\r
+ // Recursively connect each child handle\r
+ //\r
+ for (Index = 0; Index < ChildHandleCount; Index++) {\r
+ CoreConnectController (\r
+ ChildHandleBuffer[Index],\r
+ NULL,\r
+ NULL,\r
+ TRUE\r
+ ); \r
+ }\r
+\r
+ //\r
+ // Free the handle buffer of ControllerHandle's children\r
+ //\r
+ CoreFreePool (ChildHandleBuffer);\r
}\r
- CoreReleaseProtocolLock ();\r
- \r
+\r
+ //\r
+ // If a Stop() function has been called one or more time successfully, then attempt to \r
+ // repair the stale DeviceHandle fields of the Loaded Image Protocols\r
+ //\r
+ if (mRepairLoadedImage) {\r
+ //\r
+ // Assume that all Loaded Image Protocols can be repaired\r
+ //\r
+ mRepairLoadedImage = FALSE;\r
+\r
+ //\r
+ // Get list of all Loaded Image Protocol Instances\r
+ //\r
+ Status = CoreLocateHandleBuffer (\r
+ ByProtocol, \r
+ &gEfiLoadedImageProtocolGuid, \r
+ NULL,\r
+ &LoadedImageHandleCount, \r
+ &LoadedImageHandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {\r
+ for (Index = 0; Index < LoadedImageHandleCount; Index++) {\r
+ //\r
+ // Retrieve the Loaded Image Protocol\r
+ //\r
+ Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);\r
+ if (Image != NULL) {\r
+ //\r
+ // Check to see if the DeviceHandle field is a valid handle\r
+ //\r
+ Status = CoreValidateHandle (Image->Info.DeviceHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The DeviceHandle field is not valid.\r
+ // Attempt to locate a device handle with a device path that matches the one\r
+ // that was used to originally load the image\r
+ //\r
+ DevicePath = Image->DeviceHandleDevicePath;\r
+ if (DevicePath != NULL) {\r
+ Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {\r
+ //\r
+ // A device handle with a matching device path was found, so update the Loaded Image Protocol\r
+ // with the device handle discovered\r
+ //\r
+ Image->Info.DeviceHandle = DeviceHandle;\r
+ } else {\r
+ //\r
+ // There is still at least one Loaded Image Protocol that requires repair\r
+ //\r
+ mRepairLoadedImage = TRUE;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ CoreFreePool (LoadedImageHandleBuffer);\r
+ }\r
+ }\r
+\r
return ReturnStatus;\r
}\r
\r
-STATIC\r
VOID\r
AddSortedDriverBindingProtocol (\r
IN EFI_HANDLE DriverBindingHandle,\r
//\r
// See if DriverBinding is already in the sorted list\r
//\r
- for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {\r
+ for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {\r
if (DriverBinding == SortedDriverBindingProtocols[Index]) {\r
return;\r
}\r
//\r
// Add DriverBinding to the end of the list\r
//\r
- SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;\r
+ if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {\r
+ SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;\r
+ }\r
*NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;\r
\r
//\r
}\r
}\r
\r
-STATIC\r
EFI_STATUS \r
CoreConnectSingleController (\r
IN EFI_HANDLE ControllerHandle,\r
//\r
CoreFreePool (DriverBindingHandleBuffer);\r
\r
+ //\r
+ // If the number of Driver Binding Protocols has increased since this function started, then return\r
+ // EFI_NOT_READY, so it will be restarted\r
+ //\r
+ if (NumberOfSortedDriverBindingProtocols > DriverBindingHandleCount) {\r
+ //\r
+ // Free any buffers that were allocated with AllocatePool()\r
+ //\r
+ CoreFreePool (SortedDriverBindingProtocols);\r
+\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
//\r
// Sort the remaining DriverBinding Protocol based on their Version field from\r
// highest to lowest.\r
OPEN_PROTOCOL_DATA *OpenData;\r
PROTOCOL_INTERFACE *Prot;\r
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
+ EFI_HANDLE *LoadedImageHandleBuffer;\r
+ UINTN LoadedImageHandleCount;\r
+ LOADED_IMAGE_PRIVATE_DATA *Image;\r
\r
//\r
// Make sure ControllerHandle is valid\r
}\r
\r
if (StopCount > 0) {\r
+ //\r
+ // If the Loaded Image Protocols do not already need to be repaired, then\r
+ // check the status of the DeviceHandle field of all Loaded Image Protocols\r
+ // to determine if any of them now need repair because a sucessful Stop()\r
+ // may have destroyed the DeviceHandle value in the Loaded Image Protocol\r
+ //\r
+ if (!mRepairLoadedImage) {\r
+ //\r
+ // Get list of all Loaded Image Protocol Instances\r
+ //\r
+ Status = CoreLocateHandleBuffer (\r
+ ByProtocol, \r
+ &gEfiLoadedImageProtocolGuid, \r
+ NULL,\r
+ &LoadedImageHandleCount, \r
+ &LoadedImageHandleBuffer\r
+ );\r
+ if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {\r
+ for (Index = 0; Index < LoadedImageHandleCount; Index++) {\r
+ //\r
+ // Retrieve the Loaded Image Protocol\r
+ //\r
+ Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);\r
+ if (Image != NULL) {\r
+ //\r
+ // Check to see if the DeviceHandle field is a valid handle\r
+ //\r
+ Status = CoreValidateHandle (Image->Info.DeviceHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The DeviceHandle field is not longer a valid handle. This means\r
+ // that future calls to ConnectController() need to attemp to repair\r
+ // the Loaded Image Protocols with invalid DeviceHandle fields. Set \r
+ // the flag used by ConnectController().\r
+ //\r
+ mRepairLoadedImage = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ CoreFreePool (LoadedImageHandleBuffer);\r
+ }\r
+ }\r
Status = EFI_SUCCESS;\r
} else {\r
Status = EFI_NOT_FOUND;\r
return Status;\r
}\r
\r
-\r
-\r
-STATIC\r
EFI_STATUS\r
GetHandleFromDriverBinding (\r
IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed,\r