关于UEFI
什么是UEFI
简单来讲,是在硬件及操作系统之间的接口,如下图:
UEFI的优点
- 开发效率高
- 采用C/C++语言编写
- 软件分层结
- 可扩展性
- 以module的形式,如Driver的模型
- 驱动、表、protocol有版本控制
- 性能
- 提供的异步操作,event事件,减少CPU等待时间
- 舍弃了中断这种耗时的操作
- 启动时可仅仅遍历启动所需设备
- 安全
- 在执行应用及驱动前会检测程序和驱动的证书
UEFI核心概念
启动过程
重点关注以下几个入口文件:
- PeiMain.c
- DxeMain.c
- BdsEntry.c
Module
Module有统一的格式要求,一般是源文件+inf(类似于makefile)+uni(资源文件),每一种Moudle的格式稍稍有些不同,大概有以下几种类型:
Protocol
可以说Protocol是UEFI中最重要的概念。可以理解为server与client间通信的信使。
从使用者的角度来看:
从提供者的角度来看:
搞清楚以下几个问题:
1. protocol是什么?
- 从语言角度讲,是包含了属性和函数指针的结构体;
- 从功能上讲,是server与client对服务方式上的一种约定;
2. protocol安装到什么地方?
- 在image对象中的句柄中;image对象是指DXE型驱动;
3. 怎样安装protocol?
- 通过InstallprotocolInterface;
4. 什么时候安装?
- 在image初始化时(在执行模块入口函数时)
EFI_HANDLE
指向某种对象的指针,包括controller及Image对象。每个HANDLE都有一个Protocols链表用来存放属于自己的Protocol。
Controller
UEFI扫描总线后,会为每个设备建立一个Controller对象,用于控制设备。
什么时候扫描总线?PCI Scan的时候?
Image
SystemTable
用户空间通往内核空间的通道,在DXE阶段被初始化。
两个核心成员:
- BootServices
- RuntimeServices
Event
从生产者和消费者的角度理解,一个产生事件:
- CreateEvent
一个消费事件
- WaitForEvent
触发事件
- SignalEvent
- 时钟中断
Driver
服务型驱动(DXE驱动)
三个部分>
protocol服务接口设计
定义有哪些函数及变量、GUID。接口的实现
实现这些函数。-
驱动框架
- 定义inf文件
- 入口函数中安装驱动(gBS->InstallProtocolInterface)
UEFI驱动
一个设备/总线驱动程序在安装时首先要找到对应的硬件设备(在UEFI中是要找到对应的控制器),然后执行安装操作,将驱动程序安装到硬件设备的控制器上。核心是通过EFI Driver Binding Protocol管理驱动程序,在驱动的入口函数中安装EDBP到自身的Handle上,在以下三个函数:
- Supported函数用于检测一个设备是否支持该驱动。
- Start用于将驱动安装到设备上。
- Stop用于将驱动从设备上卸载。
如何写一个UEFI驱动->
- 驱动服务本身
- 一个单独的protocol,用来操作硬件相关部分
- 驱动框架部分
- 实现EDBP的三个函数,其中support判断如:是否安装EFI_PCI_IO_PROTOCOL,通过读取PCI配置空间ClassCode判断是否是相关驱动器;
- Start函数,在ControllerHandle上安装上面的驱动服务本身;
问题:
1. 所有的Controller Device是什么时候挂到ControllerHandle上面的?
2. 驱动加载后都放在ImageHandle中,以及protocol?
3. 在BDS阶段通过调用ConnectController()来匹配Controller及Driver?
应用及shell
应用有很多实用场景,如诊断、显示并监控系统信息、系统设置、网络应用。
shell是一个特殊的应用,提供了用户与UEFI系统之间的接口。
入门UEFI
如果想学习UEFI的话,有以下资源:
- 首先你得有一个真实的环境,比如一块开发板:MinnowBoard
- 然后你得有源码,如Intel官方的EDK2:Tianocore
- 相关文档
- 官网UEFI Spec:https://github.com/tianocore/tianocore.github.io/wiki/EDK-II
- 《Driver Writer’s Guide for UEFI 2.3.1》
- 《UEFI原理与编程》
总的来说,先要有C/C++的基础,然后熟悉X86的体系架构、PCI的体系,然后是熟悉UEFI的架构,辅以各种协议的了解,如ATA、USB、TCP/IP等等,最后就是不断的在Debug实践中提高总结。
什么是UEFI
简单来讲,是在硬件及操作系统之间的接口,如下图:
UEFI的优点
- 开发效率高
- 采用C/C++语言编写
- 软件分层结
- 可扩展性
- 以module的形式,如Driver的模型
- 驱动、表、protocol有版本控制
- 性能
- 提供的异步操作,event事件,减少CPU等待时间
- 舍弃了中断这种耗时的操作
- 启动时可仅仅遍历启动所需设备
- 安全
- 在执行应用及驱动前会检测程序和驱动的证书
UEFI核心概念
启动过程
重点关注以下几个入口文件:
- PeiMain.c
- DxeMain.c
- BdsEntry.c
Module
Module有统一的格式要求,一般是源文件+inf(类似于makefile)+uni(资源文件),每一种Moudle的格式稍稍有些不同,大概有以下几种类型:
Protocol
可以说Protocol是UEFI中最重要的概念。可以理解为server与client间通信的信使。
从使用者的角度来看:
从提供者的角度来看:
搞清楚以下几个问题:
1. protocol是什么?
- 从语言角度讲,是包含了属性和函数指针的结构体;
- 从功能上讲,是server与client对服务方式上的一种约定;
2. protocol安装到什么地方?
- 在image对象中的句柄中;image对象是指DXE型驱动;
3. 怎样安装protocol?
- 通过InstallprotocolInterface;
4. 什么时候安装?
- 在image初始化时(在执行模块入口函数时)
EFI_HANDLE
指向某种对象的指针,包括controller及Image对象。每个HANDLE都有一个Protocols链表用来存放属于自己的Protocol。
Controller
UEFI扫描总线后,会为每个设备建立一个Controller对象,用于控制设备。
什么时候扫描总线?PCI Scan的时候?
Image
SystemTable
用户空间通往内核空间的通道,在DXE阶段被初始化。
两个核心成员:
- BootServices
- RuntimeServices
Event
从生产者和消费者的角度理解,一个产生事件:
- CreateEvent
一个消费事件
- WaitForEvent
触发事件
- SignalEvent
- 时钟中断
Driver
服务型驱动(DXE驱动)
三个部分>
protocol服务接口设计
定义有哪些函数及变量、GUID。接口的实现
实现这些函数。-
驱动框架
- 定义inf文件
- 入口函数中安装驱动(gBS->InstallProtocolInterface)
UEFI驱动
一个设备/总线驱动程序在安装时首先要找到对应的硬件设备(在UEFI中是要找到对应的控制器),然后执行安装操作,将驱动程序安装到硬件设备的控制器上。核心是通过EFI Driver Binding Protocol管理驱动程序,在驱动的入口函数中安装EDBP到自身的Handle上,在以下三个函数:
- Supported函数用于检测一个设备是否支持该驱动。
- Start用于将驱动安装到设备上。
- Stop用于将驱动从设备上卸载。
如何写一个UEFI驱动->
- 驱动服务本身
- 一个单独的protocol,用来操作硬件相关部分
- 驱动框架部分
- 实现EDBP的三个函数,其中support判断如:是否安装EFI_PCI_IO_PROTOCOL,通过读取PCI配置空间ClassCode判断是否是相关驱动器;
- Start函数,在ControllerHandle上安装上面的驱动服务本身;
问题:
1. 所有的Controller Device是什么时候挂到ControllerHandle上面的?
2. 驱动加载后都放在ImageHandle中,以及protocol?
3. 在BDS阶段通过调用ConnectController()来匹配Controller及Driver?
应用及shell
应用有很多实用场景,如诊断、显示并监控系统信息、系统设置、网络应用。
shell是一个特殊的应用,提供了用户与UEFI系统之间的接口。
入门UEFI
如果想学习UEFI的话,有以下资源:
- 首先你得有一个真实的环境,比如一块开发板:MinnowBoard
- 然后你得有源码,如Intel官方的EDK2:Tianocore
- 相关文档
- 官网UEFI Spec:https://github.com/tianocore/tianocore.github.io/wiki/EDK-II
- 《Driver Writer’s Guide for UEFI 2.3.1》
- 《UEFI原理与编程》
总的来说,先要有C/C++的基础,然后熟悉X86的体系架构、PCI的体系,然后是熟悉UEFI的架构,辅以各种协议的了解,如ATA、USB、TCP/IP等等,最后就是不断的在Debug实践中提高总结。