UEFI 与Linux
BIOS: 是系统开机后执行的第一个firmware程序, 它通常存储在主板的flash memory中,与系统存储无关。
UEFI:支持读取分区表,和文件系统。UEFI不会执行MBR中的任何代码。而是启动NVRAM中的boot entries.
UEFI标准强制要求支持 FAT12,FAT16,FAT32文件系统(详见UEFI 标准2.7, Section 13.3.1.1 ).
但任何符合条件的供应商都可以选择添加对其它文件系统的支持,如 Apple Macs支持他们自己的HFS+文件系统.
UEFI实现中也支持用于光盘的ISO-9660。
UEFI启动 EFI应用,如:boot loader, boot managers, UEFI shell等。
这些应用通常作为文件存储在EFI系统分区中。每个供应商都可以将其文件存储在/EFI/vendor_name 目录中,
可以通过向NVRAM添加一个boot entry来启动应用,或者从UEFI shell 中启动应用。
参考:https://wiki.archlinux.org/index.php/Arch_boot_process#Firmware_types
EFI与 UEFI:
a,UEFI起始于Intel的 EFI 1.x 版。
b, 从2.0版本起,一个名为UEFI论坛的公司组织接管了其开发工作,并更名为Unified EFI(UEFI
).
c,除非特别指明是EFI 1.x, EFI和UEFI均指代UEFI 2.x固件。
d,此标准的最新版本位于 http://uefi.org/specifications.
UEFI变量:EFI variables
UEFI定义了变量,操作系统通过它们可以与firmware进行交互:
1,UEFI 引导变量
:Boot Variables. 只在早期系统启动时由引导加载程序和操作系统使用。
2,UEFI 运行时变量
:Runtime services Variables. UEFI 运行时变量允许操作系统管理UEFI firmware的某些设置(如UEFI引导管理器) 或 UEFI Secure Boot协议的密钥。
获取变量列表: efivar -l
linux中 efi variables 操作接口
: 如图示
efibootmgr: 一个用户空间的用于修改EFI Boot Manager的工具。 可以创建,删除 boot entries, 修改启动顺序。
源码参考:https://github.com/rhboot/efibootmgr 详见:EFI Specification v1.02以上。http://www.uefi.org
efibootmgr 早期使用内核模块 efivars. 新的版本中使用核模块efivarfs.
efivars
: 通过sysfs接口来实现对 EFI variables的管理。
会生成 /sys/firmware/efi/vars 目录,并在其下进行 EFI variable的管理。(只支持1024个byte长度的variable,不能兼容 EFI v1.0以上的长变量)
efivarfs
: 从 linux 3.8 开始,内核中添加的一个新的文件系统.
efivarfs文件系统是为了解决在sysfs中使用entries来维护EFI variables的缺点.
旧的sysfs EFI variables 只技持1024 bytes, 这是EFI 0.99标准之前的限制。在新的标准中已经被删除。
现在,由于variables有可能大于一个page, sysfs对此不是最佳接口,可以通过efivarfs文件系统来created,deleted,modified Variables.
efivafs 通常如下mounted(由systemd自动挂载)mount -t efivarfs none /sys/firmware/efi/efivars/
drivers/firmware/efi/Kconfig 下默认配置:
CONFIG_EFIVAR_FS=y
新版efibootmgr已使用/sys/firmware/efi/efivars/ 接口来操作UEFI运行时变量。
CONFIG_EFI_VARS=n // efivar sysfs 接口,应当禁用些选项来同时启用efivarfs和 sysfs-efivars所导致的潜在问题。efivars_sysfs_init()
EFI_VARS =n // efivars.o
EFI_VARS_PSTORE =y //会打开 EFI_VARS efi-pstore.o
efibootmgr
: 作为 UEFI Boot Manager,它是与系统中EFI firmware交互的工具,用来创建/删除,修改 boot entries.
#efibootmgr -v //列出当前boot entries
bootCurrent: 0001
Timeout: 3 seconds
BootOrder: 0001,0004,0000,0002,0003,0005
Boot0000* UiApp FvVol(64074afe-340a-4be6-94ba-91b5b4d0f71e)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001* CentOS HD(1,GPT,84e4a369-1ef4-4951-9123-d382d09b1796,0x800,0x64000)/File(\EFI\centos\shimaa64.efi)
Boot0002* UEFI Misc Device VenHw(f9b94ae2-8ba6-409b-9d56-b9b417f53cb3)N.....YM....R,Y.
Boot0003* UEFI Misc Device 2 VenHw(8047db4b-7e9c-4c0c-8ebc-dfbbaacace8f)N.....YM....R,Y.
Boot0004* UEFI QEMU QEMU HARDDISK /Pci(0x1,0x2)/Pci(0x0,0x0)/SCSI(0,0)N.....YM....R,Y.
Boot0005* EFI Internal Shell FvVol(64074afe-340a-4be6-94ba-91b5b4d0f71e)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
从上面 efibootmgr
的输出看,当前的启动项是 Boot0001, 而启动的程序是:/EFI/centos/shimaa64.efi
UEFI启动流程:
传统的BIOS启动流程:
shim: 通常用于对 bootloader(grub2)进行安全检查。
shim
: shim是一个简单的EFI应用程序,在运行时会尝试通过标准EFI LoadImage()和StartImage()调用来打开并执行另一个应用程序。
如果这些失败(因为在使能 Secure Boot
时会对二进制文件进行检查,有可能二进制应用没有适当的密钥签名),则它将根据内置证书验证二进制文件。
如果成功,并且二进制或签名密钥未列入黑名单,则shim将重定位并执行二进制文件。
源码仓库:https://github.com/rhboot/shim
MokManager
: 用来操作管理 Machine Owner Key (MOK)
这一类 key的程序。MOK一般是用户自己创建并使用的key,用来启动自定义的kernel。MOKs保存在NVRAM中。MokManager源码也在shim源码仓库中。参考
:http://www.rodsbooks.com/refind/secureboot.html
创建自己的key来创建运行自定义kernel
:https://en.opensuse.org/openSUSE:UEFI#Booting_a_custom_kernel
使用UEFI Secure Boot案例参考:https://www.aioboot.com/en/secure-boot/