PXE
简介
PXE全称是Pre-boot Execution Environment,由 Intel 公司开发的网络引导技术,工作在 Client/Server 模式,允许客户机通过网络从远程服务器下载引导镜像,并加载安装整个操作系统。PXE 严格来说是一种引导的方式。协议分为 client 和 server 端,PXE client 在网卡的 ROM 中,当计算机引导时,BIOS 把 PXE client 调入内存执行,由 PXE client 将放置在远端的boot文件通过网络下载到本地运行。PXE client先通过DHCP协议获取IP地址以及TFTP服务器地址,然后通过TFTP从服务器下载boot文件,并加载允许boot文件。所以,PXE client都集成了DHCP client和TFTP client的功能。有了PXE,就可以大规模地、自动化地实现操作系统的安装。
如前所述,PXE client的加载和执行由BIOS来负责,BIOS分Legacy和UEFI两种,Legacy是早期的接口规范,有诸多限制,UEFI则是新一代的接口规范。实现上,网卡作为一种PCIe设备,而PCIe提供PCI Expansion ROM功能,所以,通常将PXE client制作成PCI Expansion ROM烧进网卡,BIOS通过访问PCI设备空间的方式来获取PXE client。习惯上,PCI Expansion ROM也叫PCI Option ROM。
Legacy
Legacy BIOS是上世纪80年代开发的基于16位的系统固件接口标准,只支持Intel CPU,磁盘采用MBR分区,最多支持4个主分区,硬盘容量也限制在2T,启动时间较慢。
Legacy启动流程如下:
1.电脑开机后,开始启动BIOS,开始BIOS自检;
2.通过自检后,bios找到硬盘上的主引导记录MBR;
3.MBR开始读取硬盘分区表DPT,找到活动分区中的分区引导记录PBR,并且把控制权交给PBR;
4.PBR搜索活动区中的启动管理器bootmgr,找到后,PBR把控制权交给bootmgr(相当于xp里的ntldr文件);
5.Bootmgr寻找活动分区中的boot文件夹中的BCD文件(启动配置数据,相当于xp里的boot.ini文件);
6.找到BCD后,Bootmgr首先从BCD 中读取启动管理器bootmgr菜单的语言版本信息,没多系统直接加载系统,有多系统会显示多操作系统选择画面。
UEFI
UEFI全称是Unified Extensible Firmware Interface,是基于六十四位的系统固件接口标准。UEFI 是Legacy BIOS 的继承者,旨在解决其技术限制。UEFI的前身是Intel在1998年开始开发的Intel Boot Initiative,后来被重命名为可扩展固件接口(Extensible Firmware Interface,缩写EFI)。Intel在2005年将其交由统一可扩展固件接口论坛(Unified EFI Forum)来推广与发展,为了凸显这一点,EFI也更名为UEFI(Unified EFI)。UEFI论坛的创始者是11家知名电脑公司,包括Intel、IBM等硬件厂商,软件厂商Microsoft,及BIOS厂商AMI、Insyde及Phoenix。
UEFI使用GPT的分区引导方案,支持更大的硬盘。由于省去了BIOS自检的过程,所以启动速度更快。
UEFI启动流程如下:
1.电脑开机后,上电自检,UEFI固件被载,并由它初始化启动要用的硬件;
2.UEFI固件寻找EFI分区中的启动文件(\efi\Microsoft\boot\bootmgfw.efi)启动管理器;
3.启动管理器读取硬盘EFI分区中BCD文件(efi\Microsoft\BCD)系统菜单;
4.最后根据配置内容加载引导程序winload.efi(\Windows\system32\winload.efi)加载系统。
总之,UEFI是取代Legacy的新一代的BIOS,功能更加强大,而且它是以图形图像模式显示,让用户更便捷的直观操作。
Legacy与UEFI的区别
UEFI提供了更好的用户界面;
legacy使用MBR分区方案,UEFI使用GPT分区方案;
legacy最多支持4个分区,硬盘容量2TB,UEFI支持最多128个分区,硬盘容量9zB;
legacy有POST自检,启动速度慢,UEFI没有POST自检,启动速度快;
legacy仅在16位模式下运行,UEFI支持32位和六十四位模式;
legacy仅支持键盘,UEFI支持鼠标、触摸板;
legacy不支持安全启动,UEFI支持安全启动;
legacy流程复杂,UEFI流程简单。
在系统上电的时候,可以进入bios配置界面,选择Legacy还是UEFI。
Option ROM
简介
为了将操作系统加载到内存中,系统需要三类设备:
存储设备:用于保存操作系统;
显示设备:用于显示当前的启动进度;
输入设备:用于接收用户输入信息;
在这个阶段,操作系统还没有被加载到内存执行,也就意味着操作系统中对应的设备驱动程序也没有被加载,因此,就需要在Expansion ROM里面存放一份启动阶段使用的设备驱动程序。简单来说就是,BIOS阶段要使用一个PCIe设备,但是BIOS不包含这个设备的驱动程序,这个时候就从这个PCIe设备Expansion ROM里获取设备驱动程序代码,并加载到内存中执行。
PCI Expansion ROM又叫PCI Option ROM,用于设备初始化和系统启动的code。有的PCI Option ROM被存放在板卡上,而有的则保存在BIOS的binary里面。PCI Option ROM有固定的格式,BIOS通过读取PCI的配置空间来确定是否当前网卡支持Option ROM。如果支持,且配置了从网络引导,那么BIOS会负责将Option ROM中的PXE client载入内存,并执行PXE client。
配置空间
在PCI 配置空间的0X30处有这么一个寄存器,叫Expansion ROM Base Address。
关于“Expansion ROM Base Address”寄存器的具体定义细节如下:
bit11-bit31表示Expansion ROM映射到内存空间的高位地址,BIOS先全写1再回读就能获取到Option ROM的size,bit0用于控制对Expansion ROM的访问,1为使能Expansion ROM,启动地址解码。BIOS把“Expansion ROM Base Address”寄存器的基地址配置成内存空间地址并使能Expansion ROM以后,BIOS就可以对设备的Expansion ROM进行读访问了。具体过程如下:
1、 BIOS向Expansion ROM Base Address Register的高21位写入全1;
2、 BIOS读取Expansion ROM Base Address Register,如果值是0,那就表示不存在Expansion ROM;否则高21位就表示Expansion ROM所需的地址空间,所有无关的位都将返回0;
3、 BIOS给PCIe Expansion ROM映射内存空间,并把内存地址写入Expansion ROM Base Address Register的高21bit;
4、 BIOS将Expansion ROM Base Address Register bit 0置为1,使能address decode;
5、 后续BIOS访问这个内存地址即可实现对Expansion ROM的访问。
Shadow RAM
Shadow RAM也称为“影子”内存。它是为了提高系统效率而采用的一种专门技术。 Shadow RAM所使用的物理芯片仍然是CMOS DRAM(动态随机存取存储器)芯片。Shadow RAM 占据了系统主存的一部分地址空间。其编址范围为C0000~FFFFF,即为1MB主存中的 768KB~1024KB区域。这个区域通常也称为内存保留区,用户程序不能直接访问。 Shadow RAM的功能是用来存放各种ROM BIOS的内容。或者说Shadow RAM中的内容是ROM BIOS的拷贝。因此也把它称为ROM Shadow(即Shadow RAM的内容是ROM BIOS的“影 子”)。 在机器上电时,将自动地把系统BIOS、显示BIOS及其它适配器的BIOS装载到Shadow RAM 的指定区域中。由于Shadow RAM的物理编址与对应的ROM相同,所以当需要访问BIOS时, 只需访问Shadow RAM即可,而不必再访问ROM。 通常访问ROM的时间在200ns左右,而访问DRAM的时间小于100ns(最新的DRAM芯片访问时 间为60ns左右或者更小)。在系统运行的过程中,读取BIOS中的数据或调用BIOS中的程序 模块是相当频繁的。显然,采用了Shadow技术后,将大大提高系统的工作效率。 按下按键你可以看到该地址空间分配图,在如图所示的1MB主存地址空间中,640KB以下的 区域是常规内存。640KB~768KB区域保留为显示缓冲区。768KB~1024KB区域即为Shadow RAM区。在系统设置中,又把这个区域按16KB大小的尺寸分为块,由用户设定是否允许使 用。 C0000~C7FFF这两个16KB块(共32KB)通常用作显示卡的ROM BIOS的Shadow区。 C8000~EFFFF这10个16KB块可作为其它适配器的ROM BIOS的Shadow区。F0000~FFFFF 共64KB规定由系统ROM BIOS使用。 应该说明的是,只有当系统配置有640KB以上的内存时才有可能使用Shadow RAM。在系统 内存大于640KB时,用户可在CMOS设置中按照ROM Shadow分块提示,把超过640KB以上的 内存分别设置为“允许”(Enabled)即可。
格式
Option ROM为了方便BIOS解析,需要有一定的格式。每个ROM都有一个Option ROM Header和PCI Data Structure以及Image,对于UEFI Image可以是不同的CPU平台,比如Intel、AMD、ARM等;Option ROM Header和PCI Data Structure都有一定的结构,由标准定义。Other Header是用于自定义的一些头,不同的实现可以不一样;如果同时支持Leagacy PXE和UEFI PXE,那么Legacy PXE ROM必须排第一。
Option ROM Header
Option ROM Header结构定义如下:
每个ROM都必须以0x55AA开始,BIOS会对此进行校验,以表示是否是一个有效的Option ROM。
EFI ROM Header
EFI ROM Header存在一些差异。
PCI Data Structure
PCI Data Structure必须以”PCIR”开始,否则会认为是无效的;
Revision Level of Code/Data:Option ROM按版本分有2.1的Option ROM和3.0的Option ROM;
Device List Pointer:指向该ROM支持的设备id列表,值为相当于该PCI Data Structure的偏移,如果Code Type值为3,该字段必须为0;
Image Length:镜像的大小,单位512字节;
Code Type:取值范围0-3,如下:
0:Intel x86,PC-AT compatible
1:Open Firmware standard for PCI
2:Hewlett-Packard PA RISC
3:UEFI
对于Leagcy PXE来说,Code Type为0,对于UEFI PXE来说,Code Type是3;
Indicator:是否最后一个PCI Data Structure。
Expansion Header
每个Expansion Header都必须以“$PnP”开始。
PXE协议
1、 通过4次DHCP报文交互,获取分配的IP地址、TFTP server的地址和boot file name;
a)pxe client广播一个dhcp discovery广播报文;
b)dhcp server回复一个dhcp offer单播报文;
c)pxe client广播一个dhcp request广播报文;
d)dhcp server回复一个dhcp ack单播报文,dhcp ack的Next Server IP Address会提供TFTP server的IP地址,Boot file name会提供引导文件的名字;
2、 通过TFTP从TFTP Server下载boot file:
3、 执行boot file,将控制权交给boot file,boot file会继续下载OS镜像相关的文件,然后加载OS。
BIOS
中断
BIOS和Option ROM之间是通过中断来访问的,BIOS上电会注册中断服务,Option ROM在运行过程中可以重新进行注册。BIOS中断比较多,以下只列举了Option ROM常用的几个中断:
1、 INT 18h:引导失败触发该中断通知BIOS恢复,将控制权还给BIOS;
2、 INT 19h:启动引导,Option ROM注册并调用该中断就可以控制整个引导过程,BIOS默认会内置INI 19h服务,用于启动软盘、CD-ROM、硬盘等驱动器;
3、 INT 13h:访问磁盘服务,例如:读写扇区、初始化驱动器参数、读取驱动器参数、硬盘复位等;
POST流程
1、 上电初始化:所有设备上电,BIOS会完成所有Option ROM的内存映射;
2、 PnP Option ROM初始化:调用ROM header的初始化入口完成初始化并返回BIOS,该阶段不会注册与引导有关的中断;
3、 BIOS更新IPL 表和BCV表,每一个表项都存放了BCV或BEV,表项顺序代表了启动优先级;
4、 BIOS遍历BCV表,安装每一个BCV设备:调用BCV,注册INT 13h,将驱动器添加到系统中,第一个添加的驱动器获得80h编号,将作为引导设备;
5、 Legacy Option ROM初始化:调用ROM header的初始化入口;
6、 按热键,弹出启动菜单,选中的设备将优先引导;
7、 BIOS执行INT 19h处理:
a)到这一阶段,所有设备都已安装,从IPL表中的第一个设备开始尝试启动;
b)如果是软盘等不带Option ROM的设备,则调用BIOS内置的引导程序,如果是BEV设备,则调用表项中存放的BEV指针;
c)如果成功,程序永远不返回;
d)如果引导失败,则触发INT 18h中断做恢复处理,将控制权返回BIOS,BIOS则尝试下一个设备。
iPXE
简介
iPXE是一个PXE开源项目,除了DHCP/TFTP外还支持多种网络协议,如:HTTP、Iscsi、wireless、Infiniband等,集成了很多种友商网卡驱动,可以制作多种Option ROM,包括Legacy、UEFI、USB等;
代码架构
iPXE架构设计比较通用合理,从上往下分为:应用层、dhcp/tftp client、socket接口层、协议栈、驱动适配层、网卡驱动层。
dhcp/tftp client:主要实现了client功能,例如:dhcp client、tftp client、iSCSI INI等;
socket层:为上层提供统一的send/receive接口;
协议栈:提供类似Linux协议栈的功能,包括TCP/IP协议栈、Infiniband协议栈等;
驱动层适配层:向上为协议栈提供统一的接口,向下要提供框架,适配各种类型的网卡驱动;
网卡驱动层:真正的网卡驱动,负责将上层传递下来的报文递交给网卡传输出去,将网卡上送的报文递交给上层处理,驱动适配层通过UNDI API接口来访问网卡驱动层提供的服务。
目录结构
代码在src目录下
src/arch目录下主要个各种cpu平台的代码,跟体系结构相关,如:x86、arm等;
src/bin是编译rom输出的存放目录;
src/net目录是各种协议栈的实现,如TCP/IP、802.11、Infiniband等;
src/driver目录下是各种驱动,以太网卡位于driver/net目录下,driver下面又按照驱动类别划分了子目录
各种Header的定义
对于Legacy PXE来说,Option ROM Header、PCI Data Structure、Expansion Header都定义在src/arch/x86/prefix/romprefix.S文件中。除此之外,还定义了几个私有的Header:iPXE Header、UNDI Header、PXENV+ Header、!PXE Header,其中PXENV+ Header用于保护模式,!PXE Header用于实模式。因为PXE client访问服务都是通过API CALL的形式来进行的,所以增加了PXENV+ Header和!PXE Header。
pxe_api_call机制
pxe_api_call已经设计为一种通用机制,上层代码都通过该机制来访问下层提供的服务,通过opcode查找下层注册的回调函数,然后执行回调函数。
tftp pxe_api_call
应用层要启动tftp 传输,就会调用pxe_api_call来访问tftp协议层提供的服务.
udp pxe_api_call
tftp是通过udp来传输的,因此tftp层又会通过pxe_api_call来访问udp层提供的服务.
网卡的加载/卸载
上层服务通过pxe_api_call来启动网口的加载和卸载.
上层服务通过pxenv_start_undi来实现网卡的probe,通过pxenv_stop_undi来实现网口的remove。
访问网卡服务
设备的打开、关闭,报文的接收和传输,也是通过pxe_api_call机制来访问网卡驱动的:
上层服务通过pxenv_start_undi来实现网卡的probe,通过pxenv_stop_undi来实现网口的remove。
访问网卡服务
设备的打开、关闭,报文的接收和传输,也是通过pxe_api_call机制来访问网卡驱动的:
pxenv_undi_open会调用到netdev_open,pxenv_undi_close会调用到netdev_close,通过pxenv_undi_transmit来发送报文,通过pxenv_undi_isr来实现poll,注意:一张网卡可能会注册多个netdev,但当前active的只能有一个,从netdev_open和netdev_close的代码可以看出。
而pxe_netdev的设置是通过pxe_set_netdev函数实现的,pxe_set_netdev函数最终会被pxenv_start_undi调用,因此,在probe的时候就确定了当前active的netdev。因此,iPXE会从第一个网口probe开始,一直到引导成功,只有引导失败才会尝试下一个网口。
iPXE驱动框架
struct pci_driver
网卡是一种PCIe设备,因此驱动适配层提供了接口来完成PCIe设备的接入。只要对完成对struct pci_driver类型变量的定义和初始化即可完成驱动代码的接入。