handle.c

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

C
1,701
字号
    } else {
      *Interface = NULL;
    }
  }
  
  //
  // Check for invalid UserHandle
  //
  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Check for invalid Attributes
  //
  switch (Attributes) {
  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
    Status = CoreValidateHandle (ImageHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = CoreValidateHandle (ControllerHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    if (UserHandle == ControllerHandle) {
      return EFI_INVALID_PARAMETER;
    }
    break;
  case EFI_OPEN_PROTOCOL_BY_DRIVER :
  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
    Status = CoreValidateHandle (ImageHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = CoreValidateHandle (ControllerHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    break;
  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
    Status = CoreValidateHandle (ImageHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    break;
  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
    break;
  default:
    return EFI_INVALID_PARAMETER;
  }

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

  //
  // Look at each protocol interface for a match
  //
  Prot = CoreGetProtocolInterface (UserHandle, Protocol);
  if (Prot == NULL) {
    Status = EFI_UNSUPPORTED;
    goto Done;
  }

  //
  // This is the protocol interface entry for this protocol
  //    
  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
    *Interface = Prot->Interface;
  }
  Status = EFI_SUCCESS;

  ByDriver        = FALSE;
  Exclusive       = FALSE;
  for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
    ExactMatch =  (BOOLEAN)((OpenData->AgentHandle == ImageHandle) && 
                            (OpenData->Attributes == Attributes)  &&
                            (OpenData->ControllerHandle == ControllerHandle));
    if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
      ByDriver = TRUE;
      if (ExactMatch) {
        Status = EFI_ALREADY_STARTED;
        goto Done;
      }
    }
    if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
      Exclusive = TRUE;
    } else if (ExactMatch) {
      OpenData->OpenCount++;
      Status = EFI_SUCCESS;
      goto Done;
    }
  }

  //
  // ByDriver  TRUE  -> A driver is managing (UserHandle, Protocol)
  // ByDriver  FALSE -> There are no drivers managing (UserHandle, Protocol)
  // Exclusive TRUE  -> Something has exclusive access to (UserHandle, Protocol)
  // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
  //

  switch (Attributes) {
  case EFI_OPEN_PROTOCOL_BY_DRIVER :
    if (Exclusive || ByDriver) {
      Status = EFI_ACCESS_DENIED;
      goto Done;
    }
    break;
  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
    if (Exclusive) {
      Status = EFI_ACCESS_DENIED;
      goto Done;
    }
    if (ByDriver) {
      do {
        Disconnect = FALSE;
        for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
          OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
          if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
            Disconnect = TRUE;
            CoreReleaseProtocolLock ();
            Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
            CoreAcquireProtocolLock ();
            if (EFI_ERROR (Status)) {
              Status = EFI_ACCESS_DENIED;
              goto Done;
            }
          }
        }
      } while (Disconnect);
    } 
    break;
  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
    break;
  }

  if (ImageHandle == NULL) {
    Status = EFI_SUCCESS;
    goto Done;
  }
  //
  // Create new entry
  //
  OpenData = CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA));
  if (OpenData == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
  } else {
    OpenData->Signature         = OPEN_PROTOCOL_DATA_SIGNATURE;
    OpenData->AgentHandle       = ImageHandle;
    OpenData->ControllerHandle  = ControllerHandle;
    OpenData->Attributes        = Attributes;
    OpenData->OpenCount         = 1;
    InsertTailList (&Prot->OpenList, &OpenData->Link);
    Prot->OpenListCount++;
    Status = EFI_SUCCESS;
  }

Done:
  //
  // Done. Release the database lock are return
  //
  CoreReleaseProtocolLock ();
  return Status;
}

EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreCloseProtocol (
  IN  EFI_HANDLE                UserHandle,
  IN  EFI_GUID                  *Protocol,
  IN  EFI_HANDLE                AgentHandle,
  IN  EFI_HANDLE                ControllerHandle  
  )
