前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FPGA Xilinx Zynq 系列(三十七)Linux 启动

FPGA Xilinx Zynq 系列(三十七)Linux 启动

作者头像
FPGA技术江湖
发布2020-12-30 12:15:30
3.3K0
发布2020-12-30 12:15:30
举报
文章被收录于专栏:FPGA技术江湖FPGA技术江湖
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。

今天给大侠带来FPGA Xilinx Zynq 系列第三十七篇,开启第二十四章,带来Linux 启动相关内容,本篇为本系列最后一篇,本篇内容目录简介如下:

本系列分享来源于《The Zynq Book》,Louise H. Crockett, Ross A. Elliot,Martin A. Enderwitz, Robert W. Stewart. L. H. Crockett, R. A. Elliot, M. A. Enderwitz and R. W. Stewart, The Zynq Book: Embedded Processing with the ARM Cortex-A9 on the Xilinx Zynq-7000 All Programmable SoC, First Edition, Strathclyde Academic Media, 2016。

Linux 启动

在介绍了 Linux 内核之后,该花点时间来考虑 Linux 启动过程,也就是当一个 Linux 计算机或嵌入式系统上电的时候,在屏幕背后所发生的事情的顺序了。我们会从一台 Linux 台机的启动过程的高层概述开始,进而考虑启动的各个阶段。然后我们要通过用于 Zynq 的 Linux 的启动过程来看嵌入式 Linux 的启动过程和桌面的有什么不同。

24.1 概述

当一个 Linux 系统上电或重启时发生的第一件事情,是处理器要执行在某个预定的位置上的代码。对于桌面计算机,这个位置是位于主板上的闪存中的,这部分闪存里的是基本输入 / 输出系统(Basic Input/Output System,BIOS)。因为现代 的 PC 提供了如此多种多样的启动设备,BIOS 要做的第一件事情是判断从哪个设备来启动 [1]。

一旦决定了启动设备,FSBL 会被加载到 RAM 并由处理器执行。FSBL 是一片非常 小的代码 —— 小于 512 字节,也就是单个扇区 —— 它唯一的作用就是把第二阶段引导装载程序 (Second-Stage Bootloader,SSBL)装入 RAM。

在启动过程中,SSBL 这个阶段是要呈现一个引导菜单的,如果你之前用过 Linux,就可能会注意到这个菜单。这个菜单给出了可能的引导选项。当菜单中的一个引导选项被选定后,引导装载程序会装载相应的操作系统,然后那个操作系统自己的代码会解压、装载自己到内存中去,然后再初始化内核。在内核启动之前,引导装载程序还会执行一些其他的功能,不过这些以后再说。所需的内核模块成功启动后,引导过程的最后一个阶段调用第一个用户空间的 函数:init。这个函数初始化系统所有的高层部分。以上就是 Linux 启动过程的高层概述。下一节,我们把启动过程分解为几个连续的环节,更为详细地讨论每个环节。

图 24.1: 桌面 Linux 启动的阶段

24.2 桌面 Linux 引导过程的各个阶段

24.2.1 BIOS

BIOS 负责初始化系统的启动并定位到可用的引导设备。当系统上电的时候,处理器会开始执行 BIOS,这个过程分成两个部分 —— 上电自检 (Power-On Self Test,POST)和运行时刻服务。

BIOS 执行的第一个动作取决于系统是上电(冷启动)还是重启(热启动)。如果系统是上电了,第一个动作是初始化并测试系统的基本硬件部分 ——就是一个叫做 POST[1] 的过程。一旦所有的硬件设备都初始化并被验证,POST 的代码就从内存中抹掉了。不过,如果系统是被重启的,内存中会置一个特殊的标识,那么 BIOS 就不会做 POST,以节省时间。

一旦 POST 从内存中抹掉了,BIOS 就进入到运行时刻服务。这个功能搜索系统可用的引导设备,这些设备当时必须是开着的才能被找到。这些设备搜索的顺序定义在互补金属氧化物半导体(Complementary Metal Oxide Semiconductor,CMOS) 里的配置数据中。通常 Linux 的启动设备是个硬盘,不过也可以是任何东西:软盘、网络设备、U 盘或 CD-ROM。

