⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 handle.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.

Module Name:

    handle.c

Abstract:

    EFI handle & protocol handling



Revision History

--*/

#include "hand.h"

//
// ProtocolDatabase - A list of all protocols in the system.  (simple list for now)
// HandleQueue - A list of all the handles in the system
// ProtocolDatabaseLock - Lock to protect the ProtocolDatabase
//

STATIC LIST_ENTRY   ProtocolDatabase;
INTERNAL LIST_ENTRY HandleList;
INTERNAL FLOCK      ProtocolDatabaseLock;
UINT64              HandleDatabaseKey = 0;

VOID
InitializeHandle(
    VOID
    )
/*++

Routine Description:

    Initialize handle & protocol support

Arguments:
    
    None

Returns:

    None

--*/
{
    InitializeListHead (&ProtocolDatabase);
    InitializeListHead (&HandleList);
    InitializeLock (&ProtocolDatabaseLock, TPL_NOTIFY);
}

EFI_STATUS
ValidateHandle (
  IN  EFI_HANDLE                UserHandle
  )

{
  IHANDLE             *Handle;

  Handle = UserHandle;
  if (Handle == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
    return EFI_INVALID_PARAMETER;
  }
  return EFI_SUCCESS;
}

INTERNAL
PROTOCOL_ENTRY  *
FindProtocolEntry(
    IN EFI_GUID     *Protocol,
    IN BOOLEAN      Create
    )
/*++

Routine Description:

    Finds the protocl entry for the requested protocol.
    
    N.B.  The ProtocolDatabaseLock must be owned

Arguments:
    
    Protocol    - The ID of the protocol 

    Create      - Create a new entry if not found

Returns:

    Protocol entry

--*/
{
    LIST_ENTRY              *Link;
    PROTOCOL_ENTRY          *Item, *ProtEntry;


    ASSERT_LOCKED(&ProtocolDatabaseLock);

    //
    // Search the database for the matching GUID
    //

    ProtEntry = NULL;
    for (Link=ProtocolDatabase.Flink; 
         Link != &ProtocolDatabase; 
         Link=Link->Flink) {

        Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
        if (CompareGuid (&Item->ProtocolID, Protocol) == 0) {

            //
            // This is the protocol entry
            //

            ProtEntry = Item;
            break;
        }
    }

    //
    // If the protocol entry was not found and Create is TRUE, then 
    // allocate a new entry
    //
         
    if (!ProtEntry && Create) {
        ProtEntry = (PROTOCOL_ENTRY *) AllocatePool (sizeof(PROTOCOL_ENTRY));
        if (ProtEntry) {

            //
            // Initialize new protocol entry structure
            //

            ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
            ProtEntry->ProtocolID = *Protocol;
            InitializeListHead (&ProtEntry->Protocols);
            InitializeListHead (&ProtEntry->Notify);

            //
            // Add it to protocol database
            //

            InsertTailList (&ProtocolDatabase, &ProtEntry->AllEntries);
        }
    }

    return ProtEntry;
}

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

    ASSERT_LOCKED(&ProtocolDatabaseLock);
    Prot = NULL;

    //
    // Lookup the protocol entry for this protocol ID
    //

    ProtEntry = FindProtocolEntry (Protocol, FALSE);
    if (ProtEntry) {

        //
        // Look at each protocol interface for any matches
        //

        for (Link = Handle->Protocols.Flink; Link != &Handle->Protocols; Link=Link->Flink) {

            //
            // 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;
}

STATIC
EFI_STATUS
UnregisterProtocolNotifyEvent (
    IN EFI_EVENT            Event
    )
/*++

Routine Description:

    Removes an event from a register protocol notify list on a protocol.

Arguments:
    
    Event       - The event to search for in the protocol database.

Returns:

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

--*/
{
    LIST_ENTRY         *Link;
    PROTOCOL_ENTRY     *ProtEntry;
    LIST_ENTRY         *NotifyLink;
    PROTOCOL_NOTIFY    *ProtNotify;

    AcquireLock (&ProtocolDatabaseLock);

    for (Link =  ProtocolDatabase.Flink; 
         Link != &ProtocolDatabase; 
         Link =  Link->Flink) {

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

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

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

            if (ProtNotify->Event == Event) {
                RemoveEntryList(&ProtNotify->Link);
                FreePool(ProtNotify);
                ReleaseLock (&ProtocolDatabaseLock);
                return EFI_SUCCESS;
            }
        }
    }

    ReleaseLock (&ProtocolDatabaseLock);

    return EFI_NOT_FOUND;
}

