)
Comprehensive Rust 实战在 AOSP 中构建裸机 RustBare-Metal on Android【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust在 Android 开源项目AOSP中构建裸机bare-metalRust 程序通常需要把 Rust 编译产物嵌入无操作系统的启动镜像先用 Soong 的rust_ffi_static规则把 Rust 源码编成静态库再用带链接脚本的cc_binary产出 ELF最后通过raw_binary剥离成可直接加载执行的裸二进制。本指南以 Google Android 团队维护的 Comprehensive Rust 课程本仓库中 Bare-Metal on Android 一章为骨架结合仓库内 aarch64 应用处理器示例源码完整讲解三段式 Soong 构建配置、vmbase库的入口点与 UART 控制台机制以及如何把镜像跑在 QEMU/crosvm 虚拟机上。背景为什么需要在 AOSP 中构建裸机 RustComprehensive Rust 课程的 Bare Metal 是一天的独立课程涵盖no_stdRust、微控制器固件、应用处理器上的 bootloader/内核代码以及常用裸机 crate 等主题。其中 Application processors 一节指出与 Cortex-M 这类资源有限的微控制器不同应用处理器如 Arm Cortex-A、Intel Atom资源更充裕往往还要运行操作系统课程以 QEMU 的 aarch64virt开发板作为教学目标但仍然按“像写操作系统一样”的裸机方式对待它。当这类裸机程序需要以正式方式进入 Android 系统时就会面临一个现实问题Android 的编译体系是基于 SoongAndroid.bp的。Soong 原生并不直接生成“无操作系统自启动镜像”而是通过一组规则组合来完成从 Rust 源码到可运行裸二进制的转换。这正是src/bare-metal/android.md所讲解的核心内容也是 Android 虚拟化Virtualization与早期启动镜像如 pKVM 的 vmbase场景的常见做法。三段式 Soong 构建从 Rust 源码到可运行镜像原文档给出了一个完整可用的 Android.bp 配置整个流程分为三个环节rust_ffi_static把 Rust 代码编译为静态库.a这是 Rust 模块进入 Soong 构建的最小单元cc_binary链接静态库并应用链接脚本产出 ELF 格式的可执行文件raw_binary把 ELF 转换成剥离文件头、可直接加载到内存运行的裸二进制.bin。第一步用rust_ffi_static编译 Rust 代码rust_ffi_static { name: libvmbase_example, defaults: [vmbase_ffi_defaults], crate_name: vmbase_example, srcs: [src/main.rs], rustlibs: [ libvmbase, ], }各字段含义如下name模块名也是后续cc_binary引用该静态库的标识通常带lib前缀defaults继承一组预置属性。这里继承vmbase_ffi_defaults它来自vmbase库提供的构建默认值负责把no_std、目标架构等通用编译选项统一注入避免在每个模块里重复书写crate_nameRust crate 名称应与srcs中代码的 crate 声明一致srcsRust 源文件列表rustlibs依赖的其他 Rust 静态库这里是libvmbase即课程文档 vmbase 中介绍的虚拟机基础库。为什么是rust_ffi_static而不是rust_binary因为裸机场景没有操作系统加载器来解析 ELF、完成动态链接Rust 代码必须被静态链接进一个由我们自己控制布局的镜像中。rust_ffi_static恰好产出无运行时依赖的静态库可以无缝地被 C/C 链接器消费。第二步用cc_binary配合链接脚本产出 ELFcc_binary { name: vmbase_example, defaults: [vmbase_elf_defaults], srcs: [ idmap.S, ], static_libs: [ libvmbase_example, ], linker_scripts: [ image.ld, :vmbase_sections, ], }各字段含义如下defaults继承vmbase_elf_defaults注入 ELF 链接阶段所需的默认参数如架构、PIE/非 PIE 设置等srcs这里包含一个汇编文件idmap.S。它负责早期启动阶段的一级页表identity map建立即在 Rust 入口运行之前完成内存映射初始化static_libs把第一步产出的libvmbase_example静态库链接进来linker_scripts链接脚本列表包含本地文件image.ld和 Soong 模块:vmbase_sections。前者定义镜像的内存布局代码段、只读数据、可读写数据、BSS、栈等后者由vmbase提供补充与虚拟化相关的段布局。这里的链接脚本是裸机镜像的“骨架”。仓库中应用处理器示例的 image.ld 给出了同类脚本的典型形态可以对照理解ENTRY(entry) MEMORY { image : ORIGIN 0x40080000, LENGTH 2M } SECTIONS { .init : ALIGN(4096) { text_begin .; *(.init.entry) *(.init.*) } image .text : { *(.text.*) } image /* ... .rodata / .data / .bss / .stack ... */ /DISCARD/ : { *(.gnu.hash) *(.hash) *(.interp) *(.eh_frame_hdr) *(.eh_frame) *(.note.gnu.build-id) } }从这份脚本可以看到裸机镜像的几个关键点ENTRY(entry)指定入口符号镜像从entry开始执行内存被放在0x40080000起始、长度 2M 的image区域中这是 QEMUvirt等虚拟机的典型内核加载地址.init段按 4K 对齐并最先放置确保入口代码位于镜像开头通过/DISCARD/丢弃.interp、.eh_frame等“需要加载器”的段因为镜像自加载self-loading不需要这些元数据。第三步用raw_binary转换为裸二进制raw_binary { name: vmbase_example_bin, stem: vmbase_example.bin, src: :vmbase_example, enabled: false, target: { android_arm64: { enabled: true, }, }, }各字段含义如下name/stem模块名与最终输出文件名产物为vmbase_example.binsrc指向第二步的cc_binary模块vmbase_exampleenabled: falsetarget.android_arm64.enabled: true默认全局关闭仅对android_arm64目标启用。因为该裸机镜像针对 aarch64 虚拟机设计在 x86 主机编译或非 Android 目标上不应产生产物避免无意义的构建失败。raw_binary内部实际上执行了与objcopy -O binary等价的剥离操作把 ELF 中的段按LMA加载地址连续排列成裸字节流去掉 ELF 头与程序头得到可以直接拷入内存并跳转执行的镜像。仓库中 QEMU 示例的 Makefile 也展示了同一思路的等价手工操作minimal.bin: build cargo objcopy --bin minimal -- -O binary $深入 vmbase入口点、UART 控制台与 PSCI 关机构建配置中的rustlibs: [libvmbase]引用的vmbase是课程文档 vmbase 的主角。它面向在 aarch64 上由 crosvm 承载运行的虚拟机VM为这类环境提供了链接脚本与构建规则默认值即上文vmbase_elf_defaults、vmbase_sections、vmbase_ffi_defaults等 Soong 默认模块的来源让应用方无需从零编写布局入口点entry point负责接管 CPU 从 ELF/raw 镜像启动后的第一条指令之前的初始化流程包括控制台初始化UART 控制台日志提供开箱即用的串口输出能力main!宏与println!宏屏蔽底层细节让开发者像写普通程序一样书写入口函数。vmbase 的用法非常简洁课程文档给出了完整的示例#![no_main] #![no_std] use vmbase::{main, println}; main!(main); pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) { println!(Hello world); }需要特别说明的两点main!宏它把你定义的main函数登记为入口由 vmbase 的启动代码在完成初始化后调用。四个u64参数是引导加载程序bootloader或 crosvm 传递给内核的启动参数寄存器值x0–x3自动关机语义vmbase 入口点在main返回后会发起PSCI_SYSTEM_OFF调用主动关闭虚拟机。这意味着一个正常的“运行完即退出”的 VM 不需要自己处理关机逻辑。这种“main 返回即关机”的模式在仓库的独立示例中也有对应实现。比如 main_minimal.rs 中裸机程序在打印参数后显式调用system_off::Hvc()#[unsafe(no_mangle)] extern C fn main(x0: u64, x1: u64, x2: u64, x3: u64) { let mut uart unsafe { Uart::new(PL011_BASE_ADDRESS) }; writeln!(uart, main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})).unwrap(); system_off::Hvc().unwrap(); }注意这里的区别main_minimal.rs运行在 QEMUvirt板上、通过 HVChypervisor call触发system_off而 vmbase 的main!宏则把“main 返回 → PSCI_SYSTEM_OFF”这一流程内置到入口点中应用代码无需也不应手动关机。两者互为印证展示了不同抽象层级下同一机制PSCI 电源管理的用法。println!宏输出到的是 vmbase 已初始化好的 UART 控制台。在裸机环境下没有标准库的std::io日志输出必须直接落到串口寄存器如 PL011。vmbase 把这块初始化收敛在入口点中开发者拿到即可打印这在调试早期启动问题时极为重要。从构建产物到运行镜像去向与验证思路三段式 Soong 配置的最终产物是vmbase_example.bin它可能被进一步打包进系统镜像或在开发阶段直接交给模拟器/虚拟机加载。课程中与之对应的本地验证路径是在 QEMU 上直接启动裸二进制Makefile 给出了可对照的命令qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel minimal.bin -s对应到 vmbase/crosvm 场景加载方则是 crosvm 虚拟机监视器。无论哪种加载方式都遵循同一个事实CPU 从镜像入口点开始执行先完成页表与控制台等最基础的初始化再进入 Rust 的main逻辑。值得注意的是SUMMARY.md 中 “Bare-Metal on Android” 一节只有android.md与其子页vmbase.md两个文件这说明课程对 Android 裸机主题采取的是“以 vmbase 为典型实现”的精简讲解策略掌握三段式 Soong 规则rust_ffi_static→cc_binary→raw_binary即可复刻任意 AOSP 裸机模块的构建骨架而vmbase则代表这类镜像在虚拟化场景下的实际软件形态。小结把三段式构建应用到自己的 AOSP 裸机模块总结本指南的实操要点Rust 侧用rust_ffi_static声明模块srcs指向#![no_std] #![no_main]的 Rust 源码rustlibs声明对 vmbase 等基础库的依赖链接侧用cc_binary组装汇编启动文件如idmap.S与静态库linker_scripts同时挂载本地image.ld与 vmbase 提供的段脚本控制镜像布局与入口符号产物侧用raw_binary剥离 ELF 为裸镜像并通过enabled/target限定只在目标架构如android_arm64产出运行时入口点vmbase 或自写汇编负责初始化控制台与内存随后进入 Rustmain返回时通过 PSCI 关机vmbase 自动完成自实现时可调用system_off。如果希望深入学习可以继续阅读本仓库的以下相关章节vmbase 课程页vmbase 库的入口点、控制台与关机语义Application processorsaarch64 裸机编程的背景与 QEMUvirt开发板image.ld裸机镜像链接脚本的完整参考实现main_minimal.rs无 vmbase 依赖的最小化入口与 PSCI 关机示例Makefileobjcopy -O binary手工产裸二进制的等价流程。【免费下载链接】comprehensive-rustThis is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.项目地址: https://gitcode.com/GitHub_Trending/co/comprehensive-rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考