dispatcher.c

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

C
1,192
字号
  EFI_NOT_FOUND       - No DXE Drivers were dispatched

  EFI_SUCCESS         - One or more DXE Drivers were dispatched

--*/
{
  EFI_STATUS                      Status;
  EFI_STATUS                      ReturnStatus;
  EFI_LIST_ENTRY                  *Link;
  EFI_CORE_DRIVER_ENTRY           *DriverEntry;
  BOOLEAN                         ReadyToRun;
  UINT8                           Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
  EFI_STATUS_CODE_DATA            *StatusCodeData;
  EFI_DEVICE_HANDLE_EXTENDED_DATA *DeviceHandleExtData;

  DeviceHandleExtData = (EFI_DEVICE_HANDLE_EXTENDED_DATA *) Buffer;
  StatusCodeData = (EFI_STATUS_CODE_DATA *) Buffer;
  DeviceHandleExtData->DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
  DeviceHandleExtData->DataHeader.Size = 
                      sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) -
                      sizeof (EFI_STATUS_CODE_DATA);

  EfiCommonLibCopyMem (
    &DeviceHandleExtData->DataHeader.Type,
    &gEfiStatusCodeSpecificDataGuid, 
    sizeof (EFI_GUID)
    );

  if (mDispatcherRunning) {
    //
    // If the dispatcher is running don't let it be restarted.
    //
    return EFI_ALREADY_STARTED;
  }

  mDispatcherRunning = TRUE;


  ReturnStatus = EFI_NOT_FOUND;
  do {
    //
    // Drain the Scheduled Queue
    //
    while (!IsListEmpty (&mScheduledQueue)) {
      DriverEntry = CR (
                      mScheduledQueue.ForwardLink,
                      EFI_CORE_DRIVER_ENTRY,
                      ScheduledLink,
                      EFI_CORE_DRIVER_ENTRY_SIGNATURE
                      );

      //
      // Load the DXE Driver image into memory. If the Driver was transitioned from
      // Untrused to Scheduled it would have already been loaded so we may need to
      // skip the LoadImage
      //
      if (DriverEntry->ImageHandle == NULL) {
        Status = CoreLoadImage (
                        FALSE,
                        gDxeCoreImageHandle, 
                        DriverEntry->FvFileDevicePath,
                        NULL, 
                        0, 
                        &DriverEntry->ImageHandle
                        );

        //
        // Update the driver state to reflect that it's been loaded
        //
        if (EFI_ERROR (Status)) {
          CoreAcquireDispatcherLock ();

          if (Status == EFI_SECURITY_VIOLATION) {
            //
            // Take driver from Scheduled to Untrused state
            //
            DriverEntry->Untrusted = TRUE;
          } else {
            //
            // The DXE Driver could not be loaded, and do not attempt to load or start it again.
            // Take driver from Scheduled to Initialized. 
            //
            // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned
            //
            DriverEntry->Initialized  = TRUE;
          }

          DriverEntry->Scheduled = FALSE;
          RemoveEntryList (&DriverEntry->ScheduledLink);
          
          CoreReleaseDispatcherLock ();
        
          //
          // If it's an error don't try the StartImage
          //
          continue;
        }
      }

      CoreAcquireDispatcherLock ();

      DriverEntry->Scheduled    = FALSE;
      DriverEntry->Initialized  = TRUE;
      RemoveEntryList (&DriverEntry->ScheduledLink);
      
      CoreReleaseDispatcherLock ();

      //
      // Report Status Code here to notify drivers has 
      // been initialized (INIT_BEGIN)
      //
      EfiCommonLibCopyMem (
        &DeviceHandleExtData->Handle,
        &DriverEntry->ImageHandle,
        sizeof (EFI_HANDLE)
        );

      CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle);

      Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL);

      CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle);
  
      ReturnStatus = EFI_SUCCESS;
    }

    //
    // Search DriverList for items to place on Scheduled Queue
    //
    ReadyToRun = FALSE;
    for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
      DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);

      if (DriverEntry->DepexProtocolError){
    //
        // If Section Extraction Protocol did not let the Depex be read before retry the read
    //
        Status = CoreGetDepexSectionAndPreProccess (DriverEntry);
      } 

      if (DriverEntry->Dependent) {
        if (CoreIsSchedulable (DriverEntry)) {
          CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry); 
          ReadyToRun = TRUE;
        } 
      }
    }
  } while (ReadyToRun);

  mDispatcherRunning = FALSE;

  return ReturnStatus;
}


VOID
CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
  IN  EFI_CORE_DRIVER_ENTRY   *InsertedDriverEntry
  )
