oreboot: 革新的 Rust 驱动固件,引领开源硬件启动新时代
oreboot 是 coreboot 的下游分支,也就是说,oreboot 是去掉了 'c' 的 coreboot。
oreboot 主要使用 Rust 语言编写,必要时使用汇编语言。
目前,oreboot 仅计划支持 LinuxBoot 有效载荷。
演示
QEMU 中的 ARM oreboot[1] QEMU 中的 RISC-V HiFive Unleashed oreboot[2]
oreboot 🦀
v 13
cpu_pll fa001000
cpu_axi 5000100
cpu_axi 5000100
peri0_ctrl was: f8216300
peri0_ctrl lock en
peri0_ctrl PLLs
peri0_ctrl set: f8216300
DDR3@792MHz
test OK
512M 🐏
NOR flash: c2/2018
load 00018000 bytes to 40000000: ➡️.
load 00fc0000 bytes to 44000000: ➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️➡️.
load 00010000 bytes to 41a00000: ➡️.
{ɕ serial uart0 initialized
RISC-V vendor 5b7 arch 0 imp 0
==== platform CSRs ====
MXSTATUS c0408000
MHCR 00000109
MCOR 00000002
MHINT 00004000
see C906 manual p581 ff
=======================
Set up extension CSRs
==== platform CSRs ====
MXSTATUS c0638000
MHCR 0000017f
MCOR 00000003
MHINT 0000610c
see C906 manual p581 ff
=======================
timer init
reset init
ipi init
RustSBI version 0.3.1
.______ __ __ _______.___________. _______..______ __
| _ \ | | | | / | | / || _ \ | |
| |_) | | | | | | (----`---| |----`| (----`| |_) || |
| / | | | | \ \ | | \ \ | _ < | |
| |\ \----.| `--' |.----) | | | .----) | | |_) || |
| _| `._____| \______/ |_______/ |__| |_______/ |______/ |__|
Platform Name: T-HEAD Xuantie Platform
Implementation: oreboot version 0.1.0
[rustsbi] misa: RV64ACDFIMSUVX
[rustsbi] mideleg: ssoftstimersext (0x222)
[rustsbi] medeleg: imaialmalasmasauecallipagelpagespage(0xb1f3)
[rustsbi] mie: msoft ssoft mtimer stimer mext sext (00000aaa)
PMP0 0x0 - 0x40000000 (A,R,W,X)
PMP1 0x40000000 - 0x40200000 (A,R)
PMP2 0x40200000 - 0x80000000 (A,R,W,X)
PMP3 0x80000000 - 0x80200000 (A,R)
PMP4 0x80200000 - 0xfffff800 (A,R,W,X)
PMP8 0x0 - 0x0 (A,R,W,X)
DTB looks fine, yay!
Decompress 12375521 bytes from 0x44000004 to 0x40200000, reserved 25165824 bytes
Success, decompressed 21910144 bytes :)
Payload looks like Linux Image, yay!
DTB still fine, yay!
Handing over to SBI, will continue at 0x40200000
enter supervisor at 40200000 with DTB from 41a00000
...
[ 0.000000] OF: fdt: Ignoring memory range 0x40000000 - 0x40200000
[ 0.000000] Machine model: Sipeed Lichee RV Dock
[ 0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[ 0.000000] printk: bootconsole [sbi0] enabled
[ 0.000000] Zone ranges:
[ 0.000000] DMA32 [mem 0x0000000040200000-0x000000005fffffff]
[ 0.000000] Normal empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x0000000040200000-0x000000005fffffff]
[ 0.000000] Initmem setup node 0 [mem 0x0000000040200000-0x000000005fffffff]
[ 0.000000] riscv: SBI specification v1.0 detected
[ 0.000000] riscv: SBI implementation ID=0x4 Version=0x301
[ 0.000000] riscv: SBI TIME extension detected
[ 0.000000] riscv: SBI IPI extension detected
[ 0.000000] riscv: SBI SRST extension detected
[ 0.000000] riscv: base ISA extensions acdfim
[ 0.000000] riscv: ELF capabilities acdfim
[ 0.000000] percpu: Embedded 17 pages/cpu s31912 r8192 d29528 u69632
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 128520
[ 0.000000] Kernel command line: console=tty0 console=ttyS0,115200 loglevel=7 earlycon=sbi
Rust 嵌入式
![](https://files.mdnice.com/user/52232/1355a7fb-9ca1-498d-
我们基于 Rust 嵌入式工作组[3] 的模型构建,使用其 crates 和 traits,详见 他们的书籍[4]。
简而言之:Rust 嵌入式模型[5]
厂商支持
SoC 厂商应提供对其内核、外设和其他模块的文档和/或 SVD 文件,以便我们生成 PAC 和 HAL crates,或者更理想的情况是,厂商应提供并维护这些。
Rust 嵌入式书籍提供了设计模式和实现指南[6]以及术语表[7],以帮助理解结构。
启动流程和设置
要大致了解 oreboot 和固件的工作原理,请查看启动流程文档[8]。它描述了固件如何在平台/SoC 上存储和启动。
获取 oreboot
克隆此仓库并进入其目录,例如:
git clone git://github.com/oreboot/oreboot
cd oreboot
先决条件
通常,您需要安装以下软件包:
device-tree-compiler
pkg-config
libssl
rustup
对于基于 Debian 的系统,有一个 make 目标可以安装这些,通过 curl 从 https://sh.rustup.rs 拉取 rustup
:
make debiansysprepare
否则,通过您的系统包管理器安装软件包。
设置工具链
无论您的操作系统是什么,都需要为 oreboot 安装工具链。 这个命令只需要执行一次,但重复执行是安全的。
make firsttime
保持构建工具更新
每次开始使用 oreboot 时,或者甚至是每天:
cd oreboot
make update
在报告任何问题之前,您绝对应该这样做。
开发 oreboot
项目中有两种不同的东西:
src/mainboards/*
实际的目标;这些依赖并共享 crates,可以是驱动程序、SoC 初始化代码等。对于主板,**必须跟踪Cargo.lock
**。src/*
其他所有内容;这些是上述 crates,我们不跟踪Cargo.lock
文件。
检入主板的 Cargo.lock
文件记录了成功构建时其依赖项的状态,从而实现可重复性。理想情况下,锁文件应在硬件上成功启动后更新。
更多信息,请参见:https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries
创建新的主板时,查看同一架构上其他人的设置是一个很好的开始。请注意,oreboot 针对的是裸机,因此没有标准库可用。
构建 oreboot
要为特定平台构建 oreboot,请执行以下操作:
# 进入主板目录
cd src/mainboard/sunxi/nezha
# 构建主板目标
make mainboard
# 查看反汇编
make objdump
# 从 RAM 运行,不烧录
make run
# 烧录到开发板
make flash
根 Makefile
允许您快速构建所有平台:
# 构建所有主板
make mainboards
# 并行构建所有内容
make -j mainboards
QEMU
# 安装目标平台的 QEMU,例如 x86
sudo apt install qemu-system-x86
# 构建发布版本并使用 QEMU 启动
cd src/mainboard/emulation/qemu-q35 && make run
# 使用 CTRL-A X 退出 qemu
要从源代码为 RISC-V 构建 QEMU:
git clone https://github.com/qemu/qemu && cd qemu
mkdir build-riscv64 && cd build-riscv64
../configure --target-list=riscv64-softmmu
make -j$(nproc)
# QEMU 二进制文件位于 riscv64-softmmu/qemu-system-riscv64
要从源代码为 aarch64 构建 QEMU:
git clone https://github.com/qemu/qemu && cd qemu
mkdir build-aarch64 && cd build-aarch64
../configure --target-list=aarch64-softmmu
make -j$(nproc)
# QEMU 二进制文件位于 aarch64-softmmu/qemu-system-aarch64
主板
与 coreboot 类似,oreboot 中的结构是按厂商和主板组织的。 分别支持多种架构和 SoC,它们之间的公共代码在主板之间共享。如果轻微的偏差会导致过多的代码重复,主板可能有变体。
仿真
qemu-riscv
硬件
RISC-V
Allwinner D1 SoC
Sipeed Lichee RV Dock / Dock Pro MangoPi MQ-Pro DongshanPi Nezha STU Allwinner Nezha
先前实现
供参考,早期方法有文档记录[9]。看看这些对于 x86 和 Arm 平台和主板。
暂停等待复兴
早期的仿真目标已在 src.broken/mainboard/emulation/
中暂停。它们应该为 oreboot 寻求支持的每种架构提供一般性的理解:
qemu-armv7
qemu-aarch64
qemu-q35
基本原则
Makefile
必须简单。使用xtask
代替控制流程,例如,向二进制文件添加头或校验和,切换图像等。分别在 src/mainboard/$VENDOR/$BOARD
(子)目录中的Cargo.toml
允许板特定的依赖项,并并行构建所有阶段。所有代码和标记都使用 make format
自动格式化,没有例外。CI 检查会告诉您如果更改不符合格式化规则。不会用 C 语言编写代码。我们用 Rust 编写所有代码。 我们不会运行自己的 Gerrit。目前我们使用 GitHub,以及 GitHub 的 Pull Request 审查机制。 我们不会运行自己的 Jenkins。我们将使用最合适的 CI;目前,那是 GitHub,但我们会保持灵活性。
QEMU 中的 ARM oreboot: https://asciinema.org/a/Ne4Fwa4Wpt95dorEoVnHwiEkP
[2]QEMU 中的 RISC-V HiFive Unleashed oreboot: https://asciinema.org/a/XnWkMWTABuajsbGPMMTefjuZ2
[3]Rust 嵌入式工作组: https://github.com/rust-embedded
[4]他们的书籍: https://docs.rust-embedded.org/book/portability/index.html
[5]Rust 嵌入式模型: Documentation/img/rust-embedded-model.png
[6]设计模式和实现指南: https://docs.rust-embedded.org/book/design-patterns/hal/index.html
[7]术语表: https://docs.rust-embedded.org/book/appendix/glossary.html
[8]启动流程文档: Documentation/boot-flow.md
[9]早期方法有文档记录: graveyard.md