1、概述

BDS全称:Boot Dev Select(启动设备选择)
主要功能是加载并连接驱动程序,管理并启动引导项。在引导操作系统之前会初始化设备(USB键盘鼠标,VGA设备等),然后通过Variable功能来控制启动顺序,根据启动策略加载对应的引导项,启动操作系统或应用程序。
BDS主要功能:
• 加载设备驱动程序
• 初始化控制台设备
• 创建引导启动项
• 启动操作系统或应用程序
如果加载启动项失败,系统将重新执行DXE dispatcher 以加载更多的驱动,然后重新尝试加载启动项。
BDS策略通过全局NVRAM变量配置。这些变量可以通过运行时服务的GetVariable()读取,通过SetVariable() 设置。例如,变量BootOrder定义了启动顺序,变量Boot###定义了各个启动项。
用户选中某个启动项(或系统进入默认的启动项)后,OS Loader 启动,系统进入TSL阶段。

2、如何进入BDS阶段

  此模块为BDS阶段- BdsEntry生成主入口。 当DxeCore分派此模块时,gEfiBdsArchProtocolGuid将被安装 ,包含BdsEntry接口。 DxeCore完成DXE阶段后,gEfiBdsArchProtocolGuid->BdsEntry将被调用。
通过方法BdsEntry();

  1. • 构造函数 安装 gEfiBdsArchProtocolGuid Protocol
  2. • DxeMain.c
    1. 文件最上面对gBS,gST,gRT全局变量进行初始化
    2. DxeMain()
      //函数结尾调用
      gBds->Entry (gBds);
  3. • BdsDxe.inf
    MODULE_TYPE = DXE_DRIVER
    ENTRY_POINT = BdsInitialize

3、BdsEntry()

3.1 代码流程

  1. 设置厂商及版本号
  2. 校验Variable,如果异常则进行删除
  3. 获取进度条时间
  4. 设置默认语言
  5. 前平台初始化
  6. 初始化热键服务
  7. 处理驱动程序
  8. 连接所有控制台设备
  9. 后平台初始化
  10. 获取启动菜单
  11. 判断是否进入Setup
  12. 等待按键按下,如果按键按下则,启动对应引导项
  13. 判断BootNext,如果不为空,则启动对应引导项
  14. 根据启动顺序依次尝试启动
    要想理解BDS的启动流程,主要理解两部分 Connect Controller和Boot
    Manger

3.2 Connect Controller

3.2.1 驱动初始化过程

  1. 硬件相关初始化(大部分在PEI阶段或DXE阶段进行)
  2. 前平台初始化中添加Driver####并更新DriverOrder
  3. 根据DriverOrder获取Driver####存储的DriverOption
  4. 根据DriverOption中的DevicePath进行Connect
  5. 加载DriverOption中DevicePath对应的Image,并运行该Image
  6. Disconnect Controller All
  7. 连接控制台
  8. Connect Controller All
  9. 连接控制台
  10. 后平台相关初始化,如串口等设备进行连接
    •gBS->ConnectController()
    • 排序
    • 连接
    将驱动安装到指定的设备控制器
    • gBS->DisconnectController
    将驱动从指定的设备控制器上卸载
    .驱动初始化源码分析
|--> BdsEntry()|--> PlatformBootManagerBeforeConsole()            //前平台初始化|--> LoadOptions = EfiBootManagerGetLoadOptions()  //获取所有的DeviceOption|--> ProcessLoadOptions(LoadOptions)|--> for EfiBootManagerProcessLoadOption(LoadOptions)|--> EfiBootManagerConnectDevicePath(LoadOption->FilePath)  //Connect DevicePath|--> while|--> BmGetNextLoadOptionBuffer(LoadOption->FilePath)      //Image|--> gBS->LoadImage()|--> gBS->StartImage()|--> EfiBootManagerDisconnectAll()|--> EfiBootManagerConnectAll()
|--> PlatformBootManagerAfterConsole()

