110个版本
0.11.7 | 2024年2月16日 |
---|---|
0.11.5 | 2023年12月28日 |
0.11.4 | 2023年7月5日 |
0.11.3 | 2023年3月26日 |
0.2.0-alpha-001 | 2018年3月29日 |
#33 在 操作系统 中
15,203 每月下载量
在 18 个 包(17 个直接)中使用
59KB
1K SLoC
引导加载程序
一个实验性的 x86_64 引导加载程序,可在 BIOS 和 UEFI 系统上运行。使用 Rust 和一些内联汇编编写,可在所有平台上构建,无需额外的构建时依赖项(只需一些 rustup
组件)。
要求
您需要一个带有 llvm-tools-preview
组件的夜间 Rust 编译器,该组件可以通过以下命令安装:rustup component add llvm-tools-preview
。
用法
要使用此包,您首先需要调整您的内核以使其可引导。然后,您可以从编译的内核创建一个可引导的磁盘镜像。以下详细说明了这些步骤。
如果您已经在使用较旧的 bootloader
包版本,请遵循我们的 迁移指南。
内核
为了使您的内核与 bootloader
兼容
- 在您的内核的
Cargo.toml
中添加对bootloader_api
包的依赖项。 - 您的内核二进制文件应该是
#![no_std]
和#![no_main]
。 - 定义一个入口点函数,其签名如下:
fn kernel_main(boot_info: &'static mut bootloader_api::BootInfo) -> !
。函数名可以是任意的。boot_info
参数提供了有关可用内存、帧缓冲区等信息。有关bootloader_api
零件库的详细信息,请参阅 API 文档。
- 使用
entry_point
宏来注册入口点函数:bootloader_api::entry_point!(kernel_main);
- 该宏检查你的入口点函数的签名,并为其生成一个
_start
入口点符号。(如果你使用链接脚本,请确保不要将入口点名称更改为其他名称。) - 要使用非标准配置,可以将类型为
&'static bootloader_api::BootloaderConfig
的第二个参数传递给entry_point
宏。例如,你可以为你的内核指定特定的堆栈大小const CONFIG: bootloader_api::BootloaderConfig = { let mut config = bootloader_api::BootloaderConfig::new_default(); config.kernel_stack_size = 100 * 1024; // 100 KiB config }; bootloader_api::entry_point!(kernel_main, config = &CONFIG);
- 该宏检查你的入口点函数的签名,并为其生成一个
- 通过运行以下命令将内核编译为 ELF 可执行文件:
cargo build --target x86_64-unknown-none
。你可能需要在运行此命令之前执行rustup target add x86_64-unknown-none
以下载core
和alloc
零件库的预编译版本。 - 由于
entry_point
宏的存在,编译的可执行文件包含一个包含元数据和序列化配置的特殊部分,这将使bootloader
零件库能够加载它。
引导
要将内核与引导加载程序结合并创建可引导磁盘映像,请按照以下步骤操作
- 将您的完整内核代码移动到
kernel
子目录中。 - 在顶级创建一个新的
os
零件库,该库定义了一个 工作区。 - 在
bootloader
零件库上添加build-dependencies
。 - 创建一个
build.rs
构建脚本。 - 设置一个 工件依赖项 以将您的
kernel
零件库作为build-dependency
添加# in Cargo.toml [build-dependencies] kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" }
或者,您可以在# .cargo/config.toml [unstable] # enable the unstable artifact-dependencies feature, see # https://doc.rust-lang.net.cn/nightly/cargo/reference/unstable.html#artifact-dependencies bindeps = true
build.rs
脚本中使用std::process::Command
来调用内核的构建命令。 - 获取内核可执行文件的路径。当使用工件依赖项时,您可以使用
std::env::var_os("CARGO_BIN_FILE_MY_KERNEL_my-kernel")
- 使用
bootloader::UefiBoot
和/或bootloader::BiosBoot
创建一个带有内核的可引导磁盘映像。 - 在你的
main.rs
函数中对可引导磁盘镜像进行处理。例如,使用 QEMU 运行它们。
查看我们的 磁盘镜像创建模板 获取更详细的示例。
架构
本项目分为三个独立的实体
- 一个包含入口点、配置和引导信息定义的
bootloader_api
库。- 内核应将此库作为常规 cargo 依赖项包含。
- 提供的
entry_point
宏将配置设置编码到编译的内核可执行文件的单独 ELF 部分。
- BIOS 和 UEFI 二进制文件包含实际的引导加载程序实现。
- 这两种实现共享一个更高层次的 公共库。
- 两种实现都将在运行时从 FAT 分区加载内核。这个 FAT 分区是创建的
- 配置从内核 ELF 文件的特殊部分读取,该部分由
bootloader_api
库的entry_point
宏创建。
- 一个用于创建可引导磁盘镜像的
bootloader
库,该镜像运行指定的内核。此库是本项目中的顶级 crate。- 此库在
build.rs
中构建 BIOS 和 UEFI 实现。 - 它提供基于编译的 BIOS 和 UEFI 引导加载程序创建 FAT 格式可引导磁盘镜像的函数。
- 此库在
许可协议
根据您的选择,许可协议为
- Apache 许可证 2.0(《LICENSE-APACHE》或 http://www.apache.org/licenses/LICENSE-2.0》)
- MIT 许可证(《LICENSE-MIT》或 http://opensource.org/licenses/MIT》)
。
除非您明确声明,否则根据 Apache-2.0 许可证定义,您提交给作品以供包含的任何贡献,应如上所述双重许可,不附加任何额外条款或条件。
依赖项
~4–16MB
~222K SLoC