Unified Extensible Firmware Interface (简体中文)
| Summary |
|---|
| An overview of the Unified Extensible Firmware Interface. |
| Overview |
| 为了启动 Arch Linux,一个与 Linux 兼容的启动引导程序,如 GRUB, GRUB2, LILO, 或者 Syslinux 必须被安装到主引导记录(MBR), 或者GUID 分区表(GPT)。启动引导程序的任务是初始化 Arch 启动过程,然后加载内核以及初始化内存盘。 |
| Related |
| GUID Partition Table |
| Master Boot Record |
| Arch Boot Process |
统一可扩展固件界面(Unified Extensible Firmware Interface) (或简称为UEFI) 是一种新型固件,最初是由Intel设计(当时称为EFI),主要用于其基于安腾架构的系统。 它介绍了一种新的启动系统的方式,该方式有别于传统BIOS系统所使用的“MBR启动代码”。它起始于Intel EFI的1.x版本,之后被称作UEFI论坛的一群公司接管了它的开发工作。从此,它被称为统一的EFI,其版本始于2.0。自2013年7月24号起,UEFI规格2.4(在2013年7月11日发布)是最新的一个版本。
在理解 UEFI 之前,最好先理解在它之前的(BIOS)系统是如何启动的。这在随后的小节有解释。
Contents |
BIOS
BIOS 又称 基本输入输出系统,是系统打开以后,最先被执行的程序(固件)。大多数时候它被保存在属于自己的一个flash存储器中,位于主板上,和系统的存储空间是独立的。
BIOS下的启动过程
- 当系统按下电源开关 - 系统加电自检,或POST过程。
- 在 POST 之后,BIOS 初始化必要的系统硬件,用于引导(boot)。(硬盘,键盘控制器之类)
- BIOS 执行第一块磁盘上最开始的440字节(MBR引导代码区域)。
- MBR 引导代码从 BIOS 接过控制权,启动它的下一阶段代码(如果有的话)(一般是引导程序(bootloader)代码)
- 启动的(第2阶段)代码(真正的引导程序)读取自己的支持和配置文件。
- 按照配置文件,引导程序加载 内核(kernel) 和 initramfs 到系统内存(RAM)中,然后启动内核。
BIOS中的多重引导
因为被塞进启动代码区域的440字节小程序能做的事情很少,所以使用 BIOS 做多重启动需要有多重引导能力的引导程序(多重引导指的是引导多个操作系统,不是GRUB开发者指的用于引导内核的多种引导格式)。 所以一般通用的引导程序,像GRUB或Syslinux或LILO 能被BIOS装载,然后它再用 chain-loading 去装载一个操作系统,或者直接装载内核。
UEFI
UEFI 既能读取分区表也能识别文件系统。因为它不像 BIOS 系统要受限于440字节的启动代码限制(MBR引导代码)。UEFI 完全不使用MBR启动代码。
常用的 UEFI 固件既支持 MBR 也支持 GPT 分区表。苹果公司基于英特尔 CPU 的 MAC 系列的 EFI 除了支持 MBR 和 GPT 分区表外,还支持苹果公司分区映射。绝大部分的 UEFI 固件可以访问 FAT12(软盘)、 FAT16 和 FAT32 文件系统,在HDD以及符合 ISO9660(和 UDF) 规范的 CD/DVD中。Apple-Intel Mac 还可以访问 HFS/HFS+ 文件系统。
UEFI 不加载任何 MBR 的引导代码,无论其是否存在。代之以使用一个特殊的分区,该分区在分区表中称做“EFI系统分区”,其中存放固件加载所需的文件。每个设备提供者都可以把他们的文件存放在 <EFI 系统分区>/EFI/<提供者名称>/ 这个文件夹中,并由固件或其外壳程序(UEFI shell)加载引导程序。EFI 系统分区一般是 FAT32 格式。
在 UEFI 模式下,每一个程序,无论它是一个操作系统引导器还是一个工具程序(比如内存测试工具)抑或是一个独立于操作系统的系统恢复工具,它们都应该是 EFI 固件架构下的一个应用级程序,对应于EFI固件的位数/架构。大部分 UEFI 固件,包括最近的苹果 Mac,都使用 x86_64 EFI 固件。仅知的使用 IA32(32-bit) EFI 的设备是旧的(2008年以前)的苹果 Mac,已知一些最近的 Intel Cloverfield 超级本,以及一些旧的 Inter 服务器工作在 Intel EFI 1.10固件上。
x86_64 EFI 固件不支持加载32位的 EFI 应用(不像 x86_64 的 Linux 和 Windows 能支持)。因此,UEFI 应用程序必须被编译为对应架构的版本。
UEFI 引导过程
- 系统开机 - 上电自检(Power On Self Test 或 POST)。
- UEFI 固件被加载。固件初始化启动要用的硬件。
- 固件读取其引导管理器以确定从何处(比如,从哪个硬盘及分区)加载哪个 UEFI 应用。
- 固件按照引导管理器中的启动项目,加载UEFI 应用。
- 已启动的 UEFI 应用还可以启动其他应用(对应于 UEFI shell 或 rEFInd 之类的引导管理器的情况)或者启动内核及initramfs(对应于GRUB之类引导器的情况),这取决于 UEFI 应用的配置。
UEFI 的多重引导
因为每个操作系统或者提供者都可以维护自己的 EFI 系统分区中的文件,同时不影响别人,所以 UEFI 的多重启动只是简单的运行不同的UEFI 程序,对应于特定操作系统的引导程序。这避免了依赖 chainloading 机制(通过一个引导程序加载另一个引导程序,来切换操作系统)。
启动 Microsoft Windows
Linux Windows x86_64 UEFI-GPT Multiboot
Windows Vista (SP1+) and 7 pr 8 x86_64 versions support booting natively using UEFI firmware. But for this they need GPT partitioning of the disk used for UEFI booting. Windows x86_64 versions support either UEFI-GPT booting or BIOS-MBR booting. Windows 32-bit versions support only BIOS-MBR booting. Follow the instructions provided in the forum link given in the references sections as to how to do this. See http://support.microsoft.com/default.aspx?scid=kb;EN-US;2581408 for more info.
This limitation does not exist in Linux Kernel but rather depends on the bootloader used. For the sake of Windows UEFI booting, the Linux bootloader used should also be installed in UEFI-GPT mode if booting from the same disk.
检测 UEFI 固件架构版本
非苹果公司 MAC 系列的 UEFI 系统,都是 x86_64 UEFI 2.x 版的固件。
已知的 x86_64 UEFI 2.x版固件有:Phoenix SecureCore Tiano、AMI Aptio、Insyde H2O。
已知使用这些固件的系统有:华硕公司 EZ 型号的 BIOS(用于 Sandy Bridge P67 和 H67 主板上);微星公司的 ClickBIOS; 惠普公司的 EliteBooks;索尼公司的 Vaio Z 系列;以及众多英特尔公司的服务器和桌面系统主板
2008年以前的 Macs 大都使用 i386-efi 固件, 2008年以后大都使用 x86_64-efi 。有能力运行 Mac OS X Snow Leopard 64-bit 内核的 Macs 都是 x86_64 EFI 1.x 版的固件。
在 Mac OS 下输入以下命令可以找出该 Mac 的 efi 固件:
ioreg -l -p IODeviceTree | grep firmware-abi
如果命令返回 EFI32 则对应的是 i386 EFI 1.x 版本的固件,返回 EFI64 对应的则是 x86_64 EFI 1.x 版的固件. Macs 没有 UEFI 2.x 固件,Apple's EFI 的实现也不完全跟 UEFI 标准兼容。
Linux 内核对 UEFI 的支持
Linux 内核中有关 UEFI 的配置选项
内核中必需的 UEFI 选项为:
CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_RELOCATABLE=y CONFIG_FB_EFI=y CONFIG_FRAMEBUFFER_CONSOLE=y
UEFI 运行时变量/服务支持 - ‘efivars’内核模块。 这个选项对于“efibootmgr”之类的 UEFI 运行时管理工具而言十分重要
CONFIG_EFI_VARS=m
GUID 分区表GPT 选项 - 强制支持 UEFI
CONFIG_EFI_PARTITION=y
UEFI 变量支持
UEFI 通过定义变量使操作系统可以与固件交互。 UEFI 的 Boot 类变量用于引导程序和操作系统早期引导过程。UEFI 的运行时类变量则允许操作系统管理固件的特定配置(如:UEFI 引导管理器或 UEFI 安全引导协议的密钥等)
对 UEFI 运行时服务的访问由内核的“efivars”模块提供,通过打开内核的CONFIG_EFI_VAR=m选项实现。该模块将加载/sys/firmware/efi/vars目录下的变量。检查系统是否以 UEFI 模式引导的一个办法就是加载“efivars”内核模块,并检查/sys/firmware/efi/vars 目录中的内容是否类似下面这样:
输出范例 (x86_64-UEFI 2.3.1 与 x86_64 内核): # ls -1 /sys/firmware/efi/vars/ Boot0000-8be4df61-93ca-11d2-aa0d-00e098032b8c/ BootCurrent-8be4df61-93ca-11d2-aa0d-00e098032b8c/ BootOptionSupport-8be4df61-93ca-11d2-aa0d-00e098032b8c/ BootOrder-8be4df61-93ca-11d2-aa0d-00e098032b8c/ ConIn-8be4df61-93ca-11d2-aa0d-00e098032b8c/ ConInDev-8be4df61-93ca-11d2-aa0d-00e098032b8c/ ConOut-8be4df61-93ca-11d2-aa0d-00e098032b8c/ ConOutDev-8be4df61-93ca-11d2-aa0d-00e098032b8c/ ErrOutDev-8be4df61-93ca-11d2-aa0d-00e098032b8c/ Lang-8be4df61-93ca-11d2-aa0d-00e098032b8c/ LangCodes-8be4df61-93ca-11d2-aa0d-00e098032b8c/ MTC-eb704011-1402-11d3-8e77-00a0c969723b/ MemoryTypeInformation-4c19049f-4137-4dd3-9c10-8b97a83ffdfa/ PlatformLang-8be4df61-93ca-11d2-aa0d-00e098032b8c/ PlatformLangCodes-8be4df61-93ca-11d2-aa0d-00e098032b8c/ RTC-378d7b65-8da9-4773-b6e4-a47826a833e1/ del_var new_var
如果在引导菜单中使用了“noefi”内核参数,UEFI 运行时变量对操作系统将不可见。这个参数将通知操作系统完全忽略 UEFI 运行时服务。
用户空间工具
有几个访问和编辑 UEFI 变量的工具如下:
- efibootmgr - 用于创建/编辑 UEFI 引导管理器中的引导项 - 见efibootmgr 或 efibootmgr-git
- uefivars - 转储 UEFI 变量 - 见uefivars-git - 需用到 efibootmgr 库
- Ubuntu的固件测试套件(fwts)- 见fwts-git - uefidump 命令 -
fwts uefidump
非Mac UEFI 系统
efibootmgr
Initially the user may be required to manually launch the boot-loader from the firmware itself (using maybe the UEFI Shell) if the UEFI boot-loader was installed when the system is booted in BIOS mode. Then efibootmgr should be run to make the UEFI boot-loader entry as the default entry in the UEFI Boot Manager.
To use efibootmgr, first load the 'efivars' kernel module:
# modprobe efivars
If you get no such device found error for this command, that means you have not booted in UEFI mode or due to some reason the kernel is unable to access UEFI Runtime Variables (noefi?).
Verify whether there are files in /sys/firmware/efi/vars/ directory. This directory and its contents are created by "efivars" kernel module and it will exist only if you have booted in UEFI mode, without the "noefi" kernel parameter.
If /sys/firmware/efi/vars/ directory is empty or does not exist, then efibootmgr command will not work. If you are unable to make the ISO/CD/DVD/USB boot in UEFI mode try #Create_UEFI_bootable_USB_from_ISO.
Assume the boot-loader file to be launched is /boot/efi/EFI/gummiboot/gummibootx64.efi. /boot/efi/EFI/gummiboot/gummibootx64.efi can be split up as /boot/efi and /EFI/gummiboot/gummibootx64.efi, wherein /boot/efi is the mountpoint of the UEFI System Partition, which is assumed to be /dev/sdXY (here X and Y are just placeholders for the actual values - eg:- in /dev/sda1 , X=a Y=1).
To determine the actual device path for the UEFI System Partition (should be in the form /dev/sdXY), try :
# findmnt /boot/efi TARGET SOURCE FSTYPE OPTIONS /boot/efi /dev/sdXY vfat rw,flush,tz=UTC
Then create the boot entry using efibootmgr as follows :
# efibootmgr -c -g -d /dev/sdX -p Y -w -L "Gummiboot" -l '\EFI\gummiboot\gummibootx64.efi'
In the above command /boot/efi/EFI/gummiboot/gummibootx64.efi translates to /boot/efi and /EFI/gummiboot/gummibootx64.efi which in turn translate to drive /dev/sdX -> partition Y -> file /EFI/gummiboot/gummibootx64.efi.
UEFI uses backward slash as path separator (similar to Windows paths).
The 'label' is the name of the menu entry shown in the UEFI boot menu. This name is user's choice and does not affect the booting of the system. More info can be obtained from efibootmgr GIT README .
FAT32 filesystem is case-insensitive since it does not use UTF-8 encoding by default. In that case the firmware uses capital 'EFI' instead of small 'efi', therefore using \EFI\gummiboot\gummibootx64.efi or \efi\gummiboot\gummibootx64.efi does not matter (this will change if the filesystem encoding is UTF-8).
Linux Bootloaders for UEFI
See UEFI Bootloaders.
Create an UEFI System Partition in Linux
For GPT partitioned disks
Two choices:
- Using GNU Parted/GParted: Create a FAT32 partition. Set "boot" flag on for that partition.
- Using GPT fdisk (aka gdisk): Create a partition with gdisk type code "EF00". Then format that partition as FAT32 using
mkfs.vfat -F32 /dev/<THAT_PARTITION>
For MBR partitioned disks
Two choices:
- Using GNU Parted/GParted: Create FAT32 partition. Change the type code of that partition to 0xEF using fdisk, cfdisk or sfdisk.
- Using fdisk: Create a partition with partition type 0xEF and format it as FAT32 using
mkfs.vfat -F32 /dev/<THAT_PARTITION>
UEFI Shell
The UEFI Shell is a shell/terminal for the firmware which allows launching uefi applications which include uefi bootloaders. Apart from that, the shell can also be used to obtain various other information about the system or the firmware like memory map (memmap), modifying boot manager variables (bcfg), running partitioning programs (diskpart), loading uefi drivers, editing text files (edit), hexedit etc.
UEFI Shell download links
You can download a BSD licensed UEFI Shell from Intel's Tianocore UDK/EDK2 Sourceforge.net project.
- x86_64 UEFI Shell 2.0 (Beta)
- x86_64 UEFI Shell 1.0 (Old)
- i386 UEFI Shell 2.0 (Beta)
- i386 UEFI Shell 1.0 (Old)
Shell 2.0 works only in UEFI 2.3+ systems and is recommended over Shell 1.0 in those systems. Shell 1.0 should work in all UEFI systems irrespective of the spec. version the firmware follows. More info at ShellPkg and this mail
Launching UEFI Shell
Few Asus and other AMI Aptio x86_64 UEFI firmware based motherboards (from Sandy Bridge onwards) provide an option called "Launch EFI Shell from filesystem device" . For those motherboards, download the x86_64 UEFI Shell and copy it to your UEFI SYSTEM PARTITION as <UEFI_SYSTEM_PARTITION>/shellx64.efi (mostly /boot/efi/shellx64.efi) .
Systems with Phoenix SecureCore Tiano UEFI firmware are known to have embedded UEFI Shell which can be launched using either F6, F11 or F12 key.
Important UEFI Shell Commands
More info at http://software.intel.com/en-us/articles/efi-shells-and-scripting/
bcfg
BCFG command is used to modify the UEFI NVRAM entries, which allow the user to change the boot entries or driver options. This command is described in detail in page 83 (Section 5.3) of "UEFI Shell Specification 2.0" pdf document.
To dump a list of current boot entries -
Shell> bcfg boot dump -v
To add a boot menu entry for rEFInd (for example) as 4th (numbering starts from zero) option in the boot menu
Shell> bcfg boot add 3 fs0:\EFI\arch\refind\refindx64.efi "Arch Linux (rEFInd)"
where fs0: is the mapping corresponding to the UEFI System Partition and \EFI\arch\refind\refindx64.efi is the file to be launched.
To remove the 4th boot option
Shell> bcfg boot rm 3
To move the boot option #3 to #0 (i.e. 1st or the default entry in the UEFI Boot menu)
Shell> bcfg boot mv 3 0
For bcfg help text
Shell> help bcfg -v -b
or
Shell> bcfg -? -v -b
edit
EDIT command provides a basic text editor with an interface similar to nano text editor, but slightly less functional. It handles UTF-8 encoding and takes care or LF vs CRLF line endings.
To edit, for example rEFInd's refind.conf in the UEFI System Partition (fs0: in the firmware)
Shell> fs0: FS0:\> cd \EFI\arch\refind FS0:\EFI\arch\refind\> edit refind.conf
Hardware Compatibility
Main page HCL/Firmwares/UEFI
从 ISO 文件创建一个支持 UEFI 的启动盘
Due to shortcomings in Archiso, it is necessary to rebuild installation media in order for it to be UEFI-bootable.
Creating a MBR partition table and FAT32 filesystem should provide the most compatibility with incomplete/flakey UEFI implementations, and you need not worry about partition type.
Mount installation media, and create FAT filesystem using the label used in the Archiso configuration.
# mkdir -p /mnt/{usb,iso}
# mount -o loop,ro archlinux-2012.12.01-dual.iso /mnt/iso
# awk -F"archisolabel=" 'NF>1{sub(/ .*/,"",$2);print $2}' /mnt/iso/loader/entries/archiso-x86_64.conf | xargs mkfs.vfat /dev/sdb1 -n
Mount the newly created FAT filesystem, and copy the contents of the installation media to the USB media.
# mount /dev/sdb1 /mnt/usb
# cp -r /mnt/iso/* /mnt/usb
# umount /mnt/{usb,iso}
# sync
Remove UEFI boot support from ISO
Most of the 32-bit EFI Macs and some 64-bit EFI Macs refuse to boot from a UEFI(X64)+BIOS bootable CD/DVD. If one wishes to proceed with the installation using optical media, it might be necessary to remove UEFI support first.
Mount the official installation media and obtain the archisolabel as shown in the previous section.
Rebuild the ISO using xorriso from libisoburn:
$ xorriso -as mkisofs -iso-level 3 \
-full-iso9660-filenames\
-volid "ARCH_201212" \
-appid "Arch Linux CD" \
-publisher "Arch Linux <https://www.archlinux.org>" \
-preparer "prepared like a BAWSE" \
-eltorito-boot isolinux/isolinux.bin \
-eltorito-catalog isolinux/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
-isohybrid-mbr "/mnt/iso/isolinux/isohdpfx.bin" \
-output "~/archiso.iso" "/mnt/iso/"
Burn ~/archiso.iso to optical media and proceed with installation normally.
See also
- Wikipedia's page on UEFI
- Wikipedia's page on UEFI SYSTEM Partition
- Linux Kernel UEFI Documentation
- UEFI Forum - contains the official UEFI Specifications - GUID Partition Table is part of UEFI Specification
- Intel's Tianocore Project for Open-Source UEFI firmware which includes DuetPkg for direct BIOS based booting and OvmfPkg used in QEMU and Oracle VirtualBox
- Intel's page on EFI
- FGA: The EFI boot process
- Microsoft's Windows and GPT FAQ - Contains info on Windows UEFI booting also
- Convert Windows Vista SP1+ or 7 x86_64 boot from BIOS-MBR mode to UEFI-GPT mode without Reinstall
- Create a Linux BIOS+UEFI and Windows x64 BIOS+UEFI bootable USB drive
- Rod Smith - A BIOS to UEFI Transformation
- UEFI Boot problems on some newer machines (LKML)
- EFI Shells and Scripting - Intel Documentation
- UEFI Shell - Intel Documentation
- UEFI Shell - bcfg command info
- Some useful 32-bit UEFI Shell utilities
- LPC 2012 Plumbing UEFI into Linux
- LPC 2012 UEFI Tutorial : part 1
- LPC 2012 UEFI Tutorial : part 2