DxeMain中driver的加载流程

1、创建 gEfiFirmwareVolumeBlockProtocolGuid 类型的 Protocol 实例
在 ./MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c 文件的第 487 行调用了 FwVolBlockDriverInit() 函数,
其定义在 MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c 中:

EFI_STATUS
EFIAPI
FwVolBlockDriverInit (
    IN EFI_HANDLE ImageHandle,
    IN EFI_SYSTEM_TABLE *SystemTable
)
{
    ...
    //
    // Produce an FVB protocol for it
    //
    ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, AuthenticationStatus, NULL);
    ...
}

其中 ProduceFVBProtocolOnBuffer() 定义在 MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c 中:

EFI_STATUS
ProduceFVBProtocolOnBuffer (
    IN EFI_PHYSICAL_ADDRESS BaseAddress,
    IN UINT64 Length,
    IN EFI_HANDLE ParentHandle,
    IN UINT32 AuthenticationStatus,
    OUT EFI_HANDLE *FvProtocol OPTIONAL
)
{
    ...
    //
    //
    // Attach FvVolBlock Protocol to new handle
    //
    Status = CoreInstallMultipleProtocolInterfaces (
                &FvbDev->Handle,
                &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDev->FwVolBlockInstance,
                &gEfiDevicePathProtocolGuid, FvbDev->DevicePath,
                NULL
                );
    ...
}

上述 CoreInstallMultipleProtocolInterfaces() 函数创建了gEfiFirmwareVolumeBlockProtocolGuid 类型的 Protocol 实例。

2、创建 gEfiFirmwareVolume2ProtocolGuid 类型的 Protocol 实例
1)注册 gEfiFirmwareVolumeBlockProtocolGuid 实例的通知事件
在 ./MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c 文件中的第 239 行调用了 FwVolDriverInit(),

VOID
EFIAPI
DxeMain (
    IN VOID *HobStart
)
{
    ...
    Status = FwVolDriverInit (gDxeCoreImageHandle, gDxeCoreST);
    ...
}

其中,FwVolDriverInit() 定义在MdeModulePkg/Core/Dxe/FwVol/FwVol.c 文件中:

EFI_STATUS
EFIAPI
FwVolDriverInit (
    IN EFI_HANDLE ImageHandle,
    IN EFI_SYSTEM_TABLE *SystemTable
)
{
    gEfiFwVolBlockEvent = EfiCreateProtocolNotifyEvent (
                            &gEfiFirmwareVolumeBlockProtocolGuid,
                            TPL_CALLBACK,
                            NotifyFwVolBlock,
                            NULL,
                            &gEfiFwVolBlockNotifyReg
                            );
    return EFI_SUCCESS;
}

它注册了一个针对 gEfiFirmwareVolumeBlockProtocolGuid 类型的 Protocol 实例的通知事件,当这个函数被调用后,将会对系统中已存在的每一个 gEfiFirmwareVolumeBlockProtocolGuid 类型的 Protocol 实例调用 NotifyFwVolBlock(),由于上面已经创建了该类型的实例,所以 NotifyFwVolBlock() 会很快被调用。
其中,NotifyFwVolBlock() 定义在 MdeModulePkg/Core/Dxe/FwVol/FwVol.c

VOID
EFIAPI
NotifyFwVolBlock (
    IN EFI_EVENT Event,
    IN VOID *Context
)
{
    ...
    //
    // Get the FirmwareVolumeBlock protocol on that handle
    //
    Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
    ...
    //
    // Install an New FV protocol on the existing handle
    //
    Status = CoreInstallProtocolInterface (
                &Handle,
                &gEfiFirmwareVolume2ProtocolGuid,
                EFI_NATIVE_INTERFACE,
                &FvDevice->Fv
                );
    ...
}

上述 CoreInstallProtocolInterface() 函数创建了gEfiFirmwareVolume2ProtocolGuid 类型的 Protocol 实例。

2)注册 gEfiFirmwareVolume2ProtocolGuid 类型的 Protocol 实例的通知事件
在 ./MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c 文件中的第 503 行调用了 CoreInitializeDispatcher(),
其定义在 MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c 中:

VOID
CoreInitializeDispatcher (
    VOID
)
{
    mFwVolEvent = EfiCreateProtocolNotifyEvent (
                    &gEfiFirmwareVolume2ProtocolGuid,
                    TPL_CALLBACK,
                    CoreFwVolEventProtocolNotify,
                    NULL,
                    &mFwVolEventRegistration
                    );
}

它注册了一个针对 gEfiFirmwareVolume2ProtocolGuid 类型的 Protocol 实例的通知事件,当这个函数被调用后,将会对系统中已存在的每一个 gEfiFirmwareVolume2ProtocolGuid 类型的 Protocol 实例调用 CoreFwVolEventProtocolNotify(),由于上面已经创建了该类型的实例,所以 CoreFwVolEventProtocolNotify() 会很快被调用。
其中,CoreFwVolEventProtocolNotify() 定义在 MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c 中:

VOID
EFIAPI
CoreFwVolEventProtocolNotify (
    IN EFI_EVENT Event,
    IN VOID *Context
)
{
    ...
    //
    // 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
                                );
        ...
        CoreAddToDriverList (Fv, FvHandle, &NameGuid, Type);
        ...
}

上述函数会去查找 FV 中的各个 driver,并通过 CoreAddToDriverList() 将找到的 driver 依次加入到 mDiscoveredList 链表中。

3、加载 driver
在 ./MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c 文件中的第 510 行调用了 CoreDispatcher() 函数
其定义在 MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c 文件中:

EFI_STATUS
EFIAPI
CoreDispatcher (
    VOID
)
{
    ...
    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 && !DriverEntry->IsFvImage) {
                DEBUG ((DEBUG_INFO, "Loading driver %g\n", &DriverEntry->FileName));
                Status = CoreLoadImage (
                            FALSE,
                            gDxeCoreImageHandle,
                            DriverEntry->FvFileDevicePath,
                            NULL,
                            0,
                            &DriverEntry->ImageHandle
                            );

            ...
            //
            // 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);
                ...
                CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);
                ...
}

上述函数将加载队列 mScheduledQueue 中的驱动,该队列中的元素由 CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter() 函数从链表 mDiscoveredList 中取出,再将其放入队列 mScheduledQueue 中。












 

猜你喜欢

转载自blog.csdn.net/choumin/article/details/112505555
今日推荐