From 3fd9a8b428aff4c899f7cf788d1ac8a2d330df39 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 10 Sep 2020 22:57:11 +0300 Subject: [PATCH] Move EFI and core-rt to their own crates, cleanup a bit --- Cargo.lock | 13 ++++-- Cargo.toml | 4 +- Makefile | 17 ------- crates/core-rt/Cargo.toml | 9 ++++ crates/core-rt/src/lib.rs | 32 +++++++++++++ crates/efi/Cargo.toml | 9 ++++ crates/efi/src/base.rs | 23 ++++++++++ crates/efi/src/lib.rs | 54 ++++++++++++++++++++++ crates/efi/src/proto/mod.rs | 1 + crates/efi/src/proto/stop.rs | 48 ++++++++++++++++++++ qemu.sh | 8 +++- src/efi.rs | 88 ------------------------------------ src/main.rs | 50 ++++++-------------- src/println.rs | 18 ++++++++ 14 files changed, 226 insertions(+), 148 deletions(-) delete mode 100644 Makefile create mode 100644 crates/core-rt/Cargo.toml create mode 100644 crates/core-rt/src/lib.rs create mode 100644 crates/efi/Cargo.toml create mode 100644 crates/efi/src/base.rs create mode 100644 crates/efi/src/lib.rs create mode 100644 crates/efi/src/proto/mod.rs create mode 100644 crates/efi/src/proto/stop.rs delete mode 100644 src/efi.rs create mode 100644 src/println.rs diff --git a/Cargo.lock b/Cargo.lock index 437163b..f55db2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,14 +1,17 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +name = "core-rt" +version = "0.1.0" + +[[package]] +name = "efi" +version = "0.1.0" [[package]] name = "yboot2" version = "0.1.0" dependencies = [ - "spin", + "core-rt", + "efi", ] diff --git a/Cargo.toml b/Cargo.toml index 23d16bd..3413f19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -spin = { version = "0.5.2" } +#spin = { version = "0.5.2" } +efi = { path = "crates/efi" } +core-rt = { path = "crates/core-rt" } diff --git a/Makefile b/Makefile deleted file mode 100644 index 30cbc70..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -TARGET=x86_64-unknown-uefi -RUST_SRC=$(shell find src -type f -name "*.rs") \ - Cargo.toml -O=target/$(TARGET)/debug - -all: $(O)/image.fat32 - -clean: - cargo clean - -$(O)/yboot2.efi: $(RUST_SRC) - cargo build -Z build-std=core - -$(O)/image.fat32: $(O)/yboot2.efi - dd if=/dev/zero of=$@ bs=1M count=64 - mkfs.vfat -F32 $@ - mcopy -i $@ $(O)/yboot2.efi ::app.efi diff --git a/crates/core-rt/Cargo.toml b/crates/core-rt/Cargo.toml new file mode 100644 index 0000000..d42beaa --- /dev/null +++ b/crates/core-rt/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "core-rt" +version = "0.1.0" +authors = ["Mark "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/core-rt/src/lib.rs b/crates/core-rt/src/lib.rs new file mode 100644 index 0000000..3e84513 --- /dev/null +++ b/crates/core-rt/src/lib.rs @@ -0,0 +1,32 @@ +#![no_std] + +#[no_mangle] +unsafe extern "C" fn memcpy(dst: *mut u8, src: *const u8, cnt: usize) -> *mut u8 { + let mut i = 0isize; + while i < cnt as isize { + *(dst.offset(i)) = *(src.offset(i)); + i += 1; + } + return dst; +} +#[no_mangle] +unsafe extern "C" fn memset(dst: *mut u8, val: i32, cnt: usize) -> *mut u8 { + let mut i = 0isize; + while i < cnt as isize { + *(dst.offset(i)) = val as u8; + i += 1; + } + return dst; +} +#[no_mangle] +unsafe extern "C" fn memcmp(a: *const u8, b: *const u8, cnt: usize) -> i32 { + let mut i = 0isize; + while i < cnt as isize { + let diff = *(a.offset(i)) - *(b.offset(i)); + if diff != 0u8 { + return diff as i32; + } + i += 1; + } + return 0; +} diff --git a/crates/efi/Cargo.toml b/crates/efi/Cargo.toml new file mode 100644 index 0000000..8829397 --- /dev/null +++ b/crates/efi/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "efi" +version = "0.1.0" +authors = ["Mark "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/efi/src/base.rs b/crates/efi/src/base.rs new file mode 100644 index 0000000..a1c647c --- /dev/null +++ b/crates/efi/src/base.rs @@ -0,0 +1,23 @@ +use core::ffi::c_void; + +pub type Handle = *mut c_void; + +pub enum Status { + Success, + Err +} + +impl Status { + pub fn to_isize(self) -> isize { + match self { + Status::Success => 0, + Status::Err => -1, + } + } + pub fn from_isize(v: isize) -> Status { + match v { + 0 => Status::Success, + _ => Status::Err + } + } +} diff --git a/crates/efi/src/lib.rs b/crates/efi/src/lib.rs new file mode 100644 index 0000000..e730f9d --- /dev/null +++ b/crates/efi/src/lib.rs @@ -0,0 +1,54 @@ +#![no_std] + +use core::ffi::c_void; + +pub mod proto; +pub use proto::stop::*; + +pub mod base; +pub use base::*; + +#[repr(C)] +pub struct TableHeader { + signature: u64, + revision: u32, + header_size: u32, + crc32: u32, + reserved: u32 +} + +#[repr(C)] +pub struct SystemTable { + hdr: TableHeader, + pub firmware_vendor: *const i16, + pub firmware_revision: u32, + console_in_handle: Handle, + con_in: *mut c_void, // TODO + console_out_handle: Handle, + con_out: *mut SimpleTextOutputProtocol, + standard_error_handle: Handle, + std_err: *mut SimpleTextOutputProtocol, + runtime_services: *mut c_void, // TODO + boot_services: *mut c_void, // TODO + number_of_table_entries: usize, + configuration_table: *mut c_void // TODO +} + +impl SystemTable { + pub fn con_out(&self) -> &'static mut SimpleTextOutputProtocol { + unsafe { &mut *self.con_out } + } +} + +static mut SYSTEM_TABLE: Option<*mut SystemTable> = None; + +pub fn init_tables(st: *mut SystemTable) { + if st.is_null() { + panic!(); + } + unsafe { SYSTEM_TABLE = Some(st); } +} + +pub fn system_table() -> &'static mut SystemTable { + unsafe { &mut *SYSTEM_TABLE.unwrap() } +} diff --git a/crates/efi/src/proto/mod.rs b/crates/efi/src/proto/mod.rs new file mode 100644 index 0000000..73e79b3 --- /dev/null +++ b/crates/efi/src/proto/mod.rs @@ -0,0 +1 @@ +pub mod stop; diff --git a/crates/efi/src/proto/stop.rs b/crates/efi/src/proto/stop.rs new file mode 100644 index 0000000..df8b78d --- /dev/null +++ b/crates/efi/src/proto/stop.rs @@ -0,0 +1,48 @@ +use crate::Status; + +use core::ffi::c_void; +use core::fmt; + +#[repr(C)] +pub struct SimpleTextOutputProtocol { + fn_reset: *mut c_void, + fn_output_string: unsafe fn(&SimpleTextOutputProtocol, s: *const i16) -> isize +} + +impl SimpleTextOutputProtocol { + // Not the original name provided by EFI, but whatever + pub fn output_char16_string(&self, s: *const i16) -> Status { + unsafe { Status::from_isize((self.fn_output_string)(self, s)) } + } + + pub fn output_string(&self, s: &str) { + let mut buf = [0i16; 64]; + let mut iter = s.bytes(); + let mut i = 0; + + while let Some(byte) = iter.next() { + if i == 63 { + buf[i] = 0; + i = 0; + + // Output chunk + self.output_char16_string(buf.as_ptr()); + } else { + buf[i] = byte as i16; + i += 1; + } + } + + if i != 0 { + buf[i] = 0; + self.output_char16_string(buf.as_ptr()); + } + } +} + +impl fmt::Write for SimpleTextOutputProtocol { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + self.output_string(s); + Ok(()) + } +} diff --git a/qemu.sh b/qemu.sh index bedfb08..a651330 100755 --- a/qemu.sh +++ b/qemu.sh @@ -3,7 +3,13 @@ BIOS=/usr/share/edk2-ovmf/OVMF_CODE.fd IMAGE=target/x86_64-unknown-uefi/debug/image.fat32 -make +set -e + +cargo build -Z build-std=core + +dd if=/dev/zero of=${IMAGE} bs=1M count=64 +mkfs.vfat -F32 ${IMAGE} +mcopy -i ${IMAGE} target/x86_64-unknown-uefi/debug/yboot2.efi ::app.efi qemu-system-x86_64 \ -drive format=raw,file=$BIOS,readonly=on,if=pflash \ diff --git a/src/efi.rs b/src/efi.rs deleted file mode 100644 index 175d36b..0000000 --- a/src/efi.rs +++ /dev/null @@ -1,88 +0,0 @@ -use core::ffi::c_void; -use spin::Mutex; - -pub enum Status { - Success, - Err -} - -impl Status { - pub fn to_isize(self) -> isize { - match self { - Status::Success => 0, - Status::Err => -1, - } - } - pub fn from_isize(v: isize) -> Status { - match v { - 0 => Status::Success, - _ => Status::Err - } - } -} - -#[repr(C)] -pub struct TableHeader { - signature: u64, - revision: u32, - header_size: u32, - crc32: u32, - reserved: u32 -} - -#[repr(C)] -pub struct SimpleTextOutputProtocol { - fn_reset: *mut c_void, - fn_output_string: unsafe fn(&SimpleTextOutputProtocol, s: *const i16) -> isize -} - -impl SimpleTextOutputProtocol { - pub fn output_string(&self, s: *const i16) -> Status { - unsafe { Status::from_isize((self.fn_output_string)(self, s)) } - } -} - -#[repr(C)] -pub struct SystemTable { - hdr: TableHeader, - firmware_vendor: *const i16, - firmware_revision: u32, - console_in_handle: *mut c_void, - con_in: *mut c_void, - console_out_handle: *mut c_void, - con_out: *mut SimpleTextOutputProtocol, - standard_error_handle: *mut c_void, - std_err: *mut c_void, - runtime_services: *mut c_void, - boot_services: *mut c_void, - number_of_table_entries: usize, - configuration_table: *mut c_void -} - -impl SystemTable { - pub fn con_out(&self) -> &'static mut SimpleTextOutputProtocol { - unsafe { &mut *self.con_out } - } -} - -static mut SYSTEM_TABLE: Option<*mut SystemTable> = None; - -pub fn init_tables(st: *mut SystemTable) { - unsafe { SYSTEM_TABLE = Some(st); } -} - -pub fn system_table() -> &'static mut SystemTable { - unsafe { &mut *SYSTEM_TABLE.unwrap() } -} - -pub fn con_output_string(text: &str) { - let mut buf = [0i16; 512]; - let mut i = 0; - - for byte in text.bytes() { - buf[i] = byte as i16; - i += 1; - } - - system_table().con_out().output_string(buf.as_ptr()); -} diff --git a/src/main.rs b/src/main.rs index 7775d1e..e5b93a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,52 +1,30 @@ #![no_main] #![no_std] -mod efi; +extern crate efi; +extern crate core_rt; -use core::ffi::c_void; -use efi::{Status, SystemTable}; +use efi::{Status, Handle, SystemTable, system_table}; -#[no_mangle] -unsafe extern "C" fn memcpy(dst: *mut u8, src: *const u8, cnt: usize) -> *mut u8 { - let mut i = 0isize; - while i < cnt as isize { - *(dst.offset(i)) = *(src.offset(i)); - i += 1; - } - return dst; -} -#[no_mangle] -unsafe extern "C" fn memset(dst: *mut u8, val: i32, cnt: usize) -> *mut u8 { - let mut i = 0isize; - while i < cnt as isize { - *(dst.offset(i)) = val as u8; - i += 1; - } - return dst; -} -#[no_mangle] -unsafe extern "C" fn memcmp(a: *const u8, b: *const u8, cnt: usize) -> i32 { - let mut i = 0isize; - while i < cnt as isize { - let diff = *(a.offset(i)) - *(b.offset(i)); - if diff != 0u8 { - return diff as i32; - } - i += 1; - } - return 0; -} +#[macro_use] +mod println; fn main() -> Status { - efi::con_output_string("Test\n"); + let con_out = system_table().con_out(); + + print!("Firmware vendor: "); + con_out.output_char16_string(system_table().firmware_vendor); + print!(", revision: {}.{}", + system_table().firmware_revision >> 16, + system_table().firmware_revision & 0xFFFF); + println!(); return Status::Success; } #[no_mangle] -extern "C" fn efi_main(_ih: *mut c_void, st: *mut SystemTable) -> isize { +extern "C" fn efi_main(_ih: Handle, st: *mut SystemTable) -> isize { efi::init_tables(st); - return main().to_isize(); } diff --git a/src/println.rs b/src/println.rs new file mode 100644 index 0000000..028e3df --- /dev/null +++ b/src/println.rs @@ -0,0 +1,18 @@ +use efi::system_table; +use core::fmt; + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::println::do_println(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => (print!("\r\n")); + ($($arg:tt)*) => (print!("{}\r\n", format_args!($($arg)*))); +} + +pub fn do_println(args: fmt::Arguments) { + use core::fmt::Write; + system_table().con_out().write_fmt(args).unwrap(); +}