从硬盘引导 Linux 的时候,主引导记录 (Master Boot Record,MBR)—— 就 是在那个设备的第一个扇区的那 512 字节 —— 里面是第一级引导装载程序。BIOS要做的最后一件事情就是把这个 MBR 装载到内存中,一旦装载了,BIOS 就放弃了控制 [1]。

24.2.2 第一级引导装载程序 (FSBL)

FSBL 是 MBR 里的一段代码,MBR 里还有一个分区表和一个验证签名。MBR 里最 大的一块 (446 字节)就是那个初级引导装载程序,里头有可执行代码和错误消息[1]。接下去的 64 个字节是分区表,里面是 4 个主分区的记录,每个 16 字节。MBR最后一部分是两个字节的引导签名,0xAA55,用来验证 MBR 是有效的。图 24.2 表示了 MBR 的结构。

图 24.2: 主引导记录 (MBR)的结构

初级引导装载程序的工作就是搜索分区表中有效的分区,找到 SSBL 然后装载进来。一旦找到有效的分区,还会继续扫描其他的分区以确保其他都是不能引导的分区。然后就把那个有效的分区里的引导记录装载到内存来执行。

24.2.3 第二级引导装载程序 (SSBL)

SSBL 会显示这个系统目前可以引导的操作系统的列表。选择了所需的操作系统之后,就会把内核映像解压装载到内存中,然后再把处理器交给操作系统 [4]。

有两种主要的引导装载程序:Linux 装载器 (Linux Loader,LILO)和大一统引导装载程序 (Grand Unified Bootloader,GRUB)。LILO 和 GRUB 都包含了 FSBL 和 SSBL 的组合。LILO 已经出现了好一段时间了,但是现在在大多数地方都被 GRUB所替代了。LILO 需要内核文件保存在原始磁盘扇区中,而 GRUB 能从 ext2 或 ext3文件系统中装载内核 [1]。GRUB 在第一级和第二级引导之间增加了额外的步骤,能读出特定的文件系统,从而实现了这个功能。

还有其他一些引导 Linux 内核的方法,比如 SysLinux 或 Loadlin,让你可以从当前运行的 Windows/DOS 环境下引导 Linux 并替换掉当前的操作系统。

24.2.4 内核

第二个阶段引导装载程序把 CPU 的控制权交出之后,一个程序会运行一小段硬件设置,然后再解压内核映像。一旦解压完成,内核映像会被放到内存的高段 ——不受内核页表直接映射的那部分物理内存。如果存在 RAM 盘映像,这个映像也会被搬移到内存中并标记好,以备后用 [1]。到了这个时候,内核才第一次被调用并启动。

在内核启动的过程中实现硬件的设置,包括设置堆栈、配置页表、开启内存分 页以及判断 CPU 和 FPU 的类型 [1]。

24.2.5 Init

Linux 引导过程的最后一个阶段是初始化 init,这是第一个用户空间的应用程序。一旦启动起来,init 会查找 /etc/inittab 文件,从中寻找类型为 initdefault的条目,那条描述了这个 Linux 系统的初始运行级别 (runlevel)。不同的 Linux发布版本对于系统的运行级别会有不同的配置。以 Linux 标准基础规范为例,它有7 个运行级别,详列于表 24.1[3]。

init 是第一个运行的使用标准 C 库编译的程序,在此之前,任何标准 C 库的程序都不曾运行过 [1]。

表 24.1: Linux 标准基础的默认运行级别 [3]

24.3 引导 Zynq

看过传统 Linux 引导过程之后,就可以来了解在 Zynq 芯片上引导 Linux 时有些怎样的变化了。在一些关键的地方,嵌入式 Linux的引导过程和桌面版本是不同的。我们先从全局看 Zynq 整个的引导过程,然后再细看其中的某几个阶段的情况。

Zynq 芯片的引导经历一系列的阶段,起点是上电时初始化的引导 ROM。芯片的引导模式配置引脚的值决定了引导模式 [5]。引导模式定义了 FSBL 要从哪个接口装载 ——JTAG、NAND Flash、NOR Flash、QSPI Flash 还是 SD 卡 [2]。一旦引导模式 被确定了,引导 ROM 会读入引导头和给定的配置参数,验证了这个 FSBL 映像之后,把它从指定的接口装载到 OCM 中。一旦映像装入到 OCM 中,CPU 的控制就转交给 FSBL了。

