diff --git a/articles/20220319-riscv-uefi.md b/articles/20220319-riscv-uefi.md
index 24064edfc137cda5402be60d161965f0b0fb2b50..2bfa727cdec3a4261633412d9d72313beba0a718 100644
--- a/articles/20220319-riscv-uefi.md
+++ b/articles/20220319-riscv-uefi.md
@@ -1,12 +1,13 @@
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.1-rc2 - [spaces]
> Author: Jacob Wang
> Date: 2022/03/19
+> Revisor: Falcon
> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
> Sponsor: PLCT Lab, ISCAS
->
-# RISC-V UEFI 架构支持详解,第 1 部分 - OpenSBI/U-Boot/UEFI 简介
+# RISC-V UEFI 架构支持详解,第 1 部分 - OpenSBI/U-Boot/UEFI 简介
-从 [邮件列表](https://lore.kernel.org/linux-riscv) 中找到了一笔 patchset:[adds UEFI support for RISC-V](https://lore.kernel.org/linux-riscv/20200917223716.2300238-1-atish.patra@wdc.com/)。该 patchset 实现 RISC-V 如下引导启动支撑:
+从 [邮件列表][006] 中找到了一笔 patchset:[adds UEFI support for RISC-V][007]。该 patchset 实现 RISC-V 如下引导启动支撑:
```
Qemu (both RV32 & RV64) for the following bootflow
@@ -17,9 +18,10 @@ HiFive unleashed using (RV64) for the following bootflow
OpenSBI->U-Boot->Linux
EDK2->Linux
```
+
本文尝试对 OpenSBI,U-Boot 和 UEFI 的相关概念以及代码进行基本的解析。
-## OpenSBI
+## OpenSBI
OpenSBI 项目致力于为 RISC-V 平台特有固件提供 RISC-V SBI 规范的开源参考实现,这类固件运行在 RISC-V M 模式。
@@ -35,11 +37,11 @@ RISC-V 架构下有 3 种特权级别,分别是 Machine、Supervisor 和 User
OpenSBI 会经历底层初始化阶段,该阶段主要是准备 C 执行环境;然后在布置好的 C 环境执行设备初始化;最后实现二级引导的跳转。
-以下以 [OpenSBI](https://github.com/riscv/opensbi.git) v1.0 版本为例,开展源码分析如下。
+以下以 [OpenSBI][004] v1.0 版本为例,开展源码分析如下。
1. OpenSBI 底层初始化
-其实现在 `/firmware/fw_base.S`, 大体流程如下:
+其实现在 `/firmware/fw_base.S`,大体流程如下:
```
_start:
@@ -148,7 +150,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
}
```
-关于 `sbi_hart_switch_mode()` 的具体实现以及 `next_arg1`, `next_addr` 等的设定,可能需要分析 `lib/sbi/sbi_hsm.c`,待后续再结合 qemu 调试来详细分解。
+关于 `sbi_hart_switch_mode()` 的具体实现以及 `next_arg1`, `next_addr` 等的设定,可能需要分析 `lib/sbi/sbi_hsm.c`,待后续再结合 QEMU 调试来详细分解。
## U-Boot
@@ -158,7 +160,7 @@ U-Boot 是一种流行的嵌入式 Linux 系统引导加载程序。
- SRAM
- 掉电易失(失去电源供电后 SRAM 里存储的数据不存在了),可以随意 **读写** 数据。(容量小,程序运行速度快,价格高,一般在 SoC 里面)
+ 掉电易失(失去电源供电后 SRAM 里存储的数据不存在了),可以随意 **读写** 数据。(容量小,程序运行速度快,价格高,一般在 SoC 里面)
- SDRAM
@@ -166,13 +168,13 @@ U-Boot 是一种流行的嵌入式 Linux 系统引导加载程序。
- SPL
- U-Boot 分为 uboot-spl 和 uboot 两个组成部分。SPL 是 Secondary Program Loader 的简称,第二阶段程序加载器。
+ U-Boot 分为 uboot-spl 和 U-Boot 两个组成部分。SPL 是 Secondary Program Loader 的简称,第二阶段程序加载器。
这里所谓的第二阶段是相对于 SOC 中的 SRAM 来说的,SOC 启动最先执行的是固化的程序。ROM 会通过检测启动方式来加载第二阶段 bootloader。
U-Boot 已经是一个 bootloader 了,那么为什么还多一个 U-Boot SPL 呢?
-主要原因是对于一些SOC来说,它的内部 SRAM 可能会比较小,小到无法装载下一个完整的 U-Boot 镜像,那么就需要 SPL。它主要负责初始化外部 RAM 和环境,并加载真正的 U-Boot 镜像到外部 RAM 中来执行。所以由此来看,SPL 应该是一个非常小的 loader 程序,可以运行于 SOC 的内部 SRAM 中,它的主要功能就是加载真正的 U-Boot 并运行。
+主要原因是对于一些 SOC 来说,它的内部 SRAM 可能会比较小,小到无法装载下一个完整的 U-Boot 镜像,那么就需要 SPL。它主要负责初始化外部 RAM 和环境,并加载真正的 U-Boot 镜像到外部 RAM 中来执行。所以由此来看,SPL 应该是一个非常小的 loader 程序,可以运行于 SOC 的内部 SRAM 中,它的主要功能就是加载真正的 U-Boot 并运行。
### U-Boot 加载过程
@@ -215,13 +217,13 @@ SPL 会先被加载到 SRAM 中,然后初始化 DDR 或者 SDRAM,总之会
### U-Boot 代码分析
-U-Boot 其启动过程主要可以分为两个部分,Stage1 和 Stage2 。其中 Stage1 是用汇编语言实现的,主要完成硬件资源的初始化。而 Stage2 则是用 C 语言实现。
+U-Boot 其启动过程主要可以分为两个部分,Stage1 和 Stage2。其中 Stage1 是用汇编语言实现的,主要完成硬件资源的初始化。而 Stage2 则是用 C 语言实现。
-以下以 [U-boot](https://github.com/u-boot/u-boot) v2022.04 版本为例,开展源码分析如下。
+以下以 [U-boot][005] v2022.04 版本为例,开展源码分析如下。
第一阶段路径位于 `arch/riscv/cpu/start.S` 文件。
-第二阶段启动阶段中, 会重点涉及到 位于 `common/board_r.c` 的 board_init_f 函数和位于 `common/board_r.c` 文件的的 board_init_r 函数。board_init_f 会初始化必要的板卡和 global_data 结构体,然后调用 board_init_r 进行下一阶段的板卡初始化工作。board_init_r 运行结束之后, 会调用位于 `common/main.c` 的 main_loop() 函数进行。来重点看一下这三个函数。
+第二阶段启动阶段中,会重点涉及到 位于 `common/board_r.c` 的 board_init_f 函数和位于 `common/board_r.c` 文件的的 board_init_r 函数。board_init_f 会初始化必要的板卡和 global_data 结构体,然后调用 board_init_r 进行下一阶段的板卡初始化工作。board_init_r 运行结束之后,会调用位于 `common/main.c` 的 main_loop() 函数进行。来重点看一下这三个函数。
- board_init_f 分析
@@ -351,21 +353,20 @@ void main_loop(void)
## UEFI
大概 20 多年的发展和积累中,UEFI 的代码量已经很庞大,相关标准白皮书也有很多
-> 1999 年:EFI 1.0 推出
-> 2000 年:EFI 1.02 发布
-> 2002 年:EFI 1.10 发布
-> 2006 年:UEFI 2.0 发布
-> 2007 年:UEFI 2.1
+> 1999 年:EFI 1.0 推出
+> 2000 年:EFI 1.02 发布
+> 2002 年:EFI 1.10 发布
+> 2006 年:UEFI 2.0 发布
+> 2007 年:UEFI 2.1
> 2008 年:UEFI 2.2
-
剥离开技术细节,引导软件基本做的就是初始化硬件和提供硬件的软件抽象,并完成引导启动。
启动阶段搞来搞去基本就三个步骤:
1. Rom 阶段
- 该阶段没有内存,没有 C 语言运行需要的栈空间,开始往往是汇编语言,直接在 ROM 空间上运行。在找到临时空间后( Cache As Ram, CAR),C 语言可以使用,然后开始用 C 语言初始化内存。
+ 该阶段没有内存,没有 C 语言运行需要的栈空间,开始往往是汇编语言,直接在 ROM 空间上运行。在找到临时空间后 (Cache As Ram, CAR),C 语言可以使用,然后开始用 C 语言初始化内存。
2. Ram 阶段
@@ -380,7 +381,7 @@ void main_loop(void)
EFI 在过程中会提供运行时服务和 EFI 引导时服务;
-(引导时服务只在 boot time 可用,runtime service 在引导后面的 OS 后还是可以继续被使用的)
+(引导时服务只在 boot time 可用,runtime service 在引导后面的 OS 后还是可以继续被使用的)
如上图所示,EFI 在过程中会提供运行时服务和 EFI 引导时服务,其中引导时服务只在 boot time 可用,runtime service 在引导后面的 OS 后还是可以继续被使用的。
@@ -394,7 +395,7 @@ UEFI 启动过程遵循 UEFI 平台初始化(Platform Initialization)标准
-7 个阶段分别为 `SEC (Security)`,`PEI (Pre-EFi Initalization)`,`DXE (Driver Execution Environment)`,`BDS (Boot Device Selection)`,`TSL (Transient System Load)`,`RT (Runtime)`,`AL (After Life)`。前三个阶段是 UEFI 初始化阶段。 下面介绍一下每个阶段的主要任务;
+7 个阶段分别为 `SEC (Security)`,`PEI (Pre-EFi Initalization)`,`DXE (Driver Execution Environment)`,`BDS (Boot Device Selection)`,`TSL (Transient System Load)`,`RT (Runtime)`,`AL (After Life)`。前三个阶段是 UEFI 初始化阶段。下面介绍一下每个阶段的主要任务;
- SEC 阶段
@@ -438,13 +439,24 @@ EDK2 是一个现代、功能丰富的跨平台固件开发环境,适用于 UE
UEFI 的 PEI 和 DXE 阶段,分别对应 Coreboot 的 romstage 和 ramstage 阶段。
-下图比较形象的对比了两者的区别:
+下图比较形象的对比了两者的区别:
## 参考文档
-* [UEFI SPEC](https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf)
-* [riscv-uefi-edk2-docs](https://github.com/riscv-admin/riscv-uefi-edk2-docs)
-* [coreboot architecture](https://doc.coreboot.org/getting_started/architecture.html)
-* [SPL](https://stackoverflow.com/questions/31244862/what-is-the-use-of-spl-secondary-program-loader)
-* [Open-source Firmware and Bootloaders](http://lastweek.io/notes/source_code/firmware-softwares/)
+
+* [UEFI SPEC][009]
+* [riscv-uefi-edk2-docs][003]
+* [coreboot architecture][002]
+* [SPL][008]
+* [Open-source Firmware and Bootloaders][001]
+
+[001]: http://lastweek.io/notes/source_code/firmware-softwares/
+[002]: https://doc.coreboot.org/getting_started/architecture.html
+[003]: https://github.com/riscv-admin/riscv-uefi-edk2-docs
+[004]: https://github.com/riscv/opensbi.git
+[005]: https://github.com/u-boot/u-boot
+[006]: https://lore.kernel.org/linux-riscv
+[007]: https://lore.kernel.org/linux-riscv/20200917223716.2300238-1-atish.patra@wdc.com/
+[008]: https://stackoverflow.com/questions/31244862/what-is-the-use-of-spl-secondary-program-loader
+[009]: https://uefi.org/sites/default/files/resources/UEFI_Spec_2_9_2021_03_18.pdf