Add logging and implement opening RedoxFS
This commit is contained in:
Generated
+12
-1
@@ -98,8 +98,10 @@ name = "redox_bootloader"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"linked_list_allocator",
|
||||
"log",
|
||||
"redox_syscall",
|
||||
"redoxfs",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -114,7 +116,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"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/redoxfs.git?branch=0.5.0#a551f3a0b7ea2b004c62665c2bf4003b49ea7eb6"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"generic-array",
|
||||
@@ -143,6 +145,15 @@ name = "simple_endian"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/michalfita/simple-endian-rs.git?rev=7210f40881d16f7f2e3d8d40f6381fa222843caa#7210f40881d16f7f2e3d8d40f6381fa222843caa"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spinning_top"
|
||||
version = "0.2.4"
|
||||
|
||||
+2
-1
@@ -8,10 +8,11 @@ name = "bootloader"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
linked_list_allocator = "0.9.1"
|
||||
log = "0.4.14"
|
||||
redox_syscall = "0.2.10"
|
||||
spin = "0.9.2"
|
||||
|
||||
[dependencies.redoxfs]
|
||||
git = "https://gitlab.redox-os.org/redox-os/redoxfs.git"
|
||||
|
||||
@@ -26,7 +26,22 @@ build/bootloader.bin: build/bootloader.elf $(ARCH)/**
|
||||
mkdir -p build
|
||||
nasm -f bin -o $@ -l $@.lst -D STAGE3=$< -i$(ARCH) $(ARCH)/bootloader.asm
|
||||
|
||||
build/harddrive.bin: build/bootloader.bin
|
||||
build/filesystem:
|
||||
mkdir -p build
|
||||
rm -f $@.partial
|
||||
mkdir $@.partial
|
||||
fallocate -l 1MiB $@.partial/kernel
|
||||
mv $@.partial $@
|
||||
|
||||
|
||||
build/filesystem.bin: build/filesystem
|
||||
mkdir -p build
|
||||
rm -f $@.partial
|
||||
fallocate -l 255MiB $@.partial
|
||||
redoxfs-ar $@.partial $<
|
||||
mv $@.partial $@
|
||||
|
||||
build/harddrive.bin: build/bootloader.bin build/filesystem.bin
|
||||
mkdir -p build
|
||||
rm -f $@.partial
|
||||
fallocate -l 256MiB $@.partial
|
||||
@@ -34,6 +49,7 @@ build/harddrive.bin: build/bootloader.bin
|
||||
$(PARTED) -s -a minimal $@.partial mkpart primary 1MiB 100%
|
||||
dd if=$< of=$@.partial bs=1 count=446 conv=notrunc
|
||||
dd if=$< of=$@.partial bs=512 skip=1 seek=1 conv=notrunc
|
||||
dd if=build/filesystem.bin of=$@.partial bs=1MiB seek=1 conv=notrunc
|
||||
mv $@.partial $@
|
||||
|
||||
qemu: build/harddrive.bin
|
||||
|
||||
+13
-8
@@ -30,12 +30,13 @@ impl DiskAddressPacket {
|
||||
}
|
||||
|
||||
pub struct DiskBios {
|
||||
boot_disk: u8,
|
||||
thunk13: extern "C" fn(),
|
||||
}
|
||||
|
||||
impl DiskBios {
|
||||
pub fn new(thunk13: extern "C" fn()) -> Self {
|
||||
Self { thunk13 }
|
||||
pub fn new(boot_disk: u8, thunk13: extern "C" fn()) -> Self {
|
||||
Self { boot_disk, thunk13 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +48,7 @@ impl Disk for DiskBios {
|
||||
|
||||
let mut data = ThunkData::new();
|
||||
data.ax = 0x4200;
|
||||
//TODO: get original drive number!
|
||||
data.dx = 0x0080;
|
||||
data.dx = self.boot_disk as u16;
|
||||
data.si = DISK_ADDRESS_PACKET_ADDR as u16;
|
||||
|
||||
data.with(self.thunk13);
|
||||
@@ -66,12 +66,17 @@ impl Disk for DiskBios {
|
||||
}
|
||||
|
||||
unsafe fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
|
||||
//TODO
|
||||
Ok(0)
|
||||
log::error!(
|
||||
"DiskBios::write_at(0x{:X}, 0x{:X}:0x{:X}) not allowed",
|
||||
block,
|
||||
buffer.as_ptr() as usize,
|
||||
buffer.len()
|
||||
);
|
||||
Err(Error::new(EIO))
|
||||
}
|
||||
|
||||
fn size(&mut self) -> Result<u64> {
|
||||
//TODO
|
||||
Ok(0)
|
||||
log::error!("DiskBios::size not implemented");
|
||||
Err(Error::new(EIO))
|
||||
}
|
||||
}
|
||||
|
||||
+57
-17
@@ -14,12 +14,16 @@ use core::{
|
||||
slice,
|
||||
};
|
||||
use linked_list_allocator::LockedHeap;
|
||||
use log::{error, info};
|
||||
|
||||
use self::disk::DiskBios;
|
||||
use self::logger::LOGGER;
|
||||
use self::thunk::ThunkData;
|
||||
use self::vbe::{VbeCardInfo, VbeModeInfo};
|
||||
use self::vga::{VgaTextBlock, VgaTextColor, Vga};
|
||||
|
||||
mod disk;
|
||||
mod logger;
|
||||
mod panic;
|
||||
mod thunk;
|
||||
mod vbe;
|
||||
@@ -37,8 +41,11 @@ const VGA_ADDR: usize = 0xB8000;
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||
|
||||
static mut VGA: Vga = unsafe { Vga::new(VGA_ADDR as *mut VgaTextBlock, 80, 25) };
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn kstart(
|
||||
boot_disk: usize,
|
||||
thunk10: extern "C" fn(),
|
||||
thunk13: extern "C" fn(),
|
||||
thunk15: extern "C" fn(),
|
||||
@@ -59,13 +66,15 @@ pub unsafe extern "C" fn kstart(
|
||||
data.with(thunk10);
|
||||
}
|
||||
|
||||
let mut vga = Vga::new(VGA_ADDR as *mut VgaTextBlock, 80, 25);
|
||||
|
||||
for i in 0..vga.blocks.len() {
|
||||
vga.blocks[i].char = 0;
|
||||
vga.blocks[i].color =
|
||||
((VgaTextColor::DarkGray as u8) << 4) |
|
||||
(VgaTextColor::White as u8);
|
||||
{
|
||||
// Clear VGA console
|
||||
let blocks = VGA.blocks();
|
||||
for i in 0..blocks.len() {
|
||||
blocks[i] = VgaTextBlock {
|
||||
char: 0,
|
||||
color: ((VGA.bg as u8) << 4) | (VGA.fg as u8),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize allocator at the end of stage 3 with a meager 1 MiB
|
||||
@@ -76,6 +85,35 @@ pub unsafe extern "C" fn kstart(
|
||||
let heap_size = 1024 * 1024;
|
||||
ALLOCATOR.lock().init(heap_start, heap_size);
|
||||
|
||||
// Set logger
|
||||
LOGGER.init();
|
||||
|
||||
// Locate RedoxFS
|
||||
{
|
||||
//TODO: ensure boot_disk is 8-bit
|
||||
info!("DISK {:02X}", boot_disk);
|
||||
let disk = DiskBios::new(boot_disk as u8, thunk13);
|
||||
//TODO: get block from partition table
|
||||
let block = 1024 * 1024 / redoxfs::BLOCK_SIZE;
|
||||
match redoxfs::FileSystem::open(disk, Some(block), false) {
|
||||
Ok(mut fs) => {
|
||||
info!("RedoxFS {} MiB", fs.header.size() / 1024 / 1024);
|
||||
|
||||
match fs.tx(|tx| tx.find_node(redoxfs::TreePtr::root(), "kernel")) {
|
||||
Ok(node) => {
|
||||
info!("Kernel {} MiB", node.data().size() / 1024 / 1024);
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Failed to find kernel file: {:?}", err);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Failed to open RedoxFS: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut modes = Vec::new();
|
||||
{
|
||||
// Get card info
|
||||
@@ -133,20 +171,22 @@ pub unsafe extern "C" fn kstart(
|
||||
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);
|
||||
error!("Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.ax);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeln!(vga, "Failed to read VBE card info: 0x{:04X}", data.ax);
|
||||
error!("Failed to read VBE card info: 0x{:04X}", data.ax);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 enter select mode").unwrap();
|
||||
|
||||
//TODO 0x4F03 VBE function to get current mode
|
||||
let off_x = VGA.x;
|
||||
let off_y = VGA.y;
|
||||
let rows = 12;
|
||||
let mut selected = modes.get(0).map_or(0, |x| x.0);
|
||||
loop {
|
||||
@@ -158,18 +198,18 @@ pub unsafe extern "C" fn kstart(
|
||||
row = 0;
|
||||
}
|
||||
|
||||
vga.x = 1 + col * 20;
|
||||
vga.y = 1 + row;
|
||||
VGA.x = off_x + col * 20;
|
||||
VGA.y = off_y + row;
|
||||
|
||||
if *mode == selected {
|
||||
vga.bg = VgaTextColor::White;
|
||||
vga.fg = VgaTextColor::Black;
|
||||
VGA.bg = VgaTextColor::White;
|
||||
VGA.fg = VgaTextColor::Black;
|
||||
} else {
|
||||
vga.bg = VgaTextColor::DarkGray;
|
||||
vga.fg = VgaTextColor::White;
|
||||
VGA.bg = VgaTextColor::DarkGray;
|
||||
VGA.fg = VgaTextColor::White;
|
||||
}
|
||||
|
||||
write!(vga, "{}", text);
|
||||
write!(VGA, "{}", text).unwrap();
|
||||
|
||||
row += 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
use core::fmt::Write;
|
||||
use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
|
||||
|
||||
use crate::VGA;
|
||||
|
||||
pub static LOGGER: Logger = Logger;
|
||||
|
||||
pub struct Logger;
|
||||
|
||||
impl Logger {
|
||||
pub fn init(&'static self) {
|
||||
log::set_logger(self).unwrap();
|
||||
log::set_max_level(LevelFilter::Info);
|
||||
}
|
||||
}
|
||||
|
||||
impl Log for Logger {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
unsafe {
|
||||
writeln!(VGA, "{} - {}", record.level(), record.args()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
+15
-10
@@ -29,7 +29,7 @@ pub enum VgaTextColor {
|
||||
}
|
||||
|
||||
pub struct Vga {
|
||||
pub blocks: &'static mut [VgaTextBlock],
|
||||
pub ptr: *mut VgaTextBlock,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub x: usize,
|
||||
@@ -39,12 +39,9 @@ pub struct Vga {
|
||||
}
|
||||
|
||||
impl Vga {
|
||||
pub unsafe fn new(ptr: *mut VgaTextBlock, width: usize, height: usize) -> Self {
|
||||
pub const unsafe fn new(ptr: *mut VgaTextBlock, width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
blocks: slice::from_raw_parts_mut(
|
||||
ptr,
|
||||
width * height
|
||||
),
|
||||
ptr,
|
||||
width,
|
||||
height,
|
||||
x: 0,
|
||||
@@ -53,10 +50,18 @@ impl Vga {
|
||||
fg: VgaTextColor::White,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn blocks(&mut self) -> &'static mut [VgaTextBlock] {
|
||||
slice::from_raw_parts_mut(
|
||||
self.ptr,
|
||||
self.width * self.height,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for Vga {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
|
||||
let mut blocks = unsafe { self.blocks() };
|
||||
for c in s.chars() {
|
||||
if self.x >= self.width {
|
||||
self.x = 0;
|
||||
@@ -67,9 +72,9 @@ impl fmt::Write for Vga {
|
||||
for x in 0..self.width {
|
||||
let i = y * self.width + x;
|
||||
let j = i - self.width;
|
||||
self.blocks[j] = self.blocks[i];
|
||||
blocks[j] = blocks[i];
|
||||
if y + 1 == self.height {
|
||||
self.blocks[i].char = 0;
|
||||
blocks[i].char = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,15 +90,15 @@ impl fmt::Write for Vga {
|
||||
},
|
||||
_ => {
|
||||
let i = self.y * self.width + self.x;
|
||||
if let Some(block) = self.blocks.get_mut(i) {
|
||||
if let Some(block) = blocks.get_mut(i) {
|
||||
block.char = c as u8;
|
||||
block.color =
|
||||
((self.bg as u8) << 4) |
|
||||
(self.fg as u8);
|
||||
}
|
||||
self.x += 1;
|
||||
}
|
||||
}
|
||||
self.x += 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -130,6 +130,9 @@ protected_mode:
|
||||
push eax
|
||||
mov eax, thunk.int10
|
||||
push eax
|
||||
xor eax, eax
|
||||
mov al, [disk]
|
||||
push eax
|
||||
mov eax, [args.stage3_base]
|
||||
call [eax + 0x18]
|
||||
.halt:
|
||||
|
||||
Reference in New Issue
Block a user