UEFI的一点点概识

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: UEFI的一点点概识

最近看了一篇Blog讲的是关于PC安全的,其中很多的地方还是有一定相似之处。其中这个UEFI引起了我兴趣,以前安装系统的时候听说过这个名词。这里于是便来认识一下什么是UEFI。

前言

大多数人接触UEFI都是在PC的应用场景上,有在PC上安装过多操作系统的经历的同学,通常会进入UEFI界面设置操作系统引导顺序、CPU虚拟化等设置。UEFI诞生之初也确实是作为BIOS的替代者,主要应用在PC电脑上。

随着手机/平板等移动设备的发展,高通从MSM8998开始使用UEFI替代LK(Little Kernel)作为手机的Bootloader,作为一个嵌入式开发者势必比较好奇,UEFI相比嵌入式常见Bootloader(u-boot、LK等)区别在哪?

UEFI(Unified Extensible Firmware Interface,统一可扩展固件接口)定义了操作系统和平台固件之间的接口,它是UEFI Forum发布的一种标准。它只是一种标准,没有提供实现。下面让我们通过Tianocore社区提供的EDK2源码一窥UEFI的具体实现,相比其他的Bootloader有什么优势特点。

一、UEFI入门

1. 启动过程

UEFI系统从上电到关机可分为7个阶段:SEC-> PEI-> DXE-> BDS-> TSL -> RT-> AL

开源嵌入式的Bootloader大多分两个阶段(Stage1、Stage2)。(想想Uboot还真是)

  • Stage1:系统资源环境较少情况下部分硬件初始化,为Stage2准备执行环境。
  • Stage2:系统硬件进一步初始化,定制化功能的实现和操作系统的引导。
    进行类比,SEC/PEI可以看作是Stage1,DXE/BDS/TSL可以看作是Stage2。

二、UEFI的特点

LK、u-boot等开源的Bootloader都是结构简单的轻量级系统,开发门槛低。

UEFI系统虽然较为复杂,但其具有模块扩展性、多任务实现等类操作系统的特性更易实现复杂功能,且具有较好的开发灵活性,因而高通使用UEFI替换LK作为手机的Bootloader也就不奇怪了。

1. 扩展性

UEFI-统一可扩展固件接口,可扩展性是UEFI的突出优势。

这主要体现在UEFI可以动态地加载其它编译好的efi镜像而u-boot在编译完后并不能动态地加载其它定制化的驱动或者命令。那UEFI是如何实现这一特性地呢?

DXE是UEFI的核心阶段,这一阶段初始化了Boot Services(后面简称BS),BS为后面的引导过程和应用程序的执行提供了几乎所有基础服务接口。

2. 设备驱动模型

UEFI驱动实现了一种类Linux系统的驱动模型,实现了Host Bus、Driver和Device的架构解耦。(DXE_DRIVER可以看做是一种驱动类型的功能服务,不一定需要硬件支持)

以SCSI驱动为例,在UEFI中的驱动架构大致如下图:

UEFI驱动一般分为两部分,一部分是架构部分的Driver Binding Protocol,一部分是和硬件IO相关的Protocol。

3. 多任务机制

目前接触的嵌入式Bootloader都是单线程系统,但UEFI实现了Linux系统中类似eloop的单线程多任务机制,UE,eloop机制是通过Linux系统的select/epoll系统调用实现了多任务、定时器等机制,那UEFI中是如何实现这一机制的呢?

UEFI中的应用和Event的Notifier可以看作是任务,DXE中初始化的BS提供了事件相关接口实现了异步操作。

小结

u-boot、LK和UEFI等Bootloader各有优劣,无所谓哪一种更好,只有合不合适的情况。

目前在嵌入式领域应用最广的BL还是u-boot,结构简单,驱动移植和裁剪的门槛低,可以满足绝大部分嵌入式系统的需求,而UEFI在手机、平板等较复杂的嵌入式硬件更具优势,满足手机设备的多样化需求。

三、UEFI在ARM生态中现状如何?

在大多数人心目中,ARM世界的BootLoader还被uboot+DeviceTree统治。是啊,uboot简单快捷,移植容易,为什么不用呢?

但uboot有个显著的缺点:缺乏标准和互操作性。这让它更合适专用系统,而不是通用系统。