/*++

Routine Description:

  Closes a protocol on a handle that was opened using OpenProtocol().

Arguments:

  UserHandle       -  The handle for the protocol interface that was previously opened
                      with OpenProtocol(), and is now being closed.
  Protocol         -  The published unique identifier of the protocol. It is the caller’s
                      responsibility to pass in a valid GUID.
  AgentHandle      -  The handle of the agent that is closing the protocol interface.
  ControllerHandle -  If the agent that opened a protocol is a driver that follows the
                      EFI Driver Model, then this parameter is the controller handle
                      that required the protocol interface. If the agent does not follow
                      the EFI Driver Model, then this parameter is optional and may be NULL.

Returns:

  EFI_SUCCESS             - The protocol instance was closed.
  EFI_INVALID_PARAMETER   - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE. 
  EFI_NOT_FOUND           - Can not find the specified protocol or AgentHandle.
  
--*/
{
  EFI_STATUS          Status;
  PROTOCOL_INTERFACE  *ProtocolInterface;
  EFI_LIST_ENTRY      *Link;
  OPEN_PROTOCOL_DATA  *OpenData;

  //
  // Check for invalid parameters
  //
  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  Status = CoreValidateHandle (AgentHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  if (ControllerHandle != NULL_HANDLE) {
    Status = CoreValidateHandle (ControllerHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }
  if (Protocol == NULL) {
    return EFI_INVALID_PARAMETER;
  }

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

  //
  // Look at each protocol interface for a match
  //
  Status = EFI_NOT_FOUND;
  ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
  if (ProtocolInterface == NULL) {
    goto Done;
  }

  //
  // Walk the Open data base looking for AgentHandle
  //
  Link = ProtocolInterface->OpenList.ForwardLink;
  while (Link != &ProtocolInterface->OpenList) {
    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
    Link = Link->ForwardLink;
    if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
        RemoveEntryList (&OpenData->Link);  
        ProtocolInterface->OpenListCount--;
        CoreFreePool (OpenData);
        Status = EFI_SUCCESS;
    }
  }

Done:
  //
  // Done. Release the database lock and return.
  //
  CoreReleaseProtocolLock ();
  return Status;
}


EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreOpenProtocolInformation (
  IN  EFI_HANDLE                          UserHandle,
  IN  EFI_GUID                            *Protocol,
  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
  OUT UINTN                               *EntryCount
  )
/*++

Routine Description:

  Return information about Opened protocols in the system

Arguments:

  UserHandle  - The handle to close the protocol interface on

  Protocol    - The ID of the protocol 

  EntryBuffer - A pointer to a buffer of open protocol information in the form of
                EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.

  EntryCount  - Number of EntryBuffer entries

Returns:

  
--*/
{
  EFI_STATUS                          Status;
  PROTOCOL_INTERFACE                  *ProtocolInterface;
  EFI_LIST_ENTRY                      *Link;
  OPEN_PROTOCOL_DATA                  *OpenData;
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
  UINTN                               Count;
  UINTN                               Size;

  *EntryBuffer = NULL;
  *EntryCount = 0;

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

  //
  // Look at each protocol interface for a match
  //
  Status = EFI_NOT_FOUND;
  ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
  if (ProtocolInterface == NULL) {
    goto Done;
  }

  //
  // Count the number of Open Entries
  //
  for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; 
        (Link != &ProtocolInterface->OpenList) ;
        Link = Link->ForwardLink  ) {
    Count++;
  } 

  ASSERT (Count == ProtocolInterface->OpenListCount);

  if (Count == 0) {
    Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
  } else {
    Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
  }

  Buffer = CoreAllocateBootServicesPool (Size);
  if (Buffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  Status = EFI_SUCCESS;
  for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; 
        (Link != &ProtocolInterface->OpenList);
        Link = Link->ForwardLink, Count++  ) {
    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);

    Buffer[Count].AgentHandle      = OpenData->AgentHandle;
    Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
    Buffer[Count].Attributes       = OpenData->Attributes;
    Buffer[Count].OpenCount        = OpenData->OpenCount;
  } 

  *EntryBuffer = Buffer;
  *EntryCount = Count;
        
Done:
  //
  // Done. Release the database lock are return
  //
  CoreReleaseProtocolLock ();
  return Status;
}


