Skip to content

Commit 4d74604

Browse files
committed
Load a second stage from disk in Rust
1 parent 1b95736 commit 4d74604

File tree

4 files changed

+122
-4
lines changed

4 files changed

+122
-4
lines changed

real_mode/linker.ld

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,12 @@ SECTIONS {
2727
{
2828
SHORT(0xaa55) /* magic number for bootable disk */
2929
}
30-
_bootloader_end = .;
30+
31+
_second_stage_start = .;
32+
.second_stage :
33+
{
34+
*(.second_stage)
35+
}
36+
. = ALIGN(512);
37+
_second_stage_end = .;
3138
}

real_mode/src/dap.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#[repr(packed)]
2+
pub struct DiskAddressPacket {
3+
/// Size of the DAP structure
4+
packet_size: u8,
5+
/// always zero
6+
zero: u8,
7+
/// Number of sectors to transfer
8+
number_of_sectors: u16,
9+
/// Offset to memory buffer
10+
offset: u16,
11+
/// Segment of memory buffer
12+
segment: u16,
13+
/// Start logical block address
14+
start_lba: u64,
15+
}
16+
17+
impl DiskAddressPacket {
18+
pub fn new(memory_buffer_start: u16, file_offset: u64, bytes: u32) -> Self {
19+
Self {
20+
packet_size: 0x10,
21+
zero: 0,
22+
number_of_sectors: (bytes / 512) as u16,
23+
offset: memory_buffer_start,
24+
segment: 0,
25+
start_lba: file_offset / 512,
26+
}
27+
}
28+
29+
pub unsafe fn perform_load(&self, disk_number: u16) {
30+
let self_addr = self as *const Self as u16;
31+
asm!("
32+
int 0x13
33+
jc dap_load_failed
34+
" :: "{si}"(self_addr), "{ax}"(0x4200), "{dx}"(disk_number) :: "intel");
35+
}
36+
}

real_mode/src/main.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,57 @@
44

55
use core::panic::PanicInfo;
66

7+
mod dap;
8+
79
global_asm!(include_str!("boot.s"));
10+
global_asm!(include_str!("second_stage.s"));
11+
12+
extern "C" {
13+
fn second_stage() -> u32;
14+
}
15+
16+
#[allow(improper_ctypes)]
17+
extern "C" {
18+
static _bootloader_start: ();
19+
static _second_stage_start: ();
20+
static _second_stage_end: ();
21+
}
822

923
#[no_mangle]
10-
pub extern "C" fn rust_main() {
11-
println(b"Hello from Rust!");
24+
pub extern "C" fn rust_main(disk_number: u16) {
25+
load_second_stage(disk_number);
26+
27+
let val = unsafe { second_stage() };
28+
if val == 12345 {
29+
println(b"match");
30+
} else {
31+
println(b"no match");
32+
}
1233
}
1334

35+
fn bootloader_start() -> usize {
36+
unsafe { &_bootloader_start as *const _ as usize }
37+
}
38+
39+
fn second_stage_start() -> usize {
40+
unsafe { &_second_stage_start as *const _ as usize }
41+
}
42+
43+
fn second_stage_end() -> usize {
44+
unsafe { &_second_stage_end as *const _ as usize }
45+
}
46+
47+
fn load_second_stage(disk_number: u16) {
48+
use dap::DiskAddressPacket;
49+
50+
let file_offset = (second_stage_start() - bootloader_start()) as u64;
51+
let size = (second_stage_end() - second_stage_start()) as u32;
52+
53+
let dap = DiskAddressPacket::new(second_stage_start() as u16, file_offset, size);
54+
unsafe { dap.perform_load(disk_number) }
55+
}
56+
57+
#[inline(never)]
1458
fn println(s: &[u8]) {
1559
print(s);
1660
print_char(b'\n');
@@ -29,9 +73,32 @@ fn print_char(c: u8) {
2973
}
3074
}
3175

76+
#[no_mangle]
77+
pub extern "C" fn dap_load_failed() -> ! {
78+
println(b"ERROR: DAP load failed");
79+
loop {
80+
hlt()
81+
}
82+
}
83+
84+
#[no_mangle]
85+
pub extern "C" fn no_int13h_extensions() -> ! {
86+
println(b"ERROR: No int13h extensions");
87+
loop {
88+
hlt()
89+
}
90+
}
91+
3292
#[panic_handler]
3393
pub fn panic(_info: &PanicInfo) -> ! {
3494
println(b"PANIC!");
35-
loop {}
95+
loop {
96+
hlt()
97+
}
3698
}
3799

100+
fn hlt() {
101+
unsafe {
102+
asm!("hlt":::: "intel","volatile");
103+
}
104+
}

real_mode/src/second_stage.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.section .second_stage, "awx"
2+
.global second_stage
3+
.intel_syntax noprefix
4+
.code16
5+
6+
second_stage:
7+
mov eax, 12345
8+
ret

0 commit comments

Comments
 (0)