Refactor into arch and os, remove warnings

This commit is contained in:
Jeremy Soller
2022-02-08 13:17:30 -07:00
parent 2ab9afcbc4
commit 6936228dff
15 changed files with 424 additions and 413 deletions
+2 -2
View File
@@ -21,7 +21,7 @@ endif
clean:
rm -rf build
$(BUILD)/libbootloader.a: Cargo.lock Cargo.toml src/**
$(BUILD)/libbootloader.a: Cargo.lock Cargo.toml $(shell find src -type f)
mkdir -p $(BUILD)
cargo rustc --lib --target $(TARGET) --release -- -C soft-float -C debuginfo=2 --emit link=$@
@@ -31,7 +31,7 @@ $(BUILD)/bootloader.elf: linkers/$(TARGET).ld $(BUILD)/libbootloader.a
$(OBJCOPY) --only-keep-debug $@ $@.sym && \
$(OBJCOPY) --strip-debug $@
$(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf asm/$(TARGET)/**
$(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf $(shell find asm/$(TARGET) -type f)
mkdir -p $(BUILD)
nasm -f bin -o $@ -l $@.lst -D STAGE3=$< -iasm/$(TARGET) asm/$(TARGET)/bootloader.asm
+5
View File
@@ -0,0 +1,5 @@
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::x86_64::*;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86_64;
+4
View File
@@ -0,0 +1,4 @@
pub use self::paging::paging_create;
mod paging;
mod panic;
+3 -3
View File
@@ -1,9 +1,9 @@
use core::alloc::{GlobalAlloc, Layout};
use alloc::alloc;
use core::slice;
unsafe fn paging_allocate() -> Option<&'static mut [u64]> {
let ptr = crate::ALLOCATOR.alloc_zeroed(
Layout::from_size_align(4096, 4096).unwrap()
let ptr = alloc::alloc_zeroed(
alloc::Layout::from_size_align(4096, 4096).unwrap()
);
if ! ptr.is_null() {
Some(slice::from_raw_parts_mut(
+1 -2
View File
@@ -1,7 +1,6 @@
//! Intrinsics for panic handling
use core::alloc::Layout;
use core::fmt::Write;
use core::panic::PanicInfo;
#[lang = "eh_personality"]
@@ -13,7 +12,7 @@ pub extern "C" fn rust_eh_personality() {}
#[no_mangle]
pub extern "C" fn rust_begin_unwind(info: &PanicInfo) -> ! {
unsafe {
let _ = writeln!(crate::VGA.lock(), "BOOTLOADER PANIC:\n{}", info);
println!("BOOTLOADER PANIC:\n{}", info);
loop {
llvm_asm!("hlt" : : : : "intel", "volatile");
}
+2 -389
View File
@@ -6,395 +6,8 @@
#[macro_use]
extern crate alloc;
use alloc::{
string::String,
vec::Vec,
};
use core::{
alloc::{GlobalAlloc, Layout},
cmp,
convert::TryFrom,
fmt::{self, Write},
ptr,
slice,
};
use linked_list_allocator::LockedHeap;
use log::error;
use spin::Mutex;
use self::os::DiskBios;
use self::logger::LOGGER;
use self::memory_map::memory_map;
use self::thunk::ThunkData;
use self::vbe::{VbeCardInfo, VbeModeInfo};
use self::vga::{VgaTextBlock, VgaTextColor, Vga};
#[macro_use]
mod macros;
mod logger;
mod memory_map;
mod os;
mod paging;
mod panic;
mod thunk;
mod vbe;
mod vga;
// Real mode memory allocation, for use with thunk
// 0x500 to 0x7BFF is free
const DISK_BIOS_ADDR: usize = 0x1000; // 4096 bytes, ends at 0x1FFF
const VBE_CARD_INFO_ADDR: usize = 0x2000; // 512 bytes, ends at 0x21FF
const VBE_MODE_INFO_ADDR: usize = 0x2200; // 256 bytes, ends at 0x22FF
const MEMORY_MAP_ADDR: usize = 0x2300; // 24 bytes, ends at 0x2317
const DISK_ADDRESS_PACKET_ADDR: usize = 0x2318; // 16 bytes, ends at 0x2327
const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards
const VGA_ADDR: usize = 0xB8000;
const PHYS_OFFSET: u64 = 0xFFFF800000000000;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
static VGA: Mutex<Vga> = Mutex::new(
unsafe { Vga::new(VGA_ADDR, 80, 25) }
);
#[repr(packed)]
pub struct KernelArgs {
kernel_base: u64,
kernel_size: u64,
stack_base: u64,
stack_size: u64,
env_base: u64,
env_size: u64,
/// The base 64-bit pointer to an array of saved RSDPs. It's up to the kernel (and possibly
/// userspace), to decide which RSDP to use. The buffer will be a linked list containing a
/// 32-bit relative (to this field) next, and the actual struct afterwards.
///
/// This field can be NULL, and if so, the system has not booted with UEFI or in some other way
/// retrieved the RSDPs. The kernel or a userspace driver will thus try searching the BIOS
/// memory instead. On UEFI systems, searching is not guaranteed to actually work though.
acpi_rsdps_base: u64,
/// The size of the RSDPs region.
acpi_rsdps_size: u64,
}
#[no_mangle]
pub unsafe extern "C" fn kstart(
kernel_entry: extern "C" fn(
page_table: usize,
stack: u64,
func: u64,
args: *const KernelArgs,
) -> !,
boot_disk: usize,
thunk10: extern "C" fn(),
thunk13: extern "C" fn(),
thunk15: extern "C" fn(),
thunk16: extern "C" fn(),
) -> ! {
{
// Make sure we are in mode 3 (80x25 text mode)
let mut data = ThunkData::new();
data.eax = 0x03;
data.with(thunk10);
}
{
// Disable cursor
let mut data = ThunkData::new();
data.eax = 0x0100;
data.ecx = 0x3F00;
data.with(thunk10);
}
// Clear screen
VGA.lock().clear();
// Set logger
LOGGER.init();
let (heap_start, heap_size) = memory_map(thunk15)
.expect("No memory for heap");
ALLOCATOR.lock().init(heap_start, heap_size);
// Locate kernel on RedoxFS
let disk = DiskBios::new(u8::try_from(boot_disk).unwrap(), thunk13);
//TODO: get block from partition table
let block = 1024 * 1024 / redoxfs::BLOCK_SIZE;
let mut fs = redoxfs::FileSystem::open(disk, Some(block))
.expect("Failed to open RedoxFS");
print!("RedoxFS ");
for i in 0..fs.header.1.uuid.len() {
if i == 4 || i == 6 || i == 8 || i == 10 {
print!("-");
}
print!("{:>02x}", fs.header.1.uuid[i]);
}
println!(": {} MiB", fs.header.1.size / 1024 / 1024);
let mut modes = Vec::new();
{
// Get card info
let mut data = ThunkData::new();
data.eax = 0x4F00;
data.edi = VBE_CARD_INFO_ADDR as u32;
data.with(thunk10);
if data.eax == 0x004F {
let card_info = ptr::read(VBE_CARD_INFO_ADDR as *const VbeCardInfo);
let mut mode_ptr = card_info.videomodeptr as *const u16;
loop {
// Ask for linear frame buffer with mode
let mode = *mode_ptr | (1 << 14);
if mode == 0xFFFF {
break;
}
mode_ptr = mode_ptr.add(1);
// Get mode info
let mut data = ThunkData::new();
data.eax = 0x4F01;
data.ecx = mode as u32;
data.edi = VBE_MODE_INFO_ADDR as u32;
data.with(thunk10);
if data.eax == 0x004F {
let mode_info = ptr::read(VBE_MODE_INFO_ADDR as *const VbeModeInfo);
// We only support 32-bits per pixel modes
if mode_info.bitsperpixel != 32 {
continue;
}
let w = mode_info.xresolution as u32;
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,
mode_info.physbaseptr,
format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h)
));
} else {
error!("Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.eax);
}
}
} else {
error!("Failed to read VBE card info: 0x{:04X}", data.eax);
}
}
// Sort modes by pixel area, reversed
modes.sort_by(|a, b| (b.1 * b.2).cmp(&(a.1 * a.2)));
println!();
println!("Arrow keys and enter select mode");
println!();
print!(" ");
//TODO 0x4F03 VBE function to get current mode
let off_x = VGA.lock().x;
let off_y = VGA.lock().y;
let rows = 12;
let mut selected = modes.get(0).map_or(0, |x| x.0);
while ! modes.is_empty() {
let mut row = 0;
let mut col = 0;
for (mode, w, h, ptr, text) in modes.iter() {
if row >= rows {
col += 1;
row = 0;
}
VGA.lock().x = off_x + col * 20;
VGA.lock().y = off_y + row;
if *mode == selected {
VGA.lock().bg = VgaTextColor::White;
VGA.lock().fg = VgaTextColor::Black;
} else {
VGA.lock().bg = VgaTextColor::DarkGray;
VGA.lock().fg = VgaTextColor::White;
}
print!("{}", text);
row += 1;
}
// Read keypress
let mut data = ThunkData::new();
data.with(thunk16);
match (data.eax >> 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 */ => {
break;
},
_ => (),
}
}
VGA.lock().x = 0;
VGA.lock().y = off_y + rows;
VGA.lock().bg = VgaTextColor::DarkGray;
VGA.lock().fg = VgaTextColor::White;
println!();
let kernel = {
let node = fs.find_node("kernel", fs.header.1.root)
.expect("Failed to find kernel file");
let size = fs.node_len(node.0)
.expect("Failed to read kernel size");
print!("Kernel: 0/{} MiB", size / 1024 / 1024);
let ptr = ALLOCATOR.alloc_zeroed(
Layout::from_size_align(size as usize, 4096).unwrap()
);
if ptr.is_null() {
panic!("Failed to allocate memory for kernel");
}
let kernel = slice::from_raw_parts_mut(
ptr,
size as usize
);
let mut i = 0;
for chunk in kernel.chunks_mut(1024 * 1024) {
print!("\rKernel: {}/{} MiB", i / 1024 / 1024, size / 1024 / 1024);
i += fs.read_node(node.0, i, chunk, 0, 0)
.expect("Failed to read kernel file") as u64;
}
println!("\rKernel: {}/{} MiB", i / 1024 / 1024, size / 1024 / 1024);
kernel
};
let page_phys = paging::paging_create(kernel.as_ptr() as usize)
.expect("Failed to set up paging");
//TODO: properly reserve page table allocations so kernel does not re-use them
let stack_size = 0x20000;
let stack_base = ALLOCATOR.alloc_zeroed(
Layout::from_size_align(stack_size, 4096).unwrap()
);
if stack_base.is_null() {
panic!("Failed to allocate memory for stack");
}
let mut env = String::with_capacity(4096);
if let Some(mode_i) = modes.iter().position(|x| x.0 == selected) {
if let Some((mode, w, h, ptr, text)) = modes.get(mode_i) {
let mut data = ThunkData::new();
data.eax = 0x4F02;
data.ebx = *mode as u32;
data.with(thunk10);
env.push_str(&format!("FRAMEBUFFER_ADDR={:016x}\n", ptr));
env.push_str(&format!("FRAMEBUFFER_WIDTH={:016x}\n", w));
env.push_str(&format!("FRAMEBUFFER_HEIGHT={:016x}\n", h));
}
}
env.push_str(&format!("REDOXFS_BLOCK={:016x}\n", fs.block));
env.push_str("REDOXFS_UUID=");
for i in 0..fs.header.1.uuid.len() {
if i == 4 || i == 6 || i == 8 || i == 10 {
env.push('-');
}
env.push_str(&format!("{:>02x}", fs.header.1.uuid[i]));
}
let args = KernelArgs {
kernel_base: kernel.as_ptr() as u64,
kernel_size: kernel.len() as u64,
stack_base: stack_base as u64,
stack_size: stack_size as u64,
env_base: env.as_ptr() as u64,
env_size: env.len() as u64,
acpi_rsdps_base: 0,
acpi_rsdps_size: 0,
};
kernel_entry(
page_phys,
args.stack_base + args.stack_size + PHYS_OFFSET,
*(kernel.as_ptr().add(0x18) as *const u64),
&args,
);
}
mod arch;
mod logger;
+2 -3
View File
@@ -1,5 +1,4 @@
use core::fmt::Write;
use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
use log::{LevelFilter, Log, Metadata, Record};
pub static LOGGER: Logger = Logger;
@@ -13,7 +12,7 @@ impl Logger {
}
impl Log for Logger {
fn enabled(&self, metadata: &Metadata) -> bool {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
+3 -2
View File
@@ -2,8 +2,9 @@ use core::{mem, ptr};
use redoxfs::{BLOCK_SIZE, Disk};
use syscall::error::{Error, Result, EIO};
use crate::{DISK_ADDRESS_PACKET_ADDR, DISK_BIOS_ADDR, ThunkData};
use super::{DISK_ADDRESS_PACKET_ADDR, DISK_BIOS_ADDR, ThunkData};
#[allow(dead_code)]
#[derive(Clone, Copy)]
#[repr(packed)]
pub struct DiskAddressPacket {
@@ -55,7 +56,7 @@ impl Disk for DiskBios {
data.with(self.thunk13);
//TODO: return result on error
assert_eq!(data.eax, 0);
assert_eq!({ data.eax }, 0);
//TODO: check blocks transferred
dap = ptr::read(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket);
+1 -1
View File
@@ -3,7 +3,7 @@
macro_rules! print {
($($arg:tt)*) => ({
use core::fmt::Write;
write!($crate::VGA.lock(), $($arg)*).unwrap();
let _ = write!($crate::os::VGA.lock(), $($arg)*);
});
}
@@ -1,6 +1,6 @@
use core::{cmp, mem, ptr};
use crate::thunk::ThunkData;
use super::{MEMORY_MAP_ADDR, thunk::ThunkData};
#[repr(packed)]
struct MemoryMapEntry {
@@ -13,26 +13,24 @@ pub unsafe fn memory_map(thunk15: extern "C" fn()) -> Option<(usize, usize)> {
let mut heap_limits = None;
let mut data = ThunkData::new();
loop {
let index = data.ebx;
data.eax = 0xE820;
data.ecx = mem::size_of::<MemoryMapEntry>() as u32;
data.edx = 0x534D4150;
data.edi = crate::MEMORY_MAP_ADDR as u32;
data.edi = MEMORY_MAP_ADDR as u32;
data.with(thunk15);
assert_eq!(data.eax, 0x534D4150);
assert_eq!(data.ecx, mem::size_of::<MemoryMapEntry>() as u32);
let entry = ptr::read(crate::MEMORY_MAP_ADDR as *const MemoryMapEntry);
assert_eq!({ data.eax }, 0x534D4150);
assert_eq!({ data.ecx }, mem::size_of::<MemoryMapEntry>() as u32);
let entry = ptr::read(MEMORY_MAP_ADDR as *const MemoryMapEntry);
//TODO: There is a problem with QEMU crashing if we write at about 8 MiB, so skip to 16
let heap_start = 16 * 1024 * 1024;
if (
if
entry.kind == 1 &&
entry.base <= heap_start as u64 &&
(entry.base + entry.length) >= heap_start as u64
) {
{
let heap_end = cmp::min(
entry.base + entry.length,
usize::MAX as u64
+389 -1
View File
@@ -1,3 +1,391 @@
pub use self::disk::DiskBios;
use alloc::{
string::String,
vec::Vec,
};
use core::{
alloc::{GlobalAlloc, Layout},
cmp,
convert::TryFrom,
ptr,
slice,
};
use linked_list_allocator::LockedHeap;
use log::error;
use spin::Mutex;
use crate::logger::LOGGER;
use crate::arch::paging_create;
use self::disk::DiskBios;
use self::memory_map::memory_map;
use self::thunk::ThunkData;
use self::vbe::{VbeCardInfo, VbeModeInfo};
use self::vga::{VgaTextColor, Vga};
#[macro_use]
mod macros;
mod disk;
mod memory_map;
mod thunk;
mod vbe;
mod vga;
// Real mode memory allocation, for use with thunk
// 0x500 to 0x7BFF is free
const DISK_BIOS_ADDR: usize = 0x1000; // 4096 bytes, ends at 0x1FFF
const VBE_CARD_INFO_ADDR: usize = 0x2000; // 512 bytes, ends at 0x21FF
const VBE_MODE_INFO_ADDR: usize = 0x2200; // 256 bytes, ends at 0x22FF
const MEMORY_MAP_ADDR: usize = 0x2300; // 24 bytes, ends at 0x2317
const DISK_ADDRESS_PACKET_ADDR: usize = 0x2318; // 16 bytes, ends at 0x2327
const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards
const VGA_ADDR: usize = 0xB8000;
const PHYS_OFFSET: u64 = 0xFFFF800000000000;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
pub(crate) static VGA: Mutex<Vga> = Mutex::new(
unsafe { Vga::new(VGA_ADDR, 80, 25) }
);
#[allow(dead_code)]
#[repr(packed)]
pub struct KernelArgs {
kernel_base: u64,
kernel_size: u64,
stack_base: u64,
stack_size: u64,
env_base: u64,
env_size: u64,
/// The base 64-bit pointer to an array of saved RSDPs. It's up to the kernel (and possibly
/// userspace), to decide which RSDP to use. The buffer will be a linked list containing a
/// 32-bit relative (to this field) next, and the actual struct afterwards.
///
/// This field can be NULL, and if so, the system has not booted with UEFI or in some other way
/// retrieved the RSDPs. The kernel or a userspace driver will thus try searching the BIOS
/// memory instead. On UEFI systems, searching is not guaranteed to actually work though.
acpi_rsdps_base: u64,
/// The size of the RSDPs region.
acpi_rsdps_size: u64,
}
#[no_mangle]
pub unsafe extern "C" fn kstart(
kernel_entry: extern "C" fn(
page_table: usize,
stack: u64,
func: u64,
args: *const KernelArgs,
) -> !,
boot_disk: usize,
thunk10: extern "C" fn(),
thunk13: extern "C" fn(),
thunk15: extern "C" fn(),
thunk16: extern "C" fn(),
) -> ! {
{
// Make sure we are in mode 3 (80x25 text mode)
let mut data = ThunkData::new();
data.eax = 0x03;
data.with(thunk10);
}
{
// Disable cursor
let mut data = ThunkData::new();
data.eax = 0x0100;
data.ecx = 0x3F00;
data.with(thunk10);
}
// Clear screen
VGA.lock().clear();
// Set logger
LOGGER.init();
let (heap_start, heap_size) = memory_map(thunk15)
.expect("No memory for heap");
ALLOCATOR.lock().init(heap_start, heap_size);
// Locate kernel on RedoxFS
let disk = DiskBios::new(u8::try_from(boot_disk).unwrap(), thunk13);
//TODO: get block from partition table
let block = 1024 * 1024 / redoxfs::BLOCK_SIZE;
let mut fs = redoxfs::FileSystem::open(disk, Some(block))
.expect("Failed to open RedoxFS");
print!("RedoxFS ");
for i in 0..fs.header.1.uuid.len() {
if i == 4 || i == 6 || i == 8 || i == 10 {
print!("-");
}
print!("{:>02x}", fs.header.1.uuid[i]);
}
println!(": {} MiB", fs.header.1.size / 1024 / 1024);
let mut modes = Vec::new();
{
// Get card info
let mut data = ThunkData::new();
data.eax = 0x4F00;
data.edi = VBE_CARD_INFO_ADDR as u32;
data.with(thunk10);
if data.eax == 0x004F {
let card_info = ptr::read(VBE_CARD_INFO_ADDR as *const VbeCardInfo);
let mut mode_ptr = card_info.videomodeptr as *const u16;
loop {
// Ask for linear frame buffer with mode
let mode = *mode_ptr | (1 << 14);
if mode == 0xFFFF {
break;
}
mode_ptr = mode_ptr.add(1);
// Get mode info
let mut data = ThunkData::new();
data.eax = 0x4F01;
data.ecx = mode as u32;
data.edi = VBE_MODE_INFO_ADDR as u32;
data.with(thunk10);
if data.eax == 0x004F {
let mode_info = ptr::read(VBE_MODE_INFO_ADDR as *const VbeModeInfo);
// We only support 32-bits per pixel modes
if mode_info.bitsperpixel != 32 {
continue;
}
let w = mode_info.xresolution as u32;
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,
mode_info.physbaseptr,
format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h)
));
} else {
error!("Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, { data.eax });
}
}
} else {
error!("Failed to read VBE card info: 0x{:04X}", { data.eax });
}
}
// Sort modes by pixel area, reversed
modes.sort_by(|a, b| (b.1 * b.2).cmp(&(a.1 * a.2)));
println!();
println!("Arrow keys and enter select mode");
println!();
print!(" ");
//TODO 0x4F03 VBE function to get current mode
let off_x = VGA.lock().x;
let off_y = VGA.lock().y;
let rows = 12;
let mut selected = modes.get(0).map_or(0, |x| x.0);
while ! modes.is_empty() {
let mut row = 0;
let mut col = 0;
for (mode, _w, _h, _ptr, text) in modes.iter() {
if row >= rows {
col += 1;
row = 0;
}
VGA.lock().x = off_x + col * 20;
VGA.lock().y = off_y + row;
if *mode == selected {
VGA.lock().bg = VgaTextColor::White;
VGA.lock().fg = VgaTextColor::Black;
} else {
VGA.lock().bg = VgaTextColor::DarkGray;
VGA.lock().fg = VgaTextColor::White;
}
print!("{}", text);
row += 1;
}
// Read keypress
let mut data = ThunkData::new();
data.with(thunk16);
match (data.eax >> 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 */ => {
break;
},
_ => (),
}
}
VGA.lock().x = 0;
VGA.lock().y = off_y + rows;
VGA.lock().bg = VgaTextColor::DarkGray;
VGA.lock().fg = VgaTextColor::White;
println!();
let kernel = {
let node = fs.find_node("kernel", fs.header.1.root)
.expect("Failed to find kernel file");
let size = fs.node_len(node.0)
.expect("Failed to read kernel size");
print!("Kernel: 0/{} MiB", size / 1024 / 1024);
let ptr = ALLOCATOR.alloc_zeroed(
Layout::from_size_align(size as usize, 4096).unwrap()
);
if ptr.is_null() {
panic!("Failed to allocate memory for kernel");
}
let kernel = slice::from_raw_parts_mut(
ptr,
size as usize
);
let mut i = 0;
for chunk in kernel.chunks_mut(1024 * 1024) {
print!("\rKernel: {}/{} MiB", i / 1024 / 1024, size / 1024 / 1024);
i += fs.read_node(node.0, i, chunk, 0, 0)
.expect("Failed to read kernel file") as u64;
}
println!("\rKernel: {}/{} MiB", i / 1024 / 1024, size / 1024 / 1024);
kernel
};
let page_phys = paging_create(kernel.as_ptr() as usize)
.expect("Failed to set up paging");
//TODO: properly reserve page table allocations so kernel does not re-use them
let stack_size = 0x20000;
let stack_base = ALLOCATOR.alloc_zeroed(
Layout::from_size_align(stack_size, 4096).unwrap()
);
if stack_base.is_null() {
panic!("Failed to allocate memory for stack");
}
let mut env = String::with_capacity(4096);
if let Some(mode_i) = modes.iter().position(|x| x.0 == selected) {
if let Some((mode, w, h, ptr, _text)) = modes.get(mode_i) {
let mut data = ThunkData::new();
data.eax = 0x4F02;
data.ebx = *mode as u32;
data.with(thunk10);
env.push_str(&format!("FRAMEBUFFER_ADDR={:016x}\n", ptr));
env.push_str(&format!("FRAMEBUFFER_WIDTH={:016x}\n", w));
env.push_str(&format!("FRAMEBUFFER_HEIGHT={:016x}\n", h));
}
}
env.push_str(&format!("REDOXFS_BLOCK={:016x}\n", fs.block));
env.push_str("REDOXFS_UUID=");
for i in 0..fs.header.1.uuid.len() {
if i == 4 || i == 6 || i == 8 || i == 10 {
env.push('-');
}
env.push_str(&format!("{:>02x}", fs.header.1.uuid[i]));
}
let args = KernelArgs {
kernel_base: kernel.as_ptr() as u64,
kernel_size: kernel.len() as u64,
stack_base: stack_base as u64,
stack_size: stack_size as u64,
env_base: env.as_ptr() as u64,
env_size: env.len() as u64,
acpi_rsdps_base: 0,
acpi_rsdps_size: 0,
};
kernel_entry(
page_phys,
args.stack_base + args.stack_size + PHYS_OFFSET,
*(kernel.as_ptr().add(0x18) as *const u64),
&args,
);
}
+2 -1
View File
@@ -1,7 +1,8 @@
use core::ptr;
use crate::THUNK_STACK_ADDR;
use super::THUNK_STACK_ADDR;
#[allow(dead_code)]
#[derive(Clone, Copy)]
#[repr(packed)]
pub struct ThunkData {
View File
+1
View File
@@ -7,6 +7,7 @@ pub struct VgaTextBlock {
pub color: u8,
}
#[allow(dead_code)]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum VgaTextColor {
+2
View File
@@ -2,10 +2,12 @@
pub use self::bios::*;
#[cfg(all(target_arch = "x86", target_os = "none"))]
#[macro_use]
mod bios;
#[cfg(target_os = "uefi")]
pub use self::uefi::*;
#[cfg(target_os = "uefi")]
#[macro_use]
mod uefi;