EFI_STATUS
UnregisterProtocolNotify (
    IN EFI_EVENT            Event
    )
/*++

Routine Description:

    Removes all the events in the protocol database that match Event.

Arguments:
    
    Event       - The event to search for in the protocol database.

Returns:

    EFI_SUCCESS when done searching the entire database.

--*/
{
    EFI_STATUS         Status;

    do {
        Status = UnregisterProtocolNotifyEvent(Event);
    } while (!EFI_ERROR(Status));
    return EFI_SUCCESS;
}

EFI_STATUS
BOOTSERVICE
InstallProtocolInterface (
    IN OUT EFI_HANDLE           *UserHandle,
    IN EFI_GUID                 *Protocol,
    IN EFI_INTERFACE_TYPE       InterfaceType,
    IN VOID                     *Interface
    )
/*++

Routine Description:

    Installs a protocol interface into the boot services environment

Arguments:

    Handle          - The handle to install the protocol handler on,
                      or NULL if a new handle is to be allocated

    Protocol        - The protocol to add to the handle

    Interface       - The interface for the protocol being added

Returns:

    Status code    

--*/
{
    PROTOCOL_INTERFACE      *Prot;
    PROTOCOL_ENTRY          *ProtEntry;
    IHANDLE                 *Handle;
    EFI_STATUS              Status;
    VOID                    *ExistingInterface;

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

    //
    // Validate parameters
    //
    if (UserHandle == NULL || Protocol == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    //
    // Only native style interfaces are supported
    //
    if (InterfaceType != EFI_NATIVE_INTERFACE) {
        return EFI_INVALID_PARAMETER;
    }

    if (*UserHandle != NULL) {
        Status = BS->HandleProtocol(*UserHandle, Protocol, (VOID **)&ExistingInterface);

        if (!EFI_ERROR (Status)) {
          return EFI_INVALID_PARAMETER;
        }
    }

    //
    // Lock the protocol database 
    //

    AcquireLock (&ProtocolDatabaseLock);

    //
    // Lookup the Protocol Entry for the requested protocol
    //

    ProtEntry = FindProtocolEntry (Protocol, TRUE);
    if (!ProtEntry) {
        goto Done;
    }

    //
    // Allocate a new protocol interface structure
    //

    Prot = AllocateZeroPool(sizeof(PROTOCOL_INTERFACE));
    if (!Prot) {
        goto Done;
    }

    //
    // If caller didn't supply a handle, allocate a new one
    //

    Handle = *UserHandle;
    if (!Handle) {
        Handle = (IHANDLE *) AllocateZeroPool(sizeof(IHANDLE));
        if (!Handle) {
            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
        //
        HandleDatabaseKey++;
        Handle->Key = HandleDatabaseKey;

        //
        // Add this handle to the list global list of all handles
        // in the system
        //

        InsertTailList (&HandleList, &Handle->AllHandles);
    } 
      
    if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
        Status = EFI_INVALID_PARAMETER;
        goto Done;
    }

    //
    // Each interface that is added must be unique
    //

    ASSERT (FindProtocolInterface (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 
    //

    NotifyProtocolEntry (ProtEntry);
    Status = EFI_SUCCESS;

Done:
    //
    // Done, unlock the database and return
    //

    ReleaseLock (&ProtocolDatabaseLock);
    if (!EFI_ERROR(Status)) {

        //
        // Return the new handle back to the caller
        //

        *UserHandle = Handle;

    } else {
        
        //
        // There was an error, clean up
        //

        if (Prot) {
            FreePool (Prot);
        }
    }

    return Status;
}

EFI_STATUS
BOOTSERVICE
InstallMultipleProtocolInterfaces (
  IN OUT EFI_HANDLE           *Handle,
  ...
  )
/*++

Routine Description:

  Installs a list of protocol interface into the boot services environment.
  This function calls InstallProtocolInterface() in a loop. If any error
  occures all the protocols added by this function are removed. This is 
  basically a lib function to save space.

Arguments:

  Handle      - The handle to install the protocol handlers on,
                or NULL if a new handle is to be allocated


  ...         - EFI_GUID followed by protocol instance. A NULL terminates the 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -