├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile └── src ├── boot.rs └── uefi └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | build 3 | img 4 | boot.iso 5 | *.o 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/rust-core"] 2 | path = external/rust-core 3 | url = https://github.com/eholk/rust-core.git 4 | [submodule "external/binutils-gdb"] 5 | path = external/binutils-gdb 6 | url = git://sourceware.org/git/binutils-gdb.git 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Eric Holk 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | Except as contained in this notice, the name(s) of the above copyright 15 | holders shall not be used in advertising or otherwise to promote the 16 | sale, use or other dealings in this Software without prior written 17 | authorization. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LD := x86_64-efi-pe-ld 2 | 3 | .phony: all image 4 | 5 | all: image 6 | 7 | image: 8 | mkdir -p build 9 | rustc -O --emit=obj --crate-type=lib src/boot.rs --out-dir build/ 10 | mkdir -p img/efi/boot 11 | $(LD) --oformat pei-x86-64 --subsystem 10 -pie -e efi_start build/boot.o -o img/efi/boot/bootx64.efi 12 | mkisofs -o boot.iso img 13 | -------------------------------------------------------------------------------- /src/boot.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(globs)] 3 | #![feature(intrinsics)] 4 | #![feature(asm)] 5 | 6 | extern crate core; 7 | 8 | use uefi::SimpleTextOutput; 9 | 10 | #[allow(non_snake_case)] 11 | #[allow(dead_code)] 12 | #[allow(non_camel_case_types)] 13 | #[allow(missing_copy_implementations)] 14 | pub mod uefi; 15 | 16 | #[no_stack_check] 17 | pub fn efi_main(sys : uefi::SystemTable) { 18 | sys.console().write("Hello, World!\n\r"); 19 | 20 | loop {} 21 | } 22 | 23 | #[no_mangle] 24 | pub fn abort() -> ! { 25 | loop {} 26 | } 27 | 28 | #[no_mangle] 29 | pub fn breakpoint() -> ! { 30 | loop {} 31 | } 32 | -------------------------------------------------------------------------------- /src/uefi/mod.rs: -------------------------------------------------------------------------------- 1 | use core::prelude::*; 2 | 3 | pub type EFI_HANDLE = *const (); 4 | pub struct EFI_GUID(u32, u16, u16, [u8; 8]); 5 | 6 | struct EFI_TABLE_HEADER { 7 | Signature : u64, 8 | Revision : u32, 9 | HeaderSize : u32, 10 | CRC32 : u32, 11 | Reserved : u32 12 | } 13 | 14 | pub struct EFI_SYSTEM_TABLE { 15 | Hdr : EFI_TABLE_HEADER, 16 | FirmwareVendor : *const u16, 17 | FirmwareRevision : u32, 18 | ConsoleInHandle : EFI_HANDLE, 19 | ConIn : *const EFI_SIMPLE_TEXT_INPUT_PROTOCOL, 20 | ConsoleOutHandle : EFI_HANDLE, 21 | ConOut : *const EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, 22 | ConsoleErrorHandle : EFI_HANDLE, 23 | StdErr : *const EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, 24 | RuntimeServices : *const EFI_RUNTIME_SERVICES, 25 | BootServices : *const EFI_BOOT_SERVICES, 26 | NumberOfTableEntries : uint, 27 | ConfigurationTable : *const EFI_CONFIGURATION_TABLE 28 | } 29 | 30 | pub static mut SYSTEM_TABLE : *const EFI_SYSTEM_TABLE = 0 as *const EFI_SYSTEM_TABLE; 31 | 32 | struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL; 33 | 34 | struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { 35 | Reset : EFI_TEXT_RESET, 36 | OutputString : EFI_TEXT_STRING, 37 | // ... and more stuff that we're ignoring. 38 | } 39 | 40 | type EFI_TEXT_RESET = *const (); 41 | 42 | type EFI_TEXT_STRING = extern "win64" fn(*const EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, 43 | *const u16); 44 | 45 | struct EFI_RUNTIME_SERVICES; 46 | 47 | struct EFI_BOOT_SERVICES; 48 | 49 | struct EFI_CONFIGURATION_TABLE { 50 | VendorGuid : EFI_GUID, 51 | VendorTable : *const () 52 | } 53 | 54 | pub struct SystemTable(*const EFI_SYSTEM_TABLE); 55 | 56 | 57 | impl SystemTable { 58 | #[no_stack_check] 59 | pub fn console(&self) -> Console { 60 | unsafe { 61 | let &SystemTable(tbl) = self; 62 | Console { 63 | input: (*tbl).ConIn, 64 | output: (*tbl).ConOut, 65 | } 66 | } 67 | } 68 | } 69 | 70 | fn unpack(slice: &[T]) -> (*const T, uint) { 71 | unsafe { 72 | transmute(slice) 73 | } 74 | } 75 | 76 | pub trait SimpleTextOutput { 77 | unsafe fn write_raw(&self, str: *const u16); 78 | 79 | #[no_stack_check] 80 | fn write(&self, str: &str) { 81 | let mut buf = [0u16; 4096]; 82 | 83 | let mut i = 0; 84 | while i < buf.len() && i < str.len() { 85 | // TODO: make sure the characters are all ascii 86 | buf[i] = str.char_at(i) as u16; 87 | i += 1; 88 | } 89 | buf[buf.len() - 1] = 0; 90 | 91 | unsafe { 92 | let (p, _) = unpack(&buf); 93 | self.write_raw(p); 94 | } 95 | } 96 | } 97 | 98 | pub trait SimpleTextInput { 99 | } 100 | 101 | pub struct Console { 102 | input : *const EFI_SIMPLE_TEXT_INPUT_PROTOCOL, 103 | output : *const EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL, 104 | } 105 | 106 | impl SimpleTextOutput for Console { 107 | #[no_stack_check] 108 | unsafe fn write_raw(&self, str: *const u16) { 109 | ((*(*self).output).OutputString)(self.output, str); 110 | } 111 | } 112 | 113 | impl SimpleTextInput for Console { 114 | } 115 | 116 | extern "rust-intrinsic" { 117 | fn transmute(val: T) -> U; 118 | } 119 | 120 | #[no_mangle] 121 | #[no_stack_check] 122 | pub extern "win64" fn efi_start(_ImageHandle : EFI_HANDLE, 123 | sys_table : *const EFI_SYSTEM_TABLE) -> int { 124 | unsafe { SYSTEM_TABLE = sys_table; } 125 | ::efi_main(SystemTable(sys_table)); 126 | 0 127 | } 128 | 129 | #[no_mangle] 130 | #[no_stack_check] 131 | pub fn __morestack() { 132 | // Horrible things will probably happen if this is ever called. 133 | } 134 | 135 | #[no_mangle] 136 | #[no_stack_check] 137 | pub extern fn memset(s : *const u8, c : int, n : uint) -> *const u8 { 138 | unsafe { 139 | let s : &mut [u8] = transmute((s, n)); 140 | let mut i = 0; 141 | while i < n { 142 | s[i] = c as u8; 143 | i += 1; 144 | // Use inline assembly here to defeat LLVM's loop-idiom pass 145 | asm!(""); 146 | } 147 | } 148 | 149 | s 150 | } 151 | --------------------------------------------------------------------------------