用Rust写一个支持UEFI的操作系统 (1) - Have a bite

标签: | 发表时间:2023-10-19 08:32 | 作者:
出处:https://cnwzhjs.github.io

所有的代码都可以从我的 GitHub repo获得

该用UEFI写操作系统教程了

有很多操作系统教程和 YouTube 视频。然而,它们中的大多数都是为 BIOS 模式启动编写的。

然而,现在已经2023年了,离Intel开源UEFI的实现已经整整19年了。同时,Intel正在抛弃传统的 x86_64架构,转向只支持64位的 x86_64s. 当然,它只支持UEFI(UEFI CSM将被删除)。

UEFI是一个更安全、更强大的引导系统。几乎所有现代操作系统都是通过UEFI引导的。似乎没有理由继续为BIOS编写操作系统教程。我们不再需要关心如何切换到长模式,或者启用分页之类的烦人细节。

我在Google上搜索后发现,关于在UEFI中编写操作系统的信息非常有限。这些信息分散在不同的地方,很难找到完整的教程。因此,我决定写一系列关于在UEFI中编写操作系统的教程。

配置测试环境

大多数操作系统教程都使用QEMU作为测试环境,因为它有以下优点:

  1. 只需要普通用户权限就可以执行(QEMU可以在模拟器模式下运行,这意味着它不需要访问任何硬件虚拟化基础架构,例如KVM)。
  2. 它非常灵活,可以配置不同的硬件。
  3. 它支持各种客户端CPU架构。此外,模拟器可以在与客户端CPU不同的主机CPU架构上运行。
  4. 它支持模拟BIOS或UEFI作为固件接口。
  5. 它支持调试器,可以轻松调试操作系统内核(通常在裸机上使用日志记录来调试内核)。

因此,在本教程中,我们也使用QEMU作为测试环境。好吧,我使用的是MacBook Pro,所以教程的命令行是针对macOS的,但是很容易转换为Linux版本。

  1. 安装QEMU

我们通常使用 homebrew来安装qemu:

   brew install qemu
  1. 为项目创建工作空间
   mkdir tony-os && cd tony-os
git init .
mkdir -p src build buildenv {target,dist}/x86_64
  1. 为QEMU准备UEFI固件

Intel的开源UEFI固件称为 TianoCore项目。代码也托管在 GitHub.

在这个项目中,他们开发了一个支持QEMU的固件,提供了一个UEFI环境。

我们可以从 他们的持续集成服务器上下载它,找到一个以"edk2.git-ovmf.x64"开头的文件,解压它,然后将 usr/share/edk2.git/ovmf-x64/OVMF-pure-efi.fd复制到我们的工作空间的 target/x86_64/bios.bin

  1. 准备脚本来测试我们的UEFI

在我们的工作空间中写入 run.sh脚本:

   #! /bin/bash

qemu-system-x86_64 \
    -L target/x86_64 \
    -bios target/x86_64/bios.bin \
    -hda fat:rw:dist/x86_64

然后,使其可执行: chmod +x run.sh

如果你直接运行脚本的话,应该会启动并显示TianoCore的图像。

此事,你的工作空间应该是这样的:

   build
buildenv
dist
|- x86_64
src
target
|- x86_64
   |- bios.bin
run.sh

准备构建环境

Docker是一个用来固化你的构建环境的完美平台。因此,我们可以在 buildenv文件夹下准备一个 Dockerfile,来构建一个构建环境的镜像:

   FROM rust:1.73-bullseye

RUN rustup target add x86_64-unknown-uefi

VOLUME /root/env

WORKDIR /root/env

Rust对UEFI目标有第二级支持,这意味着它不是官方支持的。但是,它对我们来说足够好了,可以写一个玩具操作系统。

感谢David Rheinsberg( @dvdhrm) 和 Nicholas Bishop( @nicholasbishop)维护了Rust的UEFI目标

构建镜像

   docker build --platform linux/x86_64 buildenv -t tonyos-buildenv

准备一个最简单的内核

David Rheinsberg,UEFI目标的维护者,还维护了一个叫 r-efi的crate,提供了UEFI的接口。我们可以使用这个crate来快速开始。

  1. 创建在构建容器中运行的构建脚本:buildscript.sh
   #! /bin/bash

# build the kernel
cargo build --target x86_64-unknown-uefi || exit 1

# copy the built kernel to the dist directory
mkdir -p dist/x86_64/EFI/BOOT || exit 1

cp target/x86_64-unknown-uefi/debug/tonyos.efi \
   dist/x86_64/EFI/BOOT/BOOTX64.EFI || exit 1
  1. 创建调用容器的构建脚本:build.sh
   #! /bin/bash

docker run -it \
    --platform linux/x86_64 \
    --rm \
    -v $(pwd):/root/env \
    tonyos-buildenv \
    ./buildscript.sh
  1. 准备内核入口文件 src/main.rs
   #![no_main]
#![no_std]

extern crate r_efi;

use r_efi::efi;

#[panic_handler]
fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

const HELLO_STR: &str = "Hello, world. Press any key to return to UEFI firmware.";

#[export_name = "efi_main"]
pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Status {
    let mut s = [0u16; HELLO_STR.len() + 1];
    let mut i = 0usize;
    for c in HELLO_STR.encode_utf16() {
        s[i] = c;
        i += 1;
        if i >= s.len() {
            break;
        }
    }

    // Print "Hello World!".
    let r =
        unsafe { ((*(*st).con_out).output_string)((*st).con_out, s.as_ptr() as *mut efi::Char16) };
    if r.is_error() {
        return r;
    }

    // Wait for key input, by waiting on the `wait_for_key` event hook.
    let r = unsafe {
        let mut x: usize = 0;
        ((*(*st).boot_services).wait_for_event)(1, &mut (*(*st).con_in).wait_for_key, &mut x)
    };
    if r.is_error() {
        return r;
    }

    efi::Status::SUCCESS
}
  1. 准备 Cargo.toml文件
   [package]
