Skip to content

替代VisionFive 2 Uboot,用于加载自定义操作系统内核

License

Notifications You must be signed in to change notification settings

QIUZHILEI/vf2_bootloader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vf2_bootloader

vf2_bootloader用于取代Uboot运行于Visionfive 2平台,它是一个非常简单的程序可以用来从SD卡EFI分区加载自定义的操作系统内核。

简介

在 VisionFive2 平台上,Uboot 通常分为两部分:第一部分是 SPL(Secondary Program Loader),用于加载后续的引导程序,第二部分则是 Uboot + OpenSBI(VisionFive2启动流程)。

然而,如果我们想要开发一个操作系统内核,并将其运行于 VisionFive2 平台,使用 Uboot 加载自定义内核可能会显得较为繁琐且不够灵活。为了解决这个问题,我们开发了一个简单且极易修改的引导程序,取代了 Uboot 引导程序第二部分。

使用该 vf2_bootloader 固件的启动流程为:BootRom -> SPL -> vf2_bootloader -> 内核(SD 卡)。使用者只需根据自身的内核加载逻辑进行修改,然后将修改后的固件写入 SD 卡,即可实现自定义内核的加载。

逻辑剖析

vf2_bootloader仅通过读取SD卡来加载内核,内部实现非常简单,大致有如下几个组件组成:

  • uart驱动
  • log日志系统
  • sdio驱动
  • mem只做分配不做回收的内存分配器
  • fat只读FAT32文件系统

下面逐步的分析vf2_bootloader的逻辑。

如何替换原来的Uboot

VisionFive 2支持从三个设备引导,分别是QSPI flash、NVME设备、SD卡。无论哪个设备,都由上述的两个部分部分组成,这两个部分存储在两个分区中,要做替换就必须刷写设备,那么我们就需要考虑,哪种设备便于刷入程序,并且最好不要随意刷写焊接在板子上的硬件,因为硬件损坏不易维修。QSPI Flash和eMMC(不自带)被焊接在板子上,出现硬件问题不易解决,而NVME硬盘成本稍高,不宜反复插拔,而SD卡容易插拔、出问题更换的成本低。

因此,最好是将编写好的程序刷写到SD卡中,并从SD卡启动,是最为方便妥当的做法。

让spl加载vf2_bootloader

在VisionFive 2平台上spl将Uboot+OpenSBI加载至LPDDR内存始址,即0x40000000,之后Uboot会将本身重定位至高地址然后再将内核加载到0x40000000。而使用vf2_bootloader时,我们修改了spl加载vf2_bootloader的地址,直接将其加载到0xC0000000,这样做就省去了重定向自身的过程,可以直接将自定义的内核加载至0x40000000。

tools 目录下,mkimage工具用于给生成的裸二进制文件签名,在Uboot签名工具fit脚本fit_img.its中,修改了签名部分的加载地址,由原来的0x40000000变为0xC0000000,这个fit脚本在官方github仓库可以找到(Tools/uboot_its/visionfive2-uboot-fit-image.its at master · starfive-tech/Tools)。

相应的vf2_bootloader链接脚本也将初始地址设为0xC0000000,在 链接脚本 link.ld 中可以看到。

vf2_bootloader组件

uart:Uart设备作为用户交互的一个媒介,可以充当一个终端的角色,它的实现位于QIUZHILEI/uart_8250: Uart 8250驱动程序

log:日志系统用于打印一些日志输出,这个组件使用的是官方提供的log crate,位于rust-lang/log: Logging implementation for Rust

sd设备:sdio驱动SD卡,用于SD的IO操作,作为引导程序和内核的存储媒介,它的实现位于QIUZHILEI/dw_sd: DesignWare Cores Mobile Storage Host 驱动

mem:内存分配器的设计非常简单——只做分配,不做回收。

程序从SD的EFI分区加载内核,fat文件中实现了一个简单的只读FAT32文件系统,用于存储和加载内核。

代码逻辑

程序从entry (src/entry.S) 开始执行,初始化每个Hard栈,并将代码的末地址作为参数传递给rust_entry (src/main.rs),在rust_entry函数中,仅让hart 1,进行环境初始化和内核加载,其余hart均等待加载完成,最后一并跳转到内核执行。

hart 1首先调用init函数初始化设备和内存分配器,然后执行load_kernel (src/lib.rs) 函数,寻找SD卡的EFI分区并初始化FAT32文件系统,接着将内核加载至内存,解开BLOCK并与其他hart一同跳转到内核开始执行。

如何使用vf_bootloader可以参考 VisionFive 2上快速体验组件化的力量

About

替代VisionFive 2 Uboot,用于加载自定义操作系统内核

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published