diff --git a/Cargo.lock b/Cargo.lock index 86bdefd318..4825575c13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,7 @@ dependencies = [ [[package]] name = "redoxfs" version = "0.5.0" +source = "git+https://gitlab.redox-os.org/redox-os/redoxfs.git?branch=0.5.0#13d220fe6e954be4bbf7e20ccd117761474ae446" dependencies = [ "aes", "generic-array", diff --git a/src/disk.rs b/src/disk.rs new file mode 100644 index 0000000000..faaf0422f3 --- /dev/null +++ b/src/disk.rs @@ -0,0 +1,62 @@ +use std::fs::{File, OpenOptions}; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::path::Path; +use syscall::error::{Error, Result, EIO}; + +use crate::disk::Disk; +use crate::BLOCK_SIZE; + +#[derive(Clone, Copy)] +#[repr(packed)] +pub struct DiskAddressPacket { + size: u8, + reserved: u8, + blocks: u16, + buffer: u16, + segment: u16, + address: u64, +} + +impl DiskAddressPacket { + pub fn from_block(block: u64) -> DiskAddressPacket { + let blocks = BLOCK_SIZE / 512; + DiskAddressPacket { + size: mem::size_of::(), + reserved: 0, + blocks, + buffer: DISK_BIOS_ADDR, + segment: 0, + address: block * blocks, + } + } +} + +pub struct DiskBios { + thunk13: extern "C" fn(), +} + +impl DiskBios { + pub fn block_dap(block: u64) -> DiskAddressPacket { + } +} + +impl Disk for DiskBios { + unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result { + let mut dap = DiskAddressPacket::from_block(block); + + try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); + let count = try_disk!(self.file.read(buffer)); + Ok(count) + } + + unsafe fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result { + try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); + let count = try_disk!(self.file.write(buffer)); + Ok(count) + } + + fn size(&mut self) -> Result { + let size = try_disk!(self.file.seek(SeekFrom::End(0))); + Ok(size) + } +} diff --git a/src/lib.rs b/src/lib.rs index e9eb4e562a..c368ddfbe8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,213 +15,27 @@ use core::{ }; use linked_list_allocator::LockedHeap; -mod panic; +use self::thunk::ThunkData; +use self::vbe::{VbeCardInfo, VbeModeInfo}; +use self::vga::{VgaTextBlock, VgaTextColor, Vga}; -const VBE_CARD_INFO_ADDR: usize = 0x1000; -const VBE_MODE_INFO_ADDR: usize = 0x2000; -const STACK_ADDR: usize = 0x7C00; +mod panic; +mod thunk; +mod vbe; +mod vga; + +// Real mode memory allocation, for use with thunk +// 0x500 to 0x7BFF is free +const VBE_CARD_INFO_ADDR: usize = 0x500; // 512 bytes, ends at 0x6FF +const VBE_MODE_INFO_ADDR: usize = 0x700; // 256 bytes, ends at 0x7FF +const DISK_ADDRESS_PACKET_ADDR: usize = 0x0FF0; // 16 bytes, ends at 0x0FFF +const DISK_BIOS_ADDR: usize = 0x1000; // 4096 bytes, ends at 0x1FFF +const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards const VGA_ADDR: usize = 0xB8000; #[global_allocator] static ALLOCATOR: LockedHeap = LockedHeap::empty(); -#[derive(Clone, Copy)] -#[repr(packed)] -pub struct ThunkData { - di: u16, - si: u16, - bp: u16, - sp: u16, - bx: u16, - dx: u16, - cx: u16, - ax: u16, -} - -impl ThunkData { - pub fn new() -> Self { - Self { - di: 0, - si: 0, - bp: 0, - sp: STACK_ADDR as u16, - bx: 0, - dx: 0, - cx: 0, - ax: 0, - } - } - - pub unsafe fn save(&self) { - ptr::write((STACK_ADDR - 16) as *mut ThunkData, *self); - } - - pub unsafe fn load(&mut self) { - *self = ptr::read((STACK_ADDR - 16) as *const ThunkData); - } - - pub unsafe fn with(&mut self, f: extern "C" fn()) { - self.save(); - f(); - self.load(); - } -} - -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct VbeCardInfo { - signature: [u8; 4], - version: u16, - oemstring: u32, - capabilities: u32, - videomodeptr: u32, - totalmemory: u16, - oemsoftwarerev: u16, - oemvendornameptr: u32, - oemproductnameptr: u32, - oemproductrevptr: u32, - reserved: [u8; 222], - oemdata: [u8; 256], -} - -#[derive(Clone, Copy, Debug)] -#[repr(packed)] -pub struct VbeModeInfo { - attributes: u16, - winA: u8, - winB: u8, - granularity: u16, - winsize: u16, - segmentA: u16, - segmentB: u16, - winfuncptr: u32, - bytesperscanline: u16, - xresolution: u16, - yresolution: u16, - xcharsize: u8, - ycharsize: u8, - numberofplanes: u8, - bitsperpixel: u8, - numberofbanks: u8, - memorymodel: u8, - banksize: u8, - numberofimagepages: u8, - unused: u8, - redmasksize: u8, - redfieldposition: u8, - greenmasksize: u8, - greenfieldposition: u8, - bluemasksize: u8, - bluefieldposition: u8, - rsvdmasksize: u8, - rsvdfieldposition: u8, - directcolormodeinfo: u8, - physbaseptr: u32, - offscreenmemoryoffset: u32, - offscreenmemsize: u16, - reserved: [u8; 206], -} - -#[derive(Clone, Copy)] -#[repr(packed)] -pub struct VgaTextBlock { - char: u8, - color: u8, -} - -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum VgaTextColor { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Purple = 5, - Brown = 6, - Gray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - LightPurple = 13, - Yellow = 14, - White = 15, -} - -pub struct Vga { - blocks: &'static mut [VgaTextBlock], - width: usize, - height: usize, - x: usize, - y: usize, - bg: VgaTextColor, - fg: VgaTextColor, -} - -impl Vga { - pub unsafe fn new(ptr: *mut VgaTextBlock, width: usize, height: usize) -> Self { - Self { - blocks: slice::from_raw_parts_mut( - ptr, - width * height - ), - width, - height, - x: 0, - y: 0, - bg: VgaTextColor::DarkGray, - fg: VgaTextColor::White, - } - } -} - -impl fmt::Write for Vga { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - for c in s.chars() { - if self.x >= self.width { - self.x = 0; - self.y += 1; - } - while self.y >= self.height { - for y in 1..self.height { - for x in 0..self.width { - let i = y * self.width + x; - let j = i - self.width; - self.blocks[j] = self.blocks[i]; - if y + 1 == self.height { - self.blocks[i].char = 0; - } - } - } - self.y -= 1; - } - match c { - '\r' => { - self.x = 0; - }, - '\n' => { - self.x = 0; - self.y += 1; - }, - _ => { - let i = self.y * self.width + self.x; - if let Some(block) = self.blocks.get_mut(i) { - block.char = c as u8; - block.color = - ((self.bg as u8) << 4) | - (self.fg as u8); - } - } - } - self.x += 1; - } - - Ok(()) - } -} - #[no_mangle] pub unsafe extern "C" fn kstart( thunk10: extern "C" fn(), @@ -311,7 +125,12 @@ pub unsafe extern "C" fn kstart( continue; } - modes.push((mode, w, h, format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h))); + modes.push(( + mode, + w, h, + mode_info.physbaseptr, + format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h) + )); } else { writeln!(vga, "Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.ax); } @@ -332,7 +151,7 @@ pub unsafe extern "C" fn kstart( loop { let mut row = 0; let mut col = 0; - for (mode, w, h, text) in modes.iter() { + for (mode, w, h, ptr, text) in modes.iter() { if row >= rows { col += 1; row = 0; diff --git a/src/thunk.rs b/src/thunk.rs new file mode 100644 index 0000000000..4b96fcf518 --- /dev/null +++ b/src/thunk.rs @@ -0,0 +1,45 @@ +use core::ptr; + +use crate::THUNK_STACK_ADDR; + +#[derive(Clone, Copy)] +#[repr(packed)] +pub struct ThunkData { + pub di: u16, + pub si: u16, + pub bp: u16, + sp: u16, + pub bx: u16, + pub dx: u16, + pub cx: u16, + pub ax: u16, +} + +impl ThunkData { + pub fn new() -> Self { + Self { + di: 0, + si: 0, + bp: 0, + sp: THUNK_STACK_ADDR as u16, + bx: 0, + dx: 0, + cx: 0, + ax: 0, + } + } + + pub unsafe fn save(&self) { + ptr::write((THUNK_STACK_ADDR - 16) as *mut ThunkData, *self); + } + + pub unsafe fn load(&mut self) { + *self = ptr::read((THUNK_STACK_ADDR - 16) as *const ThunkData); + } + + pub unsafe fn with(&mut self, f: extern "C" fn()) { + self.save(); + f(); + self.load(); + } +} diff --git a/src/vbe.rs b/src/vbe.rs new file mode 100644 index 0000000000..f396afd040 --- /dev/null +++ b/src/vbe.rs @@ -0,0 +1,54 @@ +#[derive(Clone, Copy, Debug)] +#[repr(packed)] +pub struct VbeCardInfo { + pub signature: [u8; 4], + pub version: u16, + pub oemstring: u32, + pub capabilities: u32, + pub videomodeptr: u32, + pub totalmemory: u16, + pub oemsoftwarerev: u16, + pub oemvendornameptr: u32, + pub oemproductnameptr: u32, + pub oemproductrevptr: u32, + pub reserved: [u8; 222], + pub oemdata: [u8; 256], +} + +#[derive(Clone, Copy, Debug)] +#[repr(packed)] +pub struct VbeModeInfo { + pub attributes: u16, + pub win_a: u8, + pub win_b: u8, + pub granularity: u16, + pub winsize: u16, + pub segment_a: u16, + pub segment_b: u16, + pub winfuncptr: u32, + pub bytesperscanline: u16, + pub xresolution: u16, + pub yresolution: u16, + pub xcharsize: u8, + pub ycharsize: u8, + pub numberofplanes: u8, + pub bitsperpixel: u8, + pub numberofbanks: u8, + pub memorymodel: u8, + pub banksize: u8, + pub numberofimagepages: u8, + pub unused: u8, + pub redmasksize: u8, + pub redfieldposition: u8, + pub greenmasksize: u8, + pub greenfieldposition: u8, + pub bluemasksize: u8, + pub bluefieldposition: u8, + pub rsvdmasksize: u8, + pub rsvdfieldposition: u8, + pub directcolormodeinfo: u8, + pub physbaseptr: u32, + pub offscreenmemoryoffset: u32, + pub offscreenmemsize: u16, + pub reserved: [u8; 206], +} diff --git a/src/vga.rs b/src/vga.rs new file mode 100644 index 0000000000..949ae635bc --- /dev/null +++ b/src/vga.rs @@ -0,0 +1,101 @@ +use core::{fmt, slice}; + +#[derive(Clone, Copy)] +#[repr(packed)] +pub struct VgaTextBlock { + pub char: u8, + pub color: u8, +} + +#[derive(Clone, Copy)] +#[repr(u8)] +pub enum VgaTextColor { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Purple = 5, + Brown = 6, + Gray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + LightPurple = 13, + Yellow = 14, + White = 15, +} + +pub struct Vga { + pub blocks: &'static mut [VgaTextBlock], + pub width: usize, + pub height: usize, + pub x: usize, + pub y: usize, + pub bg: VgaTextColor, + pub fg: VgaTextColor, +} + +impl Vga { + pub unsafe fn new(ptr: *mut VgaTextBlock, width: usize, height: usize) -> Self { + Self { + blocks: slice::from_raw_parts_mut( + ptr, + width * height + ), + width, + height, + x: 0, + y: 0, + bg: VgaTextColor::DarkGray, + fg: VgaTextColor::White, + } + } +} + +impl fmt::Write for Vga { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + for c in s.chars() { + if self.x >= self.width { + self.x = 0; + self.y += 1; + } + while self.y >= self.height { + for y in 1..self.height { + for x in 0..self.width { + let i = y * self.width + x; + let j = i - self.width; + self.blocks[j] = self.blocks[i]; + if y + 1 == self.height { + self.blocks[i].char = 0; + } + } + } + self.y -= 1; + } + match c { + '\r' => { + self.x = 0; + }, + '\n' => { + self.x = 0; + self.y += 1; + }, + _ => { + let i = self.y * self.width + self.x; + if let Some(block) = self.blocks.get_mut(i) { + block.char = c as u8; + block.color = + ((self.bg as u8) << 4) | + (self.fg as u8); + } + } + } + self.x += 1; + } + + Ok(()) + } +}