Compare commits
2 Commits
28efc562d5
...
e6b231488d
| Author | SHA1 | Date | |
|---|---|---|---|
| e6b231488d | |||
| a2dfc5c775 |
@@ -1,5 +1,5 @@
|
||||
[build]
|
||||
target = ".cargo/target-i386.json"
|
||||
target = ".cargo/target-protected-i386.json"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core", "compiler_builtins"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ENTRY(start)
|
||||
ENTRY(start_stub)
|
||||
|
||||
SECTIONS {
|
||||
. = 1M;
|
||||
|
||||
@@ -13,11 +13,3 @@ panic = "abort"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[profile.release.package.microloader-mbr]
|
||||
codegen-units = 1
|
||||
opt-level = "z"
|
||||
|
||||
[profile.release.package.microloader-vba]
|
||||
codegen-units = 1
|
||||
opt-level = "z"
|
||||
|
||||
8
Makefile
8
Makefile
@@ -7,9 +7,11 @@ RUST_DEP := Cargo.toml Cargo.lock $(shell find .cargo -type f) $(shell find deps
|
||||
|
||||
KERNELFILE = $(OXIDE_MULTIBOOT)
|
||||
$(KERNELFILE): $(shell find members/oxide -type f) $(RUST_DEP)
|
||||
cargo b -r --target=.cargo/target-protected-i386.json --package oxide
|
||||
cargo b -r --package oxide
|
||||
|
||||
BOOTLOADER ?= grub
|
||||
# Must not contain '/' with current limitations
|
||||
CMDLINE ?=
|
||||
include mk/make_bootloader/$(BOOTLOADER).mk
|
||||
|
||||
.PHONY: clean \
|
||||
@@ -24,6 +26,6 @@ run-bootloader-qemu-nographic: $(OUTIMG)
|
||||
qemu-system-x86_64 -nographic -drive format=raw,file=$(OUTIMG)
|
||||
# one day qemu will support multiboot2
|
||||
run-qemu: $(KERNELFILE)
|
||||
qemu-system-x86_64 -kernel $(KERNELFILE)
|
||||
qemu-system-x86_64 -kernel $(KERNELFILE) -append $(CMDLINE)
|
||||
run-qemu-nographic: $(KERNELFILE)
|
||||
qemu-system-x86_64 -nographic -kernel $(KERNELFILE)
|
||||
qemu-system-x86_64 -nographic -kernel $(KERNELFILE) -append $(CMDLINE)
|
||||
|
||||
@@ -2,6 +2,6 @@ set timeout=2
|
||||
set default=0
|
||||
|
||||
menuentry "OxideOS" {
|
||||
multiboot2 /boot/kernel.bin
|
||||
multiboot2 /boot/kernel.bin $args
|
||||
boot
|
||||
}
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
#![no_main]
|
||||
#![deny(clippy::float_arithmetic)]
|
||||
#![feature(
|
||||
arbitrary_self_types,
|
||||
arbitrary_self_types_pointers,
|
||||
associated_type_defaults,
|
||||
const_convert,
|
||||
const_range,
|
||||
const_trait_impl,
|
||||
const_convert,
|
||||
decl_macro,
|
||||
generic_const_exprs,
|
||||
associated_type_defaults
|
||||
ptr_metadata
|
||||
)]
|
||||
|
||||
/// Triggers a linker failure if this reaches that phase
|
||||
@@ -19,19 +23,22 @@ fn panic(_info: &PanicInfo) -> ! {
|
||||
unsafe { __PANIC_HANDLER_WAS_LINKED__DO_NOT_DEFINE() };
|
||||
}
|
||||
|
||||
use core::{arch::asm, hint::black_box, panic::PanicInfo};
|
||||
use core::{arch::asm, fmt::Write as _, hint::black_box, panic::PanicInfo};
|
||||
|
||||
use crate::vga::{ColorNibble, VgaBuffer, VgaColor};
|
||||
use crate::{
|
||||
multiboot2::bif,
|
||||
vga::{ColorNibble, VgaBuffer, VgaColor},
|
||||
};
|
||||
|
||||
pub mod multiboot2;
|
||||
pub mod start_stub;
|
||||
pub mod vga;
|
||||
|
||||
#[used]
|
||||
#[unsafe(link_section = ".multiboot2_header")]
|
||||
static HEADER: multiboot2::Header = multiboot2::Header::new();
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
fn start() -> ! {
|
||||
extern "C" fn start(boot_info: &bif::FixedPart) -> ! {
|
||||
let mut vga = unsafe { VgaBuffer::<vga::text_modes::VGAText2>::new_uninitialized() };
|
||||
|
||||
vga.write_at(0, 1, b'H');
|
||||
@@ -42,12 +49,53 @@ fn start() -> ! {
|
||||
vt.set_color(VgaColor::new(ColorNibble::BLUE, ColorNibble::GREEN));
|
||||
vt.put_at(10, 5);
|
||||
vt.slide();
|
||||
vt.write(b"testinggg");
|
||||
// loop {
|
||||
// for x in b'a'..b'z' {
|
||||
// vt.write(&[x]);
|
||||
// }
|
||||
vt.print_n(boot_info as *const _ as usize as u32);
|
||||
vt.write(b"testinggg\ntags:\n");
|
||||
|
||||
let tags = bif::TagsIter::new(boot_info);
|
||||
for tag in tags {
|
||||
sleep_short();
|
||||
|
||||
vt.print_n(tag.typ());
|
||||
vt.write(b": ");
|
||||
let Some(tag) = tag.tag() else {
|
||||
vt.write(b"unknown tag\n");
|
||||
continue;
|
||||
};
|
||||
|
||||
// this single line pulls like half of the fmt module which means ~ 7.5KiB of BS
|
||||
let _ = writeln!(&mut vt, "{tag:?}");
|
||||
|
||||
// tbh I prefer these, I need to like, write u8 chars, on the TTY level like I really care
|
||||
// about writting binary, still need to differenciate a slice of u8's and a asciistr,
|
||||
// AsciiChar looks innteresting in std and could make astr = [AsciiChar], the thing I don't
|
||||
// like is that disply is straight up against non-utf8 output, so I'd have to make my own
|
||||
// raw-display?? but then Im going all against rust, no Display or Derive std macros
|
||||
// either...
|
||||
//
|
||||
// match tag {
|
||||
// bif::TagTagged::BootCommandLine(_) => vt.write(b"BootCommandLine\n"),
|
||||
// bif::TagTagged::BasicMemoryInformation(_) => vt.write(b"BasicMemoryInformation\n"),
|
||||
// bif::TagTagged::BIOSBootDevice(_) => vt.write(b"BIOSBootDevice\n"),
|
||||
// bif::TagTagged::Terminate(_) => vt.write(b"Terminate\n"),
|
||||
// bif::TagTagged::BootLoaderName(_) => vt.write(b"BootLoaderName\n"),
|
||||
// bif::TagTagged::ImageLoadBasePhyAddr(_) => vt.write(b"ImageLoadBasePhyAddr\n"),
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Somebody else, body else, body elseeee, e- e- e- elsee
|
||||
//
|
||||
// I don't know what to do, 'cause when you are around then I'm aaaaaalll over youuuu
|
||||
//
|
||||
// I always think about it, I can't play it coooool
|
||||
//
|
||||
// Blazing in your heeeeell, he- he- he- heeeellllll~
|
||||
//
|
||||
}
|
||||
|
||||
for _ in 0..=30 {
|
||||
sleep_short();
|
||||
}
|
||||
|
||||
for _ in 0..=5 {
|
||||
sleep_short();
|
||||
@@ -63,6 +111,7 @@ fn start() -> ! {
|
||||
fn sleep_short() {
|
||||
let mut n = 0_u64;
|
||||
while n < 100_000_000 {
|
||||
#[allow(clippy::unit_arg)]
|
||||
black_box(n += 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,175 @@ impl Default for Header {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum HeaderArchitecture {
|
||||
ProtectedI386 = 0,
|
||||
MIPS32 = 4,
|
||||
}
|
||||
|
||||
pub mod bif {
|
||||
//! # Boot Information Format
|
||||
//!
|
||||
//! <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html>
|
||||
|
||||
use core::ptr;
|
||||
|
||||
pub trait TagType {
|
||||
const ID: u32 = 4;
|
||||
}
|
||||
|
||||
pub mod types {
|
||||
macro tagset($taggedvis:vis $taggedname:ident { $( $typname:ident ($typn:expr) { $($typprop:ident : $typpropty:ty),* $(,)? } ),* $(,)? }) {
|
||||
$(
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct $typname { $(pub $typprop: $typpropty),* }
|
||||
|
||||
impl super::TagType for $typname {
|
||||
const ID: u32 = $typn;
|
||||
}
|
||||
)*
|
||||
|
||||
#[derive(Debug)]
|
||||
$taggedvis enum $taggedname<'a> {
|
||||
$( $typname(&'a $typname) ),*
|
||||
}
|
||||
}
|
||||
|
||||
tagset! { pub TagTagged {
|
||||
|
||||
Terminate(0) {},
|
||||
BootCommandLine(1) {
|
||||
string: [u8],
|
||||
},
|
||||
BootLoaderName(2) {
|
||||
string: [u8],
|
||||
},
|
||||
BasicMemoryInformation(4) {
|
||||
mem_lower: u32,
|
||||
mem_upper: u32,
|
||||
},
|
||||
BIOSBootDevice(5) {
|
||||
biosdev: u32,
|
||||
partition: u32,
|
||||
sub_partition: u32,
|
||||
},
|
||||
ImageLoadBasePhyAddr(21) {
|
||||
load_base_addr: u32,
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
pub use types::TagTagged;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TagHead {
|
||||
typ: u32,
|
||||
size: u32,
|
||||
__end: (),
|
||||
}
|
||||
|
||||
impl TagHead {
|
||||
pub fn typ(&self) -> u32 {
|
||||
self.typ
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u32 {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn aligned8_size(&self) -> u32 {
|
||||
(self.size + 7) & !7
|
||||
}
|
||||
|
||||
/// Gets the reference of the next laying in memory tag, considering this one's size.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Assumes there's a contiguous one in memory.
|
||||
pub unsafe fn next(&self) -> &Self {
|
||||
unsafe { &*ptr::from_ref(self).byte_add(self.aligned8_size() as usize) }
|
||||
}
|
||||
|
||||
pub fn tag<'a>(&self) -> Option<TagTagged<'a>> {
|
||||
let typ = self.typ;
|
||||
let size = self.size;
|
||||
|
||||
let contents_addr = ptr::addr_of!(self.__end).cast::<()>();
|
||||
|
||||
macro typ_match(match $var:ident { $($name:ident)* } fat { $($fatname:ident)* }) {
|
||||
match $var {
|
||||
$(
|
||||
types::$name::ID => Some(TagTagged::$name(unsafe {
|
||||
&*core::ptr::from_raw_parts::<types::$name>(
|
||||
contents_addr,
|
||||
(),
|
||||
)
|
||||
}))
|
||||
),*,
|
||||
$(
|
||||
types::$fatname::ID => Some(TagTagged::$fatname(unsafe {
|
||||
&*core::ptr::from_raw_parts::<types::$fatname>(
|
||||
contents_addr,
|
||||
size as usize - core::mem::size_of::<Self>(),
|
||||
)
|
||||
}))
|
||||
),*,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
typ_match!(match typ {
|
||||
BasicMemoryInformation
|
||||
BIOSBootDevice
|
||||
Terminate
|
||||
ImageLoadBasePhyAddr
|
||||
} fat {
|
||||
BootCommandLine
|
||||
BootLoaderName
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
/// Represents the fixed part of the BIF
|
||||
#[repr(C, align(8))]
|
||||
pub struct FixedPart {
|
||||
pub total_size: u32,
|
||||
_reserved: u32,
|
||||
__end: (),
|
||||
}
|
||||
|
||||
/// Iterator for the tags of a [`FixedPart`]
|
||||
pub struct TagsIter<'a> {
|
||||
rem_size: u32,
|
||||
next_ref: &'a TagHead,
|
||||
}
|
||||
|
||||
impl<'a> TagsIter<'a> {
|
||||
pub fn new(fixed: &FixedPart) -> Self {
|
||||
let rem_size = fixed.total_size - core::mem::size_of::<FixedPart>() as u32;
|
||||
let next_ptr = unsafe { &*core::ptr::addr_of!(fixed.__end).cast() };
|
||||
|
||||
Self {
|
||||
rem_size,
|
||||
next_ref: next_ptr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TagsIter<'a> {
|
||||
type Item = &'a TagHead;
|
||||
|
||||
fn next(&mut self) -> Option<&'a TagHead> {
|
||||
if self.rem_size > 0 {
|
||||
let this_ref = self.next_ref;
|
||||
self.rem_size -= this_ref.aligned8_size();
|
||||
// SAFETY: if there were no tags left we'd reach rem_size and not use this referece
|
||||
// any further
|
||||
self.next_ref = unsafe { this_ref.next() };
|
||||
Some(this_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
members/oxide/src/start_stub.rs
Normal file
16
members/oxide/src/start_stub.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
//! <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html>
|
||||
|
||||
use core::arch::naked_asm;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[unsafe(no_mangle)]
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn start_stub() -> ! {
|
||||
// In cdecl, protected i386, the first argument is passed in the stack
|
||||
|
||||
// Sadly need to call bcs stack expectations, I wanna make a extern natural compiled thing for
|
||||
// this.
|
||||
|
||||
const _: extern "C" fn(&crate::multiboot2::bif::FixedPart) -> ! = crate::start;
|
||||
naked_asm!("push ebx", "call {}", sym crate::start);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ impl<M: TextMode> VgaBuffer<M> {
|
||||
where
|
||||
[[(u8, u8); M::WIDTH as usize]; M::HEIGHT as usize]:,
|
||||
{
|
||||
unsafe { core::mem::transmute(Self::VGA_ADDR) }
|
||||
unsafe { &mut *Self::VGA_ADDR.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
use crate::vga::{ColorNibble, TextMode, VgaBuffer, VgaColor};
|
||||
|
||||
pub struct Writer<M: TextMode> {
|
||||
@@ -20,7 +22,7 @@ where
|
||||
|
||||
pub fn carry(&mut self) {
|
||||
self.pos.0 = 0;
|
||||
if self.pos.1 >= M::HEIGHT {
|
||||
if self.pos.1 + 1 >= M::HEIGHT {
|
||||
self.slide();
|
||||
} else {
|
||||
self.pos.1 += 1;
|
||||
@@ -28,7 +30,7 @@ where
|
||||
}
|
||||
|
||||
pub fn next_cell(&mut self) {
|
||||
if self.pos.0 >= M::WIDTH {
|
||||
if self.pos.0 + 1 >= M::WIDTH {
|
||||
self.carry();
|
||||
} else {
|
||||
self.pos.0 += 1;
|
||||
@@ -52,6 +54,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_n(&mut self, n: u32) {
|
||||
const BASE: u32 = 10;
|
||||
|
||||
if n == 0 {
|
||||
// TODO: print a 0 if no recursion in the future
|
||||
} else {
|
||||
let digit = (n % BASE) as u8;
|
||||
self.print_n(n / 10);
|
||||
self.write(&[b'0' + digit]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: &[u8]) {
|
||||
const BAD_CHAR_COL: VgaColor = VgaColor::new(ColorNibble::WHITE, ColorNibble::RED);
|
||||
|
||||
@@ -94,3 +108,13 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: TextMode> Write for Writer<M>
|
||||
where
|
||||
[[(u8, u8); M::WIDTH as usize]; M::HEIGHT as usize]:,
|
||||
{
|
||||
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||
self.write(s.as_bytes());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@ $(OUTIMG): $(KERNELFILE) $(GRUB_CFG)
|
||||
mkdir -p $(GRUB_DIR)/boot/grub
|
||||
cp $(KERNELFILE) $(GRUB_DIR)/boot/kernel.bin
|
||||
cp $(GRUB_CFG) $(GRUB_DIR)/boot/grub/grub.cfg
|
||||
sed -i 's/$$args/$(CMDLINE)/' $(GRUB_DIR)/boot/grub/grub.cfg
|
||||
grub-mkrescue -o $@ $(GRUB_DIR)
|
||||
|
||||
Reference in New Issue
Block a user