예제 #1
0
파일: Handle.c 프로젝트: kraxel/edk2
/**
  Attempts to disconnect all drivers that are using the protocol interface being queried.
  If failed, reconnect all drivers disconnected.
  Note: This function doesn't do parameters checking, it's caller's responsibility
  to pass in valid parameters.

  @param  UserHandle             The handle on which the protocol is installed
  @param  Prot                   The protocol to disconnect drivers from

  @retval EFI_SUCCESS            Drivers using the protocol interface are all
                                 disconnected
  @retval EFI_ACCESS_DENIED      Failed to disconnect one or all of the drivers

**/
EFI_STATUS
CoreDisconnectControllersUsingProtocolInterface (
  IN EFI_HANDLE           UserHandle,
  IN PROTOCOL_INTERFACE   *Prot
  )
{
  EFI_STATUS            Status;
  BOOLEAN               ItemFound;
  LIST_ENTRY            *Link;
  OPEN_PROTOCOL_DATA    *OpenData;

  Status = EFI_SUCCESS;

  //
  // Attempt to disconnect all drivers from this protocol interface
  //
  do {
    ItemFound = FALSE;
    for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
      if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
        CoreReleaseProtocolLock ();
        Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
        CoreAcquireProtocolLock ();
        if (!EFI_ERROR (Status)) {
          ItemFound = TRUE;
        }
        break;
      }
    }
  } while (ItemFound);

  if (!EFI_ERROR (Status)) {
    //
    // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
    //
    for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
      if ((OpenData->Attributes &
          (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {
        Link = RemoveEntryList (&OpenData->Link);
        Prot->OpenListCount--;
        CoreFreePool (OpenData);
      } else {
        Link = Link->ForwardLink;
      }
    }
  }

  //
  // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
  //
  if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
    CoreReleaseProtocolLock ();
    CoreConnectController (UserHandle, NULL, NULL, TRUE);
    CoreAcquireProtocolLock ();
    Status = EFI_ACCESS_DENIED;
  }

  return Status;
}
예제 #2
0
파일: Notify.c 프로젝트: Kohrara/edk
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreReinstallProtocolInterface (
  IN EFI_HANDLE     UserHandle,
  IN EFI_GUID       *Protocol,
  IN VOID           *OldInterface,
  IN VOID           *NewInterface
  )
/*++

Routine Description:

  Reinstall a protocol interface on a device handle.  The OldInterface for Protocol is replaced by the NewInterface.

Arguments:

  UserHandle    - Handle on which the interface is to be reinstalled
  Protocol      - The numeric ID of the interface
  OldInterface  - A pointer to the old interface
  NewInterface  - A pointer to the new interface 


Returns:

  Status code.

  On EFI_SUCCESS            The protocol interface was installed
  On EFI_NOT_FOUND          The OldInterface on the handle was not found
  On EFI_INVALID_PARAMETER  One of the parameters has an invalid value
  
--*/
{
  EFI_STATUS                Status;
  IHANDLE                   *Handle;
  PROTOCOL_INTERFACE        *Prot;
  PROTOCOL_ENTRY            *ProtEntry;

  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Handle = (IHANDLE *) UserHandle;

  //
  // Lock the protocol database
  //
  CoreAcquireProtocolLock ();

  //
  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
  //
  Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
  if (Prot == NULL) {
    CoreReleaseProtocolLock ();
    return EFI_NOT_FOUND;
  }

  //
  // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
  //
  Status = CoreDisconnectControllersUsingProtocolInterface (
             UserHandle,
             Prot
             );
  if (EFI_ERROR (Status)) {
    //
    // One or more drivers refused to release, so return the error
    //
    CoreReleaseProtocolLock ();
    return Status;
  }

  //
  // Remove the protocol interface from the protocol
  //
  Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);

  if (Prot == NULL) {
    CoreReleaseProtocolLock ();
    return EFI_NOT_FOUND;
  }

  ProtEntry = Prot->Protocol;

  //
  // Update the interface on the protocol
  //
  Prot->Interface = NewInterface;

  //
  // Add this protocol interface to the tail of the
  // protocol entry
  //
  InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);

  //
  // Update the Key to show that the handle has been created/modified
  //
  gHandleDatabaseKey++;
  Handle->Key = gHandleDatabaseKey;

  //
  // Release the lock and connect all drivers to UserHandle
  //
  CoreReleaseProtocolLock ();
  Status = CoreConnectController (
                  UserHandle, 
                  NULL, 
                  NULL, 
                  TRUE
                  );
  CoreAcquireProtocolLock ();
  
  //
  // Notify the notification list for this protocol
  //
  CoreNotifyProtocolEntry (ProtEntry);

  CoreReleaseProtocolLock ();
  
  return EFI_SUCCESS;
}
예제 #3
0
파일: Notify.c 프로젝트: lersek/edk2
/**
  Reinstall a protocol interface on a device handle.  The OldInterface for Protocol is replaced by the NewInterface.

  @param  UserHandle             Handle on which the interface is to be
                                 reinstalled
  @param  Protocol               The numeric ID of the interface
  @param  OldInterface           A pointer to the old interface
  @param  NewInterface           A pointer to the new interface

  @retval EFI_SUCCESS            The protocol interface was installed
  @retval EFI_NOT_FOUND          The OldInterface on the handle was not found
  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value

**/
EFI_STATUS
EFIAPI
CoreReinstallProtocolInterface (
  IN EFI_HANDLE     UserHandle,
  IN EFI_GUID       *Protocol,
  IN VOID           *OldInterface,
  IN VOID           *NewInterface
  )
{
  EFI_STATUS                Status;
  IHANDLE                   *Handle;
  PROTOCOL_INTERFACE        *Prot;
  PROTOCOL_ENTRY            *ProtEntry;

  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Handle = (IHANDLE *) UserHandle;

  //
  // Lock the protocol database
  //
  CoreAcquireProtocolLock ();

  //
  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
  //
  Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
  if (Prot == NULL) {
    Status = EFI_NOT_FOUND;
    goto Done;
  }

  //
  // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
  //
  Status = CoreDisconnectControllersUsingProtocolInterface (
             UserHandle,
             Prot
             );
  if (EFI_ERROR (Status)) {
    //
    // One or more drivers refused to release, so return the error
    //
    goto Done;
  }

  //
  // Remove the protocol interface from the protocol
  //
  Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);

  if (Prot == NULL) {
    Status = EFI_NOT_FOUND;
    goto Done;
  }

  ProtEntry = Prot->Protocol;

  //
  // Update the interface on the protocol
  //
  Prot->Interface = NewInterface;

  //
  // Add this protocol interface to the tail of the
  // protocol entry
  //
  InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);

  //
  // Update the Key to show that the handle has been created/modified
  //
  gHandleDatabaseKey++;
  Handle->Key = gHandleDatabaseKey;

  //
  // Release the lock and connect all drivers to UserHandle
  //
  CoreReleaseProtocolLock ();
  //
  // Return code is ignored on purpose.
  //
  CoreConnectController (
    UserHandle,
    NULL,
    NULL,
    TRUE
    );
  CoreAcquireProtocolLock ();

  //
  // Notify the notification list for this protocol
  //
  CoreNotifyProtocolEntry (ProtEntry);

  Status = EFI_SUCCESS;

Done:
  CoreReleaseProtocolLock ();

  return Status;
}