引导过程:EFI 和 iBoot
引导过程指的是从就计算机通电那一瞬间到CPU开始执行操作系统代码时的整个过程,这个过程往往是系统启动过程中被忽视的一部分。在这个非常初期的阶段中,CPU 执行标准的启动代码。这部分代码需要对硬件设备进行探测,寻找最有可能启动的操作系统并且根据用户定义的参数启动这个操作系统。其他的操作系统用的默认(通用)的引导加载器(boot loader),而OS X 和 iOS 使用的则是自己的引导加载器,引导加载器工作在预期的(preboot)固件环境中。
传统形式的引导:BIOS
大部分PC采用的是BIOS,用来加载一些基本的自举(bootstrap)代码给CPU 执行。BIOS 有很大的局限性,无可扩展性可言,还和MBR 分区方案紧密耦合。
EFI
正因为BIOS 的局限性,苹果采用了一种更新的32位/64位兼容的标准:可扩展固件接口(Extensible Fireware Interface,EFI)。和BIOS 相比,EFI 是一个全功能的运行时系统,在引导期间提供了更为强大的接口,设置在之后的运行时也提供了接口。
EFI 程序其实是一个二进制程序,只不过二进制程序采用的是 便携式可执行(Portable Executable,PE)格式。EFI 二进制程序都实现了这样的原型:
typedef EFI_STATUS (EFIAPI *EFI_IMAGE_ENTRY_POINT) (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE SystemTable);
这个原型是说,EFI 二进制程序从 EFI环境接受两个参数:
- EFI句柄:引用镜像自己,通过这个句柄可以从运行时查询各种详细信息
- EFI系统表:指向主表(master table)的指针,从这个表中可以获得所有EFI 标准的句柄和运行时API指针
NVRAM 变量
NVRAM 是固件接口中一个非常强大的功能,而且这显然是传统BIOS 没有的功能。NVRAM 变量和 shell 变量的语义是一样的,都是环境变量的功能,但是NVRAM 是在系统范围内存在的,操作系统和固件本身都可以访问。
一般来说,NVRAM 变量可以分为以下几个类别:
- 引导相关的变量:用于指定要引导的内核和根文件系统,还负责向内核传递参数
- 固件内部变量:固件使用的变量,一般被操作系统忽略
- 临时变量:根据需要设置或清空,通常在重新引导的时候不会停留
boot.efi 的执行流程
- 获得EFI 服务指针,查询CPUID
- initialConsole
- Lion 特有的初始化操作
- InitDevice Tree
- 为内核调用门分配内存
- 一些其他的初始化操作,如InitMemoryConfig.InitSupportedCPUTypes等函数
- 检查休眠恢复
- 处理引导时的按键
- Lion:确认CPU支持64位模式
- Lion:检查Core Storage
- SetConsoleMode
- DrawBootGraphics
- LoadKernelCache
- InitBootStruct
- LoadDrivers
- LoadRamDisk
- StopAnimation
- FinalizeBootStruct
- 跳转到内核入口点
引导内核
在加载了 kernelcahce 或内核本身之后,boot.efi 退出引导服务,将控制权转交给内核。内核被传入一个参数,一个包含BootStruct 的页面,这个数据结构在boot.efi 的最后阶段完成填写,内核可以通过这个数据结构提取出所需要的所有0数据。
内核对 EFI 的回调
EFI 的职责是加载内核。但是内核仍然可以和 EFI 接口,从而使用 EFI 提供的运行时服务。
- efi_init( ):这个函数从内核的引导参数中获得 EFI 运行时服务,这个函数会调用下一个函数
- efi_set_tables_[32|64](EFI_SYSTEM_TABLE)*:这个函数有32位和64位两个版本,接受员工指向EFI 系统表的指针作为参数,计算器签名和CRC,然后获得运行时服务的指针,将这个指针保存在全局变量gPEEFIRunTimesServices中
- *hibernate_newruntime_map(void map, vm_size_t map_size, unit32t system_table_offset):系统从休眠中唤醒的时候通过这个函数重新初始化运行时服务表
Mach 核心很少使用EFI, 而BSD 更是对 EFI 毫不知情。 而在 I/O Kit 中,大量使用EFI(及设备树)。
Boot Camp
苹果的EFI 实现的另一个重要的特性是Boot Camp。Boot Camp 是苹果双重引导的解决方案,这个解决方案允许在Mac 上运行非苹果的操作系统(主要是Windows)。由于苹果使用私有的硬件并且使用了 EFI,而Windows仍然使用落后的BIOS,因此苹果在Boot Camp中提供完整的驱动程序包 ,并且修改了boot.efi支持多系统引导。
bless( )
对于机器上的固件,OS X 提供的非常有限的访问能力,出了nvram( ) 命令外,提供的唯一能接触固件的工具就是bless( ),这个工具是一个控制和修改系统引导参数的工具,实际上是定义系统引导的位置和方向。这个工具支持6种模式,如下表:
模式 | 用途 |
---|---|
Folder | 将制定的目录设置为系统目录 |
Mount | 指定一个文件系统而不是目录作为引导卷。文件系统参数是已挂载的文件系统,因此是一个名字 |
Device | 通过/dev 表示的设备指定一个卷,这时设备中的文件系统还没有挂载 |
NetBoot | 设置引导的网络服务器,使用-server bsdp://[interface@]a.b.c.d参数,其中a.b.c.d 表示服务器的地址,interface 是可选项,在多 home 的系统中表示本地接口。BSDP 是苹果的“BootStrap Discovery Protocol” 是对 DHCPv4的一个扩展,在苹果之外没有其他方法使用或实现这个协议 |
Unbless | 撤销某个文件夹、挂载点、设备或网络引导的“bless” |
Indo | 仅显示信息 |
iOS 和 iBoot
苹果的i 系列设备都不支持 EFI, 其引导过程是苹果自创的。是通过iOS 特有的引导加载器iBoot。引导过程分多个阶段,如下图所示: