Пример #1
0
/**
  Finds the protocol instance for the requested handle and protocol.
  Note: This function doesn't do parameters checking, it's caller's responsibility
  to pass in valid parameters.

  @param  Handle                 The handle to search the protocol on
  @param  Protocol               GUID of the protocol
  @param  Interface              The interface for the protocol being searched

  @return Protocol instance (NULL: Not found)

**/
PROTOCOL_INTERFACE *
SmmFindProtocolInterface (
  IN IHANDLE   *Handle,
  IN EFI_GUID  *Protocol,
  IN VOID      *Interface
  )
{
  PROTOCOL_INTERFACE  *Prot;
  PROTOCOL_ENTRY      *ProtEntry;
  LIST_ENTRY          *Link;

  Prot = NULL;

  //
  // Lookup the protocol entry for this protocol ID
  //
  ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);
  if (ProtEntry != NULL) {
    //
    // Look at each protocol interface for any matches
    //
    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
      //
      // If this protocol interface matches, remove it
      //
      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
      if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
        break;
      }
      Prot = NULL;
    }
  }
  return Prot;
}
Пример #2
0
/**
  Add a new protocol notification record for the request protocol.

  @param  Protocol               The requested protocol to add the notify
                                 registration
  @param  Function               Points to the notification function
  @param  Registration           Returns the registration record

  @retval EFI_SUCCESS            Successfully returned the registration record
                                 that has been added or unhooked
  @retval EFI_INVALID_PARAMETER  Protocol is NULL or Registration is NULL
  @retval EFI_OUT_OF_RESOURCES   Not enough memory resource to finish the request
  @retval EFI_NOT_FOUND          If the registration is not found when Function == NULL

**/
EFI_STATUS
EFIAPI
SmmRegisterProtocolNotify (
    IN  CONST EFI_GUID     *Protocol,
    IN  EFI_SMM_NOTIFY_FN  Function,
    OUT VOID               **Registration
)
{
    PROTOCOL_ENTRY   *ProtEntry;
    PROTOCOL_NOTIFY  *ProtNotify;
    LIST_ENTRY       *Link;
    EFI_STATUS       Status;

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

    if (Function == NULL) {
        //
        // Get the protocol entry per Protocol
        //
        ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);
        if (ProtEntry != NULL) {
            ProtNotify = (PROTOCOL_NOTIFY * )*Registration;
            for (Link = ProtEntry->Notify.ForwardLink;
                    Link != &ProtEntry->Notify;
                    Link = Link->ForwardLink) {
                //
                // Compare the notification record
                //
                if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))) {
                    //
                    // If Registration is an existing registration, then unhook it
                    //
                    ProtNotify->Signature = 0;
                    RemoveEntryList (&ProtNotify->Link);
                    FreePool (ProtNotify);
                    return EFI_SUCCESS;
                }
            }
        }
        //
        // If the registration is not found
        //
        return EFI_NOT_FOUND;
    }

    ProtNotify = NULL;

    //
    // Get the protocol entry to add the notification too
    //
    ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
    if (ProtEntry != NULL) {
        //
        // Find whether notification already exist
        //
        for (Link = ProtEntry->Notify.ForwardLink;
                Link != &ProtEntry->Notify;
                Link = Link->ForwardLink) {

            ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
            if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
                    (ProtNotify->Function == Function)) {

                //
                // Notification already exist
                //
                *Registration = ProtNotify;

                return EFI_SUCCESS;
            }
        }

        //
        // Allocate a new notification record
        //
        ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
        if (ProtNotify != NULL) {
            ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
            ProtNotify->Protocol = ProtEntry;
            ProtNotify->Function = Function;
            //
            // Start at the ending
            //
            ProtNotify->Position = ProtEntry->Protocols.BackLink;

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

    //
    // 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;
}
Пример #3
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
SmmInstallProtocolInterfaceNotify (
  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_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface));

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

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

  //
  // Lookup the Protocol Entry for the requested protocol
  //
  ProtEntry = SmmFindProtocolEntry (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);

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

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

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

  //
  // 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) {
    SmmNotifyProtocol (Prot);
  }
  Status = EFI_SUCCESS;

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