From 6c806fc9aedb6653f4461a3d9a3c35877cc3c7e1 Mon Sep 17 00:00:00 2001 From: James Martin Date: Sun, 12 Jul 2020 22:55:13 -0700 Subject: [PATCH] UEFI hello world in Rust. --- .gitignore | 2 + Cargo.lock | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 9 +++++ README.md | 21 ++++++++++ run.sh | 4 ++ src/main.rs | 36 ++++++++++++++++++ 6 files changed, 180 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100755 run.sh create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a48bcf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/drive diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2db43e5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,108 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bit_field" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a165d606cf084741d4ac3a28fb6e9b1eb0bd31f6cd999098cfddb0b2ab381dc0" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bootproof" +version = "0.1.0" +dependencies = [ + "compiler_builtins", + "uefi", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "compiler_builtins" +version = "0.1.32" +source = "git+https://github.com/rust-lang/compiler-builtins#f3846bc05da87b8a71cd1a5a6ff9d980f46b2d0f" + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "proc-macro2" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "ucs2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85061f4e43545a613c0da6b87725bf23f8da8613cf2473719c4f71a270c4ce8a" +dependencies = [ + "bit_field", +] + +[[package]] +name = "uefi" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab1f1403ecbad37d25120161acc3db12066febf3446efcc40b7631d30678505d" +dependencies = [ + "bitflags", + "log", + "ucs2", + "uefi-macros", +] + +[[package]] +name = "uefi-macros" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a69fa8dd920e84d783769c44560484ade81f6c765cde2e1cc46c754ddf95947" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..32fe9aa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "bootproof" +version = "0.1.0" +authors = ["James Martin "] +edition = "2018" + +[dependencies] +compiler_builtins = { git = "https://github.com/rust-lang/compiler-builtins" } +uefi = "0.4.6" diff --git a/README.md b/README.md new file mode 100644 index 0000000..490cca9 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# bootproof +Messing around with UEFI apps. + +I don't have a specific goal here. +My general direction is to work towards a bootable programming language environment, +preferably one where security and allocation etc. are handled through the programming language +rather than through a traditional operating system. +I don't seriously expect to ever accomplish that, so for now I'm probably just going to... +make a forth or something. + +## Running +bootproof runs on x86_64 UEFI. You may either boot the program directly on your own computer or use an emulator. + +Make sure you have the `cargo-xbuild` crate installed and nightly Rust so you can compile to the UEFI target. + +First, build with: +``` +cargo +nightly xbuild --target x86_64-unknown-uefi +``` + +And to run, simply `./run.sh`. diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..79de8d2 --- /dev/null +++ b/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash +mkdir -p drive/EFI/Boot +cp target/x86_64-unknown-uefi/debug/bootproof.efi drive/EFI/Boot/BootX64.efi +qemu-system-x86_64 -nodefaults -machine "q35,accel=kvm:tcg" -smp 8 -m 128M -drive "if=pflash,format=raw,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on" -drive "if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS.fd,readonly=on" -drive "format=raw,file=fat:rw:drive" -serial stdio -display none diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..733b0de --- /dev/null +++ b/src/main.rs @@ -0,0 +1,36 @@ +#![no_std] +#![no_main] +#![feature(abi_efiapi)] + +use core::fmt::Write; +use core::panic::PanicInfo; +use core::writeln; +use uefi::prelude::*; + +// Required for use by the panic handler. +// This should not be used anywhere else. +static mut global_st: Option<*mut SystemTable> = None; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + let st = unsafe { &global_st.unwrap().read() }; + writeln!(st.stderr(), "stderr: {}", info); + writeln!(st.stdout(), "stdout: {}", info); + + loop {} +} + +#[entry] +fn efi_main(handle: Handle, st: SystemTable) -> Status { + let mut g_st = unsafe { st.unsafe_clone() }; + unsafe { + global_st = Some(&mut g_st); + } + + st.stdout().reset(false).expect_success("Failed to reset UEFI stdout."); + writeln!(st.stdout(), "Hello, world!"); + + loop {} + + Status::SUCCESS +} \ No newline at end of file