Skip to content
Snippets Groups Projects
Verified Commit 14993ed4 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Add allocator and set mode using VBE

parent 50b42eda
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,42 @@ ...@@ -2,6 +2,42 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "linked_list_allocator"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
dependencies = [
"spinning_top",
]
[[package]]
name = "lock_api"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
[[package]] [[package]]
name = "redox_bootloader" name = "redox_bootloader"
version = "0.1.0" version = "0.1.0"
dependencies = [
"linked_list_allocator",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "spinning_top"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
dependencies = [
"lock_api",
]
...@@ -8,4 +8,6 @@ name = "bootloader" ...@@ -8,4 +8,6 @@ name = "bootloader"
path = "src/lib.rs" path = "src/lib.rs"
crate-type = ["staticlib"] crate-type = ["staticlib"]
[dependencies] [dependencies]
linked_list_allocator = "0.9.0"
...@@ -3,14 +3,23 @@ ...@@ -3,14 +3,23 @@
#![feature(lang_items)] #![feature(lang_items)]
#![feature(llvm_asm)] #![feature(llvm_asm)]
#[macro_use]
extern crate alloc;
use alloc::vec::Vec;
use core::{ use core::{
cmp,
fmt::{self, Write}, fmt::{self, Write},
ptr, ptr,
slice, slice,
}; };
use linked_list_allocator::LockedHeap;
mod panic; mod panic;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(packed)] #[repr(packed)]
pub struct ThunkData { pub struct ThunkData {
...@@ -117,6 +126,7 @@ pub struct VgaTextBlock { ...@@ -117,6 +126,7 @@ pub struct VgaTextBlock {
color: u8, color: u8,
} }
#[derive(Clone, Copy)]
#[repr(u8)] #[repr(u8)]
pub enum VgaTextColor { pub enum VgaTextColor {
Black = 0, Black = 0,
...@@ -143,6 +153,8 @@ pub struct Vga { ...@@ -143,6 +153,8 @@ pub struct Vga {
height: usize, height: usize,
x: usize, x: usize,
y: usize, y: usize,
bg: VgaTextColor,
fg: VgaTextColor,
} }
impl Vga { impl Vga {
...@@ -156,6 +168,8 @@ impl Vga { ...@@ -156,6 +168,8 @@ impl Vga {
height, height,
x: 0, x: 0,
y: 0, y: 0,
bg: VgaTextColor::DarkGray,
fg: VgaTextColor::White,
} }
} }
} }
...@@ -192,6 +206,9 @@ impl fmt::Write for Vga { ...@@ -192,6 +206,9 @@ impl fmt::Write for Vga {
let i = self.y * self.width + self.x; let i = self.y * self.width + self.x;
if let Some(block) = self.blocks.get_mut(i) { if let Some(block) = self.blocks.get_mut(i) {
block.char = c as u8; block.char = c as u8;
block.color =
((self.bg as u8) << 4) |
(self.fg as u8);
} }
} }
} }
...@@ -233,6 +250,15 @@ pub unsafe extern "C" fn kstart( ...@@ -233,6 +250,15 @@ pub unsafe extern "C" fn kstart(
(VgaTextColor::White as u8); (VgaTextColor::White as u8);
} }
// Initialize allocator at the end of stage 3 with a meager 1 MiB
extern "C" {
static mut __end: u8;
}
let heap_start = &__end as *const _ as usize;
let heap_size = 1024 * 1024;
ALLOCATOR.lock().init(heap_start, heap_size);
let mut modes = Vec::new();
{ {
// Get card info // Get card info
let mut data = ThunkData::new(); let mut data = ThunkData::new();
...@@ -242,33 +268,47 @@ pub unsafe extern "C" fn kstart( ...@@ -242,33 +268,47 @@ pub unsafe extern "C" fn kstart(
if data.ax == 0x004F { if data.ax == 0x004F {
let card_info = ptr::read(0x1000 as *const VbeCardInfo); let card_info = ptr::read(0x1000 as *const VbeCardInfo);
let mut modes = card_info.videomodeptr as *const u16; let mut mode_ptr = card_info.videomodeptr as *const u16;
loop { loop {
let mode = *modes; // Ask for linear frame buffer with mode
let mode = *mode_ptr | (1 << 14);
if mode == 0xFFFF { if mode == 0xFFFF {
break; break;
} }
modes = modes.add(1); mode_ptr = mode_ptr.add(1);
// Get mode info // Get mode info
let mut data = ThunkData::new(); let mut data = ThunkData::new();
data.ax = 0x4F01; data.ax = 0x4F01;
// Ask for linear frame buffer with mode data.cx = mode;
data.cx = mode | (1 << 14);
data.di = 0x2000; data.di = 0x2000;
data.with(thunk10); data.with(thunk10);
if data.ax == 0x004F { if data.ax == 0x004F {
let mode_info = ptr::read(0x2000 as *const VbeModeInfo); let mode_info = ptr::read(0x2000 as *const VbeModeInfo);
// We only support 32-bits per pixel modes // We only support 32-bits per pixel modes
if mode_info.bitsperpixel == 32 { if mode_info.bitsperpixel != 32 {
writeln!( continue;
vga, }
"{}x{}",
mode_info.xresolution, let w = mode_info.xresolution as u32;
mode_info.yresolution let h = mode_info.yresolution as u32;
);
let mut aspect_w = w;
let mut aspect_h = h;
for i in 2..cmp::min(aspect_w / 2, aspect_h / 2) {
while aspect_w % i == 0 && aspect_h % i == 0 {
aspect_w /= i;
aspect_h /= i;
}
} }
//TODO: support resolutions that are not perfect multiples of 4
if w % 4 != 0 {
continue;
}
modes.push((mode, w, h, format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h)));
} else { } else {
writeln!(vga, "Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.ax); writeln!(vga, "Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.ax);
} }
...@@ -278,8 +318,39 @@ pub unsafe extern "C" fn kstart( ...@@ -278,8 +318,39 @@ pub unsafe extern "C" fn kstart(
} }
} }
// Sort modes by pixel area, reversed
modes.sort_by(|a, b| (b.1 * b.2).cmp(&(a.1 * a.2)));
writeln!(vga, "Arrow keys and space select mode, enter to continue"); writeln!(vga, "Arrow keys and space select mode, enter to continue");
//TODO 0x4F03 VBE function to get current mode
let rows = 12;
let mut selected = modes.get(0).map_or(0, |x| x.0);
loop { loop {
let mut row = 0;
let mut col = 0;
for (mode, w, h, text) in modes.iter() {
if row >= rows {
col += 1;
row = 0;
}
vga.x = 1 + col * 20;
vga.y = 1 + row;
if *mode == selected {
vga.bg = VgaTextColor::White;
vga.fg = VgaTextColor::Black;
} else {
vga.bg = VgaTextColor::DarkGray;
vga.fg = VgaTextColor::White;
}
write!(vga, "{}", text);
row += 1;
}
// Read keypress // Read keypress
let mut data = ThunkData::new(); let mut data = ThunkData::new();
data.with(thunk16); data.with(thunk16);
...@@ -289,5 +360,67 @@ pub unsafe extern "C" fn kstart( ...@@ -289,5 +360,67 @@ pub unsafe extern "C" fn kstart(
(data.ax as u8) as char, (data.ax as u8) as char,
(data.ax >> 8) as u8 (data.ax >> 8) as u8
); );
match (data.ax >> 8) as u8 {
0x4B /* Left */ => {
if let Some(mut mode_i) = modes.iter().position(|x| x.0 == selected) {
if mode_i < rows {
while mode_i < modes.len() {
mode_i += rows;
}
}
mode_i -= rows;
if let Some(new) = modes.get(mode_i) {
selected = new.0;
}
}
},
0x4D /* Right */ => {
if let Some(mut mode_i) = modes.iter().position(|x| x.0 == selected) {
mode_i += rows;
if mode_i >= modes.len() {
mode_i = mode_i % rows;
}
if let Some(new) = modes.get(mode_i) {
selected = new.0;
}
}
},
0x48 /* Up */ => {
if let Some(mut mode_i) = modes.iter().position(|x| x.0 == selected) {
if mode_i % rows == 0 {
mode_i += rows;
if mode_i > modes.len() {
mode_i = modes.len();
}
}
mode_i -= 1;
if let Some(new) = modes.get(mode_i) {
selected = new.0;
}
}
},
0x50 /* Down */ => {
if let Some(mut mode_i) = modes.iter().position(|x| x.0 == selected) {
mode_i += 1;
if mode_i % rows == 0 {
mode_i -= rows;
}
if mode_i >= modes.len() {
mode_i = mode_i - mode_i % rows;
}
if let Some(new) = modes.get(mode_i) {
selected = new.0;
}
}
},
0x1C /* Enter */ => {
let mut data = ThunkData::new();
data.ax = 0x4F02;
data.bx = selected;
data.with(thunk10);
},
_ => (),
}
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment