dispatcher.c

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

C
1,192
字号
  DriverEntry->FvHandle         = FvHandle;
  DriverEntry->Fv               = Fv;
  DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName);

  CoreGetDepexSectionAndPreProccess (DriverEntry);
  
  CoreAcquireDispatcherLock ();
  
  InsertTailList (&mDiscoveredList, &DriverEntry->Link);

  CoreReleaseDispatcherLock ();

  return EFI_SUCCESS;
}



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

Routine Description:

  Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle.

Arguments:

  Fv          - The FIRMWARE_VOLUME protocol installed on the FV.
  FvHandle    - The handle which FVB protocol installed on.
  DriverName  - The driver guid specified.

Returns:

  EFI_OUT_OF_RESOURCES    - No enough memory or other resource.
  
  EFI_VOLUME_CORRUPTED    - Corrupted volume.
  
  EFI_SUCCESS             - Function successfully returned.
  

--*/
{
  EFI_STATUS                          Status;
  EFI_SECTION_TYPE                    SectionType;
  UINT32                              AuthenticationStatus;
  VOID                                *Buffer;
  UINTN                               BufferSize;

  //
  // Read the first (and only the first) firmware volume section
  //
  SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
  Buffer      = NULL;
  BufferSize  = 0;
  Status = Fv->ReadSection (
                Fv, 
                DriverName, 
                SectionType, 
                0, 
                &Buffer, 
                &BufferSize,
                &AuthenticationStatus
                );
  if (!EFI_ERROR (Status)) {
    //
    // Produce a FVB protocol for the file
    //
    Status = ProduceFVBProtocolOnBuffer (
              (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,
              (UINT64)BufferSize,
              FvHandle,
              NULL
              );
  }

  if (EFI_ERROR (Status) && (Buffer != NULL)) {    
  //
  // ReadSection or Produce FVB failed, Free data buffer
  //
  gBS->FreePool (Buffer); 

  }

  return Status;
}


VOID
EFIAPI
CoreFwVolEventProtocolNotify (
  IN  EFI_EVENT       Event,
  IN  VOID            *Context
  )
/*++

Routine Description:

  Event notification that is fired every time a FV dispatch protocol is added. 
  More than one protocol may have been added when this event is fired, so you
  must loop on CoreLocateHandle () to see how many protocols were added and
  do the following to each FV:

  If the Fv has already been processed, skip it. If the Fv has not been 
  processed then mark it as being processed, as we are about to process it.

  Read the Fv and add any driver in the Fv to the mDiscoveredList.The 
  mDiscoveredList is never free'ed and contains variables that define
  the other states the DXE driver transitions to.. 
  
  While you are at it read the A Priori file into memory.
  Place drivers in the A Priori list onto the mScheduledQueue.

Arguments:

  Event   - The Event that is being processed, not used.
  
  Context - Event Context, not used.

Returns:

  None

--*/
{
  EFI_STATUS                    Status;
  EFI_STATUS                    GetNextFileStatus;
  EFI_STATUS                    SecurityStatus;
  EFI_FIRMWARE_VOLUME_PROTOCOL  *Fv;
  EFI_DEVICE_PATH_PROTOCOL      *FvDevicePath;
  EFI_HANDLE                    FvHandle;
  UINTN                         BufferSize;
  EFI_GUID                      NameGuid;
  UINTN                         Key;
  EFI_FV_FILETYPE               Type;
  EFI_FV_FILE_ATTRIBUTES        Attributes;
  UINTN                         Size;
  EFI_CORE_DRIVER_ENTRY         *DriverEntry;
  EFI_GUID                      *AprioriFile;
  UINTN                         AprioriEntryCount;
  UINTN                         Index;
  EFI_LIST_ENTRY                *Link;
  UINT32                        AuthenticationStatus;
  UINTN                         SizeOfBuffer;


  while (TRUE) {
    BufferSize = sizeof (EFI_HANDLE);
    Status = CoreLocateHandle (
                    ByRegisterNotify,
                    NULL,
                    mFwVolEventRegistration,
                    &BufferSize,
                    &FvHandle
                    );
    if (EFI_ERROR (Status)) {
      //
      // If no more notification events exit
      //
      return;
    }

    if (FvHasBeenProcessed (FvHandle)) {
      //
      // This Fv has already been processed so lets skip it!
      //
      continue;
    }

    Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, &Fv);
    if (EFI_ERROR (Status)) {
      //
      // If no dispatch protocol then skip, but do not marked as being processed as it
      // may show up later.
      //
      continue;
    }

    //
    // Since we are about to process this Fv mark it as processed.
    //
    FvIsBeingProcesssed (FvHandle);


    Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, &Fv);
    if (EFI_ERROR (Status)) {
      //
      // The Handle has a FirmwareVolumeDispatch protocol and should also contiain
      // a FirmwareVolume protocol thus we should never get here.
      //
      ASSERT (FALSE);
      continue;
    }
    
    Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, &FvDevicePath);
    if (EFI_ERROR (Status)) {
      //
      // The Firmware volume doesn't have device path, can't be dispatched.
      //
      continue;
    }
    
    //
    // Evaluate the authentication status of the Firmware Volume through 
    // Security Architectural Protocol
    //
    if (gSecurity != NULL) {
      SecurityStatus = gSecurity->FileAuthenticationState (
                                    gSecurity, 
                                    0, 
                                    FvDevicePath
                                    );
      if (SecurityStatus != EFI_SUCCESS) {
        //
        // Security check failed. The firmware volume should not be used for any purpose.
        //
        continue;
      }
    }   
    
    //
    // Discover Drivers in FV and add them to the Discovered Driver List. 
    // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 
    //  EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core
    //  EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb
    //
    for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {
      //
      // Initialize the search key
      //
      Key = 0;
      do {
        Type = mDxeFileTypes[Index];
        GetNextFileStatus = Fv->GetNextFile (
                                  Fv, 
                                  &Key,
                                  &Type,  
                                  &NameGuid, 
                                  &Attributes, 
                                  &Size
                                  );
        if (!EFI_ERROR (GetNextFileStatus)) {
          if (Type == EFI_FV_FILETYPE_DXE_CORE) {
            //
            // If this is the DXE core fill in it's DevicePath & DeviceHandle
            //
            if (gDxeCoreLoadedImage->FilePath == NULL) {
              if (EfiCompareGuid (&NameGuid, gDxeCoreFileName)) {
			  	CoreInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);
                mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH;
                mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
                SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL));

                gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath (
                                                  (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
                                                  );
                gDxeCoreLoadedImage->DeviceHandle = FvHandle;
              }
            }
          } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
            //
            // Found a firmware volume image. Produce a firmware volume block
            // protocol for it so it gets dispatched from. This is usually a 
            // capsule.
            //
            CoreProcessFvImageFile (Fv, FvHandle, &NameGuid);
          } else {
            //
            // Transition driver from Undiscovered to Discovered state
            //
            CoreAddToDriverList (Fv, FvHandle, &NameGuid);
          }
        }
      } while (!EFI_ERROR (GetNextFileStatus));
    }
    
    //
    // Read the array of GUIDs from the Apriori file if it is present in the firmware volume
    //
    AprioriFile = NULL;
    Status = Fv->ReadSection (
                  Fv,
                  &gAprioriGuid,
                  EFI_SECTION_RAW,
                  0,
                  &AprioriFile,
                  &SizeOfBuffer,
                  &AuthenticationStatus
                  );
    if (!EFI_ERROR (Status)) {
      AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID);
    } else {
      AprioriEntryCount = 0;
    }

    //
    // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes
    // drivers not in the current FV and these must be skipped since the a priori list
    // is only valid for the FV that it resided in.
    //
    CoreAcquireDispatcherLock ();
    
    for (Index = 0; Index < AprioriEntryCount; Index++) {
      for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {
        DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
        if (EfiCompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&
            (FvHandle == DriverEntry->FvHandle)) {
          DriverEntry->Dependent = FALSE;
          DriverEntry->Scheduled = TRUE;
          InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);
          break;
        }
      }
    }

    CoreReleaseDispatcherLock ();

    //
    // Free data allocated by Fv->ReadSection () 
    //
    gBS->FreePool (AprioriFile);  
  }
}


VOID
CoreInitializeDispatcher (
  VOID
  )
/*++

Routine Description:

  Initialize the dispatcher. Initialize the notification function that runs when
  a FV protocol is added to the system.

Arguments:

  NONE

Returns:

  NONE 

--*/
{
  mFwVolEvent = CoreCreateProtocolNotifyEvent (
                  &gEfiFirmwareVolumeProtocolGuid, 
                  EFI_TPL_CALLBACK,
                  CoreFwVolEventProtocolNotify,
                  NULL,
                  &mFwVolEventRegistration,
                  TRUE
                  );
}

//
// Function only used in debug buils
//
DEBUG_CODE (
VOID
CoreDisplayDiscoveredNotDispatched (
  VOID
  )
/*++

Routine Description:

  Traverse the discovered list for any drivers that were discovered but not loaded 
  because the dependency experessions evaluated to false

Arguments:

  NONE

Returns:

  NONE 

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

  for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) {
    DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE);
    if (DriverEntry->Dependent) {
      DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName));
    }
  }
}
)

⌨️ 快捷键说明

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