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
This commit is contained in:
Olivier Martin 2014-08-19 13:35:14 +00:00 committed by oliviermartin
parent 5e6322a530
commit 04ad241e20
3 changed files with 23 additions and 10 deletions

View File

@ -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);
}
/*// 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)) {
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 ();
}
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)) {

View File

@ -14,7 +14,6 @@
#include "BdsInternal.h"
#include <Library/DxeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/TimerLib.h>
#include <Library/PrintLib.h>

View File

@ -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>