Mac OS X 启动过程

来源:互联网 发布:淘宝粉丝排名前十店铺 编辑:程序博客网 时间:2024/05/29 03:44

一.BIOS EFI 的区别:

BIOS是一个固定的程序,通常都是封闭的;EFI 是一套接口,像是一个运行时环境,规范了一组应用程序编程接口,基于EFI 的程序可以利用这些接口实现功能。目前大部分的PC 机使用BIOS 进行引导,Mac OS X使用EFI 进行引导,他们的目的都是一样的加载一些自举程序代码给CPU执行,自举程序负责POST(上电自检)阶段,CPU探测各种硬件总线,查明安装了哪些设备,BIOS或固件定位这些引导设备,执行引导加载程序,将所有必要的命令行参数传递给操作系统内核。固件接口,包括用户接口和处理器接口,比BIOS 更为丰富,相比之下,BIOS存在很多局限性:分区方案不扩展;无法和强大的图形设备进行接口操作;没有可扩展性,没有插件式的驱动程。

二.EFI服务

EFI服务分为两类:引导服务和运行时服务。引导服务只能在FEI模式下使用,运行时服务在退出EFI模式,在加载操作系统以后也能使用。

引导服务:通常情况下,当控制权转交到操作系统之前会调用ExitBootServices()这个函数,当系统还在EFI环境中,而且还没有调用ExitBootServices()函数之前,可以访问引导服务。引导环境提供的内容特别丰富,支持带抢占的多任务、事务通知、内存管理以及硬件访问。其中特别重要的服务就是提供对硬件的访问,EFI定义了协议的概念,协议封装了和某个特定设备或某一类设备相关的API,每个协议都定义了一个128位的GUID ,在运行时服务中也可以获得这些协议。

运行时服务:运行时服务可以在系统处于EFI模式的时候使用,同样在运行时服务在退出EFI模式后仍然可以使用,即在操作系统加载以后也可以访问这些服务。因为运行时服务不能提供引导服务提供的服务以及任何直接控制设备的服务,所以他提供的服务范围比较窄,包括系统时间以及NVRAM中保存的变量的访问。运行时服务中,可以利用nvram命令在命令行和EFI服务进行通信,通过系统调用访问I/O Kitnvram驱动程序。nvram在系统引导的时候使用,还负责保存一些需要在重新引导之间持久化数据。NVRAM变量是环境变量的功能,它是在系统范围内的,操作系统和固件都可以对其进行访问。

三.Boot.efi的执行流程(查看efi文件命令:od -A x -t x4 /System/Library/CoreServices/boot.efi)

① 获得EFI服务指针,查询CPUID,即获得指向EFI运行时服务的指针并保存在全局变量中,然后通过汇编指令检查CPU是否有AESNI这一位(表示是否支持AES-NI指令,用于加速AES加密标准的计算)。

② intializeConsole,通过RumTimeServices指针查询NVRAM变量Background clear,然后,在调用LocateProtocol()CONSOLE_CONTROL_PROTOCOL 之后,调用协议的GetMode()获得当前的控制台模式。

③ Lion调用一个苹自有的协议,传入Mac OS X10.7参数,并且获得/设置APPLE_VENDOR_NVRAM_GUID下的ROMMLB变量。

④ 初始化系统上设备的层次树形结构,设备树,之后会将设备树以参数结构中一个成员的形式传入内核。对于XNU内核并不关心这个device tree,但是IOKit子系统严重依赖于这个结构。查看设备树的命令:ioreg -w 0 -l -p IODeviceTree | grep -v \``IO

⑤ 位内核调用门分配内存。内核需要从引导设备加载到内存中,所以要分配好内存。内存调用门的地址保存在全局变量中。

⑥ 一些其他初始化操作

⑦ 检查休眠恢复,CheckHibernate函数负责将系统从休眠状态恢复,若确实从休眠中恢复,不必进过下面剩下的步骤。

⑧ 处理引导时的按键。ProcessOptions是引导加载器中一个关键的函数,负责识别出各种引导选项,并且最终将这些选项整合到内核命令行参数中。ProcessOptions使用的主要文件是com.apple.Boot.plist.这个文件在/System/Preferences/SystemConfiguration目录下,是boot.efi使用的主要属性列表文件。

⑨ 确认CPU是否支持64位模式(Lion才需要)

⑩ Lion引入了对CoreStorage的支持,CoreGtorage是苹果的逻辑卷分区机制。如果检查到了CoreStorge,那么引导加载器会获得分区IDEFI句柄,然后调用LoadCoreStorageConfiguration()函数获得CoreStorage参数。

11 SetConsoleMode这个函数用来初始化为图形模式。

12 DrawBootGraphics绘制引导LOGO

13 LoadKernelCache这个函数负责定位和加载预先链接好的内核。

14 InitBootStruct命令分配并初始化引导数据结构,内核只接受一个参数,即一个指向引导数据结构的指针,引导数据结构只是一个巨大的数据结构,包含了内核需要的所有的参数,包括从命令行参数,到设备树和其他RFI相关的参数等内容。

15 LoadDrives 这个函数从/System/Library/Extensions.mkext中加载设备驱动程序kext到内核中。

16 LoadRamDisk,如果XUN加载了的时候指定了RAMDisk,这个函数负责将RAMDisk加载到内存中。

17 StopAnimation 结束EFI引导中的动画。

18 FinalizeBootStruct 这个函数最终完成要传给内核的引导数据结构,在返回之前,这个函数还负责退出引导服务。

19 跳转到内核入口点 最后,Start函数尝试跳转到内核调用门。如果成功,永不返回,否则,返回8xxxx15h错误,然后睡眠10秒钟之后退出引导服务。

四.引导内核

在加载了kernelcache或内核本身之后,boot.efi退出引导服务,将控制权转交给内核。内核被传入的一个参数(包含BootStruct的页面),这个数据结构在boot.efi的最后阶段完成填写,内核可以通过这个数据结构提取出所需要的所有数据。

五.内核对EFI的回调

EFI的职责是加载内核,但是加载完成以后,内核仍然可以和EFI接口,从而使用EFI提供的运行时服务,运行时服务很少被用到,在osfmk/i386/AT386/model_dep.c文件中定义了3个函数,I/O Kit中,大量使用EFI(设备树)。

 

1 0
原创粉丝点击