handle.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,701 行 · 第 1/3 页

C
1,701
字号
  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);
    }
  }

  return Status;
}


EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreInstallMultipleProtocolInterfaces (
  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 
                list. The pairs are the arguments to InstallProtocolInterface().
                All the protocols are added to Handle.

Returns:

  EFI_INVALID_PARAMETER       - Handle is NULL.
  
  EFI_SUCCESS                 - Protocol interfaces successfully installed.

--*/
{
  VA_LIST                   args;
  EFI_STATUS                Status;
  EFI_GUID                  *Protocol;
  VOID                      *Interface;
  EFI_TPL                   OldTpl;
  UINTN                     Index;
  EFI_HANDLE                OldHandle;
  EFI_HANDLE                DeviceHandle;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  
  if (Handle == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  
  //
  // Syncronize with notifcations. 
  // 
  OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY);
  OldHandle = *Handle;

  //
  // Check for duplicate device path and install the protocol interfaces
  //
  VA_START (args, Handle);
  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
    //
    // If protocol is NULL, then it's the end of the list
    //
    Protocol = VA_ARG (args, EFI_GUID *);
    if (Protocol == NULL) {
      break;
    }

    Interface = VA_ARG (args, VOID *);

    //
    // Make sure you are installing on top a device path that has already been added.
    //
    if (EfiCompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
      DeviceHandle = NULL;
      DevicePath   = Interface;
      Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
      if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
        Status = EFI_ALREADY_STARTED;
        continue;
      }
    }
  
    //
    // Install it
    //
    Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
  }
  
  //
  // If there was an error, remove all the interfaces that were installed without any errors
  //
  if (EFI_ERROR (Status)) {
    //
    // Reset the va_arg back to the first argument.
    //
    VA_START (args, Handle);
    for (; Index > 1; Index--) {
      Protocol = VA_ARG (args, EFI_GUID *);
      Interface = VA_ARG (args, VOID *);
      CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
    }        
    *Handle = OldHandle;
  }

  //
  // Done
  //
  CoreRestoreTpl (OldTpl);
  return Status;
}

EFI_STATUS
CoreDisconnectControllersUsingProtocolInterface (
  IN EFI_HANDLE           UserHandle,
  IN PROTOCOL_INTERFACE   *Prot
  )
/*++

Routine Description:

  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.

Arguments:

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

Returns:

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

--*/
{
  EFI_STATUS            Status;
  BOOLEAN               ItemFound;
  EFI_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) && !ItemFound;
          Link = Link->ForwardLink ) {
      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
      if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
        ItemFound = TRUE;
        CoreReleaseProtocolLock ();
        Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
        CoreAcquireProtocolLock ();
        if (EFI_ERROR (Status)) {
           ItemFound = FALSE;
           break;
        }
      }
    }
  } while (ItemFound);

  if (!EFI_ERROR (Status)) {
    //
    // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
    //
    do {
      ItemFound = FALSE;
      for ( Link = Prot->OpenList.ForwardLink;
            (Link != &Prot->OpenList) && !ItemFound;
            Link = Link->ForwardLink ) {
        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)) {
          ItemFound = TRUE;
          RemoveEntryList (&OpenData->Link);  
          Prot->OpenListCount--;
          CoreFreePool (OpenData);
        }
      }
    } while (ItemFound);
  }

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

EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreUninstallProtocolInterface (
  IN EFI_HANDLE       UserHandle,
  IN EFI_GUID         *Protocol,
  IN VOID             *Interface
  )
/*++

Routine Description:

  Uninstalls all instances of a protocol:interfacer from a handle. 
  If the last protocol interface is remove from the handle, the 
  handle is freed.

Arguments:

  UserHandle      - The handle to remove the protocol handler from

  Protocol        - The protocol, of protocol:interface, to remove

  Interface       - The interface, of protocol:interface, to remove

Returns:

  EFI_INVALID_PARAMETER       - Protocol is NULL.
  
  EFI_SUCCESS                 - Protocol interface successfully uninstalled.

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


EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreUninstallMultipleProtocolInterfaces (
  IN EFI_HANDLE           Handle,
  ...
  )
/*++

Routine Description:

  Uninstalls a list of protocol interface in the boot services environment. 
  This function calls UnisatllProtocolInterface() in a loop. This is 
  basically a lib function to save space.

Arguments:

  Handle      - The handle to uninstall the protocol

  ...         - EFI_GUID followed by protocol instance. A NULL terminates the 
                list. The pairs are the arguments to UninstallProtocolInterface().
                All the protocols are added to Handle.

Returns:

  Status code    

--*/
{
  EFI_STATUS      Status;
  VA_LIST         args;
  EFI_GUID        *Protocol;
  VOID            *Interface;
  UINTN           Index;

  VA_START (args, Handle);
  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
    //
    // If protocol is NULL, then it's the end of the list
    //
    Protocol = VA_ARG (args, EFI_GUID *);
    if (Protocol == NULL) {
      break;
    }

    Interface = VA_ARG (args, VOID *);

    //
    // Uninstall it
    //
    Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
  }

  //
  // If there was an error, add all the interfaces that were
  // uninstalled without any errors
  //
  if (EFI_ERROR (Status)) {
    //
    // Reset the va_arg back to the first argument.
    //
    VA_START (args, Handle);
    for (; Index > 1; Index--) {
      Protocol = VA_ARG(args, EFI_GUID *);
      Interface = VA_ARG(args, VOID *);
      CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
    }        
  }

  return Status;
}    

