#内核 #x86_64 #磁盘镜像 #BIOS #UEFI #实验性 #系统

引导加载程序

一个实验性的 x86_64 引导加载程序,可在 BIOS 和 UEFI 系统上运行

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-0012018年3月29日

#33操作系统

Download history 3712/week @ 2024-05-03 4035/week @ 2024-05-10 3872/week @ 2024-05-17 3671/week @ 2024-05-24 4070/week @ 2024-05-31 2854/week @ 2024-06-07 3506/week @ 2024-06-14 3676/week @ 2024-06-21 2379/week @ 2024-06-28 2001/week @ 2024-07-05 3344/week @ 2024-07-12 3744/week @ 2024-07-19 3530/week @ 2024-07-26 3318/week @ 2024-08-02 4919/week @ 2024-08-09 2870/week @ 2024-08-16

15,203 每月下载量
18 包(17 个直接)中使用

MIT/Apache

59KB
1K SLoC

引导加载程序

Docs Build Status Join the chat at https://gitter.im/rust-osdev/bootloader

一个实验性的 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 以下载 corealloc 零件库的预编译版本。
  • 由于 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 部分。
  • BIOSUEFI 二进制文件包含实际的引导加载程序实现。
    • 这两种实现共享一个更高层次的 公共库
    • 两种实现都将在运行时从 FAT 分区加载内核。这个 FAT 分区是创建的
    • 配置从内核 ELF 文件的特殊部分读取,该部分由 bootloader_api 库的 entry_point 宏创建。
  • 一个用于创建可引导磁盘镜像的 bootloader 库,该镜像运行指定的内核。此库是本项目中的顶级 crate。
    • 此库在 build.rs 中构建 BIOS 和 UEFI 实现。
    • 它提供基于编译的 BIOS 和 UEFI 引导加载程序创建 FAT 格式可引导磁盘镜像的函数。

许可协议

根据您的选择,许可协议为

除非您明确声明,否则根据 Apache-2.0 许可证定义,您提交给作品以供包含的任何贡献,应如上所述双重许可,不附加任何额外条款或条件。

依赖项

~4–16MB
~222K SLoC