在ARM多用于嵌入式设备,如摄像头和手机等等的时候,这个并不是问题。

嵌入式设备往往是垂直定制开发的,从硬件、固件、BSP和操作系统,都深度定制,没有问题是定制修改程序所不能解决的。但当ARM进入到x86的传统领域后,如PC和服务器市场,情况发生了变化。

1、ARM生态的通用性需求不断增长

与大多数人基本的概念不同,在某种意义上来说,X86体系比ARM体系更加开放。X86是很多小伙伴一起玩,以生态圈的概念提供产品,并对自己那部分负责;而ARM体系虽然也依赖生态圈,但最终有个大Boss统合整个生态链,提供最后产品并对该产品负总责。

X86生态圈玩家众多,有OS 厂商(OSV)定期发布操作系统,如Windows,Ubuntu;芯片厂商提供CPU,如Intel, AMD;主板厂商(OEM)提供电脑主板;独立硬件供应商(IHV)生产扩展板卡如显卡等等PCIE扩展卡,再如内存厂家推出一代一代不同的内存条等等。

DIY玩家可以自由选择搭配合适/兼容的产品搭配出自己心仪的机器,休闲上网用户花2000多元就可以搭配出一套可用的电脑,而游戏玩家则可能花费上万元才能满足游戏配置需求。还有些品牌机厂商如Dell和联想等,他们提供整套最终产品给用户。但他们实际上是在所有小伙伴的零件基础上拼凑出个产品,技术不强,话语权弱,并不能统一整个产业链。用户津津乐道的反而是用的什么CPU,安装的什么操作系统,用的那种显卡等等。Windows死机、蓝屏和缓慢等等时候,用户往往会抱怨微软和Intel,而不是品牌厂商。

在X86生态中,强势的是整个生态链的两端:微软和Intel,分别卡住最上游和最下游。在争取了链条利润的最大头后,也要直接面对数千数万种千奇百怪的硬件产品,于是才发明了UEFI和ACPI标准,规范了各个层面的调用接口。更重要的是,为了规范中间链条各个厂商的行为,分别推出了一软一硬两个认证:WHQL和Intel最新的EVO。保证了市面上上百种产品的质量可控。

传统ARM体系由最后品牌厂商统合整个产品,它负责打通整个产业链,并对其中所有部分负责,话语权极强,同时对技术也相对较强。用户面对的具体品牌的产品,而不是碎片化的各个部分。强势的如Apple,硬件软件一起抓,完全组成闭环的链条。稍差也如华为等安卓手机,要负责安卓系统在自己手机移植部分(BSP),客户出了问题并不会找谷歌,而会去找华为。对规范和标准的需求并不强烈。

随着采用ARM内核的芯片性能不断提高,ARM内核芯片不断进入x86传统领域。移动和桌面有Apple的Axx,服务器端有鲲鹏920(也可以用于桌面)、倚天710,、安培和Graviton系列,它们的性能完全可以和Intel/AMD的芯片打擂台。当ARM的小伙伴们进入这些领域后,他们发现一样也要面临碎片化的生态系统的问题。于是接受UEFI和ACPI变成了必然的选择。这也从EDK2社区最活跃的用户在近几年已经不是x86的开发者,而是ARM相关开发者(最近一年多换成了RISC-V)可以看出。于此同时EDK2开源平台仓库EDK2_Platforms下面也涌入了大量ARM平台,好不热闹。

现状是,所有成熟的ARM服务器产品都采用UEFI+ACPI方案;很多ARM移动和桌面产品已经采用UEFI+ACPI方案;大量ARM产品在赶来的路上;形式喜人。同时,作为ARM世界的灵魂,ARM公司也推出了大量规范和标准,来规范ARM产品的行为,如针对服务器的服务器的SBSA和SBBR规范,最新的基本系统架构(BSA)、基本启动要求(BBR),以及针对安全的基本启动安全要求(BBSR)等等。

多个层次和方向的规范标准相当繁杂,而且标准有些是必须达到的,有些则是推荐,这样给最终用户造成了不少困扰,也造成了市场的混乱。如何定义“好的”ARM产品标准,这个标准必须是可衡量的、可标识的,并且要简单易懂,最好还能朗朗上口?微软以前的答案是WHQL认证测试和Windowsxx标签,ARM的是什么呢?