PROTOCOL_INTERFACE  *
CoreGetProtocolInterface (
  IN  EFI_HANDLE                UserHandle,
  IN  EFI_GUID                  *Protocol
  )
/*++

Routine Description:

  Locate a certain GUID protocol interface in a Handle's protocols.

Arguments:

  UserHandle  - The handle to obtain the protocol interface on

  Protocol    - The GUID of the protocol 

Returns:

  The requested protocol interface for the handle
  
--*/  
{
  EFI_STATUS          Status;
  PROTOCOL_ENTRY      *ProtEntry;
  PROTOCOL_INTERFACE  *Prot;
  IHANDLE             *Handle;
  EFI_LIST_ENTRY      *Link;

  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return NULL;
  }
  
  Handle = (IHANDLE *)UserHandle;

  //
  // Look at each protocol interface for a match
  //
  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
    ProtEntry = Prot->Protocol;
    if (EfiCompareGuid (&ProtEntry->ProtocolID, Protocol)) {
      return Prot;
    }
  }
  return NULL;
}

EFI_BOOTSERVICE
EFI_STATUS
EFIAPI
CoreHandleProtocol (
  IN EFI_HANDLE       UserHandle,
  IN EFI_GUID         *Protocol,
  OUT VOID            **Interface
  )
/*++

Routine Description:

  Queries a handle to determine if it supports a specified protocol.

Arguments:

  UserHandle  - The handle being queried.

  Protocol    - The published unique identifier of the protocol.

  Interface   - Supplies the address where a pointer to the corresponding Protocol
               Interface is returned.

Returns:

  The requested protocol interface for the handle
  
--*/  
{
  return CoreOpenProtocol (
          UserHandle,     
          Protocol, 
          Interface, 
          gDxeCoreImageHandle, 
          NULL,     
          EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
          );
}

EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreOpenProtocol (
  IN  EFI_HANDLE                UserHandle,
  IN  EFI_GUID                  *Protocol,
  OUT VOID                      **Interface OPTIONAL,
  IN  EFI_HANDLE                ImageHandle,
  IN  EFI_HANDLE                ControllerHandle,
  IN  UINT32                    Attributes
  )
/*++

Routine Description:

  Locates the installed protocol handler for the handle, and
  invokes it to obtain the protocol interface. Usage information
  is registered in the protocol data base.

Arguments:

  UserHandle     - The handle to obtain the protocol interface on

  Protocol       - The ID of the protocol 

  Interface      - The location to return the protocol interface

  ImageHandle       - The handle of the Image that is opening the protocol interface
                    specified by Protocol and Interface.
  
  ControllerHandle  - The controller handle that is requiring this interface.

  Attributes     - The open mode of the protocol interface specified by Handle
                    and Protocol.

Returns:

  EFI_INVALID_PARAMETER       - Protocol is NULL.
  
  EFI_SUCCESS                 - Get the protocol interface.
  
--*/
{
  EFI_STATUS          Status;
  PROTOCOL_INTERFACE  *Prot;
  EFI_LIST_ENTRY      *Link;
  OPEN_PROTOCOL_DATA  *OpenData;
  BOOLEAN             ByDriver;
  BOOLEAN             Exclusive;
  BOOLEAN             Disconnect;
  BOOLEAN             ExactMatch;

  //
  // Check for invalid Protocol
  //
  if (Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check for invalid Interface
  //
  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
    if (Interface == NULL) {
      return EFI_INVALID_PARAMETER;

⌨️ 快捷键说明

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