EFI_BOOTSERVICE11
EFI_STATUS
EFIAPI
CoreProtocolsPerHandle (
  IN EFI_HANDLE       UserHandle,
  OUT EFI_GUID        ***ProtocolBuffer,
  OUT UINTN           *ProtocolBufferCount
  )
/*++

Routine Description:

  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
 from pool.

Arguments:

  UserHandle           - The handle from which to retrieve the list of protocol interface
                          GUIDs.

  ProtocolBuffer       - A pointer to the list of protocol interface GUID pointers that are
                          installed on Handle.

  ProtocolBufferCount  - A pointer to the number of GUID pointers present in
                          ProtocolBuffer.

Returns:
  EFI_SUCCESS   -  The list of protocol interface GUIDs installed on Handle was returned in
                   ProtocolBuffer. The number of protocol interface GUIDs was
                   returned in ProtocolBufferCount.
  EFI_INVALID_PARAMETER   -  Handle is NULL.
  EFI_INVALID_PARAMETER   -  Handle is not a valid EFI_HANDLE.
  EFI_INVALID_PARAMETER   -  ProtocolBuffer is NULL.
  EFI_INVALID_PARAMETER   -  ProtocolBufferCount is NULL.
  EFI_OUT_OF_RESOURCES    -  There is not enough pool memory to store the results.
  
--*/
{
  EFI_STATUS                          Status;
  IHANDLE                             *Handle;
  PROTOCOL_INTERFACE                  *Prot;
  EFI_LIST_ENTRY                      *Link;
  UINTN                               ProtocolCount;
  EFI_GUID                            **Buffer;

  Status = CoreValidateHandle (UserHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Handle = (IHANDLE *)UserHandle;

  if (ProtocolBuffer == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (ProtocolBufferCount == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  *ProtocolBufferCount = 0;

  ProtocolCount = 0;

  CoreAcquireProtocolLock ();
  
  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
    ProtocolCount++;
  }

  //
  // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
  //
  if (ProtocolCount == 0) {
    Status = EFI_INVALID_PARAMETER;
    goto Done;
  }

  Buffer = CoreAllocateBootServicesPool (sizeof (EFI_GUID *) * ProtocolCount);
  if (Buffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  *ProtocolBuffer = Buffer;
  *ProtocolBufferCount = ProtocolCount;

  for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
        Link != &Handle->Protocols; 
        Link = Link->ForwardLink, ProtocolCount++) {
    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
    Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
  }
  Status = EFI_SUCCESS;

Done:
  CoreReleaseProtocolLock ();
  return Status;
}


UINT64
CoreGetHandleDatabaseKey (
  VOID
  )
/*++

Routine Description:

  return handle database key.

Arguments:

  None
  
Returns:
  
  Handle database key.
  
--*/
{
  return gHandleDatabaseKey;
}


VOID
CoreConnectHandlesByKey (
  UINT64  Key
  )
/*++

Routine Description:

  Go connect any handles that were created or modified while a image executed.

Arguments:

  Key  -  The Key to show that the handle has been created/modified

Returns:
  
  None
--*/
{
  UINTN           Count;
  EFI_LIST_ENTRY  *Link;
  EFI_HANDLE      *HandleBuffer;
  IHANDLE         *Handle;
  UINTN           Index;

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

  for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
    Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
    if (Handle->Key > Key) {
      Count++;
    }
  }

  HandleBuffer = CoreAllocateBootServicesPool (Count * sizeof (EFI_HANDLE));
  if (HandleBuffer == NULL) {
    CoreReleaseProtocolLock ();
    return;
  }
  
  for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
    Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
    if (Handle->Key > Key) {
      HandleBuffer[Count++] = Handle;
    }
  }

  //
  // Unlock the protocol database
  //
  CoreReleaseProtocolLock ();

  //
  // Connect all handles whose Key value is greater than Key
  //
  for (Index = 0; Index < Count; Index++) {
    CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
  }
  
  CoreFreePool(HandleBuffer);
}

⌨️ 快捷键说明

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