一般来说,FSBL 里会有指令让 CPU 用读 / 写操作进一步配置 PS,然后用 DevC 配置 PL[5]。DevC 用高级加密标准 (dvanced Encryption Standard,AES)和基于散列的消息认证码(Hash-based Message Authentication Code,HMAC)来做 FSBL 和PL位流的解密,这是通过DevC和处理器配置访问端口(Processor Configuration Access Port,PCAP)实现的 [5]。

表 24.2 详列了 Zynq Linux 引导过程中的各个阶段,图 24.3 则是这些阶段的图 形表示。

表 24.2: Zynq Linux 引导过程的阶段 [5]

图 24.3: Zynq Linux 引导过程

在进一步了解 Zynq 的每个引导步骤之前,先看一下在 Zynq 芯片上引导 Linux 需要哪些文件,这样在后面的章节中提到这些文件的时候就不会稀里糊涂了。

24.3.1 Zynq 引导文件

为了在一个 Zynq-7000 AP 设备上启动 Linux,在引导用的介质上需要有这四个文件:

1. BOOT.BIN

2. zImage

3. devicetree.dtb

4. ramdisk8M.image.gz

这些文件中的第一个 (BOOT.BIN)是 Zynq 引导程序的映像文件。它实际上是两个必不可少的文件,FSBL 和 SSBL 的可执行可链接格式 (.elf)文件,以及一个可选的位流(.bit)文件。FSBL 和 SSBL 文件,恰如其名,是引导装载程序的最后阶段,用来在设备上载入那个 Linux 的。位流是用来配置 Zynq-7000 AP 设备上的可编程逻辑部分的。

这些文件组合起来形成这个引导程序映像的顺序是很重要的,如果需要有可选的位流文件的话,它必须放在 FSBL 文件的后面,在 SSBL 文件的前面。

图 24.4 显示了引导映像文件所需的顺序关系。

图 24.4: 引导镜像文件的顺序

zImage文件里是压缩了的Linux内核,一旦被SSBL装载进内存,它会自动解压。

Linux 要运行的硬件的数据保存在设备树 blob(devicetree.dtd)文件中。设备树是用人可读的文本文件定义的,这种文件叫做设备树源文件 (.dts),然后用编译器编译成二进制格式,成为 U-Boot 能懂的设备树 blob。

最后的那个文件 (ramdisk8M.image.gz)是一个 RAM 盘映像,载入内存后,使 得 RAM的一部分用作像一个磁盘驱动器一样。这样的一个 RAM中的临时磁盘驱动器,使得 Linux 将其当作一个文件系统用以建立根目录。

图 24.5 显示了 Zynq Linux 引导介质中的全部内容。

图 24.5: Zynq Linux 引导介质中所需的文件

下面就来详细了解 Zynq 引导过程的每一个步骤。

24.3.2 Stage-0 ( 引导 ROM)

引导 ROM 的作用是载入第一阶段 (stage-1)引导映像。第一阶段引导映像是由上电 / 重启时读到的 BOOT_MODE 信号决定的,这个信号就是施加在某些特定引脚上的弱上拉或下拉 [5]。

引导 ROM 里的程序既能装载加密(安全)的引导映像,也能装载未加密(非安 全)的。当使用当地运行 (eXecute- In-Place,XIP)功能,这个引导 ROM 还能直接执行线性闪存(只能是 NOR 或 QSPI)里的第一阶段引导映像。只有用非安全引导映像的时候才能用这个功能 [5]。

在安全引导模式并且运行安全引导 ROM代码的时候,CPU会解码、认证 PS映像, 然后才存到 ROM 中去,之后 CPU 会跳转到 OCM 中的代码去。如果用的是非安全引导,CPU 先关闭所有的安全引导功能,然后跳转到 OCM 的引导映像去,或者,如果用了XIP 功能的话,跳转到非易失性的闪存里去。除非使用了 XIP 功能,引导映像将被限制在 192KB 内 [5]。

