driversupport.c

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

C
861
字号
/*++

Copyright (c) 2004, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:

    DriverSupport.c
    
Abstract:

    EFI Driver Support Protocol

Revision History

--*/

#include "Tiano.h"
#include "hand.h"
#include "EfiPerf.h"


//
// Driver Consumed Protocol Prototypes
//
#include EFI_PROTOCOL_DEFINITION(DriverBinding)
#include EFI_PROTOCOL_DEFINITION(PlatformDriverOverride)
#include EFI_PROTOCOL_DEFINITION(BusSpecificDriverOverride)



#ifdef EFI_DXE_PERFORMANCE
STATIC
EFI_STATUS
GetHandleFromDriverBinding (
  IN EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,
  OUT  EFI_HANDLE                          *Handle 
  );
#endif

//
// Driver Support Function Prototypes
//
STATIC
EFI_STATUS 
CoreConnectSingleController (
  IN  EFI_HANDLE                ControllerHandle,
  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL
  );

//
// Driver Support Functions
//

EFI_BOOTSERVICE11
EFI_STATUS 
EFIAPI
CoreConnectController (
  IN  EFI_HANDLE                ControllerHandle,
  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
  IN  BOOLEAN                   Recursive
  )
/*++

Routine Description:

  Connects one or more drivers to a controller.

Arguments:

  ControllerHandle            - Handle of the controller to be connected.

  DriverImageHandle           - DriverImageHandle A pointer to an ordered list of driver image handles.

  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child of the
                                controller specified by ControllerHandle.
    
  Recursive                   - Whether the function would be called recursively or not.

Returns:

  Status code.

--*/
{
  EFI_STATUS                           Status;
  EFI_STATUS                           ReturnStatus;
  IHANDLE                              *Handle;
  PROTOCOL_INTERFACE                   *Prot;
  EFI_LIST_ENTRY                       *Link;
  EFI_LIST_ENTRY                       *ProtLink;
  OPEN_PROTOCOL_DATA                   *OpenData;
  EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;
  
  //
  // Make sure ControllerHandle is valid
  //
  Status = CoreValidateHandle (ControllerHandle);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Handle = ControllerHandle;

  //
  // Connect all drivers to ControllerHandle 
  //
  AlignedRemainingDevicePath = NULL;
  if (RemainingDevicePath != NULL) {
    AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
  }
  ReturnStatus = CoreConnectSingleController (
                   ControllerHandle,
                   DriverImageHandle,
                   AlignedRemainingDevicePath
                   );
  if (AlignedRemainingDevicePath != NULL) {
    CoreFreePool (AlignedRemainingDevicePath);
  }

  //
  // If not recursive, then just return after connecting drivers to ControllerHandle
  //
  if (!Recursive) {
    return ReturnStatus;
  }

  //
  // If recursive, then connect all drivers to all of ControllerHandle's children
  //
  CoreAcquireProtocolLock ();
  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
    for (ProtLink = Prot->OpenList.ForwardLink; 
           ProtLink != &Prot->OpenList; 
           ProtLink = ProtLink->ForwardLink) {
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
          CoreReleaseProtocolLock ();
          Status = CoreConnectController (
                          OpenData->ControllerHandle,
                          NULL,
                          NULL,
                          TRUE
                          ); 
          CoreAcquireProtocolLock ();
        }
    }
  }
  CoreReleaseProtocolLock ();
  
  return ReturnStatus;
}

VOID
AddSortedDriverBindingProtocol (
  IN      EFI_HANDLE                   DriverBindingHandle,
  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols, 
  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
  IN      UINTN                        DriverBindingHandleCount,
  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer
  )
/*++

Routine Description:

  Add Driver Binding Protocols from Context Driver Image Handles to sorted 
   Driver Binding Protocol list.

Arguments:

  DriverBindingHandle - Handle of the driver binding protocol.

  NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols

  SortedDriverBindingProtocols - The sorted protocol list.                        
    
  DriverBindingHandleCount - Driver Binding Handle Count.

  DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.

Returns:

  None.

--*/
{
  EFI_STATUS                   Status;
  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
  UINTN                        Index;

  //
  // Make sure the DriverBindingHandle is valid
  //
  Status = CoreValidateHandle (DriverBindingHandle);
  if (EFI_ERROR (Status)) {
    return;
  }

  //
  // Retrieve the Driver Binding Protocol from DriverBindingHandle
  //
  Status = CoreHandleProtocol(
             DriverBindingHandle,
             &gEfiDriverBindingProtocolGuid,
             &DriverBinding
             );
  //
  // If DriverBindingHandle does not support the Driver Binding Protocol then return
  //
  if (EFI_ERROR (Status) || DriverBinding == NULL) {
    return;
  }

  //
  // See if DriverBinding is already in the sorted list
  //
  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {
    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
      return;
    }
  }

  //
  // Add DriverBinding to the end of the list
  //
  SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;

  //
  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
  //
  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
      DriverBindingHandleBuffer[Index] = NULL;
    }
  }
}
 
STATIC
EFI_STATUS 
CoreConnectSingleController (
  IN  EFI_HANDLE                ControllerHandle,
  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL     
  )