3.2.2 优先级顺序

  1. Context Override
    参数传入的Image Handle
  2. Platform Driver Override
    gEfiPlatformDriverOverrideProtocolGuid->GetDriver(ImageHandle)
  3. Driver Family Override
    支持gEfiDriverFamilyOverrideProtocolGuid
  4. Bus Specific Driver Override
    BusSpecificDriverOverride->GetDriver(ImageHandle)
  5. Driver Binding
    其他
  6. 根据版本号排序
    优先级排序源码分析
    |--> while |--> if BusSpecificDriverOverride->GetDriver()|--> AddSortedDriverBindingProtocol(TRUE) // 函数内部进行递归|--> for|--> CoreHandleProtocol(DriverBinding)|--> if DriverBinding->ImageHandle == DriverBindingHandle|--> AddSortedDriverBindingProtocol(FALSE)|--> for AddSortedDriverBindingProtocol() // 5 添加剩下所有的|--> for 根据Version对最后添加的进行排序

3.2.3 连接设备控制器

  1. 在Start或Stop函数中执行Controller相关的一些初始化
  2. 在ControllerHandle下去安装一些Protocol去实现或管理Controller某些特定功能或数据
  3. Start中通常不会执行硬件初始化的操作
  4. 硬件相关初始化动作,大部分都是在Pei Phase、Dxe 前期Non EFI Driver Model的Driver, 初始化Processor、Chipset或Platform,当然有些也通过Oprom 或file in an EFI System Partition来进行初始化。
    连接设备控制器源码分析
  |--> BdsEntry()|--> ProcessLoadOptions()|--> EfiBootManagerDisconnectAll()|--> EfiBootManagerConnectAll()|--> BmConnectAllDriversToAllControllers()|--> gBS->LocateHandleBuffer()|--> for gBS->ConnectController()|--> CoreConnectController()|--> CoreConnectSingleController()|--> 排序|--> for|--> if DriverBinding->Supported() // 返回 Success|--> DriverBinding->Start()      // 一般用于安装 Protocol|--> if                                //判断是否有子控制器|--> CoreConnectController()         //递归调用

3.3 Boot Manger

概要:

3.3.1 BootManager运行流程

  1. 获取BootNext Variable
  2. 初始化平台恢复引导项
  3. 添加UEFIShell等引导项
  4. 获取Setup引导选项
  5. 添加Hotkey并注册CallBack
  6. 初始化Hotkey服务
  7. 删除无效的引导项
  8. 如果默认进入Setup,则启动该引导项
  9. 等待按键按下
  10. 如果有按键按下则启动按键对应引导选项
  11. 如果BootNext引导项存在,则启动该引导项
  12. 根据BootOrder获取引导选项
  13. 按照BootOrder中的顺序依次尝试启动
  14. 如果平台恢复选项启动,最后尝试启动平台恢复对应的启动引导选项

3.3.2 启动项与Hotkey

BdsEntry()

  1. 获取引导项
  2. 添加Key####
  3. 获取所有的Key####
  4. 将Key####中内容加入mBmHotkeyList链表
  5. 为Key####创建Callback
  6. 等待按键按下
  7. 启动 mBmHotkeyBootOption
    BmHotkeyCallback()
  8. 获取当前按键对应引导项
  9. 引导项保存至 mBmHotkeyBootOption
|--> BdsEntry()|--> PlatformBootManagerBeforeConsole()           //前平台初始化|--> PlatformRegisterOptionsAndKeys()           |--> EfiBootManagerGetBootManagerMenu()       //获取Setup启动项  |--> EfiBootManagerAddKeyOptionVariable()     //添加key#### Variable|--> EfiBootManagerStartHotkeyService()           |--> BmGetKeyOptions()|--> for BmProcessKeyOption()|--> BmGenerateKeyShiftState()|--> InsertTailList(mBmHotkeyList)|--> BmRegisterHotkeyNotify()|-->RegisterKeyNotify(BmHotkeyCallback)   //注册callback|--> BdsWait()|--> while    |--> PlatformBootManagerWaitCallback()  //显示|--> BdsReadKeys()                   |--> EfiBootManagerHotkeyBoot()         |--> EfiBootManagerBoot(&mBmHotkeyBootOption)|--> BmHotkeyCallback()|--> EfiBootManagerVariableToLoadOption(Hotkey->BootOption, &mBmHotkeyBootOption)

3.3.3 如何添加引导项