/*++

Routine Description:

  Insert InsertedDriverEntry onto the mScheduledQueue. To do this you 
  must add any driver with a before dependency on InsertedDriverEntry first.
  You do this by recursively calling this routine. After all the Befores are
  processed you can add InsertedDriverEntry to the mScheduledQueue. 
  Then you can add any driver with an After dependency on InsertedDriverEntry 
  by recursively calling this routine.

Arguments:

  InsertedDriverEntry - The driver to insert on the ScheduledLink Queue

Returns:

  NONE 

--*/
{
  EFI_LIST_ENTRY        *Link;
  EFI_CORE_DRIVER_ENTRY *DriverEntry;

  //
  // Process Before Dependency
  //
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
    if (DriverEntry->Before && DriverEntry->Dependent) {
      if (EfiCompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
        //
        // Recursively process BEFORE
        //
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
      }
    }
  }

  //
  // Convert driver from Dependent to Scheduled state
  //
  CoreAcquireDispatcherLock ();

  InsertedDriverEntry->Dependent = FALSE;
  InsertedDriverEntry->Scheduled = TRUE;
  InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink);
  
  CoreReleaseDispatcherLock ();

  //
  // Process After Dependency
  //
  for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
    if (DriverEntry->After && DriverEntry->Dependent) {
      if (EfiCompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {
        //
        // Recursively process AFTER
        //
        CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
      }
    }
  }
}


BOOLEAN
FvHasBeenProcessed (
  IN  EFI_HANDLE      FvHandle
  )
/*++

Routine Description:

  Return TRUE if the Fv has been processed, FALSE if not.

Arguments:

  FvHandle - The handle of a FV that's being tested

Returns:

  TRUE  - Fv protocol on FvHandle has been processed

  FALSE - Fv protocol on FvHandle has not yet been processed

--*/
{
  EFI_LIST_ENTRY  *Link;
  KNOWN_HANDLE    *KnownHandle;

  for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {
    KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);
    if (KnownHandle->Handle == FvHandle) {
      return TRUE;
    }
  }
  return FALSE;
}


VOID
FvIsBeingProcesssed (
  IN  EFI_HANDLE    FvHandle
  )
/*++

Routine Description:

  Remember that Fv protocol on FvHandle has had it's drivers placed on the
  mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are
  never removed/freed from the mFvHandleList.

Arguments:

  FvHandle - The handle of a FV that has been processed

Returns:

  None

--*/
{
  KNOWN_HANDLE  *KnownHandle;

  KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE));
  ASSERT (KnownHandle != NULL);

  KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;
  KnownHandle->Handle = FvHandle;
  InsertTailList (&mFvHandleList, &KnownHandle->Link);
}




EFI_DEVICE_PATH_PROTOCOL *
CoreFvToDevicePath (
  IN  EFI_FIRMWARE_VOLUME_PROTOCOL    *Fv,
  IN  EFI_HANDLE                      FvHandle,
  IN  EFI_GUID                        *DriverName
  )
/*++

Routine Description:

  Convert FvHandle and DriverName into an EFI device path

Arguments:

  Fv         - Fv protocol, needed to read Depex info out of FLASH.
  
  FvHandle   - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
               PE image can be read out of the FV at a later time.

  DriverName - Name of driver to add to mDiscoveredList.

Returns:

  Pointer to device path constructed from FvHandle and DriverName

--*/
{
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_PROTOCOL            *FvDevicePath;
  EFI_DEVICE_PATH_PROTOCOL            *FileNameDevicePath;

  //
  // Remember the device path of the FV
  //
  Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, &FvDevicePath);
  if (EFI_ERROR (Status)) {
    FileNameDevicePath = NULL;
  } else {
    //
    // Build a device path to the file in the FV to pass into gBS->LoadImage
    //
    CoreInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
    mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
    mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
    SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));
    FileNameDevicePath = CoreAppendDevicePath (
                            FvDevicePath, 
                            (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
                            );
  }

  return FileNameDevicePath;
}



EFI_STATUS
CoreAddToDriverList (
  IN  EFI_FIRMWARE_VOLUME_PROTOCOL    *Fv,
  IN  EFI_HANDLE                      FvHandle,
  IN  EFI_GUID                        *DriverName
  )
/*++

Routine Description:

  Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry, 
  and initilize any state variables. Read the Depex from the FV and store it
  in DriverEntry. Pre-process the Depex to set the SOR, Before and After state.
  The Discovered list is never free'ed and contains booleans that represent the
  other possible DXE driver states.

Arguments:

  Fv         - Fv protocol, needed to read Depex info out of FLASH.
  
  FvHandle   - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the
               PE image can be read out of the FV at a later time.

  DriverName - Name of driver to add to mDiscoveredList.

Returns:

  EFI_SUCCESS - If driver was added to the mDiscoveredList.

  EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName
                        may be active in the system at any one time.

--*/
{
  EFI_CORE_DRIVER_ENTRY               *DriverEntry;

 
  //
  // Create the Driver Entry for the list. ZeroPool initializes lots of variables to 
  // NULL or FALSE.
  //
  DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY));
  ASSERT (DriverEntry != NULL);

  DriverEntry->Signature        = EFI_CORE_DRIVER_ENTRY_SIGNATURE;
  EfiCommonLibCopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID));

⌨️ 快捷键说明

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