/*++

Routine Description:

  Connects a controller to a driver.

Arguments:

  ControllerHandle            - Handle of the controller to be connected.
  ContextDriverImageHandles   - DriverImageHandle A pointer to an ordered list of driver image handles.
  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child 
                                of the controller specified by ControllerHandle.
    
Returns:

  EFI_SUCCESS           - One or more drivers were connected to ControllerHandle.
  EFI_OUT_OF_RESOURCES  - No enough system resources to complete the request.
  EFI_NOT_FOUND         - No drivers were connected to ControllerHandle.

--*/
{
  EFI_STATUS                                 Status;
  UINTN                                      Index;
  EFI_HANDLE                                 DriverImageHandle;
  UINTN                                      PlatformDriverOverrideHandleCount;
  EFI_HANDLE                                 *PlatformDriverOverrideHandleBuffer;
  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
  UINTN                                      DriverBindingHandleCount;
  EFI_HANDLE                                 *DriverBindingHandleBuffer;
  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
  UINTN                                      NumberOfSortedDriverBindingProtocols;
  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
  UINT32                                     HighestVersion;
  UINTN                                      HighestIndex;
  UINTN                                      SortIndex;
  BOOLEAN                                    OneStarted;
  BOOLEAN                                    DriverFound;

#ifdef EFI_DXE_PERFORMANCE
  EFI_HANDLE                                 DriverBindingHandle;
#endif

  //
  // Initialize local variables
  //
  DriverBindingHandleCount              = 0;
  DriverBindingHandleBuffer             = NULL;
  PlatformDriverOverrideHandleCount     = 0;
  PlatformDriverOverrideHandleBuffer    = NULL;
  NumberOfSortedDriverBindingProtocols  = 0;
  SortedDriverBindingProtocols          = NULL;

  //
  // Get list of all Driver Binding Protocol Instances
  //
  Status = CoreLocateHandleBuffer (
             ByProtocol,   
             &gEfiDriverBindingProtocolGuid,  
             NULL,
             &DriverBindingHandleCount, 
             &DriverBindingHandleBuffer
             );
  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
    return EFI_NOT_FOUND;
  }

  //
  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
  //
  SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
  if (SortedDriverBindingProtocols == NULL) {
    CoreFreePool (DriverBindingHandleBuffer);
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Add Driver Binding Protocols from Context Driver Image Handles first
  //
  if (ContextDriverImageHandles != NULL) {
    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
      AddSortedDriverBindingProtocol (
        ContextDriverImageHandles[Index],
        &NumberOfSortedDriverBindingProtocols, 
        SortedDriverBindingProtocols,
        DriverBindingHandleCount,
        DriverBindingHandleBuffer
        );
    }
  }

  //
  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
  //
  Status = CoreLocateProtocol (
             &gEfiPlatformDriverOverrideProtocolGuid, 
             NULL, 
             &PlatformDriverOverride
             );
  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
    DriverImageHandle = NULL;
    do {
      Status = PlatformDriverOverride->GetDriver (
                                         PlatformDriverOverride,
                                         ControllerHandle,
                                         &DriverImageHandle
                                         );
      if (!EFI_ERROR (Status)) {
        AddSortedDriverBindingProtocol (
          DriverImageHandle,
          &NumberOfSortedDriverBindingProtocols, 
          SortedDriverBindingProtocols,
          DriverBindingHandleCount,
          DriverBindingHandleBuffer
          );
      }
    } while (!EFI_ERROR (Status));
  }

  //
  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
  //
  Status = CoreHandleProtocol(
             ControllerHandle,  
             &gEfiBusSpecificDriverOverrideProtocolGuid, 
             &BusSpecificDriverOverride
             );
  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
    DriverImageHandle = NULL;
    do {
      Status = BusSpecificDriverOverride->GetDriver (
                                            BusSpecificDriverOverride,
                                            &DriverImageHandle
                                            );
      if (!EFI_ERROR (Status)) {
        AddSortedDriverBindingProtocol (
          DriverImageHandle,
          &NumberOfSortedDriverBindingProtocols, 
          SortedDriverBindingProtocols,
          DriverBindingHandleCount,
          DriverBindingHandleBuffer
          );
      }
    } while (!EFI_ERROR (Status));
  }

  //
  // Then add all the remaining Driver Binding Protocols
  //
  SortIndex = NumberOfSortedDriverBindingProtocols;
  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
    AddSortedDriverBindingProtocol (
      DriverBindingHandleBuffer[Index],
      &NumberOfSortedDriverBindingProtocols, 
      SortedDriverBindingProtocols,
      DriverBindingHandleCount,
      DriverBindingHandleBuffer
      );
  }

  //
  // Free the Driver Binding Handle Buffer
  //
  CoreFreePool (DriverBindingHandleBuffer);

  //
  // Sort the remaining DriverBinding Protocol based on their Version field from
  // highest to lowest.
  //
  for ( ; SortIndex < DriverBindingHandleCount; SortIndex++) {
    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
    HighestIndex   = SortIndex;
    for (Index = SortIndex + 1; Index < DriverBindingHandleCount; Index++) {
      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
        HighestIndex   = Index;
      }

⌨️ 快捷键说明

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