driversupport.c

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

C
861
字号
    }
    if (SortIndex != HighestIndex) {
      DriverBinding = SortedDriverBindingProtocols[SortIndex];
      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
    }
  }

  //
  // Loop until no more drivers can be started on ControllerHandle
  //
  OneStarted = FALSE;
  do {

    //
    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
    // any of the Driver Binding Protocols support the controller specified by 
    // ControllerHandle.
    //
    DriverBinding = NULL;
    DriverFound = FALSE;
    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
      if (SortedDriverBindingProtocols[Index] != NULL) {
        DriverBinding = SortedDriverBindingProtocols[Index];
        Status = DriverBinding->Supported(
                                  DriverBinding, 
                                  ControllerHandle,
                                  RemainingDevicePath
                                  );
        if (!EFI_ERROR (Status)) {
          SortedDriverBindingProtocols[Index] = NULL;
          DriverFound = TRUE;

          //
          // A driver was found that supports ControllerHandle, so attempt to start the driver
          // on ControllerHandle.
          //

#ifdef EFI_DXE_PERFORMANCE
          GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
#endif 

          PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
          Status = DriverBinding->Start (
                                    DriverBinding, 
                                    ControllerHandle,
                                    RemainingDevicePath
                                    );
          PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);

          if (!EFI_ERROR (Status)) {
            //
            // The driver was successfully started on ControllerHandle, so set a flag
            //
            OneStarted = TRUE;
          }
        }
      }
    }
  } while (DriverFound);

  //
  // Free any buffers that were allocated with AllocatePool()
  //
  CoreFreePool (SortedDriverBindingProtocols);

  //
  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
  //
  if (OneStarted) {
    return EFI_SUCCESS;
  } 

  //
  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
  //
  if (RemainingDevicePath != NULL) {
    if (IsDevicePathEnd (RemainingDevicePath)) {
      return EFI_SUCCESS;
    }
  } 

  //
  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
  //
  return EFI_NOT_FOUND;
}

EFI_BOOTSERVICE11
EFI_STATUS 
EFIAPI
CoreDisconnectController (
  IN  EFI_HANDLE  ControllerHandle,
  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
  IN  EFI_HANDLE  ChildHandle        OPTIONAL
  )