添加 UEFI Shell 启动选项

  1. 根据gUefiShellFileGuid获取设备节点信息
  2. 创建新DevicePath,指向该节点
  3. 添加至Boot#### Variable,需要DevicePath和描述符,返回对应的Number
  4. 根据Number设置 Key#### Variable
  5. 根据Key####中的Opation注册Callback函数
  6. Callback中根据Number获取的BootOption并记录在全局变量中
  7. 如果有按键按下则启动全局变量中的BootOption选项

添加 FileSystem 启动选项

  1. 获取所有的 BlockIo Protocol 对应的 Handle
  2. 依次获取 BlockIo Protocol
  3. 跳过逻辑分区
  4. 跳过 Fixed Block IO 和 可移动设备(USB,移动硬盘)
  5. 获取当前BlockHandle对应的设备路径类型
//ACPI boot type
#define  BDS_EFI_ACPI_FLOPPY_BOOT         0x0201
//Message boot type
#define  BDS_EFI_MESSAGE_ATAPI_BOOT       0x0301 // Type 03; Sub-Type 01
#define  BDS_EFI_MESSAGE_SCSI_BOOT        0x0302 // Type 03; Sub-Type 02
#define  BDS_EFI_MESSAGE_USB_DEVICE_BOOT  0x0305 // Type 03; Sub-Type 05
#define  BDS_EFI_MESSAGE_SATA_BOOT        0x0312 // Type 03; Sub-Type 18
#define  BDS_EFI_MESSAGE_MAC_BOOT         0x030b // Type 03; Sub-Type 11
#define  BDS_EFI_MESSAGE_MISC_BOOT        0x03FF
//Media boot type
#define  BDS_EFI_MEDIA_HD_BOOT            0x0401 // Type 04; Sub-Type 01
#define  BDS_EFI_MEDIA_CDROM_BOOT         0x0402 // Type 04; Sub-Type 02
//BBS boot type
#define  BDS_LEGACY_BBS_BOOT              0x0501 //  Type 05; Sub-Type 01
#define  BDS_EFI_UNSUPPORT                0xFFFF
  1. 初始化BootOption并加入BootOptions数组
  2. 获取所有的SimpleFileSystemProtocol对应的Handle
  3. 依次获取 SimpleFileSystemProtocol对应的IO设备
  4. 如果文件系统中可以搜索到.\EFI\BOOT\boot.efi 文件系统启动设备,加入BdsBootOptionList启动项
  5. 搜索包含PXE启动项的文件系统,加入到BdsBootOptionLis链表
  6. 核实是否有shell启动项,加入链表

添加 Network 启动选项

  1. 将连接地址全部转换为小写字母
  2. 判断是否是http或https的地址
  3. 初始化节点信息
  4. 创建device path, 指向该节点
  5. 根据链接地址更新节点信息
  6. 重新创建device path,指向该节点
  7. 根据device path等相关信息初始化 load option
  8. 将load option 加入 Boot#### Variable

3.3.4 如何启动引导项

引导流程

  1. 搜索该选项是否存在
  2. 设置BootCurrent
  3. gBS->LocateDevicePath(Handle)
  4. gBS->ConnectController(Handle)
  5. FileBuffer = BmGetNextLoadOptionBuffer(BootOption->FilePath) //获取引导文件
  6. gBS->LoadImage() //加载Image
  7. gBS->SetWatchdogTimer() //开启看门狗
  8. gBS->StartImage() //启动Image
  9. gBS->SetWatchdogTimer() //关闭看门狗
  10. gRT->SetVariable() //删除BootCurrent Variable

