Пример #1
0
/**
  Add a new protocol notification record for the request protocol.

  @param  Protocol               The requested protocol to add the notify
                                 registration
  @param  Event                  The event to signal
  @param  Registration           Returns the registration record

  @retval EFI_INVALID_PARAMETER  Invalid parameter
  @retval EFI_SUCCESS            Successfully returned the registration record
                                 that has been added

**/
EFI_STATUS
EFIAPI
CoreRegisterProtocolNotify (
  IN EFI_GUID       *Protocol,
  IN EFI_EVENT      Event,
  OUT  VOID         **Registration
  )
{
  PROTOCOL_ENTRY    *ProtEntry;
  PROTOCOL_NOTIFY   *ProtNotify;
  EFI_STATUS        Status;

  if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL))  {
    return EFI_INVALID_PARAMETER;
  }

  CoreAcquireProtocolLock ();

  ProtNotify = NULL;

  //
  // Get the protocol entry to add the notification too
  //

  ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
  if (ProtEntry != NULL) {

    //
    // Allocate a new notification record
    //
    ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
    if (ProtNotify != NULL) {
      ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION;
      ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
      ProtNotify->Protocol = ProtEntry;
      ProtNotify->Event = Event;
      //
      // start at the begining
      //
      ProtNotify->Position = &ProtEntry->Protocols;

      InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
    }
  }

  CoreReleaseProtocolLock ();

  //
  // Done.  If we have a protocol notify entry, then return it.
  // Otherwise, we must have run out of resources trying to add one
  //

  Status = EFI_OUT_OF_RESOURCES;
  if (ProtNotify != NULL) {
    *Registration = ProtNotify;
    Status = EFI_SUCCESS;
  }

  return Status;
}
Пример #2
0
/**
  Removes an event from a register protocol notify list on a protocol.

  @param  Event                  The event to search for in the protocol
                                 database.

  @return EFI_SUCCESS   if the event was found and removed.
  @return EFI_NOT_FOUND if the event was not found in the protocl database.

**/
EFI_STATUS
CoreUnregisterProtocolNotifyEvent (
  IN EFI_EVENT      Event
  )
{
  LIST_ENTRY         *Link;
  PROTOCOL_ENTRY     *ProtEntry;
  LIST_ENTRY         *NotifyLink;
  PROTOCOL_NOTIFY    *ProtNotify;

  CoreAcquireProtocolLock ();

  for ( Link =  mProtocolDatabase.ForwardLink;
        Link != &mProtocolDatabase;
        Link =  Link->ForwardLink) {

    ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);

    for ( NotifyLink =  ProtEntry->Notify.ForwardLink;
          NotifyLink != &ProtEntry->Notify;
          NotifyLink =  NotifyLink->ForwardLink) {

      ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);

      if (ProtNotify->Event == Event) {
        RemoveEntryList(&ProtNotify->Link);
        CoreFreePool(ProtNotify);
        CoreReleaseProtocolLock ();
        return EFI_SUCCESS;
      }
    }
  }

  CoreReleaseProtocolLock ();
  return EFI_NOT_FOUND;
}
Пример #3
0
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;
}
Пример #4
0
EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreRegisterProtocolNotify (
  IN EFI_GUID       *Protocol,
  IN EFI_EVENT      Event,
  OUT  VOID           **Registration
  )
