fixed addr gdt, serial
This commit is contained in:
1 parent
b0dffe7bc8
commit
988d3d601d
9 files changed
+189
-24
No files matched your search
+16
-2
@@ -17,7 +17,21 @@
|
|||||||
| Reserved | 0x0c8000 - 0x0f0000 | bios expansions |
|
| Reserved | 0x0c8000 - 0x0f0000 | bios expansions |
|
||||||
| Reserved | 0x0f0000 - 0x100000 | motherboard bios |
|
| Reserved | 0x0f0000 - 0x100000 | motherboard bios |
|
||||||
|
|
||||||
|
### Allocations
|
||||||
|
|
||||||
|
- 0x00500 - 0x04000: stage 1/2 stack
|
||||||
|
- 0x04000 - 0x06a00: globals
|
||||||
|
- 0x07c00 - 0x07e00: stage 1 text
|
||||||
|
- 0x07e00 - 0x08000: gpt partition header
|
||||||
|
- 0x08000 - 0x08200: stage 2 partition table entry
|
||||||
|
- 0x08200 - 0x0c000: stage 2 text, stage 3 stack
|
||||||
|
- 0x0c000 : gdt
|
||||||
|
- 0x10000 : stage 3 text
|
||||||
|
|
||||||
0x10000: stage 3
|
0x10000: stage 3
|
||||||
|
|
||||||
TODO: once we're in real mode, repurpose s2 and s3 for a stack
|
TODO: once we're in real mode, repurpose s2 for a stack
|
||||||
TODO: load s4 into a separate memory region
|
TODO: load s3 into a separate memory region
|
||||||
|
|
||||||
|
TODO: use some fixed known memory address for the GDT, rather than putting it in stage 2.
|
||||||
|
That way, we can safely overwrite stage 2 once we're done with it.
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
%define S2_DATA S2_LOAD_ADDR
|
%define S2_DATA S2_LOAD_ADDR
|
||||||
%define S2_ENTRYPOINT (S2_DATA_ADDR + S2_DATA_LEN)
|
%define S2_ENTRYPOINT (S2_DATA_ADDR + S2_DATA_LEN)
|
||||||
|
|
||||||
|
%define GDT_ADDR 0xc000
|
||||||
%define S3_LOAD_ADDR 0x10000
|
%define S3_LOAD_ADDR 0x10000
|
||||||
|
|
||||||
; %define MEMMAP 0x6a00
|
; %define MEMMAP 0x6a00
|
||||||
|
|||||||
@@ -9,29 +9,33 @@ run:
|
|||||||
-m 512M \
|
-m 512M \
|
||||||
-drive format=raw,file=disk.bin
|
-drive format=raw,file=disk.bin
|
||||||
|
|
||||||
|
run_serial:
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-serial stdio \
|
||||||
|
-no-reboot \
|
||||||
|
-m 512M \
|
||||||
|
-drive format=raw,file=disk.bin
|
||||||
|
|
||||||
|
run_reset:
|
||||||
|
qemu-system-x86_64 \
|
||||||
|
-monitor stdio \
|
||||||
|
-no-reboot \
|
||||||
|
-m 512M \
|
||||||
|
-drive if=pflash,file=reset.bin,format=raw
|
||||||
|
|
||||||
|
build_reset:
|
||||||
|
nasm -f bin -werror -o reset.bin reset.s
|
||||||
|
|
||||||
#-bios seabios/out/bios.bin
|
#-bios seabios/out/bios.bin
|
||||||
|
|
||||||
build: build_stage_1 build_stage_2
|
build:
|
||||||
|
cargo xtask build
|
||||||
build_stage_1:
|
|
||||||
nasm -f bin {{common_flags}} -o stage_1/stage_1.bin stage_1/main.s
|
|
||||||
|
|
||||||
build_stage_2:
|
|
||||||
nasm -f elf {{common_flags}} -o stage_2/prelude.o stage_2/prelude.s
|
|
||||||
nasm -f elf {{common_flags}} -o stage_2/main.o stage_2/main.s
|
|
||||||
nasm -f elf {{common_flags}} -o stage_2/a20.o stage_2/a20.s
|
|
||||||
{{ld32}} -m elf_i386 -T stage_2/link.ld -o stage_2/stage_2.bin stage_2/*.o
|
|
||||||
|
|
||||||
mkimg:
|
mkimg:
|
||||||
dd if=/dev/zero of=disk.bin bs=440 count=1 conv=notrunc
|
dd if=/dev/zero of=disk.bin bs=440 count=1 conv=notrunc
|
||||||
dd if=build/stage_1/s1.bin of=disk.bin conv=notrunc
|
dd if=build/stage_1/s1.bin of=disk.bin conv=notrunc
|
||||||
dd if=build/s23.bin of=disk.bin bs=512 seek=70 conv=notrunc
|
dd if=build/s23.bin of=disk.bin bs=512 seek=70 conv=notrunc
|
||||||
|
|
||||||
# build:
|
|
||||||
# nasm -f bin -Iinclude -o boot0.bin boot0.s
|
|
||||||
# cd boot1; cargo build --release
|
|
||||||
# # nasm -f bin -Iinclude -o boot1.bin boot1.s
|
|
||||||
|
|
||||||
zero_disk:
|
zero_disk:
|
||||||
dd if=/dev/zero of=disk.bin bs=512 count=1000
|
dd if=/dev/zero of=disk.bin bs=512 count=1000
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
; flash seems to get mapped to ff000
|
||||||
|
; reset vector is f000:fff0 = ffff0
|
||||||
|
; so there's ff0 = 4080 bytes of something before the reset vector. what is it?
|
||||||
|
|
||||||
|
[bits 16]
|
||||||
|
[org 0xff000]
|
||||||
|
|
||||||
|
times (0xff0 - ($ - $$)) db 0x00
|
||||||
|
|
||||||
|
mov eax, 0xcafeface
|
||||||
|
hlt
|
||||||
|
|
||||||
|
times (0x1000 - ($ - $$)) db 0xf4
|
||||||
|
|
||||||
+6
-3
@@ -36,6 +36,12 @@ s2_main:
|
|||||||
mov cx, 0x3f00
|
mov cx, 0x3f00
|
||||||
int 0x10
|
int 0x10
|
||||||
|
|
||||||
|
; Copy the GDT
|
||||||
|
mov cx, GDT_FLAT_LEN
|
||||||
|
mov si, gdt_flat
|
||||||
|
mov di, GDT_ADDR
|
||||||
|
rep movsb
|
||||||
|
|
||||||
; Ensure interrupts are definitely disabled.
|
; Ensure interrupts are definitely disabled.
|
||||||
cli
|
cli
|
||||||
|
|
||||||
@@ -124,7 +130,6 @@ global gdt_flat_slice
|
|||||||
; - 7: present (must be set)
|
; - 7: present (must be set)
|
||||||
;
|
;
|
||||||
|
|
||||||
; FIXME: copy this to a fixed memory location
|
|
||||||
align 8
|
align 8
|
||||||
gdt_flat:
|
gdt_flat:
|
||||||
; First GDT entry must be 0.
|
; First GDT entry must be 0.
|
||||||
@@ -161,8 +166,6 @@ gdt_flat:
|
|||||||
11001111b, \
|
11001111b, \
|
||||||
0x00
|
0x00
|
||||||
|
|
||||||
global gdt_flat
|
|
||||||
|
|
||||||
GDT_FLAT_LEN equ ($ - gdt_flat)
|
GDT_FLAT_LEN equ ($ - gdt_flat)
|
||||||
|
|
||||||
GDT_FLAT_IDX_CODE_32 equ (gdt_flat.segment_code_32 - gdt_flat)
|
GDT_FLAT_IDX_CODE_32 equ (gdt_flat.segment_code_32 - gdt_flat)
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
use core::{fmt, hint};
|
||||||
|
|
||||||
|
use crate::ioport;
|
||||||
|
|
||||||
|
pub struct Com {
|
||||||
|
port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ComError;
|
||||||
|
|
||||||
|
impl Com {
|
||||||
|
pub unsafe fn init(port: u16) -> Result<Self, ComError> {
|
||||||
|
const ECHO_BYTE: u8 = 0x5a;
|
||||||
|
|
||||||
|
let echo = unsafe {
|
||||||
|
// Unset DLAB
|
||||||
|
ioport::outb(port + 3, 0x00);
|
||||||
|
// Disable interrupts
|
||||||
|
ioport::outb(port + 1, 0x00);
|
||||||
|
// Set DLAB
|
||||||
|
ioport::outb(port + 3, 0x80);
|
||||||
|
// Set baud rate divisor to 00 01 (115200)
|
||||||
|
ioport::outb(port + 0, 0x01);
|
||||||
|
ioport::outb(port + 1, 0x00);
|
||||||
|
// 8 bits, no parity, one stop bit
|
||||||
|
ioport::outb(port + 3, 0x03);
|
||||||
|
// Enable FIFO, clear them, with 14-byte threshold
|
||||||
|
ioport::outb(port + 2, 0xc7);
|
||||||
|
// IRQs enabled, RTS/DSR set
|
||||||
|
ioport::outb(port + 4, 0x0b);
|
||||||
|
// Set loopback mode
|
||||||
|
ioport::outb(port + 4, 0x1e);
|
||||||
|
ioport::outb(port + 0, ECHO_BYTE);
|
||||||
|
|
||||||
|
ioport::inb(port + 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
if echo != ECHO_BYTE {
|
||||||
|
return Err(ComError);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ioport::outb(port + 4, 0x0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
port,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_has_data(&self) -> bool {
|
||||||
|
unsafe { ioport::inb(self.port + 5) & 0x01 != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_poll(&mut self) -> u8 {
|
||||||
|
while !self.poll_has_data() {
|
||||||
|
hint::spin_loop();
|
||||||
|
}
|
||||||
|
unsafe { ioport::inb(self.port) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_has_space(&self) -> bool {
|
||||||
|
unsafe { ioport::inb(self.port + 5) & 0x20 != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_poll(&mut self, x: u8) {
|
||||||
|
while !self.poll_has_space() {
|
||||||
|
hint::spin_loop();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
ioport::outb(self.port, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for Com {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for b in s.bytes() {
|
||||||
|
self.write_poll(b);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
let s = c.encode_utf8(&mut buf);
|
||||||
|
for b in s.bytes() {
|
||||||
|
self.write_poll(b);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
pub unsafe fn inb(port: u16) -> u8 {
|
||||||
|
let x: u8;
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"in al, dx",
|
||||||
|
in("dx") port,
|
||||||
|
lateout("al") x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn outb(port: u16, x: u8) {
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"out dx, al",
|
||||||
|
in("al") x,
|
||||||
|
in("dx") port,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-1
@@ -4,9 +4,11 @@
|
|||||||
#![test_runner(crate::test_runner)]
|
#![test_runner(crate::test_runner)]
|
||||||
|
|
||||||
mod spin;
|
mod spin;
|
||||||
|
mod ioport;
|
||||||
mod vga;
|
mod vga;
|
||||||
|
mod com;
|
||||||
|
|
||||||
use core::{arch::{asm, global_asm}, panic::PanicInfo, fmt::Write};
|
use core::{arch::{asm, global_asm}, fmt::Write, panic::PanicInfo, ptr, slice};
|
||||||
|
|
||||||
global_asm!(include_str!("asm/trampoline.s"));
|
global_asm!(include_str!("asm/trampoline.s"));
|
||||||
|
|
||||||
@@ -20,11 +22,26 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
hlt()
|
hlt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const COM1_PORT: u16 = 0x3f8;
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn _start() -> ! {
|
pub extern "C" fn _start() -> ! {
|
||||||
vga::vga_init();
|
vga::vga_init();
|
||||||
|
|
||||||
|
let gdt_ptr = ptr::with_exposed_provenance::<u64>(0xc000);
|
||||||
|
let gdt_slice = unsafe { slice::from_raw_parts(gdt_ptr, 4) };
|
||||||
|
|
||||||
vga_println!("hello from rust :)");
|
vga_println!("hello from rust :)");
|
||||||
|
vga_println!("{:016x}", gdt_slice[0]);
|
||||||
|
vga_println!("{:016x}", gdt_slice[1]);
|
||||||
|
vga_println!("{:016x}", gdt_slice[2]);
|
||||||
|
vga_println!("{:016x}", gdt_slice[3]);
|
||||||
|
|
||||||
|
let mut com = unsafe { com::Com::init(COM1_PORT) };
|
||||||
|
|
||||||
|
if let Ok(com) = &mut com {
|
||||||
|
writeln!(com, "hello serial").ok();
|
||||||
|
}
|
||||||
|
|
||||||
hlt()
|
hlt()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
const BLOCK_SIZE: u64 = 512;
|
|
||||||
const PARTITION_ENTRY_SIZE: u64 = 128;
|
|
||||||
|
|
||||||
// LBA 0: MBR
|
// LBA 0: MBR
|
||||||
// LBA 1: partition header
|
// LBA 1: partition header
|
||||||
// LBA 2..33: partition table entries
|
// LBA 2..33: partition table entries
|
||||||
|
|||||||
Reference in new issue
Block a user