# Bootloader

## 简介

Bootloader作为最早执行的代码，职责是进行平台相关的设置，为Kernel创造运行环境。某种意义上，**Kernel是Bootloader的用户程序**。

RustOS开发之初，借用的是《[Writing an OS in Rust](https://os.phil-opp.com/second-edition/)》第一版的代码，而现在作者已经推出了第二版，第一版不再维护。两个版本的Bootloader有很大不同：

* 第一版中使用GRUB，它可以完成从磁盘加载内核代码，及进入32位保护模式的工作，并以multiboot2格式提供必要信息。剩余部分Boot代码，完成进入64位long mode的工作，它和kernel共存于同一个Rust项目中，使用nasm编译。整个构建流程需要依赖很多Rust工具链以外的程序。
* 第二版中抛弃了GRUB，作者用Rust和汇编从头写了一个[bootloader](https://github.com/rust-osdev/bootloader)，从磁盘加载内核代码，进入64位long mode，并根据kernel elf设置好页表，以自定义格式向kernel提供信息。整个bootloader作为一个独立项目存在。此外作者还写了[bootimage](https://github.com/rust-osdev/bootimage)工具，用来编译kernel并和bootloader打包在一起生成bin，统一了构建流程。

RustOS for x86\_64此前一直在使用第一版的boot流程，直到2018.09.12才迁移到bootimage工具链。此次改动后，配置开发环境的难度大大降低（尤其对macOS），Boot和Kernel也实现了分离。

至于RISCV，参考[ucore](https://ring00.github.io/bbl-ucore/)的做法使用[Berkeley bootloader(BBL)](https://github.com/riscv/riscv-pk)，作为M态运行环境，而Kernel运行在S态。目前BBL直接借用ucore中的C代码，以后也许可以仿照x86\_64的做法，编写Rust版本的bootloader。

哦对了，如果要跑在我们自己写的RV32I CPU上的话，只需有一个极小的bootloader。

## 代码及运行过程

### x86\_64 第一版（已废弃）

[代码在此](https://github.com/wangrunji0408/RustOS/tree/32b335adc01114e94e4c262bcdc6cc40a05f418c/kernel/src/arch/x86_64/boot)

执行过程：

* GRUB识别multiboot\_header，从磁盘中加载内核到内存，进入32位保护模式
* boot.asm：加载GDT，构造初始页表并开启页机制
* long\_mode\_init.asm：进入64位long mode，设置rsp寄存器，跳转到Rust代码

多核启动过程：

* entryother.asm：依次从16位->32位->64位，开启页机制，跳转到Rust代码（借用自xv6）
* 上述多核boot代码被放置到0x7000，在第一个核启动后，通过lapic向其它核发送信号，让它们从0x7000开始执行。

具体可参考博客第一版前两篇文章：

* [A minimal Multiboot Kernel](https://os.phil-opp.com/multiboot-kernel/)
* [Entering Long Mode](https://os.phil-opp.com/entering-longmode/)

### x86\_64 第二版

[官方仓库](https://github.com/rust-osdev/bootloader)

执行过程，分为三阶段：

1. boot.s：从0x7c00起<512B的代码，被BIOS放入内存后执行。工作是进入保护模式，从磁盘中加载bootloader剩余代码到内存。
2. second\_stage.s：将磁盘中的kernel（elf格式文件）加载到内存（0x400000），设置初始页表，开启页机制，进入64位long mode。
3. main.rs：解析elf文件并在页表中建立映射。写入BootInfo信息，跳转到kernel入口点。

目前此bootloader尚无官方文档☹️

### RISCV for QEMU

bbl位于 `riscv-pk`文件夹，相比官方仓库，经过了精简和修改。

bbl执行完毕后，跳转到固定地址（0x80020000），[代码在此](https://github.com/wangrunji0408/RustOS/blob/master/kernel/src/arch/riscv32/boot/entry.asm)，之后仅需设置sp寄存器，然后跳转到Rust代码。

bbl除了作为Bootloader，还提供M态运行环境，S态的Kernel可通过系统调用ecall使用bbl的服务，包括读写串口、CPU核间通信等。

### RISCV for FPGA

[一个极小bootloader](https://github.com/wangrunji0408/RustOS/blob/master/kernel/src/arch/riscv32/boot/boot.asm)，代替bbl。

## TODO

* [ ] 精简bootloader？
* [x] 向x86\_64 bootloader中加入多核启动功能
* [x] 在RISCV中加入多核启动功能


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rcore.gitbook.io/rust-os-docs/bootloader.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