因为 PS用了可编程逻辑中的硬件模块来做 AES-256和 HMAC(SHA-256)解密和认 证,在安全引导过程中 PL 必须被加电。芯片加密认证是用户可选择的,或者是用片内的 eFUSE 单元,或者是用带有备用电池的 RAM (Battery Backup RAM,BBRAM)。

下面列出了五种可能的引导源:

1. NAND 闪存

2. NOR 闪存

3. Quad-SPI (QSPI) 闪存

4. Secure Digital (SD) 卡

5. JTAG

第 1 到 4 种引导源用于主引导模式中,这种模式中,外部的引导映像由 CPU 从非易失性存储器装载到 PS 中。而 JTAG 则只能用于从引导模式,而且不支持安全引导。当从 JTAG 引导时,由主机充当安全主控,通过 JTAG 与设备的链接将引导映像载入到 OCM 中。

一旦第一阶段引导映像已经装载到 OCM 里了,或者是采用 XIP 把引导映像留在非易失性闪存里,引导 ROM 就把 CPU 的控制移交给第一阶段了。

图 24.6 显示了引导 ROM 的大致的流程。

图 24.6: 引导 ROM 流程

24.3.3 Stage-1 ( 第一级引导装载程序 )

初始引导阶段之后,FSBL 就由引导 ROM 装载到 OCM 了。FSBL 负责一些初始化的 工作,包括根据 PS 配置数据初始化 CPU、用位流对 PL 编程、把第二阶段引导装载程序或初始的用户应用到存储器中,然后开始执行第二阶段引导装载程序或初始用户应用代码。在 CPU的控制权转交给第二阶段引导装载程序之前,FSBL关闭了 cache和MMU,并清空了指令cache,因为U-boot开始运行的时候认为这些是关闭了的[6]。

在深入探索 FSBL 的功能之前,应该先来理解引导映像的构成,因为 PL 用的位流、SSBL,以及 SSBL、Linux 或其他操作系统要用的所有其他代码,都是组合起来放在闪存映像的分区里的。

引导镜像格式 (Boot Image Format, BIF)

引导映像格式是由以下几个部分组成的 [6]:

• 引导 ROM 头

• FSBL 映像

• 分区映像 (可能多个)

• 可能还有的未用的空间

图 24.7 画出了详细的引导映像格式。

需要指出的是,在 FSBL 里,加密不是强制的,而是让想用的人可以使用的一个选项。

图24.7: Zynq 引导映像格式 (BIF) 结构

认证证书

对于每个认证了的分区,在它的末尾都附加了一个认证证书。这个认证证书中所有的整数都是以小端形式保存的 [6]。认证证书中的数据的细节列在表 24.3 中。

表 24.3: 认证证书 [6]

为了降低FSBL里的额外开销,Xilinx BootGen工具(包含在SDK里了)事先计算了蒙哥马利模余算法中要用到的模块扩展 [6]。这些数值保存在紧接在模块字段之后的地方。认证证书的内容详列在表 24.4 中。

表 24.4: 位认证证书头 [6]

BootGen

可以用厂家给的 Bootgen 程序在 FSBL 里组合进一个 PL 位流和 SSBL 或用户程 序。Bootgen 是一个独立的桌面应用程序,用来产生 Zynq-7000 处理器适用的引导映像。这个工具在一连串分区之前加上一个头块来组合出引导映像,这一连串分区包括用户 ELF 文件、FPGA 位流和其他二进制文件,每个部分都可以做加密和认证。输出的结果是一个文件,可以直接烧录到 Zynq 系统的引导闪存中 [6]。

BootGen 工具可以经由 SDK 或是命令行使用,以自动生成引导映像可以通过 SDK 自动执行 Bootgen 来产生引导映像,也可以通过命令行来用。这个工具的源代码可用于 Windows 和 32 位 /64 位的 Linux。

