Skip to content

Commit e2cadea

Browse files
committed
Initial implementation of a new loader written in Rust
TEST=`make run_rust` and `telnet localhost 1235`
1 parent c33d326 commit e2cadea

File tree

9 files changed

+165
-0
lines changed

9 files changed

+165
-0
lines changed

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ LLDB_ARGS = -o 'settings set interpreter.prompt-on-quit false' \
105105
-o 'process launch' \
106106
-o 'process handle -s false SIGUSR1 SIGUSR2'
107107

108+
common_run_rust : files .FORCE
109+
make -C loader install
110+
$(QEMU) $(QEMU_ARGS_PMEM)
111+
108112
run_xhci_gdb : files .FORCE
109113
lldb $(LLDB_ARGS) -- $(QEMU) $(QEMU_ARGS_XHCI) $(QEMU_ARGS)
110114

common.mk

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ commit :
2424
run :
2525
make -C $(THIS_DIR) run_root
2626

27+
run_rust :
28+
make -C $(THIS_DIR) common_run_rust
29+
2730
run_docker :
2831
make -C $(THIS_DIR) run_docker_root
2932

loader/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
*.swp
3+
*.o

loader/Cargo.lock

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loader/Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "loader"
3+
version = "0.1.0"
4+
authors = ["hikalium <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
9+
[profile.dev]
10+
panic = "abort"
11+
12+
[profile.release]
13+
panic = "abort"

loader/Makefile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
default: build
2+
3+
include ../common.mk
4+
5+
.PHONY: build clean
6+
7+
build :
8+
cargo build -vv --target=x86_64-none-efi.json --release \
9+
-Z build-std=core,alloc \
10+
-Z build-std-features=compiler-builtins-mem
11+
clean:
12+
-rm -r target
13+
14+
install:
15+
cp target/x86_64-none-efi/release/loader.efi ../mnt/EFI/BOOT/BOOTX64.EFI
16+
17+
check:
18+
cargo clippy

loader/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# loader
2+
3+
This is an EFI application written in Rust, which loads liumOS.
4+
5+
## References
6+
- https://os.phil-opp.com/
7+
- https://medium.com/@gil0mendes/an-efi-app-a-bit-rusty-82c36b745f49

loader/src/main.rs

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#![no_std]
2+
#![no_main]
3+
#![feature(asm)]
4+
5+
use core::convert::TryInto;
6+
use core::fmt;
7+
use core::panic::PanicInfo;
8+
9+
#[panic_handler]
10+
fn panic(_info: &PanicInfo) -> ! {
11+
loop {}
12+
}
13+
14+
// https://doc.rust-lang.org/beta/unstable-book/library-features/asm.html
15+
16+
fn write_io_port(port: u16, data: u8) {
17+
unsafe {
18+
asm!("out dx, al",
19+
in("al") data,
20+
in("dx") port)
21+
}
22+
}
23+
fn read_io_port(port: u16) -> u8 {
24+
let mut data: u8;
25+
unsafe {
26+
asm!("in al, dx",
27+
out("al") data,
28+
in("dx") port)
29+
}
30+
data
31+
}
32+
33+
// const IO_ADDR_COM1: u16 = 0x3f8;
34+
const IO_ADDR_COM2: u16 = 0x2f8;
35+
fn com_initialize(base_io_addr: u16) {
36+
write_io_port(base_io_addr + 1, 0x00); // Disable all interrupts
37+
write_io_port(base_io_addr + 3, 0x80); // Enable DLAB (set baud rate divisor)
38+
const BAUD_DIVISOR: u16 = 0x0001; // baud rate = (115200 / BAUD_DIVISOR)
39+
write_io_port(base_io_addr, (BAUD_DIVISOR & 0xff).try_into().unwrap());
40+
write_io_port(base_io_addr + 1, (BAUD_DIVISOR >> 8).try_into().unwrap());
41+
write_io_port(base_io_addr + 3, 0x03); // 8 bits, no parity, one stop bit
42+
write_io_port(base_io_addr + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
43+
write_io_port(base_io_addr + 4, 0x0B); // IRQs enabled, RTS/DSR set
44+
}
45+
46+
fn com_send_char(base_io_addr: u16, c: char) {
47+
while (read_io_port(base_io_addr + 5) & 0x20) == 0 {
48+
unsafe { asm!("pause") }
49+
}
50+
write_io_port(base_io_addr, c as u8)
51+
}
52+
53+
fn com_send_str(base_io_addr: u16, s: &str) {
54+
let mut sc = s.chars();
55+
let slen = s.chars().count();
56+
for _ in 0..slen {
57+
com_send_char(base_io_addr, sc.next().unwrap());
58+
}
59+
}
60+
61+
pub struct Writer {}
62+
63+
impl Writer {
64+
pub fn write_str(&mut self, s: &str) {
65+
com_send_str(IO_ADDR_COM2, s);
66+
}
67+
}
68+
69+
impl fmt::Write for Writer {
70+
fn write_str(&mut self, s: &str) -> fmt::Result {
71+
com_send_str(IO_ADDR_COM2, s);
72+
Ok(())
73+
}
74+
}
75+
76+
#[no_mangle]
77+
pub extern "C" fn efi_entry() -> ! {
78+
use core::fmt::Write;
79+
com_initialize(IO_ADDR_COM2);
80+
let mut writer = Writer {};
81+
let mut n = 0;
82+
loop {
83+
write!(writer, "liumOS loader! n = {}\n\r", n).unwrap();
84+
n += 1;
85+
}
86+
}

loader/x86_64-none-efi.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"llvm-target": "x86_64-pc-windows-gnu",
3+
"env": "gnu",
4+
"target-family": "windows",
5+
"target-endian": "little",
6+
"target-pointer-width": "64",
7+
"target-c-int-width": "32",
8+
"os": "uefi",
9+
"arch": "x86_64",
10+
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
11+
"linker": "rust-lld",
12+
"linker-flavor": "lld-link",
13+
"pre-link-args": {
14+
"lld-link": [
15+
"/Subsystem:EFI_Application",
16+
"/Entry:efi_entry"
17+
]
18+
},
19+
"panic-strategy": "abort",
20+
"default-hidden-visibility": true,
21+
"executables": true,
22+
"position-independent-executables": true,
23+
"exe-suffix": ".efi",
24+
"is-like-windows": true,
25+
"emit-debug-gdb-scripts": false
26+
}

0 commit comments

Comments
 (0)