Explorar o código

Merge branch 'main' into pmp-sync

Luo Jia / Zhouqi Jiang hai 3 semanas
pai
achega
f6a0189444
Modificáronse 31 ficheiros con 941 adicións e 251 borrados
  1. 8 1
      .github/workflows/prototyper.yml
  2. 1 0
      Cargo.toml
  3. 11 0
      library/riscv-cove-rt/Cargo.toml
  4. 13 0
      library/riscv-cove-rt/src/host.rs
  5. 10 0
      library/riscv-cove-rt/src/lib.rs
  6. 57 0
      library/riscv-cove/src/host.rs
  7. 1 0
      library/sbi-rt/CHANGELOG.md
  8. 31 0
      library/sbi-rt/src/lib.rs
  9. 255 0
      prototyper/docs/booting-archlinux-in-qemu-using-edk2-and-rustsbi.md
  10. 19 17
      prototyper/docs/booting-fedora-in-qemu-using-uboot-and-rustsbi.md
  11. 25 25
      prototyper/docs/booting-freebsd-in-qemu-using-uboot-and-rustsbi.md
  12. 52 51
      prototyper/docs/booting-linux-kernel-in-qemu-using-uboot-and-rustsbi.md
  13. 21 18
      prototyper/docs/booting-openEuler-23.09-in-qemu-using-uboot-and-rustsbi.md
  14. 26 20
      prototyper/docs/booting-openwrt-in-qemu-using-uboot-and-rustsbi.md
  15. 13 13
      prototyper/docs/booting-polyos-in-qemu-using-uboot-and-rustsbi.md
  16. 56 49
      prototyper/docs/booting-test-kernel-in-qemu-using-uboot-and-rustsbi.md
  17. 20 18
      prototyper/docs/booting-ubuntu-24.04.1-in-qemu-using-uboot-and-rustsbi.md
  18. 81 0
      prototyper/docs/booting-ubuntu-24.04.3-in-qemu-using-edk2-and-rustsbi.md
  19. 2 1
      prototyper/prototyper/Cargo.toml
  20. 2 1
      prototyper/prototyper/build.rs
  21. 5 1
      prototyper/prototyper/config/default.toml
  22. 4 0
      prototyper/prototyper/config/sipeed_m1s_dock.toml
  23. 5 0
      prototyper/prototyper/src/cfg.rs
  24. 3 8
      prototyper/prototyper/src/firmware/dynamic.rs
  25. 121 23
      prototyper/prototyper/src/firmware/mod.rs
  26. 2 0
      prototyper/prototyper/src/main.rs
  27. 73 0
      prototyper/prototyper/src/platform/console.rs
  28. 8 1
      prototyper/prototyper/src/platform/mod.rs
  29. 2 2
      prototyper/prototyper/src/sbi/early_trap.rs
  30. 13 1
      prototyper/prototyper/src/sbi/heap.rs
  31. 1 1
      rust-toolchain.toml

+ 8 - 1
.github/workflows/prototyper.yml

@@ -34,7 +34,14 @@ jobs:
             cargo test -p rustsbi-prototyper
 
       - name: Install required cargo
-        run: cargo install clippy-sarif sarif-fmt
+        run: cargo install clippy-sarif sarif-fmt cargo-binutils
+
+      - name: Install required target
+        run: rustup target add riscv64imac-unknown-none-elf
+      
+      # Build the prototyper is needed before running cargo clippy for it, as the build is dependent on some logic controlled by xtask.
+      - name: Build cargo prototyper
+        run: cargo prototyper
 
       - name: Run rust-clippy
         run: |

+ 1 - 0
Cargo.toml

