oreboot: 革新的 Rust 驱动固件,引领开源硬件启动新时代

文摘   2024-06-28 14:50   江苏  

oreboot: 革新的 Rust 驱动固件,引领开源硬件启动新时代

oreboot 是 coreboot 的下游分支,也就是说,oreboot 是去掉了 'c' 的 coreboot。

oreboot 主要使用 Rust 语言编写,必要时使用汇编语言。

目前,oreboot 仅计划支持 LinuxBoot 有效载荷。

演示

  • QEMU 中的 ARM oreboot[1]
  • QEMU 中的 RISC-V HiFive Unleashed oreboot[2]
搞么乱中来自 Allwinner D1 上 oreboot 的输出示例
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

项目中有两种不同的东西:

  1. src/mainboards/* 实际的目标;这些依赖并共享 crates,可以是驱动程序、SoC 初始化代码等。对于主板,**必须跟踪 Cargo.lock**。
  2. 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,但我们会保持灵活性。
Reference
[1]

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


编程悟道
自制软件研发、软件商店,全栈,ARTS 、架构,模型,原生系统,后端(Node、React)以及跨平台技术(Flutter、RN).vue.js react.js next.js express koa hapi uniapp Astro
 最新文章