summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Martin <olivier.martin@arm.com>2014-08-19 13:35:14 +0000
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>2014-08-19 13:35:14 +0000
commit04ad241e2081312be62a9f299311949e85ed725c (patch)
treebe2ad95339379a54c7a35813504c7e39ef01e078
parent5e6322a53066b59c3d351d6ce3e07e07cd08e8dd (diff)
downloadedk2-platforms-04ad241e2081312be62a9f299311949e85ed725c.tar.xz
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 <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15835 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--ArmPkg/Library/BdsLib/BdsFilePath.c29
-rw-r--r--ArmPkg/Library/BdsLib/BdsHelper.c1
-rw-r--r--ArmPkg/Library/BdsLib/BdsInternal.h1
3 files changed, 22 insertions, 9 deletions
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 <Library/DxeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/TimerLib.h>
#include <Library/PrintLib.h>
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 <Library/ArmLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>