Skip to content

Commit b956f34

Browse files
authored
Up to date with YatSenOS-V2-Targets (#54)
1 parent a32c7e5 commit b956f34

144 files changed

Lines changed: 604 additions & 440 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/general/specification.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ no_comments: true
4949
- 使用 `rustfmt``cargo fmt --all` 命令来格式化代码;
5050
- 使用 `clippy``cargo clippy` 来检查代码风格。
5151
- 使用 [typos](https://github.com/crate-ci/typos) 检查拼写错误,可以使用 `cargo install typos-cli` 安装。
52+
- 使用 `taplo``taplo fmt` 来格式化 toml 配置文件。`taplo.toml`
5253

5354
!!! note "请注意,由于项目 target 不尽相同,`clippy` 需要在每一个 `package` 下使用。"
5455

docs/labs/0x00/tasks.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
- 如果代码格式不确定或写法不明确,记得常用 `cargo fmt` 和 `cargo clippy`。
4949
- 在你不熟悉新语言的时候,我们非常推荐你借助 LLM 进行学习。
5050
- 在满足题目描述的情况下,如有需要,**参数类型和返回值类型可以自行选择和修改**。
51+
- 你还可以通过配置文件 `rustfmt.toml` 和 `taplo.toml` 自定义你的代码 `*.rs` 和配置文件 `*.toml` 如何格式化,[实验 0x00 代码](https://github.com/YatSenOS/YatSenOS-Tutorial-Volume-2/tree/main/src/0x00/)已经给出了这样 2 个配置文件供参考。
5152

5253
1. 使用 Rust 编写一个程序,完成以下任务:
5354

@@ -216,9 +217,9 @@
216217
Cargo.toml
217218
Makefile
218219
assets/OVMF.fd
219-
pkg/boot/.cargo/config
220-
pkg/boot/Cargo.toml
221-
pkg/boot/src/main.rs
220+
crates/boot/.cargo/config
221+
crates/boot/Cargo.toml
222+
crates/boot/src/main.rs
222223
rust-toolchain.toml
223224
ysos.py
224225
```
@@ -324,7 +325,7 @@ targets = [ "x86_64-unknown-uefi" ]
324325
325326
!!! note "获取详细信息,参考 [Rust 语言基础](../../wiki/rust.md#善用-docsrs)"
326327

327-
`pkg/boot/src/main.rs` 中,完善如下的代码,修改注释部分,使用你的学号进行输出:
328+
`crates/boot/src/main.rs` 中,完善如下的代码,修改注释部分,使用你的学号进行输出:
328329

329330
```rust
330331
#![no_std]
@@ -364,8 +365,8 @@ fn efi_main() -> Status {
364365
BdsDxe: failed to load Boot0001 "UEFI QEMU DVD-ROM QM00003 " from ...: Not Found
365366
BdsDxe: loading Boot0002 "UEFI QEMU HARDDISK QM00001 " from ...
366367
BdsDxe: starting Boot0002 "UEFI QEMU HARDDISK QM00001 " from ...
367-
[ INFO]: pkg/boot/src/main.rs@017: Hello World from UEFI bootloader!
368-
[ INFO]: pkg/boot/src/main.rs@017: Hello World from UEFI bootloader!
368+
[ INFO]: crates/boot/src/main.rs@017: Hello World from UEFI bootloader!
369+
[ INFO]: crates/boot/src/main.rs@017: Hello World from UEFI bootloader!
369370
```
370371

371372
!!! note "与上述同理,这里 UEFI 尝试从磁盘启动,并成功加载运行刚刚编译出的引导程序。"

docs/labs/0x01/tasks.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
!!! note "请阅读 [ELF 文件格式](../../wiki/elf.md) 部分,了解什么是 ELF 文件。"
1818

19-
为了达到这一目的,需要对 Rust 的编译目标、链接配置进行一些修改,这部分内容已经为大家准备好,你可以在 [实验 0x01 参考代码](https://github.com/YatSenOS/YatSenOS-Tutorial-Volume-2/tree/main/src/0x01/pkg/kernel/config) 中看到进行这些配置的方式。
19+
为了达到这一目的,需要对 Rust 的编译目标、链接配置进行一些修改,这部分内容已经为大家准备好,你可以在 [实验 0x01 参考代码](https://github.com/YatSenOS/YatSenOS-Tutorial-Volume-2/tree/main/src/0x01/crates/kernel/config) 中看到进行这些配置的方式。
2020

2121
!!! tip "如何使用本次参考代码"
2222

@@ -28,9 +28,9 @@
2828

2929
请注意本次实验中的 `Makefile` 和 `ysos.py` 均有更新,并注意保留 `assets/OVMF.fd` 文件。
3030

31-
同时,自本次实验开始,采用工作区依赖的方式进行依赖管理,在根目录下的 `Cargo.toml` 中定义整个项目所需的依赖,并在 `pkg` 目录下的 `Cargo.toml` 中使用 `workspace = true` 的方式引用他们(详见参考代码)。
31+
同时,自本次实验开始,采用工作区依赖的方式进行依赖管理,在根目录下的 `Cargo.toml` 中定义整个项目所需的依赖,并在 `crates` 目录下的 `Cargo.toml` 中使用 `workspace = true` 的方式引用他们(详见参考代码)。
3232

33-
`pkg/kernel/config` 中,引用了 `config/x86_64-unknown-none.json` 的编译目标配置,该配置文件如下所示:
33+
`crates/kernel/config` 中,引用了 `config/x86_64-unknown-none.json` 的编译目标配置,该配置文件如下所示:
3434

3535
```json
3636
{
@@ -49,14 +49,14 @@
4949
"features": "-mmx,-sse,+soft-float",
5050
"rustc-abi": "x86-softfloat",
5151
"pre-link-args": {
52-
"ld.lld": ["-Tpkg/kernel/config/kernel.ld", "-export-dynamic"]
52+
"ld.lld": ["-Tcrates/kernel/config/kernel.ld", "-export-dynamic"]
5353
}
5454
}
5555
```
5656

5757
这个配置文件描述了 `cargo``rustc` 应该如何编译内核,这里指定了端序、指针长度、架构、链接器、链接脚本、目标架构等信息。具体细节留作读者自行探索。
5858

59-
`"-Tpkg/kernel/config/kernel.ld"` 指定了链接脚本的位置,该链接脚本描述了内核的链接方式,其基本内容如下所示:
59+
`"-Tcrates/kernel/config/kernel.ld"` 指定了链接脚本的位置,该链接脚本描述了内核的链接方式,其基本内容如下所示:
6060

6161
```ld
6262
ENTRY(_start)
@@ -80,7 +80,7 @@ SECTIONS {
8080

8181
!!! question "实验任务"
8282

83-
在 `pkg/kernel` 目录下运行 `cargo build --release`,之后找到编译产物,并使用 `readelf` 命令查看其基本信息,回答以下问题:
83+
在 `crates/kernel` 目录下运行 `cargo build --release`,之后找到编译产物,并使用 `readelf` 命令查看其基本信息,回答以下问题:
8484

8585
- 请查看编译产物的架构相关信息,与配置文件中的描述是否一致?
8686
- 找出内核的入口点,它是被如何控制的?结合源码、链接、加载的过程,谈谈你的理解。
@@ -90,28 +90,28 @@ SECTIONS {
9090

9191
经过上述的配置,内核将会被编译为一个 ELF 文件,下一步需要在 UEFI 程序中加载这个文件、准备好内核的运行环境,最后跳转到内核进行执行。这一过程中,这个 UEFI 程序所扮演的角色就是 bootloader。
9292

93-
实验在 `pkg/boot` 中提供了一些基本的功能实现:
93+
实验在 `crates/boot` 中提供了一些基本的功能实现:
9494

9595
- `allocator.rs`:为 `uefi` crate 中的 `UEFIFrameAllocator` 实现 `x86_64` crate 所定义的 `FrameAllocator<Size4KiB>` trait,以便在页面分配、页表映射时使用。
9696
- `config.rs`:提供了一个读取并解析 `boot.conf` 的基本实现,可以使用它来自定义 bootloader 的行为、启动参数等等。
9797
- `fs.rs`:提供了在 UEFI 环境下打开文件、列出目录、加载文件、释放 `ElfFile` 的功能,你可以参考这部分代码了解与文件系统相关操作的基本内容。在后期的实验中,你将自己实现对文件系统的相关操作。
9898
- `lib.rs`:这部分内容定义了 bootloader 将要传递给内核的信息、内核的入口点、跳转到内核的实现等等。定义在 `lib.rs` 中是为了能够在内核实现中引用这些数据结构,确保内核与 bootloader 的数据结构一致。
9999
- `main.rs`:这里是 bootloader 的入口点,你可以在这里编写你的 bootloader 代码。
100100

101-
同时在 `pkg/elf` 中实验提供了加载 ELF 文件的相关代码,其中也有需要你自己实现的部分。
101+
同时在 `crates/elf` 中实验提供了加载 ELF 文件的相关代码,其中也有需要你自己实现的部分。
102102

103103
这一个 package 将被 `boot``kernel` 共同引用,并用于加载内核和用户程序的 ELF 文件。你可以参考 `Cargo.toml` 来了解这一部分的依赖关系。
104104

105105
!!! warning "请留意代码中标注有 `FIXME:` 的部分,这些部分需要你自己实现。"
106106

107-
此部分的核心代码任务被放置在 `pkg/boot/src/main.rs` 中,你需要按照下列步骤完成这一部分的实现。
107+
此部分的核心代码任务被放置在 `crates/boot/src/main.rs` 中,你需要按照下列步骤完成这一部分的实现。
108108

109109
### 加载相关文件
110110

111111
1. 加载配置文件:加载配置文件,解析其中的内核栈大小、内核栈地址等内容。
112112
2. 加载内核 ELF:根据配置文件中的信息,加载内核 ELF 文件到内存中,并将其加载为 `ElfFile` 以便进行后续的操作。
113113

114-
为了方便你的实现,在 `pkg/boot/src/fs.rs` 中,提供了一些函数可供调用,对于一个正常的文件读取流程,你可以参考如下代码:
114+
为了方便你的实现,在 `crates/boot/src/fs.rs` 中,提供了一些函数可供调用,对于一个正常的文件读取流程,你可以参考如下代码:
115115

116116
```rust
117117
let mut file = open_file(file_path);
@@ -156,13 +156,13 @@ unsafe {
156156

157157
### 映射内核文件
158158

159-
在成功加载内核,并禁用根页表写保护后,需要将内核的代码段、数据段、BSS 段等映射到虚拟地址空间中。你可以参考和使用 `pkg/elf/src/lib.rs` 中的 `load_elf` 函数来帮助你完成。
159+
在成功加载内核,并禁用根页表写保护后,需要将内核的代码段、数据段、BSS 段等映射到虚拟地址空间中。你可以参考和使用 `crates/elf/src/lib.rs` 中的 `load_elf` 函数来帮助你完成。
160160

161161
!!! tip "一些提示"
162162

163163
- `physical_memory_offset` 在配置结构体中,它描述了物理地址进行线性映射的偏移量,你可能会使用到。
164164
- 你可以使用 `&mut UEFIFrameAllocator` 表达式作为参数传递帧分配器。
165-
- `pkg/elf/src/lib.rs` 中的 `load_segment` 函数需要你进行补全。**请认真学习实验文档所提供的有关分页内存权限管理、内核 ELF 文件格式的内容,以便你能够完成这一部分的实现。**
165+
- `crates/elf/src/lib.rs` 中的 `load_segment` 函数需要你进行补全。**请认真学习实验文档所提供的有关分页内存权限管理、内核 ELF 文件格式的内容,以便你能够完成这一部分的实现。**
166166
- 阅读配置文件定义中有关内核栈的内容,利用相关参数来初始化内核栈。
167167
- 别忘了将你修改过的控制寄存器恢复原样。
168168

@@ -223,9 +223,9 @@ unsafe {
223223

224224
[UART 串口通信](../../wiki/uart.md) 部分中介绍了 UART 的基本原理,以及相关的基础知识。在这一部分实验中,你将会实现一个简单的串口驱动,并将其用于内核的日志输出。
225225

226-
由于这是第一次进行驱动的编写,你可以在 `pkg/kernel/src/drivers` 目录下看到一个基本的代码框架,你需要完成其中的 `uart16550` 驱动。
226+
由于这是第一次进行驱动的编写,你可以在 `crates/kernel/src/drivers` 目录下看到一个基本的代码框架,你需要完成其中的 `uart16550` 驱动。
227227

228-
`pkg/kernel/src/drivers/serial.rs` 中存放了串口初始化的相关代码,你所实现的 `SerialPort` 结构体将会在这里被调用:
228+
`crates/kernel/src/drivers/serial.rs` 中存放了串口初始化的相关代码,你所实现的 `SerialPort` 结构体将会在这里被调用:
229229

230230
```rust
231231
use super::uart16550::SerialPort;
@@ -269,7 +269,7 @@ guard_access_fn!(pub get_serial(SERIAL: SerialPort));
269269

270270
在 Rust 中对全局变量的写入是一个 unsafe 操作,因为这是**线程不安全的**,如果直接使用全局静态变量,编译器会进行报错。但是对于 **“串口设备”** 这一类 **静态的全局对象** 我们确实需要进行一些数据存储,为了内存安全,就会不可避免的引入了**互斥锁**来进行保护。
271271

272-
!!! question "在 `pkg/boot/lib.rs` 中的 `ENTRY` 是如何被处理的?"
272+
!!! question "在 `crates/boot/lib.rs` 中的 `ENTRY` 是如何被处理的?"
273273

274274
在内核框架中,我们提供了两个宏来帮助你实现这一功能:
275275

@@ -278,7 +278,7 @@ once_mutex!(pub SERIAL: SerialPort);
278278
guard_access_fn!(pub get_serial(SERIAL: SerialPort));
279279
```
280280

281-
!!! note "你可以在 `pkg/kernel/src/utils/macros.rs` 中找到这些宏的定义。"
281+
!!! note "你可以在 `crates/kernel/src/utils/macros.rs` 中找到这些宏的定义。"
282282

283283
这两段代码将会被展开为:
284284

@@ -445,7 +445,7 @@ char read_serial() {
445445

446446
#### 串口驱动的测试
447447

448-
`pkg/kernel/src/utils/macros.rs` 中,你可以找到 `print!``println!` 宏面向串口输出的实现:
448+
`crates/kernel/src/utils/macros.rs` 中,你可以找到 `print!``println!` 宏面向串口输出的实现:
449449

450450
```rust
451451
#[macro_export]
@@ -481,7 +481,7 @@ pub fn print_internal(args: Arguments) {
481481

482482
为了获取更好的日志管理,我们将使用 `log` crate 来进行日志输出,并将其输出接入到前文所实现的串口驱动中。
483483

484-
你可以在 `pkg/kernel/src/utils/logger.rs` 中找到日志输出的相关代码,你需要完成其中的 `init` 函数和 `log` 函数。
484+
你可以在 `crates/kernel/src/utils/logger.rs` 中找到日志输出的相关代码,你需要完成其中的 `init` 函数和 `log` 函数。
485485

486486
> `Logger` 是一个 Zero Sized Types (ZSTs),在编译之后不会占用任何空间,它更像是一种类型标记,方便我们进行更灵活的操作。
487487
@@ -503,13 +503,13 @@ println!("{}", record.args());
503503

504504
`src/utils/macros.rs` 中,你可以选择按照自己的预期修改 `panic_handler` 的实现。
505505

506-
!!! note "`PanicInfo` 实现了 `Debug` trait,在最简的情况下,你可以使用 `{:#?}` 来输出它。"
506+
!!! note "`PanicInfo` 实现了 `Debug` trait,在最简的情况下,你可以使用 `{:#?}` 来输出它。为了方便调试,这里已经实现了输出内核程序本身完整的调用栈(Kernel Call Stack)。"
507507

508508
## 思考题
509509

510-
1. 在根目录的 `Cargo.toml` 中,指定了依赖中 `boot` 包为 `default-features = false`,而它会被内核引用,禁用默认 feature 是为了避免什么问题?请结合 `pkg/boot``Cargo.toml` 谈谈你的理解。
510+
1. 在根目录的 `Cargo.toml` 中,指定了依赖中 `boot` 包为 `default-features = false`,而它会被内核引用,禁用默认 feature 是为了避免什么问题?请结合 `crates/boot``Cargo.toml` 谈谈你的理解。
511511

512-
2.`pkg/boot/src/main.rs` 中参考相关代码,聊聊 `max_phys_addr` 是如何计算的,为什么要这么做?
512+
2.`crates/boot/src/main.rs` 中参考相关代码,聊聊 `max_phys_addr` 是如何计算的,为什么要这么做?
513513

514514
3. 串口驱动是在进入内核后启用的,那么在进入内核之前,显示的内容是如何输出的?
515515

docs/labs/0x02/tasks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
合并后的代码并不能直接运行,你需要基于合并后的代码、按照文档进行修改补充,才能逐步实现本次实验的功能。
2222

23-
`pkg/kernel/src/memory` 文件夹中,增量代码补充包含了如下的模块:
23+
`crates/kernel/src/memory` 文件夹中,增量代码补充包含了如下的模块:
2424

2525
- `address.rs`:定义了物理地址到虚拟地址的转换函数,这一模块接受启动结构体提供的物理地址偏移,从而对物理地址进行转换。此部分内容在 lab 1 中已经有所涉及,你可以参考[完整的物理地址映射](https://os.phil-opp.com/paging-implementation/#map-the-complete-physical-memory)进行深入了解。
2626
- `frames.rs`:利用 bootloader 传入的内存布局进行物理内存帧分配,实现 x86_64 的 `FrameAllocator` trait。**本次实验中不会涉及,后续实验中会用到。**
@@ -29,7 +29,7 @@
2929

3030
!!! note "动态内存分配算法在这里不做要求,本次实验直接使用现有的库赋予内核堆分配能力。"
3131

32-
`pkg/kernel/src/interrupt` 文件夹中,增量代码补充包含了如下的模块:
32+
`crates/kernel/src/interrupt` 文件夹中,增量代码补充包含了如下的模块:
3333

3434
- `apic`:有关 XAPIC、IOAPIC 和 LAPIC 的定义和实现。
3535
- `consts.rs`:有关于中断向量、IRQ 的常量定义。

docs/labs/0x03/tasks.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,12 @@ pub const STACK_INIT_TOP: u64 = STACK_MAX - 8;
390390
2. 部分代码的使用**需要自行补全 `lib.rs` 和 `mod.rs` 等文件**,你也可以**添加、修改任何所需函数**。
391391
3. 功能在逐步实现的过程中,部分未使用代码可以进行注释以通过编译检查。
392392

393-
`pkg/kernel/src/utils` 文件夹中,增量代码补充包含了如下的模块:
393+
`crates/kernel/src/utils` 文件夹中,增量代码补充包含了如下的模块:
394394

395395
- `regs.rs`:对需要保存的一系列寄存器进行了封装,规定了其输出方式,补全了进程切换时需要使用的汇编代码及 `as_handler` 宏。
396396
- `func.rs`:定义了用于测试执行的两个函数,其中 `test` 用以验证进程调度、并发的正确性,`huge_stack` 用以验证处理缺页异常的正确性。
397397

398-
`pkg/kernel/src/proc` 文件夹中,增量代码补充包含了如下的模块:
398+
`crates/kernel/src/proc` 文件夹中,增量代码补充包含了如下的模块:
399399

400400
- `context.rs`:进程上下文的定义和实现,其中包含了加载、保存进程上下文的相关函数。
401401
- `data.rs`:进程数据结构体的定义,这里存储的数据在进程被杀死后会被释放,包含了使用 `Arc` 保护的线程间共享的数据(子进程相关内容将在下次实验中使用)。

0 commit comments

Comments
 (0)