代码分析UEFI的执行流程

UEFI的运行阶段

UEFI启动流程
本文的分析只会涉及到DXE之后的阶段,前面的略过。

DXE 阶段

DXE阶段的实现函数在edk2的MdeModulePkg/Core/Dxe/DxeMain目录中,主入口函数为:

 VOID  EFIAPI  DxeMain (   IN  VOID *HobStart   )
{
......

  gBds->Entry (gBds);    //DXE的最后调用BDS的主入口函数
 //
 // BDS should never return
 //
 ASSERT (FALSE);
 CpuDeadLoop ();
 UNREACHABLE ();

}

在该函数中会调用各个DXE driver的入口函数,并且在函数的最后调用BDS的入口函数,进入BDS运行阶段。实际上BDS对于DXE来说也就是一个DXE Driver,它会在Driver初始化时注册BDS Procotol。然后在DXE的最后调用该procotol进入BDS阶段,实际上gBds对应的就是gEfiBdsArchProtocolGuid这个Procotol,这个gBds的定义在 MdeModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c 文件中:


EFI_CORE_PROTOCOL_NOTIFY_ENTRY  mArchProtocols[] = {
  { &gEfiSecurityArchProtocolGuid,         (VOID **)&gSecurity,      NULL, NULL, FALSE },
  { &gEfiCpuArchProtocolGuid,              (VOID **)&gCpu,           NULL, NULL, FALSE },
  { &gEfiMetronomeArchProtocolGuid,        (VOID **)&gMetronome,     NULL, NULL, FALSE },
  { &gEfiTimerArchProtocolGuid,            (VOID **)&gTimer,         NULL, NULL, FALSE },
  { &gEfiBdsArchProtocolGuid,              (VOID **)&gBds,           NULL, NULL, FALSE },
  { &gEfiWatchdogTimerArchProtocolGuid,    (VOID **)&gWatchdogTimer, NULL, NULL, FALSE },
  { &gEfiRuntimeArchProtocolGuid,          (VOID **)&gRuntime,       NULL, NULL, FALSE },
  { &gEfiVariableArchProtocolGuid,         (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiVariableWriteArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiCapsuleArchProtocolGuid,          (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiResetArchProtocolGuid,            (VOID **)NULL,            NULL, NULL, FALSE },
  { &gEfiRealTimeClockArchProtocolGuid,    (VOID **)NULL,            NULL, NULL, FALSE },
  { NULL,                                  (VOID **)NULL,            NULL, NULL, FALSE }
};

BDS阶段

UEFI运行到DXE阶段的最后,会调用BDS Procotol Entry来进入到BDS阶段(boot device select),前面提到BDS也是一个DXE的driver,它的实现是平台相关的,edk2主线分支上的实现有一个:

MdeModulePkg/Universal/BdsDxe

而在高通平台上BDS的实现使用的是如下目录中的:


QcomPkg/Drivers/QcomBds

以它BdsDxe驱动作为例子,它的主要目的是注册一个Procotol到DXECore中,DXECore最后会触发Procotol的Entry操作,而该操作的内容就是执行BDS阶段的任务。

///
/// BDS arch protocol instance initial value.
///
EFI_BDS_ARCH_PROTOCOL  gBds = {
  BdsEntry
};




 EFI_STATUS
 EFIAPI
 BdsInitialize (
   IN EFI_HANDLE                            ImageHandle,
   IN EFI_SYSTEM_TABLE                      *SystemTable
   )
 {
   EFI_STATUS  Status;
   EFI_HANDLE  Handle;
   //
   // Install protocol interface
   //
   Handle = NULL;
   Status = gBS->InstallMultipleProtocolInterfaces (
                   &Handle,
                   &gEfiBdsArchProtocolGuid, &gBds,
                   NULL
                   );
   ASSERT_EFI_ERROR (Status);
 
   DEBUG_CODE (
     EFI_EVENT   Event;
     //
     // Register notify function to check deferred images on ReadyToBoot Event.
     //
     Status = gBS->CreateEventEx (
                     EVT_NOTIFY_SIGNAL,
                     TPL_CALLBACK,
                     CheckDeferredLoadImageOnReadyToBoot,
                     NULL,
                     &gEfiEventReadyToBootGuid,
                     &Event
                     );
     ASSERT_EFI_ERROR (Status);
   );
   return Status;
 }

它会注册一个procotol到DXECore,而具体调用的地方在DXE Main的最后:

  gBds->Entry (gBds);    //DXE的最后调用BDS的主入口函数

该procotol的Guid为gEfiBdsArchProtocolGuid,进入BDS阶段的入口为BdsEntry,它主要做的任务是:加载和启动kernel。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值