ostool
🌐 Language | 语言
English | 简体中文 (当前 | Current)
📖 项目简介
axloader 0.2 的网络控制、持久 MAC 绑定、Web 管理和内建 QEMU 虚拟板设计见 docs/axloader-network-control.md,完整接口契约见 docs/api.md。
ostool 是一个专为操作系统开发而设计的 Rust 工具集,旨在为 OS 开发者提供便捷的构建、配置和启动环境。它特别适合嵌入式系统开发,支持通过 Qemu 虚拟机和 U-Boot 引导程序进行系统测试和调试。
✨ 核心特性
- 🔧 一体化工具链 - 集构建、配置、运行于一体的完整解决方案
- 🖥️ 现代化 TUI - 基于终端的用户界面,提供直观的配置编辑体验
- ⚙️ 智能配置管理 - JSON Schema 驱动的配置验证和编辑
- 🚀 多种启动方式 - 支持 Qemu 虚拟机和 U-Boot 硬件启动
- 🌐 跨平台支持 - Linux、Windows 等多平台兼容
- 📦 模块化架构 - 可扩展的组件设计,便于定制和集成
🏗️ 项目架构
ostool 采用 Rust 工作空间架构,包含以下核心模块:
核心组件
| 组件 | 功能描述 | 主要用途 |
|---|---|---|
| ostool | 主要工具包 | CLI 工具,构建和运行系统 |
| jkconfig | 配置编辑器 | TUI 配置编辑界面 |
| fitimage | FIT 镜像构建 | U-Boot 兼容的启动镜像生成 |
| uboot-shell | U-Boot 通信 | 串口通信和命令执行 |
技术栈
- Rust - 核心开发语言,提供内存安全和性能
- Ratatui - 现代化 TUI 框架
- JSON Schema - 配置验证和类型安全
- Tokio - 异步运行时
- Serialport - 串口通信
- Clap - 命令行参数解析
🚀 快速开始
安装
# 从 crates.io 安装
# 或从源码构建
基本使用
1. 查看帮助
# 查看主帮助
# 查看构建帮助
# 查看运行帮助
# 查看配置帮助
2. 配置管理
# 使用 TUI 编辑构建配置
# 配置 QEMU 运行参数
# 配置 U-Boot 运行参数
3. 构建系统
# 构建项目(使用默认配置文件 .build.toml)
# 指定配置文件构建
# 临时覆盖 Cargo package / binary target
# 临时构建 Cargo test target
# 在指定工作目录中构建
4. 运行系统
# 使用 Qemu 运行
# 使用 Qemu 运行并启用调试
# 使用 Qemu 运行并转储 DTB 文件
# 指定 Qemu 配置文件运行
# 临时覆盖 Cargo package / binary/test target 后运行
# 使用 U-Boot 运行
# 指定 U-Boot 配置文件运行
# 配置远端开发板服务器
# 查看远端开发板类型
# 在远端开发板上运行
# 在远端开发板上运行指定 Cargo binary/test target
交互退出:在串口终端(如
ostool run uboot)中,按下Ctrl+A后再按x,工具会检测到该序列并优雅退出,不会将按键发送到目标设备。 更多键盘快捷键映射可参考源码ostool/src/sterm/mod.rs。
⚙️ 配置文件
ostool 使用多个独立的 TOML 配置文件,每个文件负责不同的功能模块:
构建配置 (.build.toml)
构建配置文件定义了如何编译你的操作系统内核。
Cargo 构建系统示例
[]
# 使用 Cargo 构建系统
= "Cargo"
[]
# 目标三元组
= "aarch64-unknown-none"
# 包名称
= "my-os-kernel"
# 二进制 target 名称。包内只有一个 binary 时可省略;
# 包内有多个 binary 时建议设置,或在命令行传 `--bin <name>`。
= "my-os-kernel"
# test target 名称。用于构建可执行 `[[test]]` 目标,例如 `harness = false`
# 的内核测试;与 `bin` 互斥,也可在命令行传 `--test <name>`。
# test = "my-os-kernel-axtest"
# 启用的特性
= ["page-alloc-4g"]
# 日志级别
= "Info"
# 环境变量
= { = "-C link-arg=-Tlinker.ld" }
# Cargo 构建 profile,可选值为 "Debug" 或 "Release"。
# 省略时保持兼容行为:QEMU --debug 使用 Debug,其它构建/运行使用 Release。
= "Release"
# 如需禁用从 someboot build-info.toml 自动注入 Cargo 参数,可显式设置为 true。
# disable_someboot_build_config = true
# 额外的 cargo 参数
= []
# 构建前执行的命令
= ["make prepare"]
# 构建后执行的命令
= ["make post-process"]
# 可选兼容字段。U-Boot、board 和 UEFI QEMU 运行会自动准备所需 BIN。
= false
命令行 --package/--bin/--test 会先覆盖 .build.toml 中的 Cargo 包/目标选择,再用于
${package} 变量展开和 someboot build-info.toml 自动参数注入。
自定义构建系统示例
[]
# 使用自定义构建系统
= "Custom"
[]
# 构建命令
= "make ARCH=aarch64 A=examples/helloworld"
# 生成的 ELF 文件路径
= "examples/helloworld/helloworld_aarch64-qemu-virt.elf"
# 可选兼容字段。U-Boot、board 和 UEFI QEMU 运行会自动准备所需 BIN。
= false
QEMU 配置 (.qemu.toml)
QEMU 配置文件定义了虚拟机的启动参数。
# QEMU 启动参数
= ["-machine", "virt", "-cpu", "cortex-a57", "-nographic"]
# 启用 UEFI 引导
= false
# 可选兼容字段。UEFI QEMU 会自动准备所需 BIN。
= false
# 失败运行的正则表达式(用于自动检测)
= ["panic", "error", "failed"]
U-Boot 配置 (.uboot.toml)
U-Boot 配置文件定义了硬件启动参数。
# 串口设备
= "/dev/ttyUSB0"
# 波特率
= "115200"
# 设备树文件(可选)
= "tools/device_tree.dtb"
# 内核加载地址(可选)
= "0x80080000"
# 板子重置命令(可选)
= "reset"
# 板子断电命令(可选)
= "poweroff"
# 失败启动的正则表达式
= ["Boot failed", "Error loading kernel"]
# 网络启动配置(可选)
[]
= "eth0"
= "192.168.1.100"
有序 Shell 初始化步骤
QEMU、U-Boot 和 board 配置都使用 shell_check_steps 描述有序的 shell 命令与结果检查。例如先从 Axvisor shell 切换到 VM console,再在 guest shell 中执行测试命令:
= ["(?i)failed|panic"]
= [
{ = "axvisor:/$", = "vm console 1" },
{ = "root@starry:/root #", = "pwd && echo 'starry guest test pass'", = ["(?m)^starry guest test pass\\s*$"], = ["(?i)failed|panic"], = 30 },
]
数组下标就是执行顺序。需要发送命令的步骤必须能取得非空 shell_prefix;后续命令步骤省略它时会自动继承前一步的 prefix,显式写空字符串会报错。shell_cmd 可以省略,此时该步骤不等待 prompt、不发送命令,只按 success_regex/fail_regex 检查输出,适合 profile autorun 或内核自行运行测试的场景。
步骤同时配置 success_regex 和 fail_regex 时,ostool 会先检查失败表达式,再检查成功表达式;任意一个成功表达式匹配后就进入下一步,任意一个失败表达式匹配则测试失败。只配置 fail_regex 会因为没有成功完成条件而被拒绝。timeout 是命令步骤发送完成后的等待秒数,且必须大于 0;不发送命令的被动步骤应使用顶层总 timeout。
如果一步没有配置 success_regex 和 fail_regex,命令完成 write/flush 后直接进入下一步。最后一步完成后,整个 shell-check 序列即视为测试成功。顶层 fail_regex 和 timeout 分别是全局失败条件和总超时;步骤内 fail_regex 只在当前步骤等待结果时生效。
顶层 success_regex 已移除;成功条件必须放到相应的 shell_check_steps 步骤中。步骤的 prefix、命令和正则支持普通变量展开。board 的 ${boardServerIp}、${boardServerHttpBaseUrl} 和 ${sessionFile:<relative-path>} 仅在每一步的 shell_cmd 中展开。
只检查自行产生的输出时,可以使用无命令步骤:
[[]]
= ["(?m)^TEST_PASSED\\s*$"]
这是一次配置硬切换:旧的顶层 shell prefix/command、旧步骤数组及旧步骤命令字段已经移除,旧配置需要整体迁移到 shell_check_steps,不会被兼容读取。
U-Boot 进入 shell 时默认通过 <INTERRUPT> 自动识别 prompt。某些厂商 U-Boot 会给
中断提示加时间戳,例如 => [ 2.209] <INTERRUPT> 或
[ 115.141] <INTERRUPT>;ostool 会内建识别这些格式,无需额外配置。
对于运行在 Axvisor 后面的 Starry guest,把旧的顶层成功表达式放到执行 guest 命令的步骤中;这样该步骤自己的 success/fail 负责判断命令结果,顶层 fail 继续兜底整个运行过程。
环境变量支持
配置文件支持环境变量替换,使用 ${env:VAR_NAME:-default} 格式:
# .uboot.toml 示例
= "${env:SERIAL_DEVICE:-/dev/ttyUSB0}"
= "${env:BAUD_RATE:-115200}"
Board 全局配置 (~/.ostool/config.toml)
ostool board 系列命令默认读取用户级全局配置。首次执行相关命令时,如果该文件不存在,会自动创建默认配置:
[]
= "http://localhost:2999"
= "disabled"
可以通过下面的命令打开 TUI 编辑器修改:
server 应使用包含 http:// 或 https:// 的完整 URL;可选的 port 会覆盖 URL 中的端口。为兼容旧的局域网配置,裸 IPv4 或 IPv6 地址会自动补为 http://。基线版本写出的 server_ip / port 也会在读取时迁移为 server / port,下一次保存配置时只写新格式;无 scheme 的主机名不支持。项目级 .board.toml 中的 server / port 仍可用于 ostool board run,其优先级低于命令行参数,高于全局配置。
.board.toml 可以用 session_files 声明相对于配置文件目录的共享文件。调用方通过
BoardRunRequest::with_session_files 提供该目录,ostool 会在 board session
建立后按原相对路径上传,并在每个 shell_check_steps 的 shell_cmd 中展开
${boardServerIp}、${boardServerHttpBaseUrl} 和
${sessionFile:<relative-path>}。绝对路径、..、符号链接逃逸、重复路径及缺失
文件都会在运行前被拒绝;接口不提供 alias 或上传改名。
公网开发板认证
局域网直接连接 ostool-server 时保留上述匿名 HTTP 配置。公网认证网关使用完整 HTTPS 地址:
[]
= "https://203.0.113.10:8443"
= "required"
登录使用浏览器设备授权流程,或从标准输入导入在 Web 管理台创建的个人访问令牌(PAT):
|
OAuth 登录会自动刷新短期 access token;PAT 直接用于 Bearer 认证,不会刷新。凭据优先保存到系统 credential store;不可用时会警告并退回用户级凭据文件。自动化场景可设置 OSTOOL_BOARD_ACCESS_TOKEN,该 token 不保存也不刷新。
公网认证必须使用 HTTPS。客户端仅使用系统信任库验证证书;部署组织私有 CA 时,需由运维将其根证书安装到客户端系统。不要使用 HTTP、跳过证书验证或把 token 放进配置文件。
🛠️ 子项目详解
JKConfig - 智能配置编辑器
JKConfig 是一个基于 JSON Schema 的 TUI 配置编辑器,提供以下功能:
主要特性
- 🎯 智能界面生成 - 自动从 JSON Schema 生成编辑界面
- 🔒 类型安全 - 支持复杂数据类型和验证规则
- 📝 多格式支持 - TOML、JSON 格式读写
- 💾 自动备份 - 保存时自动创建备份文件
- ⌨️ 快捷键支持 - Vim 风格的键盘操作
使用方法
# 安装
# 编辑配置
# 自动检测 schema
键盘快捷键
导航:
↑/↓ 或 j/k - 上下移动
Enter - 编辑项目
Esc - 返回上级
操作:
S - 保存并退出
Q - 不保存退出
C - 清除当前值
M - 切换菜单状态
Tab - 切换选项
~ - 调试控制台
FitImage - FIT 镜像构建工具
FitImage 是用于创建 U-Boot 兼容的 FIT (Flattened Image Tree) 镜像的专业工具:
主要特性
- 🏗️ 标准 FIT 格式 - 完全符合 U-Boot FIT 规范
- 📦 多组件支持 - 内核、设备树、ramdisk 等
- 🗜️ 压缩功能 - gzip 压缩减少镜像大小
- 🔐 校验支持 - CRC32、SHA1 等多种校验算法
- 🎯 架构兼容 - ARM、ARM64 等多种架构
使用示例
use ;
// 创建 FIT 镜像配置
let config = new
.with_kernel
.with_fdt;
// 构建镜像
let mut builder = new;
let fit_data = builder.build?;
// 保存文件
write?;
🎯 使用场景
1. 本地开发工作流
# 1. 初始化项目
# 2. 使用 menuconfig 配置构建参数
# 3. 配置 QEMU 运行参数
# 4. 构建项目
# 5. 使用 Qemu 运行
# 6. 启用调试模式运行
2. 远程构建和硬件测试
# 1. 使用 menuconfig 配置自定义构建
# 2. 配置 U-Boot 运行参数
# 3. 执行构建
# 4. 通过 U-Boot 启动到硬件
# 5. 指定自定义 U-Boot 配置
3. 嵌入式系统开发
- 🎯 多架构支持 - ARM64、RISC-V64 等多种架构
- 🔧 设备树管理 - 自动处理 DTB 文件和设备树配置
- 📡 网络启动 - 支持 TFTP 网络启动和远程加载
- 🖥️ 串口调试 - 实时串口监控和调试信息输出
- 🔐 FIT 镜像 - 创建 U-Boot 兼容的 FIT 启动镜像
- ⚡ 自动化构建 - 支持构建前后脚本和自定义命令
4. 高级调试场景
# 启用详细日志
RUST_LOG=debug
# 转储 DTB 文件用于调试
# 在指定工作目录中操作
🔧 高级配置
U-Boot 网络启动设置
# TFTP 需要 root 权限绑定 69 端口
在 Linux 上使用系统 TFTP 根目录(默认 /srv/tftp)时,ostool 会在
/srv/tftp/ostool 下暂存 FIT 镜像,并在任务结束后使用普通用户权限删除暂存目录。
请为该目录配置专用用户组:
# 首次配置
配置完成后,重新登录;也可以在当前终端启动一个已应用新用户组的 shell:
如果 ostool 组已经存在,可以跳过 groupadd。执行 newgrp ostool 或重新登录后,
新用户组权限才会生效;不需要重启 tftpd-hpa。ostool 不会在任务结束时使用
sudo rmdir;目录缺少组写权限时,清理操作会返回错误。
调试配置
[]
= "-s -S" # 启用 GDB 调试
[]
# 启用详细日志
= "debug"
🐛 故障排除
常见问题
Q: U-Boot 启动失败? A: 检查以下几点:
- 串口设备路径是否正确(
/dev/ttyUSB0或其他) - 串口权限是否足够(可能需要
sudo usermod -a -G dialout $USER) - 波特率设置是否与硬件匹配
- 设备树文件路径是否正确
Q: Qemu 无法启动? A: 检查以下几点:
- 构建生成的内核文件是否存在
- QEMU 配置中的架构参数是否正确
- 是否安装了对应架构的 QEMU(如
qemu-system-aarch64)
Q: 构建失败? A: 检查以下几点:
- 构建配置文件格式是否正确
- 自定义构建命令是否能在终端中执行
- 目标架构的交叉编译工具链是否安装
Q: 配置文件格式错误? A: 检查以下几点:
- TOML 语法是否正确(使用在线 TOML 验证器)
- 配置文件是否使用了正确的字段名
- 数组和字符串格式是否符合规范
Q: menuconfig 无法启动? A: 检查以下几点:
- 终端是否支持 TUI 界面
- 是否安装了必要的依赖(如 ncurses)
- 配置文件权限是否正确
调试技巧
# 启用详细日志
RUST_LOG=debug
# 查看完整的命令行帮助
# 检查配置文件是否被正确加载
RUST_LOG=debug |
# 在指定工作目录中调试
权限问题解决
# 将用户添加到 dialout 组以访问串口设备
# 重新登录或重启使权限生效
# 或者临时使用 sudo 运行
🤝 贡献指南
我们欢迎社区贡献!请遵循以下步骤:
- Fork 本仓库
- 创建 特性分支 (
git checkout -b feature/amazing-feature) - 提交 更改 (
git commit -m 'Add some amazing feature') - 推送 到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
开发环境设置
📄 许可证
本项目采用双重许可证:
🔗 相关链接
🙏 致谢
感谢所有为 ostool 项目做出贡献的开发者和用户!