uefi 调用ExitBootServices

本文详细介绍了在UEFI环境中如何使用CreateEventEx创建事件并监听ExitBootServices事件,以便在内核启动的最后阶段执行特定操作。此外,还解释了如何在CoreExitBootServices函数中触发该事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所有的boot service 都会在进入kernel的最后阶段退出,如果driver想接受这一个event的话,可以参考下面的写法创建一个新的event,注意一定要是 gEfiEventExitBootServicesGuid
Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  XhcExitBootService,
                  Xhc,
                  &gEfiEventExitBootServicesGuid,
                  &Xhc->ExitBootServiceEvent
                  );
  if (EFI_ERROR (Status)) {
    goto FREE_POOL;
  }

这样当调用CoreExitBootServices 是
EFI_STATUS
EFIAPI
CoreExitBootServices (
  IN EFI_HANDLE   ImageHandle,
  IN UINTN        MapKey
  )
{
  EFI_STATUS                Status;

  //
  // Disable Timer
  //
  gTimer->SetTimerPeriod (gTimer, 0);

  //
  // Terminate memory services if the MapKey matches
  //
  Status = CoreTerminateMemoryMap (MapKey);
  if (EFI_ERROR (Status)) {
    //
    // Notify other drivers that ExitBootServices fail
    //
    CoreNotifySignalList (&gEventExitBootServicesFailedGuid);
    return Status;
  }

  gMemoryMapTerminated = TRUE;

  //
  // Notify other drivers that we are exiting boot services.
  //
  CoreNotifySignalList (&gEfiEventExitBootServicesGuid);

  //
  // Report that ExitBootServices() has been called
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)
    );

  //
  // Disable interrupt of Debug timer.
  //
  SaveAndSetDebugTimerInterrupt (FALSE);

  //
  // Disable CPU Interrupts
  //
  gCpu->DisableInterrupt (gCpu);

  //
  // Clear the non-runtime values of the EFI System Table
  //
  gDxeCoreST->BootServices        = NULL;
  gDxeCoreST->ConIn               = NULL;
  gDxeCoreST->ConsoleInHandle     = NULL;
  gDxeCoreST->ConOut              = NULL;
  gDxeCoreST->ConsoleOutHandle    = NULL;
  gDxeCoreST->StdErr              = NULL;
  gDxeCoreST->StandardErrorHandle = NULL;

  //
  // Recompute the 32-bit CRC of the EFI System Table
  //
  CalculateEfiHdrCrc (&gDxeCoreST->Hdr);

  //
  // Zero out the Boot Service Table
  //
  ZeroMem (gBS, sizeof (EFI_BOOT_SERVICES));
  gBS = NULL;

  //
  // Update the AtRuntime field in Runtiem AP.
  //
  gRuntime->AtRuntime = TRUE;

  return Status;
}
在CoreExitBootServices 中调用CoreNotifySignalList 来将要通知的event 添加到queue中
VOID
CoreNotifySignalList (
  IN EFI_GUID     *EventGroup
  )
{
  LIST_ENTRY              *Link;
  LIST_ENTRY              *Head;
  IEVENT                  *Event;

  CoreAcquireEventLock ();

  Head = &gEventSignalQueue;
  for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {
    Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE);
    if (CompareGuid (&Event->EventGroup, EventGroup)) {
      CoreNotifyEvent (Event);
    }
  }

  CoreReleaseEventLock ();
}
CoreNotifySignalList 通过CompareGuid来比较guid是否是gEfiEventExitBootServicesGuid。如果是的话,就调用CoreNotifyEvent
VOID
CoreNotifyEvent (
  IN  IEVENT      *Event
  )
{

  //
  // Event database must be locked
  //
  ASSERT_LOCKED (&gEventQueueLock);

  //
  // If the event is queued somewhere, remove it
  //

  if (Event->NotifyLink.ForwardLink != NULL) {
    RemoveEntryList (&Event->NotifyLink);
    Event->NotifyLink.ForwardLink = NULL;
  }

  //
  // Queue the event to the pending notification list
  //

  InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink);
  gEventPending |= (UINTN)(1 << Event->NotifyTpl);
}
在CoreNotifyEvent 中就会将event添加到gEventQueue 这个queue中,并在gEventPending 之根据event的tpl 将对应的bit置1.
然后会在下一次time中断中调用CoreRestoreTpl。
VOID
EFIAPI
CoreRestoreTpl (
  IN EFI_TPL NewTpl
  )
{

  while (((-2 << NewTpl) & gEventPending) != 0) {
    gEfiCurrentTpl = (UINTN) HighBitSet64 (gEventPending);
    if (gEfiCurrentTpl < TPL_HIGH_LEVEL) {
      CoreSetInterruptState (TRUE);
    }
    CoreDispatchEventNotifies (gEfiCurrentTpl);
  }

}
这个函数中就会检测gEventPending 只能个是否有置位,如果有的话,就调用CoreDispatchEventNotifies
CoreDispatchEventNotifies (
  IN EFI_TPL      Priority
  )
{
  IEVENT          *Event;
  LIST_ENTRY      *Head;

  CoreAcquireEventLock ();
  ASSERT (gEventQueueLock.OwnerTpl == Priority);
  Head = &gEventQueue[Priority];

  //
  // Dispatch all the pending notifications
  //
  while (!IsListEmpty (Head)) {

    Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE);
    RemoveEntryList (&Event->NotifyLink);

    Event->NotifyLink.ForwardLink = NULL;

    //
    // Only clear the SIGNAL status if it is a SIGNAL type event.
    // WAIT type events are only cleared in CheckEvent()
    //
    if ((Event->Type & EVT_NOTIFY_SIGNAL) != 0) {
      Event->SignalCount = 0;
    }

    CoreReleaseEventLock ();

    //
    // Notify this event
    //
    ASSERT (Event->NotifyFunction != NULL);
    Event->NotifyFunction (Event, Event->NotifyContext);

    //
    // Check for next pending event
    //
    CoreAcquireEventLock ();
  }

  gEventPending &= ~(UINTN)(1 << Priority);
  CoreReleaseEventLock ();
}
这个函数中就会遍历整个gEventQueue 分别调用其NotifyFunction函数.
### UEFI 的运行环境及其所在硬件/软件层 UEFI(统一可扩展固件接口)是一种位于硬件与操作系统之间的中间层技术,主要用于替代传统 BIOS 提供更加灵活高效的系统引导过程。具体而言,UEFI 主要运行在一个特殊的硬件抽象层之上,并且紧密依赖于底层硬件的支持。 #### 1. **硬件层面的位置** 在物理架构中,UEFI 固件通常驻留在主板上的闪存芯片里[^1]。这些芯片保存了必要的启动代码以及配置设置等内容。每当机器通电之后,CPU 就会从这里读取初始指令开始执行一系列预定的操作序列直到最终将控制权移交给高级别的操作系统为止。 #### 2. **软件层次中的角色** - **启动前阶段 (Pre-boot Environment)** 此时期间,UEFI 处理所有基本外围设备初始化工作,例如键盘鼠标控制器、显示适配器等等;同时还会扫描可用存储介质寻找合适的 EFI 系统分区(ESP),从中加载相应的 Bootloader 映像文件[^3]。 - **移交至 OS 加载程序** 当找到合法的目标镜像后,通过调用 ExitBootServices API 函数结束自身的主导地位并将后续任务完全交由选定好的 OS Loader 完成剩余部分的工作流——即实际意义上的“操作系统接管”时刻到来之前的一瞬间。 #### 3. **与其他组件的关系** 相较于旧式的 Legacy BIOS 模型,新的 UEFI 规范定义了一套全新的应用程序编程接口(APIs)集合允许开发者创建独立的小型实用工具甚至完整的操作系统内核直接在其基础上构建而无需关心太多低级细节差异[^2]。这使得整个计算生态变得更加开放兼容同时也增强了安全防护能力比如 Secure Boot 功能便是建立在这种设计理念之上的典型代表案例之一。 综上所述,UEFI 属于介于裸机状态和完整运作态之间的一个过渡桥梁性质的存在形式,既依托特定种类的实体电路单元又服务于更高阶逻辑运算需求构成了当代个人电脑体系结构不可或缺的一部分组成部分。 ```python # 示例伪代码展示简单的 UEFI 启动流程概览 def uefi_boot_process(): initialize_hardware_components() esp_partition = locate_efi_system_partition() bootloader_image = load_bootloader_from_esp(esp_partition) exit_boot_services() transfer_control_to_os_loader(bootloader_image) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值