/*++

Routine Description:

  Add a new protocol notification record for the request protocol.

Arguments:

  Protocol      - The requested protocol to add the notify registration

  Event         - The event to signal 

  Registration  - Returns the registration record


Returns:

  EFI_INVALID_PARAMETER       - Invalid parameter

  EFI_SUCCESS                 - Successfully returned the registration record that has been added
  
--*/
{
  PROTOCOL_ENTRY      *ProtEntry;
  PROTOCOL_NOTIFY     *ProtNotify;
  EFI_STATUS        Status;
  
  if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL))  {
    return EFI_INVALID_PARAMETER;
  }

  CoreAcquireProtocolLock ();

  ProtNotify = NULL;
  
  //
  // Get the protocol entry to add the notification too
  //

  ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
  if (ProtEntry != NULL) {

    //
    // Allocate a new notification record
    //

    ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));

    if (ProtNotify != NULL) {
      
      ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
      ProtNotify->Protocol = ProtEntry;
      ProtNotify->Event = Event;
      //
      // start at the begining
      //
      ProtNotify->Position = &ProtEntry->Protocols; 

      InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
    }
  }

  CoreReleaseProtocolLock ();

  //
  // Done.  If we have a protocol notify entry, then return it.
  // Otherwise, we must have run out of resources trying to add one
  //

  Status = EFI_OUT_OF_RESOURCES;
  if (ProtNotify != NULL) {
    *Registration = ProtNotify;
    Status = EFI_SUCCESS;
  }

  return Status;
}
Пример #5
0
/**
  Uninstalls all instances of a protocol:interfacer from a handle.
  If the last protocol interface is remove from the handle, the
  handle is freed.

  @param  UserHandle             The handle to remove the protocol handler from
  @param  Protocol               The protocol, of protocol:interface, to remove
  @param  Interface              The interface, of protocol:interface, to remove

  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
  @retval EFI_SUCCESS            Protocol interface successfully uninstalled.

**/
EFI_STATUS
EFIAPI
CoreUninstallProtocolInterface (
  IN EFI_HANDLE       UserHandle,
  IN EFI_GUID         *Protocol,
  IN VOID             *Interface
  )
{
  EFI_STATUS            Status;
  IHANDLE               *Handle;
  PROTOCOL_INTERFACE    *Prot;

  //
  // Check that Protocol is valid
  //
  if (Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check that UserHandle is a valid handle
  //
  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

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

  //
  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
  //
  Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
  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 removed
  //
  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
  //
  Status = EFI_NOT_FOUND;
  Handle = (IHANDLE *)UserHandle;
  Prot   = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);

  if (Prot != NULL) {
    //
    // Update the Key to show that the handle has been created/modified
    //
    gHandleDatabaseKey++;
    Handle->Key = gHandleDatabaseKey;

    //
    // Remove the protocol interface from the handle
    //
    RemoveEntryList (&Prot->Link);

    //
    // Free the memory
    //
    Prot->Signature = 0;
    CoreFreePool (Prot);
    Status = EFI_SUCCESS;
  }

  //
  // If there are no more handlers for the handle, free the handle
  //
  if (IsListEmpty (&Handle->Protocols)) {
    Handle->Signature = 0;
    RemoveEntryList (&Handle->AllHandles);
    CoreFreePool (Handle);
  }

Done:
  //
  // Done, unlock the database and return
  //
  CoreReleaseProtocolLock ();
  return Status;
}
Пример #6
0
/**
  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;
}
Пример #7
0
/**
  Installs a protocol interface into the boot services environment.

  @param  UserHandle             The handle to install the protocol handler on,
                                 or NULL if a new handle is to be allocated
  @param  Protocol               The protocol to add to the handle
  @param  InterfaceType          Indicates whether Interface is supplied in
                                 native form.
  @param  Interface              The interface for the protocol being added
  @param  Notify                 indicates whether notify the notification list
                                 for this protocol

  @retval EFI_INVALID_PARAMETER  Invalid parameter
  @retval EFI_OUT_OF_RESOURCES   No enough buffer to allocate
  @retval EFI_SUCCESS            Protocol interface successfully installed

**/
EFI_STATUS
CoreInstallProtocolInterfaceNotify (
  IN OUT EFI_HANDLE     *UserHandle,
  IN EFI_GUID           *Protocol,
  IN EFI_INTERFACE_TYPE InterfaceType,
  IN VOID               *Interface,
  IN BOOLEAN            Notify
  )
{
  PROTOCOL_INTERFACE  *Prot;
  PROTOCOL_ENTRY      *ProtEntry;
  IHANDLE             *Handle;
  EFI_STATUS          Status;
  VOID                *ExistingInterface;

  //
  // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
  // Also added check for invalid UserHandle and Protocol pointers.
  //
  if (UserHandle == NULL || Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (InterfaceType != EFI_NATIVE_INTERFACE) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Print debug message
  //
  DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));

  Status = EFI_OUT_OF_RESOURCES;
  Prot = NULL;
  Handle = NULL;

  if (*UserHandle != NULL) {
    Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
    if (!EFI_ERROR (Status)) {
      return EFI_INVALID_PARAMETER;
    }
  }

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

  //
  // Lookup the Protocol Entry for the requested protocol
  //
  ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
  if (ProtEntry == NULL) {
    goto Done;
  }

  //
  // Allocate a new protocol interface structure
  //
  Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));
  if (Prot == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // If caller didn't supply a handle, allocate a new one
  //
  Handle = (IHANDLE *)*UserHandle;
  if (Handle == NULL) {
    Handle = AllocateZeroPool (sizeof(IHANDLE));
    if (Handle == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto Done;
    }

    //
    // Initialize new handler structure
    //
    Handle->Signature = EFI_HANDLE_SIGNATURE;
    InitializeListHead (&Handle->Protocols);

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

    //
    // Add this handle to the list global list of all handles
    // in the system
    //
    InsertTailList (&gHandleList, &Handle->AllHandles);
  } else {
    Status = CoreValidateHandle (Handle);
    if (EFI_ERROR (Status)) {
      DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
      goto Done;
    }
  }

  //
  // Each interface that is added must be unique
  //
  ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);

  //
  // Initialize the protocol interface structure
  //
  Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
  Prot->Handle = Handle;
  Prot->Protocol = ProtEntry;
  Prot->Interface = Interface;

  //
  // Initalize OpenProtocol Data base
  //
  InitializeListHead (&Prot->OpenList);
  Prot->OpenListCount = 0;

  //
  // Add this protocol interface to the head of the supported
  // protocol list for this handle
  //
  InsertHeadList (&Handle->Protocols, &Prot->Link);

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

  //
  // Notify the notification list for this protocol
  //
  if (Notify) {
    CoreNotifyProtocolEntry (ProtEntry);
  }
  Status = EFI_SUCCESS;

Done:
  //
  // Done, unlock the database and return
  //
  CoreReleaseProtocolLock ();
  if (!EFI_ERROR (Status)) {
    //
    // Return the new handle back to the caller
    //
    *UserHandle = Handle;
  } else {
    //
    // There was an error, clean up
    //
    if (Prot != NULL) {
      CoreFreePool (Prot);
    }
    DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
  }

  return Status;
}
Пример #8
0
/**
  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;
}