0%

RISC-V启动流程详解

详细介绍RISC-V架构的系统启动流程,包括OpenSBI、U-Boot等bootloader的配置和使用方法,以及各类固件文件的说明。

网址

https://buildroot.org/
https://github.com/riscv-software-src/opensbi
https://github.com/u-boot/u-boot
https://kernel.org/

为了通过 U-Boot 启动 RISC-V 64 架构的 Linux,我们需要在编译时选择交叉编译工具链 riscv64-linux-gnu-gcc。在 U-Boot 目录下执行以下命令:
$ cd u-boot
$ export CROSS_COMPILE=riscv64-linux-gnu-
$ make qemu-riscv64_smode_defconfig
$ make -j $(nproc)

直接引导 S 模式下的 U-Boot 镜像,使用以下命令:

$ qemu-system-riscv64 -M virt -smp 4 -m 2G \
    -display none -serial stdio \
    -kernel /path/to/u-boot.bin

FW_PAYLOAD

如需启动 U-Boot 或 Linux,需要在 OpenSBI 编译时指定 U-Boot 或 Linux 的 payload 路径。以 U-Boot 为例,切换到 OpenSBI 目录下,编译命令如下:
$ cd opensbi
$ export CROSS_COMPILE=riscv64-linux-gnu-
$ make PLATFORM=generic FW_PAYLOAD_PATH=/u-boot.bin

运行:

$ qemu-system-riscv64 -M virt -m 256M -nographic \
    -bios build/platform/generic/firmware/fw_payload.elf

FW_JUMP

或是使用以下命令运行:

$ qemu-system-riscv64 -M virt -m 256M -nographic \
    -bios build/platform/generic/firmware/fw_jump.bin \
    -kernel <uboot_build_directory>/u-boot.bin

FW_DYNAMIC

如果要使用 U-Boot SPL,使用如下命令:
$ cd u-boot
$ export CROSS_COMPILE=riscv64-linux-gnu-

$ export OPENSBI=/path/to/opensbi/build/platform/generic/firmware/fw_dynamic.bin
$ make qemu-riscv64_spl_defconfig
$ make -j $(nproc)
$ qemu-system-riscv64 -M virt -smp 4 -m 2G \
    -display none -serial stdio \
    -bios /path/to/u-boot-spl \
    -device loader,file=/path/to/u-boot.itb,addr=0x80200000

opensbi
固件和负载(Payload)文件
fw_dynamic.bin / fw_jump.bin / fw_payload.bin: 这些.bin文件是二进制格式的固件或负载文件,可以直接烧录到目标设备的Flash存储或通过引导加载程序(如U-Boot)加载。它们分别可能代表动态固件、跳转固件(用于引导加载程序中跳转到特定地址执行)、以及具体的负载(如操作系统内核、应用程序或服务)。
fw_dynamic.elf / fw_jump.elf / fw_payload.elf: .elf文件是可执行链接格式(Executable and Linkable Format)文件,它们包含了用于调试和执行的代码和数据,以及关于如何在目标系统上布局这些代码和数据的信息。ELF文件在开发过程中用于调试目的,因为它们包含了丰富的调试信息。
依赖和链接脚本文件
fw_dynamic.dep / fw_jump.dep / fw_payload.dep: .dep文件通常包含关于源文件之间依赖关系的信息。在构建过程中,这些依赖信息被用来确定哪些文件需要重新编译。这些文件对于管理大型项目中的依赖关系非常有用。
fw_dynamic.elf.dep / fw_jump.elf.dep / fw_payload.elf.dep: 这些文件可能包含了特定于ELF文件的依赖信息,指明了构建ELF文件所需的依赖项。
fw_dynamic.elf.ld / fw_jump.elf.ld / fw_payload.elf.ld: .ld文件是链接脚本,用于控制ELF文件的链接过程,包括指定各个代码和数据段在目标内存中的布局。这对于确保固件或负载正确地放置在目标设备的内存中非常重要。
对象文件
fw_dynamic.o / fw_jump.o / fw_payload.o: .o文件是对象文件,包含编译单个源文件后的机器代码和数据。在最终链接阶段,这些对象文件被合并生成最终的可执行文件或二进制固件。
负载目录
payloads: 这个目录可能包含一系列负载文件,这些文件可以是操作系统映像、应用程序或其他为特定目的准备的代码。在引导加载程序中,可以选择从这些负载中加载特定项。

