コード例 #1
0
/**
  Connect a Device Path and return the handle of the driver that support this DevicePath

  @param  DevicePath            Device Path of the File to connect
  @param  Handle                Handle of the driver that support this DevicePath
  @param  RemainingDevicePath   Remaining DevicePath nodes that do not match the driver DevicePath

  @retval EFI_SUCCESS           A driver that matches the Device Path has been found
  @retval EFI_NOT_FOUND         No handles match the search.
  @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL

**/
EFI_STATUS
BdsConnectDevicePath (
    IN  EFI_DEVICE_PATH_PROTOCOL* DevicePath,
    OUT EFI_HANDLE                *Handle,
    OUT EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath
)
{
    EFI_DEVICE_PATH*            Remaining;
    EFI_DEVICE_PATH*            NewDevicePath;
    EFI_STATUS                  Status;

    if ((DevicePath == NULL) || (Handle == NULL)) {
        return EFI_INVALID_PARAMETER;
    }

    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);
        }*/
    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining));

    if (!EFI_ERROR (Status)) {
        // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
        // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
        Remaining = DevicePath;
        Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid,&Remaining,Handle);
        if (!EFI_ERROR (Status)) {
            Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);
            if (EFI_ERROR (Status)) {
                // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
                if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
                    Status = EFI_SUCCESS;
                }
            }
        }
    } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) {

        /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly
        if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {
          Status = EFI_SUCCESS;
        } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
          Status = EFI_SUCCESS;
        }*/

        //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath
        Status = EFI_SUCCESS;
    } else {
        Status = TryRemovableDevice (DevicePath, Handle, &NewDevicePath);
        if (!EFI_ERROR (Status)) {
            return BdsConnectDevicePath (NewDevicePath, Handle, RemainingDevicePath);
        }
    }

    if (RemainingDevicePath) {
        *RemainingDevicePath = Remaining;
    }

    return Status;
}
コード例 #2
0
ファイル: BdsFilePath.c プロジェクト: FishYu1222/edk2
STATIC
EFI_STATUS
BdsConnectAndUpdateDevicePath (
  IN OUT EFI_DEVICE_PATH_PROTOCOL  **DevicePath,
  OUT    EFI_HANDLE                *Handle,
  OUT    EFI_DEVICE_PATH_PROTOCOL  **RemainingDevicePath
  )
{
  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)) {
      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)) {
    // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
    // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
    Remaining = *DevicePath;
    Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle);
    if (!EFI_ERROR (Status)) {
      Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE);
      if (EFI_ERROR (Status)) {
        // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
        if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
            Status = EFI_SUCCESS;
        }
      }
    }
  } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) {

    /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly
    if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) {
      Status = EFI_SUCCESS;
    } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) {
      Status = EFI_SUCCESS;
    }*/

    //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath
    Status = EFI_SUCCESS;
  } else {
    Status = TryRemovableDevice (*DevicePath, Handle, &NewDevicePath);
    if (!EFI_ERROR (Status)) {
      Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath);
      *DevicePath = NewDevicePath;
      return Status;
    }
  }

  if (RemainingDevicePath) {
    *RemainingDevicePath = Remaining;
  }

  return Status;
}