name = "tonyos"
version = "0.1.0"
authors = ["Tony Huang <[email protected]>"]
edition = "2021"

[build]
build-stage = 1
target = ["x86_64-unknown-uefi"]

[dependencies]
r-efi = "4"

# the profile used for `cargo build`
[profile.dev]
panic = "abort" # disable stack unwinding on panic

# the profile used for `cargo build --release`
[profile.release]
panic = "abort" # disable stack unwinding on panic

构建和运行你的第一个UEFI内核

现在,我们可以构建和运行我们的第一个UEFI内核了:

   ./build.sh && ./run.sh

UEFI Hello World


相关 [rust uefi 操作系统] 推荐:

用Rust写一个支持UEFI的操作系统 (1) - Have a bite

- -
该用UEFI写操作系统教程了. 有很多操作系统教程和 YouTube 视频. 然而,它们中的大多数都是为 BIOS 模式启动编写的. 然而,现在已经2023年了,离Intel开源UEFI的实现已经整整19年了. 同时,Intel正在抛弃传统的 x86_64架构,转向只支持64位的 x86_64s.

UEFI Secure Boot 对 Linux 的影响

- SotongDJ - LinuxTOY
Red Hat 协同 Linux 基金会以及 Canonical 发布了针对 UEFI 中安全启动对于 Linux 系统影响的评估白皮书. 前段时间某些朝内站点上关于 UEFI 将禁止其他非 Win 系统的谣言总算以 M$ 方面澄清的方式告一段落. 现在来自 Linux 阵营的参与者们作出了自己的回应,对于 Secure Boot 进行了评估.

Android操作系统安全

- - CSDN博客推荐文章
        Android在迅猛发展的同时,其安全问题一直没有引起足够的重视,但在2010年6月研究人员发布Android平台的KernelRootkit以来,Android平台的安全问题引来了越来越多的关注,而同时,Android平台的恶意软件也开始流行起来.        根据以上的Android系统架构分析,可以发现在三个层面可能存在恶意软件.

Windows 8 和傳統 BIOS 說拜拜,將以 UEFI 為主

- 小趴 八足趴 八足 ramener - Engadget 中文版
在遙遠遙遠的過去,Windows 和 GUI 還沒有成為大家對「電腦」操作的標準印象之前,電腦的操作大多是靠鍵盤下指令達成的(當然使用 Linux 的朋友大概會說現在還是...). 時至今日,大部份的電腦操作都在 Windows Logo 出來之後,但偶爾開機過程出問題的時候,還是有機會看到純文字介面,必須要鍵盤操作的選單畫面.

Windows 8 和传统 BIOS 说拜拜,将以 UEFI 为主

- Zhaojing - Engadget 中国版
在遥远遥远的过去,Windows 和 GUI 还没有成为大家对「电脑」操作的标准印象之前,电脑的操作大多是靠键盘下指令达成的(当然使用 Linux 的朋友大概会说现在还是...). 时至今日,大部份的电脑操作都在 Windows Logo 出来之后,但偶尔开机过程出问题的时候,还是有机会看到纯文本键盘,必须要键盘操作的选单画面.

Mozilla将开发独立操作系统

- ccyuling - Solidot
Mozilla宣布了一个新项目“Boot to Gecko”,旨在为开放互联网开发一种完整独立的操作系统,成为ChromeOS或Android的某种竞争对手. 源代码将发布在Github上(暂时只有README). Mozilla此举是为了推广开放Web技术,Boot to Gecko针对的不是笔记本,而是智能手机,为Android兼容设备提供基质.

五家移动操作系统盘点

- 离歌 - 互联网的那点事
这篇文章,我起草有一段日子了,现在我觉得该是时候完成它. 伴随着iPhone更新的传言、RIM的诽谤、对触摸板的既爱又恨等这些话题的出现,我认为现在就是发表看法的最好时机. 博客之间近来出现了一场大型的拔河较力,热论某些公司的命运或者某些手机操作系统的优势,又或者仅仅只是移动通讯技术的整体发展方向.

Joyent 发布 SmartOS 开源操作系统

- ArBing - vpsee.com
以 OpenSolaris 为基础架构的云计算公司 Joyent 上周发布了他们自己的操作系统 SmartOS,并在 github 上公开了其所有的源代码,很高兴看到又一个云计算厂商加入到开源的队伍. 和其他依赖 Linux 的云计算系统不同,Joyent 提供的 SmartOS 基于 illumos(SUN 被 Oracle 收购后,OpenSolaris 分裂出来的版本).

Cosmos--基于C#的操作系统

- Amom - Solidot
Shawn the R0ck 写道 "不论从MIT开放课程6.828操作系统工程(Operating System Engineering)还是实际工程中的Unix-like系统,使用C语言和少量的汇编已经是铁律一般的工程原则,虽然也有不少hacker尝试基于Lisp的OS比如试验性项目LOSAK,但都还没有大规模的工程应用.

Ubuntu发布移动版操作系统

- - Ubuntusoft
Ubuntu刚刚在其官方主页发布了移动版操作系统. 该系统完全开源免费,并且分为“普通版”和“高级版”两个版本. 其中“普通版”对手机配置的要求较低,但是功能有限. 系统采用全手势操作,屏幕每个边缘都会对应不同操作,比如短暂的在屏幕左端边缘滑动手指便可呼出程序菜单,从屏幕左端滑到右端则可以显示目前打开的应用程序,短暂的在屏幕右侧滑动手指则是类似“返回键”的功能等等.