u-boot
u-boot:这是U-Boot的主可执行文件,通常为未压缩的ELF(Executable and Linkable Format)格式。
u-boot.bin:这是u-boot的二进制格式,通过将ELF文件中的可执行代码提取并转换成纯二进制数据得到。通常用于烧录到目标设备的引导存储器中。
u-boot.cfg:U-Boot的配置文件,包含了编译U-Boot时的配置选项。
u-boot.dtb(Device Tree Blob):设备树文件,包含了硬件设备的结构和配置信息,U-Boot使用它来了解硬件的详细信息。
u-boot-dtb.bin:这是包含了设备树信息的u-boot.bin文件。它将U-Boot和对应的设备树合并为一个二进制文件。
u-boot-dtb.img:同u-boot-dtb.bin,是一个包含了设备树的U-Boot镜像,格式和用途可能略有不同,具体取决于构建系统。
u-boot.dtb.out:可能是在构建过程中生成的包含设备树的中间文件,用于调试或进一步处理。
u-boot.img:通常是一个为特定平台准备的U-Boot镜像,格式可能是二进制或其他特定格式。
u-boot.itb(Image Tree Blob):一个FIT(Flattened Image Tree)格式的镜像,可以包含U-Boot、设备树和其他数据(如内核映像)。
u-boot.lds:链接脚本,用于控制U-Boot可执行文件的内存布局。
u-boot.map:生成的映射文件,详细列出了U-Boot中符号的地址和布局。
u-boot-nodtb.bin:这是不包含设备树信息的u-boot.bin文件,适用于系统不需要在引导加载程序阶段使用设备树的场景。
u-boot-spl.dtb.out:U-Boot的第二阶段加载程序(SPL)的设备树中间文件,用于较小的引导阶段。
u-boot.srec:SREC(S-record)格式的U-Boot文件,是一种用于表示二进制数据的ASCII文本格式。
u-boot.sym:符号文件,列出了U-Boot所有符号及其地址,有助于调试。

u-boot/spl
u-boot.cfg: 这是U-Boot构建过程中生成的配置文件,包含了编译U-Boot时使用的配置选项。它由make menuconfig、make savedefconfig等命令生成或修改。
u-boot-spl: 这可能是U-Boot的第一阶段引导加载程序(SPL)的未压缩的可执行文件。具体格式(如ELF格式)取决于构建配置。
u-boot-spl.bin: 这是u-boot-spl的二进制格式文件,通常通过将u-boot-spl的可执行文件转换成纯二进制形式来生成。这个文件适合直接烧录到启动介质(如SD卡、NOR Flash等)。
u-boot-spl.dtb: 设备树二进制文件(Device Tree Blob),包含了U-Boot SPL需要的硬件配置和布局信息。在某些系统上,SPL可能需要加载设备树来正确初始化硬件。
u-boot-spl-dtb.bin: 这是一个合并了设备树信息的u-boot-spl.bin文件。它将SPL和对应的设备树合并为一个单一的二进制文件,便于加载和执行。
u-boot-spl.lds: U-Boot SPL的链接脚本(Linker Script),定义了SPL二进制文件的内存布局。链接脚本指导链接器如何将代码和数据段映射到目标系统的地址空间。
u-boot-spl.map: 这是构建过程生成的内存映射文件,列出了SPL中所有符号的地址和布局信息。这对于调试和分析SPL非常有用。
u-boot-spl-nodtb.bin: 这是一个不包含设备树的u-boot-spl.bin文件。在系统中如果设备树以另一种方式提供(如通过另一个分区或在主U-Boot映像中),则可能会使用此版本。
u-boot-spl.sym: 符号文件,包含了SPL构建过程中生成的所有符号及其地址。这对于开发者在调试阶段定位问题非常有帮助。