ARM公司在ARM进入服务器领域不久就发现了这种需求,推出ARM ServerReady计划。随着ARM内核芯片的市场不断外延,ARM在2020年10月开发者峰会上,正式宣布升级版:ARM SystemReady [1]和白皮书[2] 。

ARM SystemReady: ARM公司在ARM进入服务器领域不久就发现了这种需求,推出ARM ServerReady计划。随着ARM内核芯片的市场不断外延,ARM在2020年10月开发者峰会上,正式宣布升级版:ARM SystemReady [1]和白皮书[2] 。

ARM SystemReady的口号是“Just Work”(即开即用,不是仅仅工作),强调它的可用性和已验证性。它主要包括四种认证:

  • SystemReady SR:即以前的ServerReady,适用于server和workstation。它除了要求SBBR之外,SBSA和SBBR被替换为通用的BSA规范和SBSA规范。
  • SystemReady ES:适用于基础架构和物联网边缘设备等嵌入式服务器。
  • SystemReady IR:用于基础架构物联网和物联网边缘设备。
  • SystemReady LS:适用于当下火热的LinuxBoot来启动server。

标准可以说涵盖了从云端到物联网边缘计算中的所有部分。因为覆盖范围大,所以各个部分的标准要求各有不同:

如果通过了基本启动安全要求(BBSR)的要求,还可以在Logo旁配享ARM特制小盾牌:

关于BSA、SBSA、SBBR和BBSR等标准大家可以在ARM官网或者System Ready Spec[3]页面 找到相关链接,并仔细阅读。如果大家留言足够踊跃,也许今后本专栏会专文介绍其中比较重要的SBBR和SBSA规范。

这里要特别一点,那就是UEFI和ACPI、DeviceTree(DT)的关系。我们可以看到,SystemReady IR固件spec是个奇怪的组合UEFI+DeviceTree。我们普通看到的系统都是UEFI+ACPI,或是uboot+DeviceTree,但是实际上,DT和UEFI并不矛盾,更有甚者,有些定制化奇怪的系统上甚至出现UEFI+ACPI+DT的怪异组合。这里采用DT主要是考虑物联网IOT系统使用DT更加简单。关于为什么在ARM中,ACPI要替代DT见参考资料5 。

四、UEFI之 Secure boot

1、概要

Secure Boot的目的,是防止恶意软件侵入。它的做法就是采用密钥。UEFI规定,主板出厂的时候,可以内置一些可靠的公钥。

然后,任何想要在这块主板上加载的操作系统或者硬件驱动程序,都必须通过这些公钥的认证。也就是说,这些软件必须用对应的私钥签署过,否则主板拒绝加载。由于恶意软件不可能通过认证,因此就没有办法感染Boot。

在安全启动中,证书颁发机构 (Ca) 包括 OEM (或其委托) 和 Microsoft。Ca 生成构成信任根的密钥对,然后使用私钥对合法操作(如允许的早期启动 EFI 模块和固件服务请求)进行签名。对应的公钥将嵌入到启用了安全启动的 Pc 上的 UEFI 固件中,并用于验证这些操作。

