From a1fb76387800b41b1028409668c5c3ba6e3c3327 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 10 Sep 2020 22:02:35 +0300 Subject: [PATCH] Initial commit --- .cargo/config | 5 +++ .gitignore | 1 + Cargo.lock | 14 ++++++++ Cargo.toml | 10 ++++++ Makefile | 17 ++++++++++ qemu.sh | 14 ++++++++ src/efi.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 57 +++++++++++++++++++++++++++++++++ 8 files changed, 206 insertions(+) create mode 100644 .cargo/config create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100755 qemu.sh create mode 100644 src/efi.rs create mode 100644 src/main.rs diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..e2dee73 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,5 @@ +[build] +target = "x86_64-unknown-uefi" + +[target.x86_64-unknown-uefi] +rustflags = ["-Ccode-model=small", "-Clink-arg=/debug:none"] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..437163b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,14 @@ +# 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" + +[[package]] +name = "yboot2" +version = "0.1.0" +dependencies = [ + "spin", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..23d16bd --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "yboot2" +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] +spin = { version = "0.5.2" } diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..30cbc70 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +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/qemu.sh b/qemu.sh new file mode 100755 index 0000000..bedfb08 --- /dev/null +++ b/qemu.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +BIOS=/usr/share/edk2-ovmf/OVMF_CODE.fd +IMAGE=target/x86_64-unknown-uefi/debug/image.fat32 + +make + +qemu-system-x86_64 \ + -drive format=raw,file=$BIOS,readonly=on,if=pflash \ + -drive format=raw,file=$IMAGE \ + -net none \ + -enable-kvm \ + -M q35 \ + -cpu host diff --git a/src/efi.rs b/src/efi.rs new file mode 100644 index 0000000..175d36b --- /dev/null +++ b/src/efi.rs @@ -0,0 +1,88 @@ +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 new file mode 100644 index 0000000..7775d1e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,57 @@ +#![no_main] +#![no_std] + +mod efi; + +use core::ffi::c_void; +use efi::{Status, SystemTable}; + +#[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; +} + +fn main() -> Status { + efi::con_output_string("Test\n"); + + return Status::Success; +} + +#[no_mangle] +extern "C" fn efi_main(_ih: *mut c_void, st: *mut SystemTable) -> isize { + efi::init_tables(st); + + return main().to_isize(); +} + +use core::panic::PanicInfo; +#[panic_handler] +fn panic(_panic: &PanicInfo<'_>) -> ! { + loop {} +}