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

📄 handle.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
                list. The pairs are the arguments to InstallProtocolInterface().
                All the protocols are added to Handle.

Returns:

  Status code    

--*/
{
  va_list         args;
  EFI_STATUS      Status;
  EFI_GUID        *Protocol;
  VOID            *Interface;
  EFI_TPL         OldTpl;
  UINTN           Index;
  EFI_HANDLE                OldHandle;
  EFI_DEVICE_PATH           *DevicePath;
  EFI_HANDLE                DeviceHandle;

  //
  // Syncronize with notifcations. 
  // 
  OldTpl = BS->RaiseTPL (TPL_NOTIFY);
  OldHandle = *Handle;

  //
  // Check for duplicate device path 
  //
  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 *);
    //
    // Install it
    //
    if (CompareGuid (Protocol, &DevicePathProtocol) == 0) {
      //
      // Make sure you are installing on top a device path that has already
      // been added.
      //
      DeviceHandle = NULL;
      DevicePath   = Interface;
      Status = LocateDevicePath (&DevicePathProtocol, &DevicePath, &DeviceHandle);
      if (!EFI_ERROR(Status) && DeviceHandle != NULL && IsDevicePathEnd(DevicePath)) {
        BS->RestoreTPL(OldTpl);
        return EFI_ALREADY_STARTED;
      }
    }
  }

  //
  // 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 *);
    //
    // Install it
    //
    DEBUG((D_INFO, "InstallProtocolInterface: %d %x\n", Protocol, Interface));
    Status = InstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
    if (EFI_ERROR(Status)) {
      break;
    }
  }

  //
  // 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);
    while (Index) {
      Protocol = va_arg(args, EFI_GUID *);
      Interface = va_arg(args, VOID *);
      UninstallProtocolInterface (*Handle, Protocol, Interface);
      Index -= 1;
    }        
    *Handle = OldHandle;
  }

  //
  // Done
  //
  BS->RestoreTPL(OldTpl);
  return Status;
}

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

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:

  Handle      - The handle to remove the protocol handler from

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

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

Returns:

  Status code    

--*/
{
  EFI_STATUS            Status;
  BOOLEAN               ItemFound;
  LIST_ENTRY            *Link;
  OPEN_PROTOCOL_DATA    *OpenData;

  //
  // Attempt to disconnect all drivers from this protocol interface
  //
  do {
    ItemFound = FALSE;
    for ( Link = Prot->OpenList.Flink;
          (Link != &Prot->OpenList) & !ItemFound;
          Link = Link->Flink
          ) {
      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
      if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
        ItemFound = TRUE;
        ReleaseLock (&ProtocolDatabaseLock);
//        Status = BS->DisconnectController (OpenData->ControllerHandle, OpenData->AgentHandle, NULL);
        Status = BS->DisconnectController (UserHandle, OpenData->AgentHandle, NULL);
        AcquireLock (&ProtocolDatabaseLock);
        if (EFI_ERROR (Status)) {
          return EFI_ACCESS_DENIED;
        }
      }
    }
  } while (ItemFound == TRUE);

  //
  // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
  //
  do {
    ItemFound = FALSE;
    for ( Link = Prot->OpenList.Flink;
          (Link != &Prot->OpenList) & !ItemFound;
          Link = Link->Flink
          ) {
      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--;
        BS->FreePool (OpenData);
      }
    }
  } while (ItemFound == TRUE);

  //
  // If there are still Open Items in the list, then reconnect all the drivers and return an error
  //
  if (Prot->OpenListCount > 0) {
    ReleaseLock (&ProtocolDatabaseLock);
    Status = BS->ConnectController (UserHandle, NULL, NULL, TRUE);
    AcquireLock (&ProtocolDatabaseLock);
    return EFI_ACCESS_DENIED;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
BOOTSERVICE
UninstallProtocolInterface (
  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:

  Handle      - The handle to remove the protocol handler from

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

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

Returns:

  Status code    

--*/
{
  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 = ValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Lock the protocol database
  //
  AcquireLock (&ProtocolDatabaseLock);

  //
  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
  //
  Prot = FindProtocolInterface (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 = DisconnectControllersUsingProtocolInterface (
             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 = UserHandle;
  Prot   = RemoveInterfaceFromProtocol (Handle, Protocol, Interface);

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

  if (Prot != NULL) {
    //
    // Remove the protocol interface from the handle
    //
    RemoveEntryList (&Prot->Link);

    //
    // Free the memory
    //
    Prot->Signature = 0;
    BS->FreePool (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);
    BS->FreePool (Handle);
  }

Done:  
  //
  // Done, unlock the database and return
  //
  ReleaseLock (&ProtocolDatabaseLock);
  return Status;
}

EFI_STATUS
BOOTSERVICE
UninstallMultipleProtocolInterfaces (
  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;

  //
  // Uninstall 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 *);
    //
    // Uninstall it
    //
    DEBUG((D_INFO, "UninstallProtocolInterface: %d %x\n", Protocol, Interface));
    Status = UninstallProtocolInterface (Handle, Protocol, Interface);
    if (EFI_ERROR(Status)) {
      break;
    }
  }

  //
  // 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);
    while (Index) {
      Protocol = va_arg(args, EFI_GUID *);
      Interface = va_arg(args, VOID *);
      InstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
      Index -= 1;
    }        
  }

  return Status;
}    

PROTOCOL_INTERFACE  *
GetProtocolEntry (
  IN  EFI_HANDLE                UserHandle,
  IN  EFI_GUID                  *Protocol
  )
{
  PROTOCOL_ENTRY      *ProtEntry;
  PROTOCOL_INTERFACE  *Prot;
  IHANDLE             *Handle;
  LIST_ENTRY      *Link;

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

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

EFI_STATUS
BOOTSERVICE
HandleProtocol (
  IN EFI_HANDLE       UserHandle,
  IN EFI_GUID         *Protocol,
  OUT VOID            **Interface
  )
{
  return OpenProtocol (
          UserHandle,     
          Protocol, 
          Interface, 
          NULL, //gMyImageHandle, 
          NULL,     
          EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
          );
}

EFI_STATUS
BOOTSERVICE
OpenProtocol (
  IN  EFI_HANDLE                UserHandle,
  IN  EFI_GUID                  *Protocol,
  OUT VOID                      **Interface,
  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    -
  
  NotifyFunction -

  Attributes     -

Returns:

  The requested protocol interface for the handle
  
--*/
{
  EFI_STATUS          Status;
  PROTOCOL_INTERFACE  *Prot;
  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 && Interface == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //

⌨️ 快捷键说明

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