From 9f0b2c8090970a6cd42a7cc5a7bfa6c4e45802c2 Mon Sep 17 00:00:00 2001 From: Kepontry Date: Mon, 13 Feb 2023 07:45:48 -0800 Subject: [PATCH] add 20230213-vf2-uboot-spl.md Signed-off-by: Kepontry --- articles/20230213-vf2-uboot-spl.md | 318 +++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 articles/20230213-vf2-uboot-spl.md diff --git a/articles/20230213-vf2-uboot-spl.md b/articles/20230213-vf2-uboot-spl.md new file mode 100644 index 0000000..e64bd67 --- /dev/null +++ b/articles/20230213-vf2-uboot-spl.md @@ -0,0 +1,318 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.1 - [codeinline urls pangu epw]
+ +> Author: Kepontry
+> Date: 2023/2/13
+> Revisor: Falcon
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Proposal: [VisionFive 2 开发板软硬件评测及软件 gap 分析](https://gitee.com/tinylab/riscv-linux/issues/I64ESM)
+> Sponsor: PLCT Lab, ISCAS + +# 基于 VisionFive 2 的 SPL 和 U-Boot 编译与烧写 + +## 简介 + +### U-Boot + + U-Boot 是“Universal Boot Loader”的缩写,是一个 Linux 系统的通用引导加载程序,主要用于嵌入式场景下。由于操作系统体积较大且存放在非易失性存储介质中,当开发板上电后,需要由引导加载程序初始化内存,并将操作系统代码加载到内存中执行。 + +### SPL + +SPL 是“Secondary Program Loader”的缩写,负责初始化内存并将 U-Boot 加载到内存中。由于 U-Boot 体积通常大于板上 SRAM 体积,所以需要先将 SPL 加载进 SRAM,在 SPL 初始化完内存后,将 U-Boot 加载进内存。 + +### OpenSBI + +SBI 是“Supervisor Binary Interface”的缩写,用于规范定义 M 态向 S 态提供的服务。Bootloader 启动内核以后,M 态的服务还驻留在内存,在 S 态可以调用这些服务。OpenSBI 是 SBI 的一种实现。 + +### 启动流程分析 + +JH7110 的启动流程为:BootROM -> SPL -> U-Boot -> Linux + +BootROM 是一段硬编码写在 ROM 中的程序,用于加载和启动 SPL,SPL 中的”Secondary“就是相对于 BootROM 来说的”第二个“程序加载器。SPL 和 U-Boot 合在一起完成了 Linux 系统的加载引导,这称为”两阶段加载引导“。SPL 也被称为”第一阶段引导加载程序“,即”first-stage bootloader“。 + +## 编译 SPL 和 U-Boot + +接下来介绍 VisionFive 2 开发板的 U-Boot、OpenSBI 和 SPL 的编译方式,该部分参考自官方提供的“[昉·星光 2 单板计算机软件技术参考手册][001]”。官方的[VisionFive2 SDK][006]仓库中有编译好的版本,想直接烧录的可以跳过该节。 + +在 X86 架构的服务器上编译 RISCV 的软件,首先要执行以下命令,更新软件列表,并安装交叉编译工具。 + +```shell +$ sudo apt update +$ sudo apt install gcc-riscv64-linux-gnu +``` + +### U-Boot + +首先从 starfive 的 GitHub 仓库中下载源码。使用 `git branch -a` 查看本地当前分支是否为“JH7110_VisionFive2_devel”,如果不是则需要新建分支并拉取远程最新代码。 + +```shell +$ git clone https://github.com/starfive-tech/u-boot.git +$ cd u-boot +$ git checkout -b JH7110_VisionFive2_devel origin/JH7110_VisionFive2_devel +$ git pull +``` + +configs 文件夹中存放着各类开发板的配置文件,我们选取“starfive_visionfive2_defconfig”配置文件,指定架构和交叉编译工具链后编译生成 `make` 命令可识别的“.config”配置文件。 + +```shell +$ make starfive_visionfive2_defconfig ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- + + HOSTCC scripts/basic/fixdep + HOSTCC scripts/kconfig/conf.o + YACC scripts/kconfig/zconf.tab.c + LEX scripts/kconfig/zconf.lex.c + HOSTCC scripts/kconfig/zconf.tab.o + HOSTLD scripts/kconfig/conf +# +# configuration written to .config +# +``` + +接着使用 `make` 命令编译 U-Boot,输出如下: + +```shell +$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- + + ...... + LDS spl/u-boot-spl.lds + LD spl/u-boot-spl + OBJCOPY spl/u-boot-spl-nodtb.bin + COPY spl/u-boot-spl.bin + SYM spl/u-boot-spl.sym + MKIMAGE u-boot.img +===================== WARNING ====================== +CONFIG_OF_EMBED is enabled. This option should only +be used for debugging purposes. Please use +CONFIG_OF_SEPARATE for boards in mainline. +See doc/README.fdt-control for more info. +==================================================== + CFGCHK u-boot.cfg +``` + +编译后生成三个文件,”u-boot.bin“,”starfive_visionfive2.dtb“和”u-boot-spl.bin“。前两者将被用于后面的 OpenSBI 编译,最后一个文件将被用于生成 SPL 文件。 + +```shell +$ ll u-boot.bin +-rwxr-xr-x. 1 root root 699016 Feb 12 20:26 u-boot.bin* +$ ll arch/riscv/dts/starfive_visionfive2.dtb +-rw-r--r--. 1 root root 41776 Feb 12 20:26 arch/riscv/dts/starfive_visionfive2.dtb +$ ll spl/u-boot-spl.bin +-rwxr-xr-x. 1 root root 130048 Feb 12 20:27 spl/u-boot-spl.bin* +``` + +### OpenSBI + +返回上级目录,获取 OpenSBI 源码 + +```shell +$ cd ../ +$ git clone https://github.com/starfive-tech/opensbi.git +$ cd opensbi +``` + +OpenSBI 支持三种类型的 Firmware,分别为:dynamic、jump 和 payload。详见[RISC-V OpenSBI 快速上手][009]。这里采用的是 payload 类型,将下一级引导 U-Boot 的二进制可执行文件打包进来,且其在 VisionFive 2 开发板的 Flash 和 eMMC 上的位置固定。 + +接下来指定好架构、交叉编译工具链、目标平台、U-Boot 文件、设备树描述文件和在内存中的起始位置后,使用 `make` 命令编译,生成“fw_payload.bin”文件。该文件的大小通常大于 2M,这里为 2.7M。 + +```shell +$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic +FW_PAYLOAD_PATH=../u-boot/u-boot.bin +FW_FDT_PATH=../u-boot/arch/riscv/dts/starfive_visionfive2.dtb FW_TEXT_START=0x40000000 + + ...... + AS platform/generic/firmware/fw_dynamic.o + CPP platform/generic/firmware/fw_dynamic.elf.ld + ELF platform/generic/firmware/fw_dynamic.elf + OBJCOPY platform/generic/firmware/fw_dynamic.bin + AS platform/generic/firmware/fw_jump.o + CPP platform/generic/firmware/fw_jump.elf.ld + ELF platform/generic/firmware/fw_jump.elf + OBJCOPY platform/generic/firmware/fw_jump.bin + AS platform/generic/firmware/fw_payload.o + CPP platform/generic/firmware/fw_payload.elf.ld + ELF platform/generic/firmware/fw_payload.elf + OBJCOPY platform/generic/firmware/fw_payload.bin + +$ ls -lh build/platform/generic/firmware/fw_payload.bin +-rwxr-xr-x. 1 root root 2.7M Feb 12 20:35 build/platform/generic/firmware/fw_payload.bin +``` + +### SPL 和 U-Boot 的官方辅助构建工具 + +starfive-tech 的“Tools”仓库里存放着制作 VisionFive 2 开发板的 SPL 和 U-Boot 文件的工具,以及烧写错误后的恢复工具。执行如下命令,从官方仓库克隆最新代码,使用 master 分支。 + +```shell +$ cd ../ +$ git clone https://github.com/starfive-tech/Tools +$ cd Tools +$ git checkout master +$ git pull +``` + +接着执行如下命令,将上一步得到的”fw_payload.bin“文件拷贝到当前目录下,用 U-Boot 提供的工具 mkimage 和”Tools/uboot_its“目录下的”visionfive2-uboot-fit-image.its“文件给 U-Boot 镜像加上信息头。其中,`-f` 参数指定镜像信息描述文件,`-A` 参数指定 CPU 类型,`-O` 参数指定操作系统,`-T` 参数指定 image 类型。最后在当前目录下生成最终的”U-Boot+OpenSBI“镜像”visionfive2_fw_payload.img”。 + +```shell +$ cd uboot_its +$ cp ../../opensbi/build/platform/generic/firmware/fw_payload.bin ./ +$ ../../u-boot/tools/mkimage -f visionfive2-uboot-fit-image.its -A riscv -O u-boot -T firmware visionfive2_fw_payload.img +FIT description: U-boot-spl FIT image for JH7110 VisionFive2 +Created: Sun Feb 12 21:18:11 2023 + Image 0 (firmware) + Description: u-boot + Created: Sun Feb 12 21:18:11 2023 + Type: Firmware + Compression: uncompressed + Data Size: 2796184 Bytes = 2730.65 KiB = 2.67 MiB + Architecture: RISC-V + OS: U-Boot + Load Address: 0x40000000 + Default Configuration: 'config-1' + Configuration 0 (config-1) + Description: U-boot-spl FIT config for JH7110 VisionFive2 + Kernel: unavailable + Firmware: firmware +``` + +### SPL + +进入“Tools/spl_tool”文件夹,使用 make 命令构建 spl_tool 工具。执行如下命令,使用该工具制作 SPL 文件,其中,`-c` 参数用于创建 spl hdr,`-f` 参数用于指定输入文件。最后生成“u-boot-spl.bin.normal.out”文件。 + +```shell +$ cd ../spl_tool +$ make +$ ./spl_tool -c -f ../../u-boot/spl/u-boot-spl.bin +ubsplhdr.sofs:0x240, ubsplhdr.bofs:0x200000, ubsplhdr.vers:0x1010101 name:../../u-boot/spl/u-boot-spl.bin +SPL written to ../../u-boot/spl/u-boot-spl.bin.normal.out successfully. +``` + +## 将 SPL 和 U-Boot 烧写进 VisionFive 2 开发板 + +上文介绍了 SPL 和 U-Boot 的编译方法,但除非官方要求,一般这两个文件是不需要更新的,但为了体验新特性,可以尝试自行手动更新。官方现在提供了两个 Debian 工程版镜像,[Debian Image 69][004]和[Debian Image 55][003],都是基于 5.15 版本的 Linux 内核,SDK 版本分别为 2.5 和 2.3。Debian Image 69 的烧写需要更新 SPL 和 U-Boot,以解决 eth0 网络以及 ddr 容量不对问题。 + +官方文档中介绍了 SPL 与 U-Boot 的两种更新方式和一种恢复方式。第一种更新方式是通过使开发板和电脑处于同一网段,让开发板在启动 U-Boot 后通过 tftp 从电脑上获取这两个文件,并使用 sf 命令将文件刷入 SPI flash。第二种更新方式是在开发板的系统上通过 flashcp 将文件写入 MTD 分区,但这种方法仅支持 SDK 版本在 VF2_v2.5.0 以上的系统。 + +由于网络配置问题,开发板 ping 不通电脑,所以本文采用恢复 SPL 和 U-Boot 的方法,即进入 recovery 模式。首先拨动开发板上的两个启动模式选择开关,设为 UART 模式。再将使用 USB 转串口模块(如 CH340 等)将开发板连接到电脑的 USB 口,并设置波特率为 115200。启动开发板,窗口持续输出字母“C”,则表示开发板正在等待文件传输。使用 XMODEM 协议将[恢复程序][005]上传至开发板中,程序执行结果如下,我们在输入 0 后按下回车,更新 flash 中的 SPL。此时使用 XMODEM 协议将本地的 u-boot-spl.bin.normal.out 文件上传至开发板,等出现“updata success”时表示更新成功,并再次出现选择页面。接下来选择 2,用本地的“visionfive2_fw_payload.img”文件更新 flash 中的 uboot。 + +最后在讲一下在 Windows 端使用 XMODEM 协议上传时用到的软件,最初使用的是 Xshell,但只有 YMODEM 协议能够上传恢复文件,在上传 SPL 与 U-Boot 时卡死。之后陆续尝试了 MobaXterm 和 Putty,都没有成功。最后搜索到了华为的一篇技术支持文章“[FAQ-如何通过 Xmodem 方式向交换机传文件][008]”,使用文章中提到的 IPOP 工具传输成功,下载页面见“[IPOP—华为内部使用的强大网络设置工具][002]”。 + +```shell +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +JH7110 secondboot version: 221205-74596a9 +CPU freq: 1250MHz +idcode: 0x1860C8 +ddr 0x00000000, 4M test +ddr 0x00400000, 8M test +DDR clk 2133M, size 8GB + +********************************************************* +****************** JH7110 program tool ****************** +********************************************************* +0: update 2ndboot/SPL in flash +1: update 2ndboot/SPL in emmc +2: update fw_verif/uboot in flash +3: update fw_verif/uboot in emmc +4: update otp, caution!!!! +5: exit +NOTE: current xmodem receive buff = 0x40000000, 'load 0x********' to change. +select the function to test: 0 +send file by xmodem +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCupdata first section +. +................................................................ +...............................................................updata backup section +. +................................................................ +...............................................................updata success + +********************************************************* +****************** JH7110 program tool ****************** +********************************************************* +0: update 2ndboot/SPL in flash +1: update 2ndboot/SPL in emmc +2: update fw_verif/uboot in flash +3: update fw_verif/uboot in emmc +4: update otp, caution!!!! +5: exit +NOTE: current xmodem receive buff = 0x40000000, 'load 0x********' to change. +select the function to test: 2 +send file by xmodem +CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +CCCCCCCCCCCCCCCCupdata first section + +................................................................ +................................................updata success +``` + +更新完成后,拨动开发板上的两个启动模式选择开关,设为 SPI Flash 模式,并重启系统,发现 SDK 版本升级到 2.6,两个文件的修改时间均为 2023 年 2 月 12 日,为更新后的版本。 + +```shell +U-Boot SPL 2021.10 (Feb 12 2023 - 20:22:27 +0800) +DDR version: dc2e84f0. +Trying to boot from SPI + +OpenSBI VF2_v2.6.0 + ____ _____ ____ _____ + / __ \ / ____| _ \_ _| + | | | |_ __ ___ _ __ | (___ | |_) || | + | | | | '_ \ / _ \ '_ \ \___ \| _ < | | + | |__| | |_) | __/ | | |____) | |_) || |_ + \____/| .__/ \___|_| |_|_____/|____/_____| + | | + |_| + +Platform Name : StarFive VisionFive V2 +Platform Features : medeleg +Platform HART Count : 5 +Platform IPI Device : aclint-mswi +Platform Timer Device : aclint-mtimer @ 4000000Hz +Platform Console Device : uart8250 +Platform HSM Device : --- +Platform Reboot Device : --- +Platform Shutdown Device : --- +Firmware Base : 0x40000000 +Firmware Size : 356 KB +Runtime SBI Version : 0.3 + +Domain0 Name : root +Domain0 Boot HART : 2 +Domain0 HARTs : 0*,1*,2*,3*,4* +Domain0 Region00 : 0x0000000002000000-0x000000000200ffff (I) +Domain0 Region01 : 0x0000000040000000-0x000000004007ffff () +Domain0 Region02 : 0x0000000000000000-0xffffffffffffffff (R,W,X) +Domain0 Next Address : 0x0000000040200000 +Domain0 Next Arg1 : 0x0000000042200000 +Domain0 Next Mode : S-mode +Domain0 SysReset : yes + +Boot HART ID : 2 +Boot HART Domain : root +Boot HART Priv Version : v1.11 +Boot HART Base ISA : rv64imafdcbx +Boot HART ISA Extensions : none +Boot HART PMP Count : 8 +Boot HART PMP Granularity : 4096 +Boot HART PMP Address Bits: 34 +Boot HART MHPM Count : 2 +Boot HART MIDELEG : 0x0000000000000222 +Boot HART MEDELEG : 0x000000000000b109 + +U-Boot 2021.10 (Feb 12 2023 - 20:22:27 +0800) +``` + +## 总结 + +本文介绍了 SPL 和 U-Boot 的基本概念、编译及烧写方法,方便大家及时体验到官方提供的新特性。 + +## 参考资料 + +- [What is the use of SPL][007] + +[001]: https://doc.rvspace.org/VisionFive2/PDF/VisionFive2_SW_TRM.pdf +[002]: https://forum.huawei.com/enterprise/zh/thread/580889902600568832 +[003]: https://forum.rvspace.org/t/2-debian-image-55/995 +[004]: https://forum.rvspace.org/t/2-debian-image-69/1101 +[005]: https://github.com/starfive-tech/Tools/blob/master/recovery/jh7110-recovery-20221205.bin +[006]: https://github.com/starfive-tech/VisionFive2/releases +[007]: https://stackoverflow.com/questions/31244862/what-is-the-use-of-spl-secondary-program-loader +[008]: https://support.huawei.com/enterprise/zh/knowledge/EKB1000087697 +[009]: https://tinylab.org/riscv-opensbi-quickstart/ -- Gitee