From 04ad241e2081312be62a9f299311949e85ed725c Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 19 Aug 2014 13:35:14 +0000 Subject: ArmPkg/BdsLib: Prevent a hang in BdsConnectDevicePath() when a sub-device path is not found Some device paths were making BdsConnectDevicePath() hang. To prevent these hangs we check if the handle returned by gBS->LocateDevicePath() is the same after each iteration. An example of a device path that hangs: PciRoot(0x0)/Pci(0x1,0x0)/USB(0x0,0x0)/USB(0x3,0x0)/HD(...) The connect controller function manages to find PciRoot()/Pci(0x1,0x0) but the USB driver does not produce USB(0x0,0x0)/USB(0x3,0x0) and returns EFI_SUCCESS on its initialization. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15835 6f19259b-4bc3-4df7-8a09-765794883524 --- ArmPkg/Library/BdsLib/BdsFilePath.c | 29 +++++++++++++++++++++-------- ArmPkg/Library/BdsLib/BdsHelper.c | 1 - ArmPkg/Library/BdsLib/BdsInternal.h | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'ArmPkg') diff --git a/ArmPkg/Library/BdsLib/BdsFilePath.c b/ArmPkg/Library/BdsLib/BdsFilePath.c index 710821cd05..f26ba39ddb 100644 --- a/ArmPkg/Library/BdsLib/BdsFilePath.c +++ b/ArmPkg/Library/BdsLib/BdsFilePath.c @@ -311,27 +311,40 @@ BdsConnectAndUpdateDevicePath ( EFI_DEVICE_PATH* Remaining; EFI_DEVICE_PATH* NewDevicePath; EFI_STATUS Status; + EFI_HANDLE PreviousHandle; if ((DevicePath == NULL) || (*DevicePath == NULL) || (Handle == NULL)) { return EFI_INVALID_PARAMETER; } + PreviousHandle = NULL; do { Remaining = *DevicePath; + // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified // to point to the remaining part of the device path Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle); + if (!EFI_ERROR (Status)) { - // Recursive = FALSE: We do not want to start all the device tree - Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE); - } + if (*Handle == PreviousHandle) { + // + // If no forward progress is made try invoking the Dispatcher. + // A new FV may have been added to the system and new drivers + // may now be found. + // Status == EFI_SUCCESS means a driver was dispatched + // Status == EFI_NOT_FOUND means no new drivers were dispatched + // + Status = gDS->Dispatch (); + } - /*// We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling - // NextDevicePathNode () will return an undetermined Device Path Node - if (!IsDevicePathEnd (RemainingDevicePath)) { - RemainingDevicePath = NextDevicePathNode (RemainingDevicePath); - }*/ + if (!EFI_ERROR (Status)) { + PreviousHandle = *Handle; + + // Recursive = FALSE: We do not want to start the whole device tree + Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE); + } + } } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining)); if (!EFI_ERROR (Status)) { diff --git a/ArmPkg/Library/BdsLib/BdsHelper.c b/ArmPkg/Library/BdsLib/BdsHelper.c index 1d4aa35728..7f83c2be8a 100644 --- a/ArmPkg/Library/BdsLib/BdsHelper.c +++ b/ArmPkg/Library/BdsLib/BdsHelper.c @@ -14,7 +14,6 @@ #include "BdsInternal.h" -#include #include #include #include diff --git a/ArmPkg/Library/BdsLib/BdsInternal.h b/ArmPkg/Library/BdsLib/BdsInternal.h index 88117016ce..9b5d3a4ff6 100644 --- a/ArmPkg/Library/BdsLib/BdsInternal.h +++ b/ArmPkg/Library/BdsLib/BdsInternal.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3