在 SDK 里用 BootGen 工具创建引导映像的时候,第一个分区必须是 FSBL ELF, 然后是可选的位流分区,再接着是 SSBL/ 应用代码的 ELF (需要指出的是,如果用了定制的 FSBL,引导顺序也可以相应地调整)。如果可选的位流被包含进了引导映像中,它必须紧接在 FSBL 之后。SSBL/ 应用程序的 ELF 的执行地址必须大于 1MB,因为在执行 FSBL 的时候,DDR RAM 还没有被重映射,任何低于 1MB 的地址都是无法访问的 [6]。

图 24.8 给出了 FSBL 的详细执行流程。

图 24.8: FSBL 执行流程

24.3.4 Stage-2 ( 第二级引导装载程序 )

Zynq 引导过程的 Stage-2 与具体要引导起来的操作系统的类型有关。如果是一个独立的应用,在这个阶段,应用的代码会被装载进来然后执行。不过,如果是一个像 Linux 或 Android 这样的操作系统要载入的话,第二阶段会是一个像 U-Boot 这样的二级引导装载程序。

微处理器执行的是驻留在本地存储器里的代码。这对于独立或是裸机程序来说很方便,但是不适用于像 Linux 这样的较大型的操作系统。这是因为操作系统保存在像硬盘、U 盘或光盘这样较大的持久存储介质上。当处理器上电的时候,内存中并没有操作系统,因此需要引导装载程序把操作系统从持久存储介质中装载到内存里来 [6]。

U-Boot 是一个在 Linux 社区里流行的开源通用引导装载程序,Xilinx 也将其用于 Zynq-7000 AP 处理器上。Xilinx 给出了定制的运行在 Xilinx 开发板上的 U-Boot 源代码,代码以 Git 方式保存在 Xilinx 的 Git 仓库中 [7]:

https://github.com/xilinx

正如本章之前所解释的,Zynq 的引导过程分为三个阶段:Boot ROM 装载 FSBL、 FSBL 装载可选的位流和 SSBL。这里的 SSBL 是 U-Boot,它负责把压缩了的 Linux 内核映像、系统设备树和 ramdisk映像装载到内存中。一旦这些映像装载到了内存里,U-Boot 会启动 Linux 内核的执行。

24.4 本章回顾

本章我们看过了桌面环境下的 Linux 的传统的引导过程,这包括对各种阶段的说明,这些阶段有 BIOS、第一和第二级引导装载程序、内核和 init。然后介绍了在 Zynq-7000 AP 芯片上引导嵌入式 Linux 的过程,并与桌面的引导 顺序作了比较。仔细描述了成功完成引导过程所需的各种文件,包括 BOOT.BIN、zImage、devicetree.dtb 和 ramdisk8M.image.gz,还介绍了 BIF 和所需的认证证书的细节。最后,详细说明了用来组成引导映像的 bootgen 工具。

24.5 参考文献

注意:所有的 URL 最后是在 2014 年 6 月访问过。

[1] IBM, “Inside the Linux boot process”, 网页位于 : http://www.ibm.com/developerworks/linux/library/l-linuxboot/

[2] Digilent, Inc, “Embedded Linux Development Guide”, January 2013. 位于 : https://www.digilentinc.com/Data/Products/EMBEDDED-LINUX/Digilent_Embedded_Linux_Guide.pdf

[3] Free Standards Group, “System Initialization - Run Levels” in Linux Standard Base Core Specification 3.1, 2005. 位于 : http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/runlevels.html

[4] B. Ward, “How Linux Boots” in How Linux Works, 1st. Ed, No Starch Press, 2004, pp. 54 - 63.

[5] Xilinx, Inc, “Zynq-7000 All Programmable SoC Technical Reference Manual”, UG585, v1.7, February 2014.位于 : http://www.xilinx.com/support/documentation/user_guides/ug821-zynq-7000-swdev.pdf

[6] Xilinx, Inc, “Zynq-7000 All Programmable SoC Software Developers Guide”, UG821, v9.0, June 2014.位于 : http://www.xilinx.com/support/documentation/user_guides/ug821-zynq-7000-swdev.pdf

[7] Xilinx, Inc, “U-Boot”, 网页位于 : http://www.wiki.xilinx.com/U-boot

第三十七篇到此结束,本系列到此完结,各位大侠有缘再见。

END

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA技术江湖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档