@@ -7,6 +7,7 @@ members = [
     "library/sbi-testing",
     "library/rustsbi",
     "library/riscv-cove",
+    "library/riscv-cove-rt",
     "library/penglai",
     "library/pmpm",
     "prototyper/prototyper",

+ 11 - 0
library/riscv-cove-rt/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "riscv-cove-rt"
+version = "0.1.0"
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+
+[dependencies]
+riscv-cove = { version = "0.0.0", path = "../riscv-cove" }
+sbi-spec = { version = "0.0.8", path = "../sbi-spec" }
+sbi-rt = { version = "0.0.3", path = "../sbi-rt" }

+ 13 - 0
library/riscv-cove-rt/src/host.rs

@@ -0,0 +1,13 @@
+//! Chapter 10, COVE Host Extension (EID #0x434F5648 "COVH").
+use riscv_cove::host::{EID_COVH, GET_TSM_INFO, TsmInfo};
+use sbi_spec::binary::{Physical, SbiRet};
+
+/// Reads the current TSM state, its configuration and supported features.
+#[inline]
+#[doc(alias = "sbi_covh_get_tsm_info")]
+pub fn covh_get_tsm_info(mem: Physical<&mut TsmInfo>) -> SbiRet {
+    // TODO mem.phys_addr_hi should be used. The physical memory parameter should be parsed in `_hi` and `_lo` pairs, ref: https://lists.riscv.org/g/tech-ap-tee/topic/114646239#msg207 .
+    unsafe { sbi_rt::raw::sbi_call_2(EID_COVH, GET_TSM_INFO, mem.phys_addr_lo(), mem.num_bytes()) }
+}
+
+// TODO other functions

+ 10 - 0
library/riscv-cove-rt/src/lib.rs

@@ -0,0 +1,10 @@
+// TODO crate level descriptions.
+#![no_std]
+
+mod host;
+// TODO mod guest;
+// TODO mod interrupt;
+
+pub use host::*;
+// TODO pub use guest::*;
+// TODO pub use interrupt::*;

+ 57 - 0
library/riscv-cove/src/host.rs

@@ -108,3 +108,60 @@ mod fid {
     #[doc(alias = "SBI_EXT_COVH_TVM_REMOVE_PAGES")]
     pub const TVM_REMOVE_PAGES: usize = 19;
 }
+
+/// Possible state of a TEE Security Manager (TSM).
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+#[repr(u32)]
+pub enum TsmState {
+    /// TSM has not been loaded on this platform.
+    NotLoaded = 0,
+    /// TSM has been loaded, but has not yet been initialized.
+    Loaded = 1,
+    /// TSM has been loaded & initialized, and is ready to accept ECALLs.
+    Ready = 2,
+}
+
+// TODO generic type of T replacing `usize`s, see sbi_spec::binary::SbiRet
+/// Information structure of a TEE Security Manager (TSM).
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[repr(C)]
+pub struct TsmInfo {
+    /// The raw current state of the TSM.
+    ///
+    /// If the state is not [`Ready`], the remanining fields are invalid
+    /// and will be initialized to zero.
+    ///
+    /// [`Ready`]: struct.TsmState.html#Ready
+    pub tsm_state: u32,
+    /// Identifier of the TSM implementation.
+    ///
+    /// This identifier is intended to distinguish among different TSM
+    /// implementations, potentially managed by different organizations,
+    /// that might target different deployment models and, thus,
+    /// implement subset of CoVE specification.
+    pub tsm_impl_id: u32,
+    /// Version number of the running TSM.
+    pub tsm_version: u32,
+    /// A bit mask of CoVE features supported by the running TSM.
+    ///
+    /// Every bit in this field corresponds to a capability defined by
+    /// constants. Presense of bit `i` indicates that both the TSM and
+    /// hardware support the corresponding capability.
+    pub tsm_capabilities: usize,
+    /// The number of 4-KiB pages which must be donated to the TSM for
+    /// storing TVM state in `covh_create_tvm_vcpu`.
+    ///
+    /// `0` if the TSM does not support the dynamic memory allocation
+    /// capability.
+    pub tvm_state_pages: usize,
+    /// The maximum number of vCPUs a TVM can support.
+    pub tvm_max_vcpus: usize,
+    /// The number of 4-KiB pages which must be donated to the TSM when
+    /// creating a new vCPU.
+    ///
+    /// `0` if the TSM does not support the dynamic memory allocation
+    /// capability.
+    pub tvm_vcpu_state_pages: usize,
+}
+
+// TODO unit tests on offsets of TsmInfo.

+ 1 - 0
library/sbi-rt/CHANGELOG.md

@@ -19,6 +19,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 - rt: add structure for SSE, FWFT, DBTR, and MPXY extensions
 - rt: add SSE extension support to SBI implementation.
 - feat(rt): add MPXY extension support to SBI runtime library.
+- lib: add `raw` module for raw SBI calls; they may be used in runtime libraries for custom SBI extensions.
 
 ### Modified
 

+ 31 - 0
library/sbi-rt/src/lib.rs

@@ -73,3 +73,34 @@ pub use sse::*;
 pub use sta::*;
 pub use susp::*;
 pub use time::*;
+
+/// Raw RISC-V SBI calls.
+///
+/// This module is not intended for direct use; it should be used by runtime libraries for custom
+/// SBI extensions, to wrap SBI `ecall` instruction into Rust friendly functions.
+///
+/// SBI runtime users should use functions from root of this library, or functions from other SBI
+/// runtime libraries.
+pub mod raw {
+    use sbi_spec::binary::SbiRet;
+
+    /// Raw SBI call with 0 parameters.
+    #[inline(always)]
+    pub unsafe fn sbi_call_0(eid: usize, fid: usize) -> SbiRet {
+        super::binary::sbi_call_0(eid, fid)
+    }
+
+    /// Raw SBI call with 1 parameter.
+    #[inline(always)]
+    pub unsafe fn sbi_call_1(eid: usize, fid: usize, arg0: usize) -> SbiRet {
+        super::binary::sbi_call_1(eid, fid, arg0)
+    }
+
+    /// Raw SBI call with 2 parameters.
+    #[inline(always)]
+    pub unsafe fn sbi_call_2(eid: usize, fid: usize, arg0: usize, arg1: usize) -> SbiRet {
+        super::binary::sbi_call_2(eid, fid, arg0, arg1)
+    }
+
+    // TODO sbi_call_3, ..., sbi_call_6
+}

+ 255 - 0
prototyper/docs/booting-archlinux-in-qemu-using-edk2-and-rustsbi.md

@@ -0,0 +1,255 @@
+# 使用RustSBI和EDK2在QEMU中启动Arch Linux
+
+本教程将介绍如何使用RustSBI和EDK2在QEMU中启动Arch Linux。
+
+运行本教程需要在安装了Arch Linux x86_64的系统上进行。
+
+## 创建根文件系统
+
+首先创建一个`rootfs`文件夹并修改权限为`root`。
+
+```bash
+mkdir rootfs
+sudo chown root:root ./rootfs
+```
+
+然后使用`pacstrap`这个`pacman`的初始化工具在`rootfs`安装`base`软件包,最好也顺便装一个`vim`。
+
+```bash
+sudo pacstrap \
+	-C /usr/share/devtools/pacman.conf.d/extra-riscv64.conf \
+	-M ./rootfs \
+	base vim
+sudo cp /usr/share/devtools/pacman.conf.d/extra-riscv64.conf rootfs/etc/
+```
+
+> `extra-riscv64.conf`是在`archlinuxcn/devtools-riscv64`软件包中提供的便利工具,
+> 其中包括了`archriscv`该移植的`pacman.conf`文件,当然一般推荐修改一下该文件的镜像站点,以提高安装的速度。
+
+然后清理一下`pacman`的缓存文件,缩小`rootfs`的大小,尤其是考虑到后面因为各种操作失误可能会反复解压`rootfs`文件。
+
+```bash
+sudo pacman  \
+	--sysroot ./rootfs \
+	--sync --clean --clean
+```
+
+然后设置一下该`rootfs`的`root`账号密码:
+
+```bash
+sudo usermod --root $(realpath ./rootfs) --password $(openssl passwd -6 "$password") root
+```
+
+就可以将`rootfs`打包为压缩包文件备用了。
+
+```bash
+sudo bsdtar --create \
+    --auto-compress --options "compression-level=9"\
+    --xattrs --acls\
+    -f archriscv-rootfs.tar.zst -C rootfs/ .
+```
+
+## 初始化虚拟机镜像
+
+首先,创建一个`qcow2`格式的QEMU虚拟机磁盘镜像:
+
+```bash
+qemu-img create -f qcow2 rustsbi-edk2-archriscv.img 10G
+```
+
+其中磁盘的大小可以自行定义。
+
+为了能够像正常的磁盘一样进行读写,需要将该文件映射到一个块设备,而这通过`qemu-nbd`程序实现。首先需要加载该程序需要使用的内核驱动程序:
+
+```bash
+sudo modprobe nbd max_part=8
+```
+
+命令中的`max_part`指定了最多能够挂载的块设备(文件)个数。然后将该文件虚拟化为一个块设备:
+
+```bash
+sudo qemu-nbd -c /dev/nbd0 rustsbi-edk2-archriscv.img
+```
+
+挂载完毕之后就可以进行初始化虚拟机磁盘镜像的工作了。初始化虚拟机镜像主要涉及到如下几步:
+
+- 格式化磁盘并安装根文件系统;
+- 编译内核和生成初始化RAM磁盘。
+
+使用EDK2进行引导需要磁盘的分区方式符合UEFI规范的要求,即使用`GPT`作为分区表的格式,并创建一个ESP(EFI System Parition)分区
+存放启动系统。
+
+首先使用`fdisk`工具进行格式化,这里生成的分区如下表所示。
+
+| 分区          | 类型        | 格式  | 挂载点 | 大小       |
+| ------------ | ---------- | ------ | ----- | ------ | 
+| /dev/nbd0p1  | EFI System |FAT32     | /boot  | 512M       |
+| /dev/nbd0p2  | Linux Filesystem |EXT4      | /      | 余下的空间 |
+
+在使用`fdisk`完成硬盘的分区之后,进行分区的格式化。
+
+```bash
+sudo mkfs.fat -F 32 /dev/nbd0p1
+sudo mkfs.ext4 /dev/nbd0p2
+```
+
+格式化完成之后,创建一个新的`mnt`目录,用于挂载新创建的硬盘。
+
+```bash
+sudo mkdir mnt
+sudo mount /dev/nbd0p2 mnt
+sudo mkdir mnt/boot
+sudo mount /dev/nbd0p1 mnt/boot
+```
+
+将上一步中创建的根文件系统解压到`mnt`文件夹中:
+
+```bash
+cd mnt
+sudo bsdtar -kpxf ../archriscv-rootfs.tar.zst
+```
+
+### 编译Linux RISC-V内核
+
+这里不能使用Arch RISC-官方打包的Linux镜像,因为官方打包的镜像进行了压缩,不符合UEFI启动的标准,无法使用UEFI直接启动。
+
+> 使得Linux符合UEFI标准的功能称作[Linux EFI STUB](https://docs.kernel.org/admin-guide/efi-stub.html)
+
+这里使用Linux源代码自行编译内核。
+
+```bash
+wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.15.9.tar.xz
+tar xvf linux-6.15.9.tar.xz
+cd linux-6.15.9
+ARCH=riscv make CROSS_COMPILE=riscv64-linux-gnu- defconfig
+ARCH=riscv make CROSS_COMPILE=riscv64-linux-gnu- Image -j$(nproc)
+```
+编译完成之后的`arch/riscv/boot/Image`就是一个符合UEFI规范要求的EFI应用程序,将它复制到`mnt/boot`目录中。
+
+```bash
+cd ..
+sudo cp linux-6.15.9/arch/riscv/boot/Image mnt/boot/linux-6.15.9.elf
+```
+
+编译Linux内核模块并安装到rootfs中。
+
+```bash
+cd linux-6.15.9
+ARCH=riscv make CROSS_COMPILE=riscv64-linux-gnu- modules -j$(nproc)
+sudo ARCH=riscv make CROSS_COMPILE=riscv64-linux-gnu- modules_install INSTALL_MOD_PATH=../mnt/usr
+```
+
+### 生成初始化RAM磁盘
+
+使用如下的命`systemd-nspawn切换进行rootfs文件系统中。
+
+```bash
+sudo systemd-nspawn -D mnt /bin/bash
+```
+
+> 这也是在系统启动失败时进入系统进行修复的常用命令,采用`qemu-riscv64-static`实现跨架构二进制文件执行。
+
+首先安装`mkinitcpio`,这是Arch Linux推荐的RAM磁盘生成工具。
+
+```bash
+pacman -Sy mkinitcpio
+```
+
+在`/etc/mkinitcpio.d/linux-6.15.9.preset`中复制如下的内容:
+
+```
+# mkinitcpio preset file for the 'linux' package
+
+#ALL_config="/etc/mkinitcpio.conf"
+ALL_kver="/boot/linux-6.15.9.elf"
+
+PRESETS=('default')
+
+#default_config="/etc/mkinitcpio.conf"
+default_image="/boot/initramfs-6.15.9.img"
+#default_uki="/efi/EFI/Linux/arch-linux.efi"
+#default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
+```
+
+生成启动使用`initramfs`。
+
+```bash
+mkinitcpio -P
+```
+
+退出`systemd-nspawn`。
+
+### 生成启动脚本
+
+首先查看镜像中启动根文件系统的UUID。
+
+```bash
+export uuid=$(sudo findmnt mnt -o uuid -n)
+```
+
+在`mnt/boot`中生成启动脚本
+
+```bash
+cd mnt/boot
+echo "\linux-6.15.9.elf initrd=initramfs-6.15.9.img rw root=UUID=${uuid} rootwait console=ttyS0,115200" | sudo tee startup.nsh
+```
+
+取消对于硬盘的挂载。
+
+```bash
+sudo umount -R mnt
+sudo qemu-nbd -d /dev/nbd0
+```
+
+## 编译RustSBI和EDK2
+
+首先拉取RustSBI的源代码并编译RustSBI:
+
+```bash
+git clone https://github.com/rustsbi/rustsbi.git --depth 1
+cd rustsbi
+cargo prototyper
+```
+
+然后拉取EDK2的源代码并编译EDK2:
+
+```bash
+git clone --recurse-submodules https://github.com/tianocore/edk2.git -b edk2-stable202505
+cd edk2
+export GCC5_RISCV64_PREFIX=riscv64-linux-gnu-
+source edksetup.sh
+build -a RISCV64 -b RELEASE -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc -t GCC5
+```
+
+为了符合QEMU对于PFLASH固件的要求,将编译好的UEFI固件大小扩展到32M。
+
+```bash
+truncate -s 32M Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_VARS.fd 
+truncate -s 32M Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_CODE.fd
+```
+
+## 启动QEMU
+
+使用如下的指令启动QEMU:
+
+```bash
+qemu-system-riscv64  \
+        -M virt,pflash0=pflash0,pflash1=pflash1,acpi=off \
+        -m 4096 -smp 8 \
+        -bios rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper-dynamic.bin \
+        -blockdev node-name=pflash0,driver=file,read-only=on,filename=edk2/Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_CODE.fd  \
+        -blockdev node-name=pflash1,driver=file,filename=edk2/Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_VARS.fd \
+        -device virtio-blk-device,drive=hd0  \
+        -drive file=rustsbi-edk2-archriscv.img,format=qcow2,id=hd0,if=none \
+        -netdev user,id=n0 -device virtio-net,netdev=n0 \
+        -monitor unix:/tmp/qemu-monitor,server,nowait \
+        -nographic \
+        -serial mon:stdio
+```
+
+启动系统并登录之后,验证是否使用UEFI启动成功:
+
+```bash
+$ cat /sys/firmware/efi/fw_platform_size 
+64
+```

+ 19 - 17
prototyper/docs/booting-fedora-in-qemu-using-uboot-and-rustsbi.md

@@ -11,28 +11,30 @@
 |  RustSBI Prototyper   |  0.0.0  |
 |        U-Boot         | 2024.04 |
 
-## 准备RustSBI Prototyper, U-Boot ,Fedora 
+## 准备RustSBI Prototyper, U-Boot ,Fedora
 
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
-### Clone RustSBI Prototyper
+### Clone RustSBI
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 ### Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
+
 ### 下载 Fedora 镜像文件
 
 下载链接:<https://dl.fedoraproject.org/pub/alt/risc-v/disk_images/Fedora-40/Fedora.riscv64-40-20240429.n.0.qcow2>
+
 ```shell
 $ mkdir -p fedora
 $ cd fedora
@@ -40,17 +42,17 @@ $ wget https://dl.fedoraproject.org/pub/alt/risc-v/disk_images/Fedora-40/Fedora.
 $ cd ..
 ```
 
-## 编译RustSBI  Prototyper
+## 编译RustSBI Prototyper
 
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -58,7 +60,7 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
@@ -67,7 +69,7 @@ $ cd u-boot
 ```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件,编译U-Boot
@@ -103,13 +105,13 @@ genisoimage \
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 \
     -nographic -machine virt \
     -smp 4 -m 8G \

+ 25 - 25
prototyper/docs/booting-freebsd-in-qemu-using-uboot-and-rustsbi.md

@@ -14,7 +14,7 @@ RustSBI 原型系统提供动态固件,根据前一个阶段传入的信息动
 |  qemu-system-riscv64  |  9.1.1  |
 |  RustSBI Prototyper   |  0.0.0  |
 |        U-Boot         | 2024.04 |
-|       FreeBSD         |  14.1   |
+|        FreeBSD        |  14.1   |
 
 ## 环境配置
 
@@ -22,7 +22,7 @@ RustSBI 原型系统提供动态固件,根据前一个阶段传入的信息动
 
 For Arch Linux
 
-``` shell
+```shell
 $ sudo pacman -S git riscv64-linux-gnu-gcc qemu-system-riscv
 ```
 
@@ -30,7 +30,7 @@ $ sudo pacman -S git riscv64-linux-gnu-gcc qemu-system-riscv
 
 For riscv64-linux-gnu-gcc:
 
-``` shell
+```shell
 $ riscv64-linux-gnu-gcc --version
 ```
 
@@ -45,7 +45,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 For QEMU:
 
-``` shell
+```shell
 $ qemu-system-riscv64 --version
 ```
 
@@ -60,39 +60,39 @@ Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
 
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
 
 Download FreeBSD
-``` shell
+
+```shell
 $ wget https://download.freebsd.org/releases/VM-IMAGES/14.1-RELEASE/riscv64/Latest/FreeBSD-14.1-RELEASE-riscv-riscv64.raw.xz && xz -d FreeBSD-14.1-RELEASE-riscv-riscv64.raw.xz
 ```
 
+## 编译RustSBI Prototyper
 
-## 编译RustSBI  Prototyper
-
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -100,28 +100,28 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 ```
 
 编译U-Boot
 
-``` shell
+```shell
 # To build U-Boot
 $ make -j$(nproc)
 ```
@@ -132,16 +132,16 @@ $ make -j$(nproc)
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 -M virt -smp 1 -m 256M -nographic \
           -bios ./u-boot/spl/u-boot-spl \
           -device loader,file=./u-boot/u-boot.itb,addr=0x80200000 \
           -blockdev driver=file,filename=./FreeBSD-14.1-RELEASE-riscv-riscv64.raw,node-name=hd0 \
           -device virtio-blk-device,drive=hd0
-```
+```

+ 52 - 51
prototyper/docs/booting-linux-kernel-in-qemu-using-uboot-and-rustsbi.md

@@ -27,28 +27,28 @@ RustSBI 原型系统提供动态固件,根据前一个阶段传入的信息动
 
 For Arch Linux:
 
-``` shell
+```shell
 $ sudo pacman -S git riscv64-linux-gnu-gcc qemu-system-riscv
 ```
 
 For Ubuntu:
 
-``` shell
+```shell
 $ sudo apt-get update && sudo apt-get upgrade
-$ sudo apt-get install git qemu-system-misc gcc-riscv64-linux-gnu 
+$ sudo apt-get install git qemu-system-misc gcc-riscv64-linux-gnu
 ```
 
 #### 测试是否成功安装
 
 For riscv64-linux-gnu-gcc:
 
-``` shell
+```shell
 $ riscv64-linux-gnu-gcc --version
 ```
 
 它将输出以下版本信息
 
-``` 
+```
 riscv64-linux-gnu-gcc (GCC) 14.1.0
 Copyright (C) 2024 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -56,13 +56,13 @@ This is free software; see the source for copying conditions.  There is NO warra
 
 For QEMU:
 
-``` shell
+```shell
 $ qemu-system-riscv64 --version
 ```
 
 它将输出以下版本信息
 
-``` 
+```
 QEMU emulator version 9.0.1
 Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
 ```
@@ -71,70 +71,70 @@ Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
 
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
 
 Clone busybox
 
-``` shell
-$ git clone https://github.com/mirror/busybox.git && cd busybox && git checkout 1_36_0 && cd ..
+```shell
+$ git clone -b 1_36_0 https://github.com/mirror/busybox.git
 ```
 
 Clone Linux Kernel
 
-``` shell
-$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git && cd linux && git checkout v6.2 && cd ..
+```shell
+$ git clone -b v6.2 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 ```
 
 ## 编译Linux Kernel
 
 进入`linux`目录
 
-``` shell
+```shell
 $ cd linux
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
 ```
 
 生成`.config`文件
 
-``` shell
+```shell
 $ make defconfig
 ```
 
 验证`.config`文件是否存在RISC-V
 
-``` shell
+```shell
 $ grep --color=always -ni 'riscv' .config
 ```
 
 观察到RISC-V 配置选项已启用
 
-``` 
+```
 CONFIG_RISCV=y
 ```
 
 编译Linux Kernel
 
-``` shell
+```shell
 $ make -j$(nproc)
 ```
 
@@ -148,20 +148,20 @@ $ make -j$(nproc)
 
 进入busybox目录
 
-``` shell
+```shell
 $ cd busybox
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
 ```
 
 编译busybox
 
-``` shell
+```shell
 $ make defconfig
 $ make menuconfig
 # Enable the Build static binary (no shared libs) option in Settings-->Build Options
@@ -173,7 +173,7 @@ $ make install
 
 在`workshop`目录运行以下命令来创建一个1 GB的磁盘镜像
 
-``` shell
+```shell
 # Create a 1 GB disk image
 $ qemu-img create linux-rootfs.img 1g
 ```
@@ -184,13 +184,13 @@ $ qemu-img create linux-rootfs.img 1g
 
 `parted`命令将用于在镜像`linux-rootfs.img`中创建分区。在镜像中创建分区表:
 
-``` shell
+```shell
 $ sudo parted linux-rootfs.img mklabel gpt
 ```
 
 现在`linux-rootfs.img`中有一个分区表。将`linux-rootfs.img`挂载为loop device,以便它可以用作块设备。将`linux-rootfs.img`挂载为块设备将允许在其中创建分区。
 
-``` shell
+```shell
 # Attach linux-rootfs.img with the first available loop device
 $ sudo losetup --find --show linux-rootfs.img
 ```
@@ -202,7 +202,7 @@ $ sudo losetup --find --show linux-rootfs.img
 
 对`/dev/loop0`分区
 
-``` shell
+```shell
 # Create a couple of primary partitions
 $ sudo parted --align minimal /dev/loop0 mkpart primary ext4 0 100%
 
@@ -213,7 +213,7 @@ $ sudo parted /dev/loop0 print
 
 通过以下命令查看分区:
 
-``` shell
+```shell
 $ ls -l /dev/loop0*
 ```
 
@@ -221,7 +221,7 @@ $ ls -l /dev/loop0*
 
 格式化分区并创建`ext4`文件系统,同时将分区设置为可引导分区。
 
-``` shell
+```shell
 $ sudo mkfs.ext4 /dev/loop0p1
 
 # Mark first partition as bootable
@@ -230,20 +230,22 @@ $ sudo parted /dev/loop0 set 1 boot on
 
 #### 将Linux Kernel和根文件系统拷贝进启动盘
 
-``` shell
+```shell
 # Mount the 1st partition
 $ sudo mkdir rootfs
 $ sudo mount /dev/loop0p1 rootfs
 $ cd rootfs
 ```
+
 拷贝Linux Kernel镜像
-``` shell
+
+```shell
 $ sudo cp ../linux/arch/riscv/boot/Image .
 ```
 
 拷贝根文件系统
 
-``` shell
+```shell
 $ sudo cp -r ../busybox/_install/* .
 $ sudo mkdir proc sys dev etc etc/init.d
 $ cd etc/init.d/
@@ -258,28 +260,28 @@ $ sudo chmod +x rcS
 
 卸载`rootfs`
 
-``` shell
+```shell
 $ cd workshop
 $ sudo umount rootfs
 ```
 
 将`/dev/loop0`分离
 
-``` shell
+```shell
 $ sudo losetup -d /dev/loop0
 ```
 
-## 编译RustSBI  Prototyper
+## 编译RustSBI Prototyper
 
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -287,21 +289,21 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 # add bootcmd value
@@ -310,13 +312,13 @@ $ make menuconfig
 
 U-Boot 配置选项将加载到终端。导航到 `Boot options` $\rightarrow$ `bootcmd value` 并将以下内容写入 `bootcmd` 值:
 
-``` 
+```
 ext4load virtio 0:1 84000000 Image; setenv bootargs root=/dev/vda1 rw console=ttyS0; booti 0x84000000 - ${fdtcontroladdr}
 ```
 
 编译U-Boot
 
-``` shell
+```shell
 # To build U-Boot
 $ make -j$(nproc)
 ```
@@ -327,17 +329,16 @@ $ make -j$(nproc)
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 -M virt -smp 1 -m 256M -nographic \
           -bios ./u-boot/spl/u-boot-spl \
           -device loader,file=./u-boot/u-boot.itb,addr=0x80200000 \
           -blockdev driver=file,filename=./linux-rootfs.img,node-name=hd0 \
           -device virtio-blk-device,drive=hd0
 ```
-

+ 21 - 18
prototyper/docs/booting-openEuler-23.09-in-qemu-using-uboot-and-rustsbi.md

@@ -12,44 +12,47 @@
 |        U-Boot         | 2024.04 |
 
 ## 准备RustSBI Prototyper, U-Boot ,openEuler 23.09
+
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 ### Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 ### Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
+
 ### 下载openEuler 23.09 Qemu磁盘镜像文件
 
 下载链接:[openEuler 23.09](https://mirror.iscas.ac.cn/openeuler-sig-riscv/openEuler-RISC-V/preview/openEuler-23.09-V1-riscv64/QEMU/openEuler-23.09-V1-base-qemu-preview.qcow2.zst)
+
 ```shell
  $ unzstd openEuler-23.09-V1-base-qemu-preview.qcow2.zst
 ```
+
 - The password of user `root` is `openEuler12#$`.
 - The password of the default user `openeuler` is `openEuler12#$`.
 
+## 编译RustSBI Prototyper
 
-## 编译RustSBI  Prototyper
-
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -57,21 +60,21 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件,编译U-Boot
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 $ ./scripts/config -e CMD_BTRFS -e FS_BTRFS
@@ -84,13 +87,13 @@ $ make -j$(nproc)
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 \
     -nographic -machine virt \
     -smp 4 -m 8G \

+ 26 - 20
prototyper/docs/booting-openwrt-in-qemu-using-uboot-and-rustsbi.md

@@ -12,28 +12,29 @@
 |        U-Boot         | 2024.04 |
 
 ## 准备RustSBI Prototyper, U-Boot ,Openwrt
+
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 ### Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 ### Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
 
 ### Clone & Patch Openwrt
 
-``` shell
-$ git clone https://git.openwrt.org/openwrt/openwrt.git 
+```shell
+$ git clone https://git.openwrt.org/openwrt/openwrt.git
 $ cd ./openwrt
 $ git checkout 603a3c6
 ```
@@ -45,17 +46,17 @@ $ curl https://raw.githubusercontent.com/rustsbi/prototyper/refs/heads/main/docs
 $ git apply openwrt-patch.patch
 ```
 
-## 编译RustSBI  Prototyper
+## 编译RustSBI Prototyper
 
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -63,21 +64,21 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件,编译U-Boot
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 $ sed -i.bak 's/CONFIG_BOOTCOMMAND=*/CONFIG_BOOTCOMMAND="scsi scan; fatload scsi 0:3 84000000 Image; setenv bootargs root=\/dev\/sda4 rw earlycon console=\/dev\/ttyS0 rootwait; booti 0x84000000 - ${fdtcontroladdr};"/' .config
@@ -91,6 +92,7 @@ $ make -j$(nproc)
 (以下内容参照并修改自 <https://openwrt.org/docs/guide-developer/toolchain/use-buildsystem>)
 
 更新 Feeds:
+
 ```shell
 $ cd openwrt
 # Update the feeds
@@ -99,6 +101,7 @@ $ ./scripts/feeds install -a
 ```
 
 修改配置:
+
 ```shell
 $ make -j$(nproc) menuconfig
 ```
@@ -106,22 +109,25 @@ $ make -j$(nproc) menuconfig
 进入 `Target System`,选中 `$SiFive U-based RISC-V boards`。
 
 修改内核配置:
+
 ```shell
 $ make -j$(nproc) kernel_menuconfig
 ```
 
-进入后将   
+进入后将  
 `Device Drivers` $\rightarrow$ `Serial ATA and Parallel ATA drivers (libata)` $\rightarrow$ `AHCI SATA support`  
 `Device Drivers` $\rightarrow$ `Network device support` $\rightarrow$ `Ethernet driver support` $\rightarrow$ `Intel devices` $\rightarrow$ `Intel(R) PRO/1000 Gigabit Ethernet support`  
 设为 `built-in`。
 
 编译镜像:
+
 ```shell
 # Build the firmware image
 $ make -j$(nproc) defconfig download clean world
 ```
 
 拷贝并解压镜像:
+
 ```shell
 $ cd ..
 $ cp ./openwrt/bin/targets/sifiveu/generic/openwrt-sifiveu-generic-sifive_unleashed-ext4-sdcard.img.gz ./
@@ -132,13 +138,13 @@ $ gzip -dk openwrt-sifiveu-generic-sifive_unleashed-ext4-sdcard.img.gz
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 \
 -machine virt -nographic -m 4096 -smp 1 \
 -bios ./u-boot/spl/u-boot-spl \

+ 13 - 13
prototyper/docs/booting-polyos-in-qemu-using-uboot-and-rustsbi.md

@@ -8,51 +8,50 @@
 
 ### Clone & Compile RustSBI Prototyper
 
-``` shell
+```shell
 $ cd $workdir
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
 ### Clone & Compile U-Boot
 
-``` shell
+```shell
 $ cd $workdir
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件,编译U-Boot
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 $ make -j$(nproc)
 ```
 
-
 ### Download & Configure PolyOS
 
 下载 PolyOS Mobile 镜像:<https://polyos.iscas.ac.cn/downloads/polyos-mobile-latest.img.tar.xz>。
@@ -120,6 +119,7 @@ $ losetup -d /dev/loop1
 ### USE Qemu to bootup
 
 使用 qemu 启动:
+
 ```shell
 $ cd $workdir/image
 image_path=`pwd`

+ 56 - 49
prototyper/docs/booting-test-kernel-in-qemu-using-uboot-and-rustsbi.md

@@ -3,6 +3,7 @@
 本教程给出了使用RustSBI和U-Boot在QEMU中启动Test Kernel的基本流程。
 
 其中启动流程分为两种类型:
+
 1. 只使用U-Boot SPL的启动流程
 2. 同时使用U-Boot SPL和U-Boot的启动流程。
 
@@ -31,13 +32,13 @@
 
 For Arch Linux:
 
-``` shell
+```shell
 $ sudo pacman -S git riscv64-linux-gnu-gcc qemu-system-riscv uboot-tools
 ```
 
 For Ubuntu:
 
-``` shell
+```shell
 $ sudo apt-get update && sudo apt-get upgrade
 $ sudo apt-get install git qemu-system-misc gcc-riscv64-linux-gnu u-boot-tools
 ```
@@ -46,7 +47,7 @@ $ sudo apt-get install git qemu-system-misc gcc-riscv64-linux-gnu u-boot-tools
 
 For riscv64-linux-gnu-gcc:
 
-``` shell
+```shell
 $ riscv64-linux-gnu-gcc --version
 ```
 
@@ -60,7 +61,7 @@ This is free software; see the source for copying conditions.  There is NO warra
 
 For QEMU:
 
-``` shell
+```shell
 $ qemu-system-riscv64 --version
 ```
 
@@ -75,59 +76,60 @@ Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
 
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
 
 ## 使用U-Boot SPL启动Test Kernel
-### 编译RustSBI  Prototyper和Test Kernel
 
-进入prototyper目录
+### 编译RustSBI Prototyper和Test Kernel
+
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
 编译RustSBI Prototyper和Test Kernel
 
-``` shell
+```shell
 $ cargo prototyper
 $ cargo test-kernel --pack
 ```
 
-本小节将使用二进制文件 `./target/riscv64imac-unknown-none-elf/release/rustsbi-test-kernel.itb`。
+本小节将使用二进制文件 `./target/riscv64gc-unknown-none-elf/release/rustsbi-test-kernel.itb`。
 
 ### 编译U-Boot SPL
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 # add bootcmd value
@@ -136,7 +138,7 @@ $ make menuconfig
 
 编译U-Boot
 
-``` shell
+```shell
 # To build U-Boot
 $ make -j$(nproc)
 ```
@@ -147,54 +149,56 @@ $ make -j$(nproc)
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 -M virt -smp 1 -m 256M -nographic \
           -bios ./u-boot/spl/u-boot-spl \
-          -device loader,file=./prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-test-kernel.itb,addr=0x80200000
+          -device loader,file=./rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-test-kernel.itb,addr=0x80200000
 ```
 
 ## 使用U-Boot SPL和U-Boot启动Test Kernel
-### 编译RustSBI  Prototyper和Test Kernel
 
-进入prototyper目录
+### 编译RustSBI Prototyper和Test Kernel
 
-``` shell
-$ cd prototyper
+进入rustsbi目录
+
+```shell
+$ cd rustsbi
 ```
 
 编译RustSBI Prototyper和Test Kernel
 
-``` shell
-$ cargo make prototyper
-$ cargo make test-kernel
+```shell
+$ cargo prototyper
+$ cargo test-kernel
 ```
-本小节将使用二进制文件 `./target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin`和`./target/riscv64imac-unknown-none-elf/release/rustsbi-test-kernel.bin`。
+
+本小节将使用二进制文件 `./target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin`和`./target/riscv64gc-unknown-none-elf/release/rustsbi-test-kernel.bin`。
 
 ### 编译U-Boot SPL
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 # add bootcmd value
@@ -209,7 +213,7 @@ ext4load virtio 0:1 84000000 rustsbi-test-kernel.bin; booti 0x84000000 - ${fdtco
 
 编译U-Boot
 
-``` shell
+```shell
 # To build U-Boot
 $ make -j$(nproc)
 ```
@@ -217,9 +221,10 @@ $ make -j$(nproc)
 本小节将使用二进制文件 `./spl/u-boot-spl`和`./u-boot.itb `。
 
 ### 创建启动盘
+
 在`workshop`目录运行以下命令来创建一个256 MB的磁盘镜像
 
-``` shell
+```shell
 # Create a 256 MB disk image
 $ qemu-img create test-kernel.img 256m
 ```
@@ -230,13 +235,13 @@ $ qemu-img create test-kernel.img 256m
 
 `parted`命令将用于在镜像`test-kernel.img`中创建分区。在镜像中创建分区表:
 
-``` shell
+```shell
 $ sudo parted test-kernel.img mklabel gpt
 ```
 
 现在`test-kernel.img`中有一个分区表。将`test-kernel.img`挂载为loop device,以便它可以用作块设备。将`test-kernel.img`挂载为块设备将允许在其中创建分区。
 
-``` shell
+```shell
 # Attach test-kernel.img with the first available loop device
 $ sudo losetup --find --show test-kernel.img
 ```
@@ -248,7 +253,7 @@ $ sudo losetup --find --show test-kernel.img
 
 对`/dev/loop0`分区
 
-``` shell
+```shell
 # Create a couple of primary partitions
 $ sudo parted --align minimal /dev/loop0 mkpart primary ext4 0 100%
 
@@ -259,7 +264,7 @@ $ sudo parted /dev/loop0 print
 
 通过以下命令查看分区:
 
-``` shell
+```shell
 $ ls -l /dev/loop0*
 ```
 
@@ -267,7 +272,7 @@ $ ls -l /dev/loop0*
 
 格式化分区并创建`ext4`文件系统,同时将分区设置为可引导分区。
 
-``` shell
+```shell
 $ sudo mkfs.ext4 /dev/loop0p1
 
 # Mark first partition as bootable
@@ -276,27 +281,29 @@ $ sudo parted /dev/loop0 set 1 boot on
 
 #### 将Linux Kernel和根文件系统拷贝进启动盘
 
-``` shell
+```shell
 # Mount the 1st partition
 $ sudo mkdir test-kernel
 $ sudo mount /dev/loop0p1 test-kernel
 $ cd test-kernel
 ```
+
 拷贝Linux Kernel镜像
-``` shell
-$ sudo cp ../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-test-kernel.bin .
+
+```shell
+$ sudo cp ../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-test-kernel.bin .
 ```
 
 卸载`test-kernel`
 
-``` shell
+```shell
 $ cd workshop
 $ sudo umount test-kernel
 ```
 
 将`/dev/loop0`分离
 
-``` shell
+```shell
 $ sudo losetup -d /dev/loop0
 ```
 
@@ -304,13 +311,13 @@ $ sudo losetup -d /dev/loop0
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 -M virt -smp 1 -m 256M -nographic \
           -bios ./u-boot/spl/u-boot-spl \
           -device loader,file=./u-boot/u-boot.itb,addr=0x80200000 \

+ 20 - 18
prototyper/docs/booting-ubuntu-24.04.1-in-qemu-using-uboot-and-rustsbi.md

@@ -12,26 +12,29 @@
 |        U-Boot         | 2024.04 |
 
 ## 准备RustSBI Prototyper, U-Boot ,Ubuntu 24.04.1
+
 创建工作目录并进入该目录
 
-``` shell
+```shell
 $ mkdir workshop && cd workshop
 ```
 
 ### Clone RustSBI Prototyper
 
-``` shell
-$ git clone https://github.com/rustsbi/prototyper.git && cd prototyper && git checkout main && cd ..
+```shell
+$ git clone -b main https://github.com/rustsbi/rustsbi.git
 ```
 
 ### Clone U-Boot
 
-``` shell
-$ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2024.04 && cd ..
+```shell
+$ git clone -b v2024.04 https://github.com/u-boot/u-boot.git
 ```
+
 ### 下载并扩容 Ubuntu 24.04.1 磁盘镜像文件
 
 下载链接:[Ubuntu 24.04.1](https://cdimage.ubuntu.com/releases/noble/release/ubuntu-24.04.1-preinstalled-server-riscv64.img.xz)
+
 ```shell
  $ unar ubuntu-24.04.1-preinstalled-server-riscv64.img.xz
  $ qemu-img resize -f raw ubuntu-24.04.1-preinstalled-server-riscv64.img +5G
@@ -41,18 +44,17 @@ $ git clone https://github.com/u-boot/u-boot.git && cd u-boot && git checkout v2
 - 登录后应会被要求更改登录密码。
 - 可以通过 `sudo` 更改 root 密码。
 
+## 编译RustSBI Prototyper
 
-## 编译RustSBI  Prototyper
-
-进入prototyper目录
+进入rustsbi目录
 
-``` shell
-$ cd prototyper
+```shell
+$ cd rustsbi
 ```
 
-编译RustSBI  Prototyper
+编译RustSBI Prototyper
 
-``` shell
+```shell
 $ cargo prototyper
 ```
 
@@ -60,21 +62,21 @@ $ cargo prototyper
 
 进入U-Boot目录
 
-``` shell
+```shell
 $ cd u-boot
 ```
 
 导出环境变量
 
-``` shell
+```shell
 $ export ARCH=riscv
 $ export CROSS_COMPILE=riscv64-linux-gnu-
-$ export OPENSBI=../prototyper/target/riscv64imac-unknown-none-elf/release/rustsbi-prototyper.bin 
+$ export OPENSBI=../rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper.bin
 ```
 
 生成`.config`文件,编译U-Boot
 
-``` shell
+```shell
 # To generate .config file out of board configuration file
 $ make qemu-riscv64_spl_defconfig
 $ make -j$(nproc)
@@ -84,13 +86,13 @@ $ make -j$(nproc)
 
 进入`workshop`目录
 
-``` shell
+```shell
 $ cd workshop
 ```
 
 运行下面命令
 
-``` shell
+```shell
 $ qemu-system-riscv64 \
     -nographic -machine virt \
     -smp 4 -m 8G \

+ 81 - 0
prototyper/docs/booting-ubuntu-24.04.3-in-qemu-using-edk2-and-rustsbi.md

@@ -0,0 +1,81 @@
+# 使用RustSBI和EDK2在QEMU中启动Ubuntu 24.04.3
+
+本教程将介绍如何使用RustSBI和EDK2在QEMU中启动Ubuntu 24.04.3。
+
+运行本教程已经在Arch Linux x86_64系统上经过测试,但理论上其他的Linux发行版亦可以参照使用。
+
+测试本教程时使用的软件版本如下:
+
+|          软件           |      版本       |
+|:---------------------:|:-------------:|
+| riscv64-linux-gnu-gcc |    15.1.0     |
+|  qemu-system-riscv64  |    10.1.0     |
+|  RustSBI Prototyper   |    master     |
+|         EDK2          | stable202505  |
+
+## 准备Ubuntu镜像
+
+访问[Download Ubuntu for RISC-V](https://ubuntu.com/download/risc-v)页面,查找当前Ubuntu针对**QEMU Emulator**平台发行的
+最新预安装镜像进行下载。
+
+本教程撰写时的最新镜像版本为[24.04.3 LTS](https://cdimage.ubuntu.com/releases/24.04.3/release/ubuntu-24.04.3-preinstalled-server-riscv64.img.xz),复制链接进行下载:
+
+```bash
+wget https://cdimage.ubuntu.com/releases/24.04.3/release/ubuntu-24.04.3-preinstalled-server-riscv64.img.xz
+xz -d ubuntu-24.04.3-preinstalled-server-riscv64.img.xz
+```
+
+## 编译RustSBI和EDK2
+
+首先拉取RustSBI的源代码并编译RustSBI:
+
+```bash
+git clone https://github.com/rustsbi/rustsbi.git --depth 1
+cd rustsbi
+cargo prototyper
+```
+
+然后拉取EDK2的源代码并编译EDK2:
+
+```bash
+git clone --recurse-submodules https://github.com/tianocore/edk2.git -b edk2-stable202505
+cd edk2
+export GCC5_RISCV64_PREFIX=riscv64-linux-gnu-
+source edksetup.sh
+build -a RISCV64 -b RELEASE -p OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc -t GCC5
+```
+
+为了符合QEMU对于PFLASH固件的要求,将编译好的UEFI固件大小扩展到32M。
+
+```bash
+truncate -s 32M Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_VARS.fd 
+truncate -s 32M Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_CODE.fd
+```
+
+## 启动系统
+
+使用如下的指令启动QEMU:
+
+```bash
+qemu-system-riscv64  \
+        -M virt,pflash0=pflash0,pflash1=pflash1,acpi=off \
+        -m 4096 -smp 8 \
+        -bios rustsbi/target/riscv64gc-unknown-none-elf/release/rustsbi-prototyper-dynamic.bin \
+        -blockdev node-name=pflash0,driver=file,read-only=on,filename=edk2/Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_CODE.fd  \
+        -blockdev node-name=pflash1,driver=file,filename=edk2/Build/RiscVVirtQemu/RELEASE_GCC5/FV/RISCV_VIRT_VARS.fd \
+        -device virtio-blk-device,drive=hd0  \
+        -drive file=ubuntu-24.04.3-preinstalled-server-riscv64.img,format=raw,id=hd0,if=none \
+        -netdev user,id=n0 -device virtio-net,netdev=n0 \
+        -monitor unix:/tmp/qemu-monitor,server,nowait \
+        -nographic \
+        -serial mon:stdio
+```
+
+启动系统的过程中需要注意,在默认情况下,EDK2启动之后会启动GRUB2作为引导程序,启动之后的默认账户和密码是`ubuntu`和`ubuntu`。
+
+启动系统并登录之后,验证是否使用UEFI启动成功:
+
+```bash
+ubuntu@ubuntu:~$ cat /sys/firmware/efi/fw_platform_size 
+64
+```

+ 2 - 1
prototyper/prototyper/Cargo.toml

@@ -25,7 +25,7 @@ pmpm = { version = "0.0.0", path = "../../library/pmpm" }
 serde = { version = "1.0.202", default-features = false, features = ["derive"] }
 aclint = { git = "https://github.com/rustsbi/aclint", rev = "b2136a66" }
 fast-trap = { git = "https://github.com/rustsbi/fast-trap", rev = "8d855afa", features = ["riscv-m"] }
-serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", rev = "2a5d6ab7", default-features = false }
+serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", rev = "f051687", default-features = false, features = ["ser"] }
 uart_xilinx = { git = "https://github.com/duskmoon314/uart-rs/", rev = "12be9142" }
 xuantie-riscv = { git = "https://github.com/rustsbi/xuantie", rev = "7a521c04" }
 bouffalo-hal = { git = "https://github.com/rustsbi/bouffalo-hal", rev = "968b949", features = [
@@ -35,6 +35,7 @@ static-toml = "1"
 seq-macro = "0.3.5"
 pastey = "0.1.0"
 uart_sifive = { git = "https://github.com/duskmoon314/uart-rs/" }
+arm-pl011-uart = "0.3.2"
 
 [[bin]]
 name = "rustsbi-prototyper"

+ 2 - 1
prototyper/prototyper/build.rs

@@ -77,11 +77,12 @@ SECTIONS {
     }
 
     . = ALIGN(0x1000);
-    sbi_end = .;
 
     .text : ALIGN(0x1000) {
         *(.fdt)
     }
+    . = ALIGN(4);
+    sbi_end = .;
 
     .text 0x80200000 : ALIGN(0x1000) {
         *(.payload)

+ 5 - 1
prototyper/prototyper/config/default.toml

@@ -1,7 +1,11 @@
 num_hart_max = 8
 stack_size_per_hart = 16384 # 16 * 1024
-heap_size = 32768 # 32 * 1024
+heap_size = 1048576 # 1024 * 1024
 page_size = 4096
 log_level = "INFO"
 jump_address = 0x80200000
 tlb_flush_limit = 16384 # page_size * 4
+
+[[next_addr]]
+start = 0x80000000
+end = 0x90000000

+ 4 - 0
prototyper/prototyper/config/sipeed_m1s_dock.toml

@@ -5,3 +5,7 @@ page_size = 4096
 log_level = "INFO"
 jump_address = 0x50000000
 tlb_flush_limit = 16384 # page_size * 4
+
+[[next_addr]]
+start = 0x80000000
+end = 0x90000000

+ 5 - 0
prototyper/prototyper/src/cfg.rs

@@ -7,6 +7,8 @@ static_toml! {
     const CONFIG = include_toml!("../../target/config.toml");
 }
 
+pub type NextAddr = crate::cfg::config::next_addr::NextAddr;
+
 /// Maximum number of supported harts.
 pub const NUM_HART_MAX: usize = CONFIG.num_hart_max as usize;
 /// Stack size per hart (hardware thread) in bytes.
@@ -23,3 +25,6 @@ pub const JUMP_ADDRESS: usize = CONFIG.jump_address as usize;
 /// TLB_FLUSH_LIMIT defines the TLB refresh range limit.
 /// If the TLB refresh range is greater than TLB_FLUSH_LIMIT, the entire TLB is refreshed.
 pub const TLB_FLUSH_LIMIT: usize = CONFIG.tlb_flush_limit as usize;
+
+/// The dynamic valid next addr ranges.
+pub const DYNAMIC_NEXT_ADDR_RANGE: &NextAddr = &CONFIG.next_addr;

+ 3 - 8
prototyper/prototyper/src/firmware/dynamic.rs

@@ -62,11 +62,6 @@ pub struct DynamicInfo {
 // https://github.com/riscv-software-src/opensbi/blob/019a8e69a1dc0c0f011fabd0372e1ba80e40dd7c/include/sbi/fw_dynamic.h#L75
 
 const DYNAMIC_INFO_INVALID_ADDRESSES: usize = 0x00000000;
-const NEXT_ADDR_VALID_ADDRESSES: [Range<usize>; 2] = [
-    // Qemu Virt pflash address
-    0x20000000..0x22000000,
-    0x80000000..0x90000000,
-];
 pub(crate) const MAGIC: usize = 0x4942534f;
 const SUPPORTED_VERSION: Range<usize> = 0..3;
 
@@ -117,7 +112,7 @@ pub struct DynamicError<'a> {
 /// Validates and extracts privilege mode and next address from dynamic info.
 ///
 /// Returns Result containing tuple of (MPP, next_addr) or error details.
-pub fn mpp_next_addr(info: &DynamicInfo) -> Result<(mstatus::MPP, usize), DynamicError> {
+pub fn mpp_next_addr(info: &DynamicInfo) -> Result<(mstatus::MPP, usize), DynamicError<'_>> {
     let mut error = DynamicError {
         invalid_mpp: false,
         invalid_next_addr: false,
@@ -125,9 +120,9 @@ pub fn mpp_next_addr(info: &DynamicInfo) -> Result<(mstatus::MPP, usize), Dynami
     };
 
     // fail safe, errors will be aggregated after whole checking process.
-    let next_addr_valid = NEXT_ADDR_VALID_ADDRESSES
+    let next_addr_valid = crate::cfg::DYNAMIC_NEXT_ADDR_RANGE
         .iter()
-        .any(|x| x.contains(&info.next_addr));
+        .any(|r| info.next_addr >= r.start as usize && info.next_addr < r.end as usize);
     let mpp_valid = matches!(info.next_mode, 0 | 1 | 3);
 
     if !next_addr_valid {

+ 121 - 23
prototyper/prototyper/src/firmware/mod.rs

@@ -11,10 +11,14 @@ cfg_if::cfg_if! {
     }
 }
 
+use alloc::{format, vec};
 #[allow(unused)]
 use core::arch::{asm, naked_asm};
 use core::{ops::Range, usize};
+use crate::fail;
+
 use riscv::register::mstatus;
+use serde::Serialize;
 
 use pmpm::{PmpSlice, get_pmp_entry, set_pmp_entry};
 
@@ -30,7 +34,7 @@ pub struct BootHart {
 
 #[unsafe(naked)]
 #[unsafe(link_section = ".fdt")]
-#[repr(align(16))]
+#[rustc_align(16)]
 #[cfg(feature = "fdt")]
 pub extern "C" fn raw_fdt() {
     naked_asm!(concat!(".incbin \"", env!("PROTOTYPER_FDT_PATH"), "\""),)
@@ -62,6 +66,97 @@ pub fn get_boot_hart(opaque: usize, nonstandard_a2: usize) -> BootHart {
     }
 }
 
+pub fn patch_device_tree(device_tree_ptr: usize) -> usize {
+    use serde_device_tree::buildin::Node;
+    use serde_device_tree::ser::serializer::ValueType;
+    use serde_device_tree::{Dtb, DtbPtr};
+    let Ok(ptr) = DtbPtr::from_raw(device_tree_ptr as *mut _) else {
+        panic!("Can not parse device tree!");
+    };
+    let original_length = ptr.align();
+    let dtb = Dtb::from(ptr);
+
+    // Update const
+    unsafe {
+        asm!("la {}, sbi_start", out(reg) SBI_START_ADDRESS, options(nomem));
+        asm!("la {}, sbi_end", out(reg) SBI_END_ADDRESS, options(nomem));
+    }
+    let sbi_start = unsafe { SBI_START_ADDRESS };
+    let sbi_end = unsafe { SBI_END_ADDRESS };
+
+    let dtb = dtb.share();
+    let root: Node =
+        serde_device_tree::from_raw_mut(&dtb).unwrap_or_else(fail::device_tree_deserialize_root);
+    let tree: Node = root.deserialize();
+
+    #[derive(Serialize)]
+    struct ReservedMemory {
+        #[serde(rename = "#address-cells")]
+        pub address_cell: u32,
+        #[serde(rename = "#size-cells")]
+        pub size_cell: u32,
+        pub ranges: (),
+    }
+    #[derive(Serialize)]
+    struct ReservedMemoryItem {
+        pub reg: [u32; 4],
+        #[serde(rename = "no-map")]
+        pub no_map: (),
+    }
+    // Make patch list and generate reserved-memory node.
+    let sbi_length: u32 = (sbi_end - sbi_start) as u32;
+    let new_base = ReservedMemory {
+        address_cell: 2,
+        size_cell: 2,
+        ranges: (),
+    };
+    let new_base_2 = ReservedMemoryItem {
+        reg: [(sbi_start >> 32) as u32, sbi_start as u32, 0, sbi_length],
+        no_map: (),
+    };
+    let patch1 = serde_device_tree::ser::patch::Patch::new(
+        "/reserved-memory",
+        &new_base as _,
+        ValueType::Node,
+    );
+    let path_name = format!("/reserved-memory/mmode_resv1@{:x}", sbi_start);
+    let patch2 =
+        serde_device_tree::ser::patch::Patch::new(&path_name, &new_base_2 as _, ValueType::Node);
+    let raw_list = [patch1, patch2];
+    // Only add `reserved-memory` section when it not exists.
+    let list = if tree.find("/reserved-memory").is_some() {
+        &raw_list[1..]
+    } else {
+        &raw_list[..]
+    };
+
+    // Firstly, allocate a temporary buffer to store the fdt and get the real total size of the patched fdt.
+    // TODO: The serde_device_tree can provide a function to calculate the accuracy size of patched fdt.
+    debug!(
+        "Allocate temporary DTB buffer with length 0x{:x}.",
+        original_length + 2048
+    );
+    let mut temporary_buffer = vec![0u8; original_length + 2048];
+    serde_device_tree::ser::to_dtb(&tree, &list, &mut temporary_buffer).unwrap();
+    let Ok(patched_dtb_ptr) = DtbPtr::from_raw(temporary_buffer.as_mut_ptr()) else {
+        panic!("Failed to parse the patched dtb.")
+    };
+    let patched_length = patched_dtb_ptr.align();
+
+    // Secondly, allocate the exactly buffer to store the fdt.
+    let mut patched_dtb_buffer = vec![0u8; patched_length];
+    serde_device_tree::ser::to_dtb(&tree, &list, &mut patched_dtb_buffer).unwrap();
+    // Intentionally leak the buffer so that the patched DTB remains valid for the lifetime of the firmware.
+    // This is required because the returned pointer is used elsewhere and must not be deallocated.
+    let patched_dtb = patched_dtb_buffer.leak();
+    info!(
+        "The patched dtb is located at 0x{:x} with length 0x{:x}.",
+        patched_dtb.as_ptr() as usize,
+        patched_length
+    );
+    patched_dtb.as_ptr() as usize
+}
+
 static mut SBI_START_ADDRESS: usize = 0;
 static mut SBI_END_ADDRESS: usize = 0;
 static mut RODATA_START_ADDRESS: usize = 0;
@@ -90,29 +185,32 @@ pub fn set_pmp(memory_range: &Range<usize>) {
         assert_eq!(RODATA_START_ADDRESS & 0x3, 0);
         assert_eq!(RODATA_END_ADDRESS & 0x3, 0);
 
-        // pmpcfg0::set_pmp(0, Range::OFF, Permission::NONE, false);
-        // pmpaddr0::write(0);
-        // pmpcfg0::set_pmp(1, Range::TOR, Permission::RWX, false);
-        // pmpaddr1::write(memory_range.start >> 2);
-        // pmpcfg0::set_pmp(2, Range::TOR, Permission::RWX, false);
-        // pmpaddr2::write(SBI_START_ADDRESS >> 2);
-        // pmpcfg0::set_pmp(3, Range::TOR, Permission::NONE, false);
-        // pmpaddr3::write(RODATA_START_ADDRESS >> 2);
-        // pmpcfg0::set_pmp(4, Range::TOR, Permission::NONE, false);
-        // pmpaddr4::write(RODATA_END_ADDRESS >> 2);
-        // pmpcfg0::set_pmp(5, Range::TOR, Permission::NONE, false);
-        // pmpaddr5::write(SBI_END_ADDRESS >> 2);
-        // pmpcfg0::set_pmp(6, Range::TOR, Permission::RWX, false);
-        // pmpaddr6::write(memory_range.end >> 2);
-        // pmpcfg0::set_pmp(7, Range::TOR, Permission::RWX, false);
-        // pmpaddr7::write(usize::MAX >> 2);
-        set_pmp_entry(0, PmpSlice::new(0, 0, 0), Range::OFF, Permission::NONE);
+        pmpcfg0::set_pmp(0, Range::OFF, Permission::NONE, false);
+        pmpaddr0::write(0);
+        pmpcfg0::set_pmp(1, Range::TOR, Permission::RWX, false);
+        pmpaddr1::write(memory_range.start >> 2);
+        pmpcfg0::set_pmp(2, Range::TOR, Permission::RWX, false);
+        pmpaddr2::write(SBI_START_ADDRESS >> 2);
+        pmpcfg0::set_pmp(3, Range::TOR, Permission::R, false);
+        pmpaddr3::write(RODATA_START_ADDRESS >> 2);
+        pmpcfg0::set_pmp(4, Range::TOR, Permission::NONE, false);
+        pmpaddr4::write(RODATA_END_ADDRESS >> 2);
+        pmpcfg0::set_pmp(5, Range::TOR, Permission::R, false);
+        pmpaddr5::write(SBI_END_ADDRESS >> 2);
+        pmpcfg0::set_pmp(6, Range::TOR, Permission::RWX, false);
+        pmpaddr6::write(memory_range.end >> 2);
+        pmpcfg0::set_pmp(7, Range::TOR, Permission::RWX, false);
+        pmpaddr7::write(usize::MAX >> 2);
+    }
+}
+
+pub fn log_pmp_cfg(memory_range: &Range<usize>) {
+    unsafe {
+        info!("PMP Configuration");
 
-        set_pmp_entry(
-            1,
-            PmpSlice::new(0, memory_range.start, 0),
-            Range::TOR,
-            Permission::RWX,
+        info!(
+            "{:<10} {:<10} {:<15} {:<30}",
+            "PMP", "Range", "Permission", "Address"
         );
 
         set_pmp_entry(

+ 2 - 0
prototyper/prototyper/src/main.rs

@@ -78,6 +78,8 @@ extern "C" fn rust_main(_hart_id: usize, opaque: usize, nonstandard_a2: usize) {
             PLATFORM.print_board_info();
         }
 
+        let fdt_address = firmware::patch_device_tree(fdt_address);
+
         firmware::set_pmp(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
         firmware::log_pmp_cfg(unsafe { PLATFORM.info.memory_range.as_ref().unwrap() });
 

+ 73 - 0
prototyper/prototyper/src/platform/console.rs

@@ -1,4 +1,9 @@
+use arm_pl011_uart::{
+    DataBits, LineConfig, PL011Registers, Parity, StopBits, Uart, UniqueMmioPointer,
+};
 use bouffalo_hal::uart::RegisterBlock as BflbUartRegisterBlock;
+use core::cell::UnsafeCell;
+use core::ptr::NonNull;
 use uart_sifive::MmioUartSifive;
 use uart_xilinx::MmioUartAxiLite;
 use uart16550::{Register, Uart16550};
@@ -10,6 +15,7 @@ pub(crate) const UART16650U32_COMPATIBLE: [&str; 1] = ["snps,dw-apb-uart"];
 pub(crate) const UARTAXILITE_COMPATIBLE: [&str; 1] = ["xlnx,xps-uartlite-1.00.a"];
 pub(crate) const UARTBFLB_COMPATIBLE: [&str; 1] = ["bflb,bl808-uart"];
 pub(crate) const UARTSIFIVE_COMPATIBLE: [&str; 1] = ["sifive,uart0"];
+pub(crate) const UARTPL011_COMPATIBLE: [&str; 1] = ["pl011"];
 
 #[doc(hidden)]
 #[allow(unused)]
@@ -20,6 +26,7 @@ pub enum MachineConsoleType {
     UartAxiLite,
     UartBflb,
     UartSifive,
+    UartPl011,
 }
 
 /// For Uart 16550
@@ -127,3 +134,69 @@ impl ConsoleDevice for UartBflbWrap {
         count
     }
 }
+
+/// PL011 UART wrapper for RustSBI console
+pub struct UartPl011Wrap {
+    uart: UnsafeCell<Uart<'static>>,
+}
+
+impl UartPl011Wrap {
+    /// Create a new PL011 UART wrapper
+    pub fn new(base: usize) -> Self {
+        let uart_pointer =
+            unsafe { UniqueMmioPointer::new(NonNull::new(base as *mut PL011Registers).unwrap()) };
+
+        let mut uart = Uart::new(uart_pointer);
+
+        // Configure and enable UART with default settings
+        let line_config = LineConfig {
+            data_bits: DataBits::Bits8,
+            parity: Parity::None,
+            stop_bits: StopBits::One,
+        };
+        if let Err(_) = uart.enable(line_config, 115_200, 24_000_000) {
+            // If enabling fails, we still create the wrapper but it may not work properly
+        }
+        Self {
+            uart: UnsafeCell::new(uart),
+        }
+    }
+
+    unsafe fn uart_mut(&self) -> &mut Uart<'static> {
+        unsafe { &mut *self.uart.get() }
+    }
+}
+
+unsafe impl Send for UartPl011Wrap {}
+unsafe impl Sync for UartPl011Wrap {}
+
+impl ConsoleDevice for UartPl011Wrap {
+    fn read(&self, buf: &mut [u8]) -> usize {
+        let mut count = 0;
+
+        let uart = unsafe { self.uart_mut() };
+
+        for slot in buf.iter_mut() {
+            match uart.read_word() {
+                Ok(Some(byte)) => {
+                    *slot = byte;
+                    count += 1;
+                }
+                Ok(None) => break,
+                Err(_) => break,
+            }
+        }
+
+        count
+    }
+
+    fn write(&self, buf: &[u8]) -> usize {
+        let uart = unsafe { self.uart_mut() };
+
+        for &byte in buf {
+            uart.write_word(byte);
+        }
+
+        buf.len()
+    }
+}

+ 8 - 1
prototyper/prototyper/src/platform/mod.rs

@@ -15,10 +15,11 @@ use crate::fail;
 use crate::platform::clint::{MachineClintType, SIFIVE_CLINT_COMPATIBLE, THEAD_CLINT_COMPATIBLE};
 use crate::platform::console::Uart16550Wrap;
 use crate::platform::console::UartBflbWrap;
+use crate::platform::console::UartPl011Wrap;
 use crate::platform::console::UartSifiveWrap;
 use crate::platform::console::{
     MachineConsoleType, UART16650U8_COMPATIBLE, UART16650U32_COMPATIBLE, UARTAXILITE_COMPATIBLE,
-    UARTBFLB_COMPATIBLE, UARTSIFIVE_COMPATIBLE,
+    UARTBFLB_COMPATIBLE, UARTPL011_COMPATIBLE, UARTSIFIVE_COMPATIBLE,
 };
 use crate::platform::reset::SIFIVETEST_COMPATIBLE;
 use crate::sbi::SBI;
@@ -122,6 +123,9 @@ impl Platform {
                         if UARTSIFIVE_COMPATIBLE.contains(&device_id) {
                             self.info.console = Some((regs.start, MachineConsoleType::UartSifive));
                         }
+                        if UARTPL011_COMPATIBLE.contains(&device_id) {
+                            self.info.console = Some((regs.start, MachineConsoleType::UartPl011));
+                        }
                     }
                 }
             }
@@ -290,6 +294,9 @@ impl Platform {
                 MachineConsoleType::UartSifive => Some(SbiConsole::new(Mutex::new(Box::new(
                     UartSifiveWrap::new(base),
                 )))),
+                MachineConsoleType::UartPl011 => Some(SbiConsole::new(Mutex::new(Box::new(
+                    UartPl011Wrap::new(base),
+                )))),
             };
         } else {
             self.sbi.console = None;

+ 2 - 2
prototyper/prototyper/src/sbi/early_trap.rs

@@ -8,7 +8,7 @@ use riscv::register::mtvec;
 /// This function will change a0 and a1 and will NOT change them back.
 // TODO: Support save trap info.
 #[unsafe(naked)]
-#[repr(align(16))]
+#[rustc_align(16)]
 pub(crate) unsafe extern "C" fn light_expected_trap() {
     naked_asm!(
         "add a0, zero, zero",
@@ -39,7 +39,7 @@ impl Default for TrapInfo {
 }
 
 #[unsafe(naked)]
-#[repr(align(16))]
+#[rustc_align(16)]
 pub(crate) unsafe extern "C" fn expected_trap() {
     naked_asm!(
         "csrr a4, mepc",

+ 13 - 1
prototyper/prototyper/src/sbi/heap.rs

@@ -4,8 +4,9 @@ use buddy_system_allocator::LockedHeap;
 #[unsafe(link_section = ".bss.heap")]
 static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
 
+const BUDDY_MAX_ORDER: usize = 20;
 #[global_allocator]
-static HEAP_ALLOCATOR: LockedHeap<15> = LockedHeap::<15>::empty();
+static HEAP_ALLOCATOR: LockedHeap<BUDDY_MAX_ORDER> = LockedHeap::<BUDDY_MAX_ORDER>::empty();
 
 pub fn sbi_heap_init() {
     unsafe {
@@ -17,5 +18,16 @@ pub fn sbi_heap_init() {
 
 #[alloc_error_handler]
 pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
+    error!("Heap stats:");
+    {
+        let heap = HEAP_ALLOCATOR.lock();
+        error!("\tTotal size: {}", heap.stats_total_bytes());
+        error!("\tRequested size: {}", heap.stats_alloc_user());
+        error!("\tAllocated size: {}", heap.stats_alloc_actual());
+        error!(
+            "Currently the heap only support allocate buffer with max length {} bytes.",
+            1 << (BUDDY_MAX_ORDER - 1)
+        );
+    }
     panic!("Heap allocation error, layout = {:?}", layout);
 }

+ 1 - 1
rust-toolchain.toml

@@ -1,4 +1,4 @@
 [toolchain]
 profile = "minimal"
-channel = "nightly"
+channel = "nightly-2025-08-01"
 components = ["rustfmt", "clippy", "llvm-tools-preview", "rust-src"]