BootROM Code是在系统复位后执行的一段代码,用于配置PS(处理器系统)。本文将详细解释BootROM的启动过程及BootROM Header的格式。
1 BootROM流程
Zynq 7000在系统复位后进行配置。整个启动过程在图6-1中进行了说明,而BootROM的执行过程则在图6-5中展示。CPU 0执行BootROM代码,同时禁用DAP和TAP JTAG控制器。BootROM并不初始化DDR内存控制器和其他外设。
PL的上电和初始化序列可以与PS的启动并行进行,也可以在PS启动后进行。如果BootROM需要PL上电,那么在BootROM执行的早期阶段,BootROM会向devcfg.CTRL [PCFG_PROG_B]位写入数据,并等待devcfg.STATUS [PCFG_INIT]位断言后再继续执行BootROM。
PL电源对于PCAP访问和镜像解密是必要的。在访问其资源之前,BootROM会测试PL的状态,并使用90秒的超时时间。在启动过程中,PROGRAM_B设备引脚必须保持高位。如果在启动过程中将PROGRAM_B设备引脚保持低位,将导致设备锁定事件。
在BootROM的执行过程中,CPU 0按照预定的程序流程执行代码,确保系统按照正确的顺序和条件进行初始化。这包括了与PL的交互,以及对各种资源的访问和配置。如果任何步骤出现问题或超时,BootROM可能会返回错误代码或进入错误处理流程。
1.1 安全与非安全启动
出于安全考虑,在所有PS内部的主模块中,CPU 0始终是第一个退出复位状态的设备。CPU 1则被保持在WFE(等待事件)状态。当BootROM运行时,JTAG总是被禁用,无论复位类型如何,以确保安全性。在BootROM运行完毕后,如果启动模式为非安全模式,JTAG才会被启用。
BootROM代码还负责加载FSBL(第一阶段引导加载程序)/用户代码。当BootROM将控制权释放给第一阶段时,用户软件将接管整个系统的控制权。要再次执行BootROM,只能通过生成系统复位之一来实现。FSBL/用户代码的大小,无论是加密还是未加密,都限制在192 KB以内。这一限制不适用于非安全就地执行选项。
PS的启动源是通过BOOT_MODE绑定引脚(由弱上拉或下拉电阻指示)来选择的,这些引脚在电源上电复位(POR)期间被采样一次。采样值存储在slcr.BOOT_MODE寄存器中。
BootROM支持加密/验证和未加密的图像,分别称为安全启动和非安全启动。
当使用execute-in-place选项时,BootROM支持直接从NOR或Quad-SPI执行第一阶段图像,但仅限于非安全启动图像。execute-in-place仅适用于NOR和Quad-SPI启动模式。
在安全启动中,运行BootROM代码的CPU会对启动设备上的用户PS图像进行身份验证和解密,将其存储在OCM(片上存储器)中,然后跳转到该图像。
在非安全启动中,运行BootROM代码的CPU在跳转到OCM内存或闪存设备中的用户图像之前,会禁用所有安全启动功能,包括PL内的AES单元(如果使用了就地执行)。
无论是PS还是PL,其后续的所有启动阶段均由您负责并处于您的控制之下。BootROM代码对您是不可访问的。在第一阶段安全启动之后,您可以选择进行安全或非安全的后续启动阶段。而如果在第一阶段进行了非安全启动,那么后续阶段只能是非安全的启动。
1.2 启动源
存在五种可能的启动源:NAND、NOR、SD卡、Quad-SPI和JTAG。前四个启动源用于主启动方法,其中CPU从非易失性存储器中将外部启动映像加载到PS中。
JTAG是从属启动模式,仅支持非安全启动。外部主机计算机作为主设备,通过JTAG连接将启动映像加载到OCM中。在加载启动映像时,PS CPU保持空闲模式。
1.3 APU初始化
BootROM配置APU和MIO多路复用器以支持启动过程。BootROM使用CPU 0来执行ROM代码,而CPU 1执行WFE指令。缓存和TLB被无效化。BootROM配置MMU和其他系统资源以满足BootROM执行的需求。APU的状态在Post BootROM State部分有描述。
FSBL/用户代码和操作系统软件必须根据自己的需求配置APU。
2 BootROM Header
对于所有的主启动模式(闪存设备),BootROM都需要一个Header。然而,在JTAG从属启动模式下,BootROM Header并不被使用,并且BootROM代码不会加载FSBL/User代码。
BootROM Header的参数在表6-5中列出,包括它们的字号、字节地址偏移以及它们对于三种设备启动模式的适用性。
2.1 执行原地的中断表 — 0x000 到 0x01C
此区域预留了八个32位字用于中断映射。这对于NOR和Quad-SPI设备的执行原地(execute-in-place)特别有用。它允许以两种方式管理CPU向量表:
①使用MMU(内存管理单元)将flash线性地址空间重映射到0x0。
②使用协处理器VBAR寄存器来管理向量表的位置。
2.2 宽度检测 — 0x020
对于Quad-SPI启动模式,需要进行宽度检测。确保BootROM Header包含值0xAA995566,这样BootROM就能确定flash设备(们)的最大硬件I/O数据连接宽度。这个值有助于BootROM确定单个Quad-SPI设备(x1、x2或x4)的数据宽度,并检测8位并行I/O配置中的第二个设备。如果Quad-SPI启动模式没有这个值,BootROM会锁定系统并生成错误代码。
2.3 映像标识 — 0x024
此字有一个强制性的值0x584C4E58,即’XLNX’。这个值允许BootROM(连同Header校验和字段)确定是否存在有效的BootROM Header。如果值不匹配,在Quad-SPI、NAND或NOR启动模式下,BootROM代码会执行Header搜索。如果启动模式是SD卡,BootROM会锁定系统并生成错误代码。
2.4 加密状态 — 0x028
加密状态决定启动是安全的(启动映像已加密)还是非安全模式。此字段的有效值为:
• 0xA5C3C5A3:已加密的FSBL/User代码(需要eFUSE密钥源)。
• 0x3A5C3C5A:已加密的FSBL/User代码(需要电池支持的RAM密钥源)。
• 非0xA5C3C5A3或0x3A5C3C5A:未加密的FSBL/User代码(无密钥)。
eFuse的状态和加密状态字决定了加密密钥的来源(如果有的话)。有效的组合显示在表6-6中。
加密状态字段用于指示FSBL/User代码的加密状态,并确定加密密钥的来源。在安全的启动过程中,确保使用正确的密钥对代码进行加密和解密是至关重要的,以防止未经授权的访问和篡改。
2.5 FSBL/User Defined — 0x02C
该字段用于存储BootROM Header版本。
2.6 Source Offset — 0x030
此参数包含从有效BootROM Header开始到FSBL/User代码映像所在位置的字节数。这个偏移量必须对齐到64字节边界,并且必须从BootROM Header开始的地址偏移量0x8C0或更大。
2.7 Length of Image — 0x034
此字段包含要传输到OCM(On-Chip Memory,片上存储器)的加载映像的字节数。对于非安全模式,映像长度等于总映像长度参数,并且最大值为192KB。对于安全模式,映像长度等于经过身份验证和解密处理步骤后的映像长度。在这种情况下,由于加密开销,映像长度总是小于192KB。
当Quad-SPI或NOR闪存模式中的值为零时,BootROM将从关联的闪存设备中执行FSBL/User代码,而无需将映像复制到OCM(即原位执行)。
2.8 FSB Load Address — 0x038
此地址用于将FSBL(First Stage Boot Loader,第一阶段引导加载程序)复制到目标地址。
2.9 Start of Execution — 0x03C
这个字段定义了FSBL/User代码开始执行的内存地址。对于从OCM执行的代码,这个地址是相对于系统内存起始地址的,并且需要满足特定的对齐要求。在非安全模式下,这个地址有一个确定的范围,而在安全模式下,这个地址必须是0x0。对于原位执行的情况,地址需要指向特定大小的内存范围内,这取决于使用的启动模式(Quad-SPI或NOR)。
2.10 Total Image Length — 0x040
这个字段表示从闪存中加载到OCM(片上存储器)的总字节数。对于非安全启动,Total Image Length参数必须设置为与Length of Image参数相等。对于安全映像,Total Image Length参数包括HMAC头部、加密开销和对齐要求,并且总是大于Length of Image参数。Total Image Length参数由设计工具提供。
2.11 QSPI Config Word — 0x044
QSPI配置字,硬编码为0x01。这个字段用于配置QSPI(四线SPI)接口的相关参数。
2.12 Header Checksum — 0x048
这是Header的校验和值,在使用Header内的数据之前会进行检查。校验和是通过将0x020到0x044之间的字相加并取反结果计算得出的。
2.13 FSBL/User Defined — 0x04C to 0x097
这个区域可以在Bootgen中使用BIF文件的udf_bh字段。
2.14 Boot Header Table Offset — 0x098
指向映像头部表的指针。
2.15 QSPI Config Word — 0x09C
指向分区Header表的指针。这里提到的QSPI配置字与0x044处的配置字可能具有不同的用途或上下文,具体取决于系统的设计和实现。
2.16 Register Initialization Parameters — 0x0A0 to 0x89C
这个区域包含256对地址和数据字,可用于在访问FSBL/User代码之前初始化PS(处理系统)寄存器,例如用于MIO多路复用器、启动设备时钟和其他功能的寄存器。这些寄存器写入通常用于优化启动设备接口并设置其时钟频率以最大化性能。
寄存器初始化对包含两个32位字,首先是寄存器地址,然后是寄存器写入值。寄存器初始化可以以任何顺序进行,并且同一个寄存器可以根据需要被初始化为不同的值多次。寄存器初始化在复制FSBL/User代码之前进行,这样用户就可以修改默认的复位寄存器值,以减少访问代码和处理代码的时间。
BootROM在处理寄存器初始化列表时,会在地址寄存器为0xFFFF_FFFF或列表结束(256个地址/写入数据对)时停止。
2.17 FSBL/User Defined — 0x8A0 - 0x8BF
这段内存区域可以被FSBL(First Stage Boot Loader,第一阶段引导加载程序)或用户代码使用。
2.18 FSBL Image or User Code Start Address — 0x8C0
FSBL映像或用户代码必须从这个位置开始或在该位置之上。这个位置由Source Offset参数指向,并且必须对齐到64字节。
这里提到的FSBL是引导加载过程的一个阶段,通常用于初始化硬件、配置内存等,以便能够加载并执行更高级别的代码。User Code通常指的是在FSBL之后执行的应用程序或操作系统代码。
Source Offset参数用于指定FSBL映像或用户代码在引导加载器生成的二进制映像中的偏移量。通过这个参数,可以确保FSBL或用户代码从正确的内存地址开始。
对齐到64字节是为了确保代码在内存中的布局符合某些硬件或系统的要求,这通常可以提高性能或满足特定的访问模式。如果代码没有正确对齐,可能会导致性能下降或系统不稳定。