2、说明

  • 缩写CA: Certificate authority;PUK: Public key;RSA:One public-key cryptosystems;SHA: Secure hash algorithm
  • 公钥加密,公钥加密使用一对数学相关的加密密钥,称为公钥和私钥。如果你知道其中一个密钥,则无法轻松地计算其他密钥。如果使用一个密钥对信息进行加密,则只有对应的密钥才能对该信息进行解密。对于安全启动,私钥用于对代码进行数字签名,公钥用于验证该代码的签名以证明其真实性。如果私钥被泄露,则具有相应公钥的系统不再安全。这可能会导致启动工具包攻击,并会损害负责确保私钥安全性的实体的信誉。
  • 密钥对:公钥分发,私钥自留。常见的公钥格式:cer/der,常见的私钥格式:pfx
  • RSA 2048 加密:RSA-2048 是一种非对称加密算法。以原始形式存储 RSA-2048 模块所需的空间为2048位。
  • 自签名证书由与证书的公钥匹配的私钥签名的证书称为自签名证书。根证书颁发机构 (CA) 证书属于此类别。
  • 证书数字证书的主要用途是验证签名数据(如二进制等)的来源。证书的常见用途是使用传输层安全性 (TLS) 或安全套接字层 (SSL) 的 internet 消息安全。通过使用证书验证已签名的数据,接收方可以知道数据的来源,以及是否在传输过程中对其进行了更改。通常,数字证书包含一个可分辨名称 (DN) 、一个公钥和一个签名。DN 标识一个实体(例如,公司),其中包含与证书的公钥匹配的私钥。使用私钥对证书进行签名,并在证书中放置签名会将私钥与公钥进行联系。证书可以包含某些其他类型的数据。例如,一个 X.509 证书包括该证书的格式、该证书的序列号、用于对该证书进行签名的算法、颁发该证书的 CA 的名称、请求该证书的实体的名称和公钥以及 CA 的签名。
  • PK(Platform Key):平台密钥(允许操作KEK的私钥)平台密钥在平台所有者和平台固件之间建立了信任关系,可以在Setup UI中设置,此步骤会在安装模式下将平台移到用户模式。Microsoft 建议平台密钥的类型为 EFI _ CERT _ X509 _ GUID ,其中包含公钥算法 RSA、公钥长度为2048位和签名算法 sha256RSA。如果需要考虑存储空间,则平台所有者可以使用类型 EFI _ CERT _ RSA2048 _ GUID;规定一个硬件平台只能被一个拥有者所拥有,即 PK 只能存在一个 ,与拥有者相关的公钥被存储在 FLASH 里面的 PK 变量里面,同时,拥有者的私钥可以来对 PK, KEK, db, dbx 进行签名和管理。
  • KEK(Key Exchange Key):密钥交换密钥 (允许操作db的公钥集合)是用于在硬件平台和操作系统之间建立信任关系 ,KEK 的公钥可以在主板的 FLASH 存在多个不同项,即 KEK 可以存在多个 ,每一项对应一种可以被启动的操作系统,同样,KEK 的私钥可以来对 db, dbx 进行签名和管理。清除 KEK可以 “清除” (删除 KEK) 。请注意,如果平台上未安装 PK,则不需要对 “clear” 请求进行签名。如果已对其进行签名,则清除 KEK 需要使用 PK 签名的包,若要清除 db 或 .dbx,需要由 KEK 中存在的任何实体签名的包。
  • db(Database):白名单数据库 (允许bootloaders的公钥集合)是用于对 被许可的 EFI 文件予以加载的数据签名库 ,和 KEK 一样, db 的公钥可以存在很多项 。(在 UEFI 平台里面,操作系统加载文件就是一个 EFI 文件)
  • dbx(Database Excluded):黑名单数据库 (不允许bootloaders的公钥集合)是一个 黑名单数据签名库 ,只要谁的 EFI 签名在这,谁就被屏蔽掉, dbx 的公钥也可以存在很多项 。
  • 清除平台密钥平台所有者通过调用 SetVariable (大小为0的变量,并重置平台)来清除平台密钥(PKpub) 。如果平台处于设置模式,则无需对空变量进行身份验证。如果平台处于用户模式,则必须用当前 PKpriv 对空变量进行签名; 强烈建议不要将生产 PKpriv 用于对包进行签名以重置平台,因为这样可以通过编程方式禁用安全启动。这主要是一种预生产测试方案。还可以使用安全的平台特定方法(Delete PK)清除平密钥。在这种情况下,全局变量安装模式也必须更新为1(Setup mode)。

3、原理

UEFI 只管验efi文件,grub也是efi文件,grub验kernel,kenel验module,Bios Secure Boot的原理:

把公钥包在code里面,当使用gBS->LoadImage()去加载模块(UEFI Image)的时候会用BIOS里面的公钥去验证Image有没有正确签名,验证通过则Image成功被加载签名实例:signtoolx64.exe sign -f 私钥.pfx -fd sha256 shell.efi

**例如:**当我们在BIOS里面把Secure Boot[Enable]之后,会发现我们的U盘shell进不去,这是因为shell环境(bootx64.efi)没有经过签名,如果要使Secure Boot[Enable]之后,也能进U盘shell,需要对bootx64.efi进行签名,同时把签名用的私钥的对应公钥包到BIOS里面。

参考文献

UEFI