/*++

Routine Description:

  Disonnects a controller from a driver

Arguments:

  ControllerHandle  - ControllerHandle The handle of the controller from which driver(s) 
                        are to be disconnected.
  DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
  ChildHandle       - ChildHandle The handle of the child to destroy.

Returns:

  EFI_SUCCESS           -  One or more drivers were disconnected from the controller.
  EFI_SUCCESS           -  On entry, no drivers are managing ControllerHandle.
  EFI_SUCCESS           -  DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
  EFI_INVALID_PARAMETER -  ControllerHandle is not a valid EFI_HANDLE.
  EFI_INVALID_PARAMETER -  DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
  EFI_INVALID_PARAMETER -  ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
  EFI_OUT_OF_RESOURCES  -  There are not enough resources available to disconnect any drivers from ControllerHandle.
  EFI_DEVICE_ERROR      -  The controller could not be disconnected because of a device error.

--*/
{
  EFI_STATUS                          Status;
  IHANDLE                             *Handle;
  EFI_HANDLE                          *DriverImageHandleBuffer;
  EFI_HANDLE                          *ChildBuffer;
  UINTN                               Index;
  UINTN                               HandleIndex;
  UINTN                               DriverImageHandleCount;
  UINTN                               ChildrenToStop;
  UINTN                               ChildBufferCount;
  UINTN                               StopCount;
  BOOLEAN                             Duplicate;
  BOOLEAN                             ChildHandleValid;
  BOOLEAN                             DriverImageHandleValid;
  EFI_LIST_ENTRY                      *Link;
  EFI_LIST_ENTRY                      *ProtLink;
  OPEN_PROTOCOL_DATA                  *OpenData;
  PROTOCOL_INTERFACE                  *Prot;
  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;

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

  //
  // Make sure ChildHandle is valid if it is not NULL
  //
  if (ChildHandle != NULL) {
    Status = CoreValidateHandle (ChildHandle);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  Handle = ControllerHandle;

  //
  // Get list of drivers that are currently managing ControllerHandle
  //
  DriverImageHandleBuffer = NULL;
  DriverImageHandleCount  = 1;  
  
  if (DriverImageHandle == NULL) {
    //
    // Look at each protocol interface for a match
    //
    DriverImageHandleCount = 0;

    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_DRIVER) != 0) {
          DriverImageHandleCount++;
        }
      }
    }
    CoreReleaseProtocolLock ();
    
    //
    // If there are no drivers managing this controller, then return EFI_SUCCESS
    //
    if (DriverImageHandleCount == 0) {
      Status = EFI_SUCCESS;
      goto Done;
    }

    DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
    if (DriverImageHandleBuffer == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto Done;
    }

    DriverImageHandleCount = 0;

    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_DRIVER) != 0) {
          Duplicate = FALSE;
          for (Index = 0; Index< DriverImageHandleCount; Index++) {
            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
              Duplicate = TRUE;
              break;
            }
          }
          if (!Duplicate) {
            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
            DriverImageHandleCount++;
          }
        }
      }
    }
    CoreReleaseProtocolLock ();
  }

  StopCount = 0;
  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {

    if (DriverImageHandleBuffer != NULL) {
      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
    }

    //
    // Get the Driver Binding Protocol of the driver that is managing this controller
    //
    Status = CoreHandleProtocol (
               DriverImageHandle,  
               &gEfiDriverBindingProtocolGuid,   
               &DriverBinding
               );
    if (EFI_ERROR (Status)) {
      Status = EFI_INVALID_PARAMETER;
      goto Done;
    }

    //
    // Look at each protocol interface for a match
    //
    DriverImageHandleValid = FALSE;
    ChildBufferCount = 0;

    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->AgentHandle == DriverImageHandle) {
          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
            ChildBufferCount++;
          } 
          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
            DriverImageHandleValid = TRUE;
          }
        }
      }
    }
    CoreReleaseProtocolLock ();

    if (DriverImageHandleValid) {
      ChildHandleValid = FALSE;
      ChildBuffer = NULL;
      if (ChildBufferCount != 0) {
        ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
        if (ChildBuffer == NULL) {
          Status = EFI_OUT_OF_RESOURCES;
          goto Done;
        }

        ChildBufferCount = 0;

        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->AgentHandle == DriverImageHandle) &&
                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
              Duplicate = FALSE;
              for (Index = 0; Index < ChildBufferCount; Index++) {
                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
                  Duplicate = TRUE;
                  break;
                }
              }
              if (!Duplicate) {
                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
                  ChildHandleValid = TRUE;
                }
                ChildBufferCount++;
              }
            }
          }
        }
        CoreReleaseProtocolLock ();
      }

      if (ChildHandle == NULL || ChildHandleValid) {
        ChildrenToStop = 0;
        Status = EFI_SUCCESS;
        if (ChildBufferCount > 0) {
          if (ChildHandle != NULL) {
            ChildrenToStop = 1;
            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
          } else {
            ChildrenToStop = ChildBufferCount;
            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
          }
        }
        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
        }
        if (!EFI_ERROR (Status)) {
          StopCount++;
        }
      }

      if (ChildBuffer != NULL) {
        CoreFreePool (ChildBuffer);
      }
    }
  }

  if (StopCount > 0) {
    Status = EFI_SUCCESS;
  } else {
    Status = EFI_NOT_FOUND;
  }
  
Done:  

  if (DriverImageHandleBuffer != NULL) {
    CoreFreePool (DriverImageHandleBuffer);
  }

  return Status;
}



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

Routine Description:

  Locate the driver binding handle which a specified driver binding protocol installed on.

Arguments:

  DriverBindingNeed  - The specified driver binding protocol.
  
  Handle             - The driver binding handle which the protocol installed on.
  

Returns:

  EFI_NOT_FOUND         - Could not find the handle.
  
  EFI_SUCCESS           - Successfully find the associated driver binding handle.
  
--*/ 
 {
  EFI_STATUS                          Status ;
  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
  UINTN                               DriverBindingHandleCount;
  EFI_HANDLE                          *DriverBindingHandleBuffer;
  UINTN                               Index;
  
  DriverBindingHandleCount = 0;
  DriverBindingHandleBuffer = NULL;
  *Handle = NULL_HANDLE;
  Status = gBS->LocateHandleBuffer (
              ByProtocol,   
              &gEfiDriverBindingProtocolGuid,  
              NULL,
              &DriverBindingHandleCount, 
              &DriverBindingHandleBuffer
              );
  if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
    return EFI_NOT_FOUND;
  }
  
  for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
    Status = gBS->OpenProtocol(
                      DriverBindingHandleBuffer[Index],
                      &gEfiDriverBindingProtocolGuid,
                      &DriverBinding,
                      gDxeCoreImageHandle,
                      NULL,
                      EFI_OPEN_PROTOCOL_GET_PROTOCOL
                      );
                      
   if (!EFI_ERROR (Status) && DriverBinding != NULL) {
    
    if ( DriverBinding == DriverBindingNeed ) {
      *Handle = DriverBindingHandleBuffer[Index];
      CoreFreePool (DriverBindingHandleBuffer);         
      return EFI_SUCCESS ;
    }
   }
 }
 
 CoreFreePool (DriverBindingHandleBuffer);
 return EFI_NOT_FOUND ;
}
#endif

⌨️ 快捷键说明

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