BIOS的BDS阶段解析相关推荐

  1. datax源码解析-JobContainer的初始化阶段解析

    datax源码解析-JobContainer的初始化阶段解析 写在前面 此次源码分析的版本是3.0.因为插件是datax重要的组成部分,源码分析过程中会涉及到插件部分的源码,为了保持一致性,插件都已大 ...

  2. 【app运营】3阶段解析O2O产品的APP该如何运营推广?

    o2o,现在依然是在风口上,传统企业也好,互联网企业也好,还有许多创业者都想在此分一杯羹,但是实际上好多都已经折戟.经常听到这家公司.那家公司创始人拿着一个idea加商业计划书就拿到天使轮投资了,自己 ...

  3. UEFI.源码分析.DXE阶段的执行

    源码EDK2 : Tianocore UEFI源码分析系列第一篇,DXE阶段的初始化与执行流程 源码结构 MdeModulePkg/ Core/ Dxe/ Dispatcher/ DXE调度器 Dxe ...

  4. BIOS/UEFI基础——Protocol介绍

    简要说明 Protocol是UEFI中的一个重要概念(事实上<UEFI SPEC>中有超过70%的内容都是在讲Protocol),下面简单说明下: 1. 首先,非常重要的一点,Protoc ...

  5. BIOS、UEFI、Boot Loader都是些什么

    BIOS.UEFI.Boot Loader都是些什么 文章目录 BIOS.UEFI.Boot Loader都是些什么 什么是BIOS 基本的输入输出是什么 自检程序"检"了什么 系 ...

  6. BIOS/UEFI基础——FDF文件

    综述 FDF的全称是Flash Description File. 它是构成BIOS二进制的描述符,即FDF文件描述了BIOS二进制的组成结构. 本文的目的就是介绍FDF文件内部的组成以及它们是如何完 ...

  7. BIOS追code之DXE phase

    DXE Phase Overview DXE Core DXE Dispatcher EFI System Table DXE Driver - Non-Driver Model DXE Driver ...

  8. Bios工程师手边事—IGD VBIOS

    现代社会,是计算机技术高速发展的时代.计算机的发展,总是以人们生活的方便为目的.早期的计算机要想看到计算机的计算结果,要根据打孔的卡片来计算输出结果.而现在想看计算机的输出,就方便多了,一台显示器,男 ...

  9. UEFI BIOS和 传统BIOS 启动模式对比

    传统BIOS开机流程 从你按下主机机壳上的电源键,到进入作业系统的期间,储存於主机板上那颗EEPROM(电气可抹除暨可程式化唯读记忆体)裡的BIOS便会开始执行以下的工作: 1. 初始化: 当电脑打开 ...

最新文章

  1. 只要可能,就缓存数据和页输出
  2. 其他算法-两大随机采样方法简介
  3. 如何创建一张表mysql_如何创建一张规范的MySQL表
  4. 2008年浙江大学计算机及软件工程研究生机试真题
  5. xwpftablecell设置字体样式_HTML的文字样式
  6. oracle回滚段空间满了,Oracle回滚段表空间文件丢损怎样处理?
  7. stone 的 log4j配置详解
  8. frida需要Java基础吗_Android Hook工具之Frida 基础使用
  9. c# 通用类扩展方法 备注
  10. 机器学习基础(二十二)—— decision tree
  11. 华为鸿蒙系统英语报纸_“鸿蒙”系统的英文名叫这个!华为注册的这些《山海经》神兽都该怎么翻译?...
  12. System.IO.Directory.Delete 方法的使用
  13. 怎么用计算机里的坦克大战,FC经典90坦克大战电脑版
  14. 马悦凌:从初级护士到“民间奇医”[7]
  15. list之按照中文拼音首字母排序
  16. USRP X310使用的准备工作--Linux进行FPGA image烧录
  17. 本地html图片载入很慢,打开网页时图片加载很慢怎么办?网页图片打开慢的解决方法...
  18. nuke11安装教程 nuke11破解教程
  19. mysql如何收费,mysql收费吗
  20. 探索测试-大富翁KYM练习笔记

热门文章

  1. 什么是临时表,临时表什么时候删除
  2. 物联网大数据平台TIZA STAR架构解析
  3. C++信息学奥赛题目归类:初赛普及组阅读程序写结果题
  4. IATF16949认证|申请IATF认证审核常犯问题汇总
  5. dd命令生成随机大小的二进制文件
  6. 新浪微博橙v升级金v的多种方法
  7. 电力预测|基于新型MDPSO-SVR混合模型的电力预测特征选择(Matlab代码实现)
  8. 国宝上新计划-四大博物馆独家数字珍藏强势来袭!
  9. 【C语言中缀转后缀】
  10. 惠普笔记本型号全解析