1. EDK2源码:https://github.com/tianocore/edk2
2. 《UEFI原理与编程》-- 戴正华
3. https://mp.weixin.qq.com/s/tgW9-FDo2hgxm8Uwne8ySw

SystemReady

[0]https://mp.weixin.qq.com/s/yUlsCdIcg3W2g3BIDCNvAg
[1]SystemReady官网: https://developer.arm.com/architectures/system-architectures/arm-systemready
[2]白皮书: https://armkeil.blob.core.windows.net/developer/Files/pdf/white-paper/arm-systemready-whitepaper.pdf
[3]Specs: https://developer.arm.com/architectures/system-architectures/arm-systemready/specifications
[4]ACS官网: https://github.com/ARM-software/arm-systemready
[5]ACPI on ARM: https://www.kernel.org/doc/html/latest//arm64/arm-acpi.html#why-acpi-on-arm
[6]partners: https://www.arm.com/zh-tw/why-arm/architecture/systems/systemready-certification-program/partners
[7]SystemReady的最新进展: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/progress-in-arm-system-ready-program

UEFI之 Secure boot

https://mp.weixin.qq.com/s/gJST89ei_JHwyIGl3XzKfQ
相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
安全 Linux Windows
Linux科普扫盲系列(Linux启动安装U盘的制作)
Linux科普扫盲系列(Linux启动安装U盘的制作)
731 0
Linux科普扫盲系列(Linux启动安装U盘的制作)
|
6月前
|
存储 Linux 存储控制器
BootLoader这个玩意
BootLoader这个玩意
83 0
|
缓存 运维 监控
你在服务器上的一举一动,我可都看着!linux超骚技巧三分钟Get
你在服务器上的一举一动,我可都看着!linux超骚技巧三分钟Get
你在服务器上的一举一动,我可都看着!linux超骚技巧三分钟Get
|
存储 缓存 Linux
Linux之RAID介绍、软RAID5实操配置(失望攒够了就放手,不打扰是我最后的温柔)(一)
Linux之RAID介绍、软RAID5实操配置(失望攒够了就放手,不打扰是我最后的温柔)(一)
323 0
Linux之RAID介绍、软RAID5实操配置(失望攒够了就放手,不打扰是我最后的温柔)(一)
|
存储 Linux 计算机视觉
Linux之RAID介绍、软RAID6实操配置(失望攒够了就放手,不打扰是我最后的温柔)(二)
Linux之RAID介绍、软RAID6实操配置(失望攒够了就放手,不打扰是我最后的温柔)(二)
532 0
Linux之RAID介绍、软RAID6实操配置(失望攒够了就放手,不打扰是我最后的温柔)(二)
|
存储 程序员 芯片
肝了很久!一文了解操作系统 I/O(1)
我们之前的文章提到了操作系统的三个抽象,它们分别是进程、地址空间和文件,除此之外,操作系统还要控制所有的 I/O 设备。操作系统必须向设备发送命令,捕捉中断并处理错误。它还应该在设备和操作系统的其余部分之间提供一个简单易用的接口。操作系统如何管理 I/O 是我们接下来的重点。 不同的人对 I/O 硬件的理解也不同。对于电子工程师而言,I/O 硬件就是芯片、导线、电源和其他组成硬件的物理设备。而我们程序员眼中的 I/O 其实就是硬件提供给软件的接口,比如硬件接受到的命令、执行的操作以及反馈的错误。我们着重探讨的是如何对硬件进行编程,而不是其工作原理。
149 0
肝了很久!一文了解操作系统 I/O(1)
|
Windows 内存技术
Win系统 - 为什么开机不快?为什么人家不装固态比我快?
Win系统 - 为什么开机不快?为什么人家不装固态比我快?
188 0
Win系统 - 为什么开机不快?为什么人家不装固态比我快?
|
存储 缓存 监控
肝了很久!一文了解操作系统 I/O(5)
肝了很久!一文了解操作系统 I/O(5)
肝了很久!一文了解操作系统 I/O(5)
肝了很久!一文了解操作系统 I/O(4)
肝了很久!一文了解操作系统 I/O(4)
肝了很久!一文了解操作系统 I/O(4)
|
存储 Unix 程序员
肝了很久!一文了解操作系统 I/O(3)
肝了很久!一文了解操作系统 I/O(3)
肝了很久!一文了解操作系统 I/O(3)