saving this just in case i give up

This commit is contained in:
Husky Susbaka 2023-03-13 15:31:06 -07:00
parent 83180d098b
commit 882b6898f3
No known key found for this signature in database
GPG key ID: 6B3D8CB511646891
15 changed files with 779 additions and 112 deletions

View file

@ -6,12 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ieee1275 = { git = "https://github.com/floppydiskette/ieee1275-rs", features = ["no_panic_handler"] }
ieee1275 = { git = "https://github.com/floppydiskette/ieee1275-rs", features = ["no_panic_handler", "no_global_allocator"] }
builddate = { path = "../builddate" }
[profile.dev]
panic = "abort"
strip = true
[profile.release]
panic = "abort"

View file

@ -1,17 +1,22 @@
arch ?= ppc32
target ?= powerpc-unknown-linux-gnu
kernel ?= target/$(target)/release/vap
build_type ?= release
kernel ?= target/$(target)/$(build_type)/vap
linker_script := assembly/$(arch)/linker.ld
KERNEL_FLAGS ?= -Zbuild-std=core,alloc
final = build/$(target)/release/vap
final = build/$(target)/$(build_type)/vap
ifeq "$(arch)" "ppc32"
target := powerpc-unknown-linux-gnu
kernel := target/$(target)/release/vap
kernel := target/$(target)/$(build_type)/vap
linker_script := assembly/$(arch)/linker.ld
KERNEL_FLAGS :=
endif
ifeq "$(build_type)" "release"
KERNEL_FLAGS += --release
endif
.PHONY: all clean quick_invalidate
all: $(final)
@ -31,4 +36,4 @@ $(final): $(kernel)
@cp $(kernel) $(final)
$(kernel):
@RUST_TARGET_PATH="$(shell pwd)" VAP_ARCH="$(arch)" cross +nightly build --release --target $(target) $(KERNEL_FLAGS)
@RUST_TARGET_PATH="$(shell pwd)" VAP_ARCH="$(arch)" cross +nightly build --target $(target) $(KERNEL_FLAGS)

View file

@ -199,6 +199,7 @@
// _decrementer_exception_wrapper
// called when the decrementer exception occurs (i.e. when it reaches 0)
.org ABSOLUTE(0x900)
.global _decrementer_exception_wrapper
_decrementer_exception_wrapper:
rfi
CTX_SAVE

314
assembly/ppc32/get_real.S Normal file
View file

@ -0,0 +1,314 @@
.section .text
// oh how much more powerpc assembly must i write. woe is me
// BAT stuff is completely ripped from helenos
.macro BAT_COMPUTE base size mask lower upper
// less than 128 KB -> no BAT
lis \upper, 0x0002
cmpw \size, \upper
blt no_bat
// mask = total >> 18
li \upper, 18
srw \mask, \size, \upper
// create Block Length mask by replicating
// the leading logical one 14 times
li \upper, 14
mtctr \mask
li \upper, 1
0:
// mask = (mask >> 1) | mask
srw \lower, \mask, \upper
or \mask, \mask, \lower
bdnz 0b
// mask = mask & 0x07ff
// (BAT can map up to 256 MB)
andi. \mask, \mask, 0x07ff
// mask = (mask << 2) | 0x0002
// (priviledged access only)
li \upper, 2
slw \mask, \mask, \upper
ori \mask, \mask, 0x0002
lis \upper, (0x8000 + \base)
or \upper, \upper, \mask
lis \lower, \base
ori \lower, \lower, 0x0002
.endm
.global get_real
get_real:
// r3 = address of the function to call once we're in real mode (physical address)
// r4 = kernel base address (physical address)
// r5 = kernel size
// r6 = final address (physical address)
// r7 translate table (physical address)
// r8 = memory size (physical address)
// r9 = pages to translate
// get msr value
mfmsr 31
// disable interrupts
rlwinm 31,31,0,17,15
// set msr
mtmsr 31
// move r3 into srr0 (so we can jump to it with the rfi instruction)
mtsrr0 3
// set srr1 to the pending msr value we want for real mode
mfmsr 31
lis 30, ~0@h
// "interrupts, instruction relocation, and data relocation"
ori 30, 30, ~((1<<15) | (1<<5) | (1<<4))@l
and 31, 31, 30
mtsrr1 31
// WE'RE GETTING REAL
sync
isync
rfi
#define PAGE_WIDTH 12
#define PAGE_SIZE (1 << PAGE_WIDTH)
.global get_fake
get_fake:
// we want parameters in the format of
// memory_size, translate_table, pages_to_translate, kernel_fake_address, kernel_real_address
// so lets move them into the right registers
mr 31, 4
mr 3, 8
mr 4, 7
mr 5, 9
mr 6, 6
mr 7, 31
// r3 = memory size, r4 = translate table, r5 = pages to translate, r6 = where we jump after finishing
li 31, PAGE_SIZE >> 2 // number of words to copy per page
mr 30, 7 // 30 = beginning of kernel (physical address), we want to copy it to the beginning of the kernel (virtual address)
page_copy:
cmpwi 5, 0 // are pages = 0?
beq page_copy_done
mtctr 31 // load counter with number of words to copy
lwz 29, 0(4) // 29 = address of this page as a physical address
page_copy_loop:
lwz 28, 0(29) // load word from physical address
stw 28, 0(30) // store word to virtual address
dcbst 0, 30 // sync
sync
icbi 0, 30
sync
isync
addi 29, 29, 4 // add 4 to physical address
addi 30, 30, 4 // add 4 to virtual address
bdnz page_copy_loop
// move to next translate table entry
addi 4, 4, 4 // most confusing assembly language award goes to...
subi 5, 5, 1
b page_copy
page_copy_done:
// infinite loop for debugging
debug_loop:
b debug_loop
// fill segment registers
li 31, 0
li 29, 8
mtctr 29
li 30, 0
seg_fill_unpriv:
mtsrin 30, 31
addi 30, 30, 1
addis 31, 31, 0x1000
bdnz seg_fill_unpriv
li 29, 8
mtctr 29
lis 30, 0x4000
ori 30, 30, 8
seg_fill_priv:
mtsrin 30, 31
addi 30, 30, 1
addis 31, 31, 0x1000
bdnz seg_fill_priv
// invalidate bat registers
li 31, 0
mtspr 528, 31
mtspr 529, 31
mtspr 530, 31
mtspr 531, 31
mtspr 532, 31
mtspr 533, 31
mtspr 534, 31
mtspr 535, 31
mtspr 536, 31
mtspr 537, 31
mtspr 538, 31
mtspr 539, 31
mtspr 540, 31
mtspr 541, 31
mtspr 542, 31
mtspr 543, 31
// set up page hash table
lis 31, 65536@h
ori 31, 31, 65536@l
subi 29, 31, 1
sub 30, 3, 31
andc 31, 31, 29
mtsdr1 30
li 29, 2
srw 31, 31, 29
li 29, 0
pht_clear:
stw 29, 0(30)
dcbst 0, 30
sync
isync
addi 30, 30, 4
subi 31, 31, 4
cmpwi 31, 0
beq pht_clear_done
bdnz pht_clear
pht_clear_done:
mr 31, 3
lis 30, 268435456@h
ori 30, 30, 268435456@l // 256MiB
// bat 0
cmpw 31, 30
blt bat0_31
mr 29, 30
b bat0_30
bat0_31:
mr 29, 31
bat0_30:
BAT_COMPUTE 0x0000 29 28 27 26
mtspr 528, 26
mtspr 529, 27
mtspr 536, 26
mtspr 537, 27
// BAT1
sub 31, 31, 29
cmpw 31, 30
blt bat1_r31
mr 29, 30
b bat1_r30
bat1_r31:
mr 29, 31
bat1_r30:
BAT_COMPUTE 0x1000 29 28 27 26
mtspr 530, 26
mtspr 531, 27
mtspr 538, 26
mtspr 539, 27
// BAT2
sub 31, 31, 29
cmpw 31, 30
blt bat2_r31
mr 29, 30
b bat2_r30
bat2_r31:
mr 29, 31
bat2_r30:
BAT_COMPUTE 0x2000 29 28 27 26
mtspr 532, 26
mtspr 533, 27
mtspr 540, 26
mtspr 541, 27
// BAT3
sub 31, 31, 29
cmpw 31, 30
blt bat3_r31
mr 29, 30
b bat3_r30
bat3_r31:
mr 29, 31
bat3_r30:
BAT_COMPUTE 0x3000 29 28 27 26
mtspr 534, 26
mtspr 535, 27
mtspr 542, 26
mtspr 543, 27
no_bat:
// flush tlb
li 31, 0
sync
eieio
tlbsync
sync
// jump to the final function!
mtsrr0 6
li 1, 0 // stack pointer
mfmsr 31
ori 31, 31, ((1<<5) | (1<<4))@l
mtsrr1 31
sync
isync
rfi

View file

@ -1,17 +1,30 @@
OUTPUT_FORMAT("elf32-powerpc")
OUTPUT_ARCH("powerpc:common")
ENTRY(ppc_entry)
ENTRY(_start)
SECTIONS {
/*.vector_table (SIZEOF_HEADERS): AT (SIZEOF_HEADERS) {
. = ALIGN(0x100);
*(V_TEXT_GENESIS);
}*/
. = 0x10000000;
.text : {
*(.text .text.*)
}
.program_code 0x10008000 : {
*(*);
}
.rodata : {
*(.rodata .rodata.*)
}
.data : {
*(.data .data.*)
}
.bss : {
*(COMMON)
*(.bss .bss.*)
}
.other : {
*(*)
}
VAP_KERN_END = .;
}

View file

@ -5,6 +5,7 @@ fn main() {
let mut cc_build = cc::Build::new();
let cc_build = cc_build
.file(format!("assembly/{}/get_real.S", arch))
.file(format!("assembly/{}/pls_stabilise_inline_ppc_asm.S", arch))
.file(format!("assembly/{}/exception.S", arch));
@ -22,8 +23,8 @@ fn main() {
cc_build.compile("vap_asm");
// link to the assembly file
//println!("cargo:rustc-link-lib=static=vap_asm");
println!("cargo:rustc-link-lib=static=vap_asm");
// specify the linker.ld script
//println!("cargo:rustc-link-arg=-Tassembly/{}/linker.ld", arch);
println!("cargo:rustc-link-arg=-Tassembly/{}/linker.ld", arch);
}

172
src/bootstrap.rs Normal file
View file

@ -0,0 +1,172 @@
use core::alloc::Layout;
use core::arch::asm;
use ieee1275::IHandle;
use ieee1275::services::{Args, CallMethodArgs};
use crate::{debug, kernel_main, ofhelpers};
use crate::prom::PROMHNDL;
/// when our program first starts up, we will be in the openfirmware virtual address space.
/// the purpose of this module (in combination with `get_real.S`) is to switch to our own
/// virtual address space, which will give the kernel access to the physical memory.
///
/// it is incredibly important that we do not allocate any memory before we switch to our
/// own virtual address space. this is because rust will think that an allocator
/// exists, when in reality it does not. this will cause a panic when we try to allocate
/// memory. and because our panic function requires memory allocation, we will lock up the
/// system.
extern "C" {
//fn get_real(call_once_real: usize, kernel_base_addr: usize, kernel_size: usize, kernel_fake_address: usize, translate_table: usize, memory_size: usize, pages: usize);
//fn get_fake(memory_size: usize, translate_table: usize, pages: usize, kernel_fake_address: usize);
// the following aren't functions, but rather pointers to the locations
// unfortunately, rust doesn't let me define extern variables, so i have to
// define these as functions
fn VAP_KERN_END();
}
pub fn bootstrap() {
let base_addr = get_kernel_base_addr();
debug!("kernel base address: {:#x}", base_addr);
let size = get_kernel_size();
debug!("kernel size: {:#x}", size);
let true_real_function = translate_to_phys(get_fake as usize);
debug!("real function (translated): {:#x}", true_real_function);
let true_base_addr = translate_to_phys(base_addr);
debug!("kernel base address (translated): {:#x}", true_base_addr);
let (translate_table, pages) = create_translate_table(base_addr);
debug!("translate table created with {} pages", pages);
let kernel_main_fake = final_function_translated();
let real_translate_table = translate_to_phys(translate_table);
let memory_size = get_mem_size();
debug!("final function: {:#x}", kernel_main_fake);
debug!("memory size: {}MiB", memory_size / 1024 / 1024);
// add base_addr to get_real
//let get_real = get_real as usize + base_addr;
//let get_real = get_real as *const fn(usize, usize, usize, usize, usize, usize, usize);
debug!("get_real: {:#x}", get_real as usize);
unsafe {
(get_real)(true_real_function, true_base_addr, size, kernel_main_fake, real_translate_table, memory_size, pages);
}
debug!("oops! we should never get here!");
}
#[no_mangle]
pub extern "C" fn final_function() -> ! {
// now, we can jump to the kernel entry point
kernel_main();
// we should never get here
loop {}
}
fn translate_to_phys(addr: usize) -> usize {
let prom = unsafe { &mut PROMHNDL };
let chosen = prom.get().find_device("/chosen\0").unwrap();
let mut mmu: *const IHandle = core::ptr::null_mut();
prom.get().get_property(chosen, "mmu\0", &mut mmu as *mut *const IHandle, core::mem::size_of::<*const IHandle>()).unwrap();
#[repr(C)]
struct TranslateArgs {
args: Args,
slots: [u32; 16],
}
let mut args = TranslateArgs {
args: Args {
service: "call-method\0".as_ptr(),
nargs: 4,
nret: 5,
},
slots: [0; 16],
};
args.slots[0] = "translate\0".as_ptr() as u32; // takes 4 args, returns 5
args.slots[1] = mmu as u32;
args.slots[2] = 1;
args.slots[3] = addr as u32;
match (prom.get().entry_fn)(&mut args.args as *mut Args) {
0 => (),
e => panic!("failed to translate virtual address {:x}: {}", addr, e),
}
if args.slots[4 + 0] != 0 {
panic!("failed to translate virtual address {:x}: {}", addr, args.slots[1]);
}
//debug!("translated {:x} to {:?}", addr, args.slots);
args.slots[4 + 2] as usize
}
fn get_kernel_base_addr() -> usize {
//let mut load_base = 0u32;
//let res = ofhelpers::of_singlevar_get("load-base\0", &mut load_base).unwrap();
//res[2] as usize
unsafe { VAP_KERN_START as usize }
}
fn get_kernel_size() -> usize {
//let kern_base = get_kernel_base_addr();
let kern_end = unsafe { VAP_KERN_END as usize };
//kern_end - kern_base
kern_end
}
pub fn ofw_alloc(layout: Layout) -> *mut u8 {
let prom = unsafe { &mut PROMHNDL };
match prom.get().claim(layout.size(), layout.align()) {
Ok(addr) => addr,
Err(e) => panic!("failed to allocate memory: {}", e),
}
}
pub fn ofw_free(ptr: *mut u8, layout: Layout) {
let prom = unsafe { &mut PROMHNDL };
prom.get().release(ptr, layout.size());
}
fn align_up(addr: usize, align: usize) -> usize {
(addr + align - 1) & !(align - 1)
}
// translate table addr, pages
// format:
// let i be the page number of some page of the kernel's virtual address space
// table[i] = phys addr of page i
fn create_translate_table(kern_base: usize) -> (usize, usize) {
const PAGE_WIDTH: usize = 12;
const PAGE_SIZE: usize = 1 << PAGE_WIDTH;
let pages = (align_up(get_kernel_size(), PAGE_SIZE)) >> PAGE_WIDTH;
debug!("creating translate table with {} pages", pages);
let mut table = ofw_alloc(Layout::from_size_align(pages * 4, 4).unwrap()) as *mut u32;
for i in 0..pages {
let addr = kern_base + (i << PAGE_WIDTH);
let phys = translate_to_phys(addr);
unsafe {
*table = phys as u32;
table = table.add(1);
}
//debug!("page {} (virt: {:#x}, phys: {:#x})", i, addr, phys);
}
(table as usize, pages)
}
fn final_function_translated() -> usize {
let kernel_entry = final_function as usize;
//let kernel_entry = translate_to_phys(kernel_entry);
kernel_entry
}
fn get_mem_size() -> usize {
let prom = unsafe { &mut PROMHNDL };
let memory = prom.get().find_device("/memory\0").unwrap(); // todo: check if this is standard
let mut reg = [0u32; 2];
prom.get().get_property(memory, "reg\0", &mut reg as *mut [u32; 2] as *mut u32, core::mem::size_of::<[u32; 2]>()).unwrap();
reg[1] as usize
}

View file

@ -2,27 +2,41 @@ use core::arch::asm;
use core::sync::atomic::{AtomicU32};
use crate::{kernel_callback, println};
//pub static DECREMENTER_VAL: AtomicU32 = AtomicU32::new(100000000);
pub static DECREMENTER_VAL: AtomicU32 = AtomicU32::new(100000);
//extern {
//fn reset_decrementer(val: u32);
//}
extern {
fn _decrementer_exception_wrapper();
}
//#[no_mangle]
//pub extern "C" fn _decrementer_exception_fn() {
// //println!("decrementer exception");
// unsafe {
// //reset_decrementer(DECREMENTER_VAL.load(core::sync::atomic::Ordering::Relaxed));
// }
//}
#[no_mangle]
pub extern "C" fn _decrementer_exception_fn() {
println!("decrementer exception");
unsafe {
asm!("mtdec {}", in(reg) DECREMENTER_VAL.load(core::sync::atomic::Ordering::Relaxed));
}
}
pub fn init_decrementer() {
let ptr = _decrementer_exception_wrapper as *const u32;
unsafe {
//reset_decrementer(DECREMENTER_VAL.load(core::sync::atomic::Ordering::Relaxed));
//asm!("mtspr 22, {}", in(reg) ptr);
asm!("mtdec {}", in(reg) DECREMENTER_VAL.load(core::sync::atomic::Ordering::Relaxed));
// asm!("mtspr 9, {}", in(reg) 0x8000_0000u32);
}
println!("decrementer initialized");
let val = unsafe {
let mut val: u32;
asm!("mfdec {}", out(reg) val);
val
};
println!("decrementer value: {}", val);
println!("decrementer initialised");
}
pub fn what_is_decrementer() {
println!("decrementer value: fuckyou");
}
let val = unsafe {
let mut val: u32;
asm!("mfdec {}", out(reg) val);
val
};
println!("decrementer value: {}", val);
}

View file

@ -1 +1,73 @@
pub mod decrementer;
use core::arch::asm;
use ieee1275::services::Args;
use crate::prom::PROMHNDL;
extern {
fn _decrementer_exception_wrapper();
}
pub mod decrementer;
pub fn init_exceptions() {
// okay so this is a very hacky way to do this, but i like the idea of having all kernel
// functionality within one binary.
// so the decrementer exception is at the physical address 0x900, but we only have access
// to virtual addresses. so we need to map the physical address to a virtual address.
// then, we copy the exception handler to the virtual address.
// this way, we can use interrupts from openfirmware!
let prom = unsafe { &mut PROMHNDL };
let prom = prom.get();
// use the "map" service to map the physical address to a virtual address
// here, we will map the physical address 0x900 to the virtual address 0x900
#[repr(C)]
struct MapArgs {
args: Args,
phys_lo: u32,
phys_hi: u32,
virt: u32,
size: u32,
mode: u32,
}
let mut map_args = MapArgs {
args: Args {
service: "map\0".as_ptr(),
nargs: 3,
nret: 2,
},
phys_lo: 0x900,
phys_hi: 0,
virt: 0xF0000000,
size: 0x1000,
mode: 0,
};
match (prom.entry_fn)(&mut map_args.args as *mut Args) {
0 => (),
e => panic!("failed to map physical address 0x900 to virtual address 0xF0000000: {}", e),
}
// now, we need to copy the decrementer exception handler to the virtual address 0x900
// we can probably just get away with memcpying the bytes from _decrementer_exception_wrapper
// + 1000
let mut ptr = _decrementer_exception_wrapper as usize;
let mut dest = 0x900 as *mut u8;
unsafe {
let bytes = ptr.to_be_bytes();
for i in 0..4 {
*dest.add(i) = bytes[i];
}
}
// now, we can initialize the decrementer exception
decrementer::init_decrementer();
enable_the_interrupts_we_use();
}
pub fn enable_the_interrupts_we_use() {
unsafe {
// we only use the decrementer exception, so we only need to enable that
asm!("mtmsr {}", in(reg) 0x8000_0000u32);
// enable exceptions
asm!("wrteei 1");
}
}

View file

@ -20,24 +20,32 @@ macro_rules! debug {
pub static USE_RAW: AtomicBool = AtomicBool::new(true);
use core::fmt::Write;
struct OFPrinter;
impl Write for OFPrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
let _ = unsafe { &mut PROMHNDL }.get().write_stdout(s);
Ok(())
}
}
struct TerminalPrinter;
impl Write for TerminalPrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
terminal::queue_str(s);
Ok(())
}
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
#[cfg(target_arch = "powerpc")]
{
use core::fmt::Write;
struct OFPrinter;
impl Write for OFPrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
let _ = unsafe { &mut PROMHNDL }.get().write_stdout(s);
Ok(())
}
}
match USE_RAW.load(core::sync::atomic::Ordering::Relaxed) {
true => {
OFPrinter.write_fmt(args).unwrap();
},
false => {
terminal::queue_str(&format!("{}", args));
TerminalPrinter.write_fmt(args).unwrap();
}
}
}
@ -47,14 +55,6 @@ pub fn _print(args: fmt::Arguments) {
pub fn _debug(args: fmt::Arguments) {
#[cfg(target_arch = "powerpc")]
{
use core::fmt::Write;
struct OFPrinter;
impl Write for OFPrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
let _ = unsafe { &mut PROMHNDL }.get().write_stdout(s);
Ok(())
}
}
match USE_RAW.load(core::sync::atomic::Ordering::Relaxed) {
true => {
OFPrinter.write_str("[debug] ").unwrap();
@ -62,7 +62,9 @@ pub fn _debug(args: fmt::Arguments) {
OFPrinter.write_str("\r\n").unwrap();
},
false => {
terminal::queue_str(&format!("[debug] {}\r\n", args));
TerminalPrinter.write_str("[debug] ").unwrap();
TerminalPrinter.write_fmt(args).unwrap();
TerminalPrinter.write_str("\r\n").unwrap();
}
}
}

View file

@ -1,6 +1,7 @@
#![feature(panic_info_message)]
#![feature(alloc_error_handler)]
#![feature(lang_items)]
#![feature(asm_experimental_arch)]
#![no_std]
#![no_main]
@ -19,6 +20,8 @@ mod windows;
mod window_optimised_linked_list;
mod exceptions;
mod message_queue;
mod bootstrap;
mod memory;
extern crate alloc;
@ -32,46 +35,69 @@ fn panic_wrapper(info: &PanicInfo) -> ! {
panic(info)
}
pub static PANIC_LEVEL: AtomicU8 = AtomicU8::new(0);
fn panic(info: &PanicInfo) -> ! {
macros::USE_RAW.store(true, core::sync::atomic::Ordering::Relaxed);
//println!("---KERNEL FUCKY WUKKY UWU (panic)---");
//if let Some(s) = info.payload().downcast_ref::<&str>() {
// println!("panic payload: {s:?}")
//} else {
// println!("no panic payload")
//};
//if let Some(msg) = info.message() {
// println!("panic msg: {}", msg)
//} else {
// println!("no message");
//}
//if let Some(location) = info.location() {
// println!("location: file {} line {}", location.file(), location.line());
//} else {
// println!("no location");
//};
let fb_size = OFFramebuffer::fb_size();
OFFramebuffer::rectangle(COMMUNISM_RED, 0, 0, fb_size.0, fb_size.1);
let mut y = 0;
OFFramebuffer::put_string(0,y, "---KERNEL FUCKY WUKKY UWU (panic)---", VAPOREON_BLACK);
y += 16;
if let Some(s) = info.payload().downcast_ref::<&str>() {
OFFramebuffer::put_string(0,y, &format!("panic payload: {s:?}"), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0,y, "no panic payload", VAPOREON_BLACK);
};
y += 16;
if let Some(msg) = info.message() {
OFFramebuffer::put_string(0,y, &format!("panic msg: {}", msg), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0,y, "no message", VAPOREON_BLACK);
};
y += 16;
if let Some(location) = info.location() {
OFFramebuffer::put_string(0,y, &format!("location: file {} line {}", location.file(), location.line()), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0,y, "no location", VAPOREON_BLACK);
};
match PANIC_LEVEL.load(Ordering::Relaxed) {
0 => {
use core::fmt::{Write, Result};
struct OFPrinter;
impl Write for OFPrinter {
fn write_str(&mut self, s: &str) -> Result {
let _ = unsafe { &mut PROMHNDL }.get().write_stdout(s);
Ok(())
}
}
let _ = unsafe { &mut PROMHNDL }.get().write_stdout("panic: ");
if let Some(msg) = info.message() {
OFPrinter.write_fmt(format_args!("{}", msg)).unwrap();
}
if let Some(location) = info.location() {
OFPrinter.write_fmt(format_args!("locationg: file {} line {}", location.file(), location.line())).unwrap();
}
}
_ => {
//println!("---KERNEL FUCKY WUKKY UWU (panic)---");
//if let Some(s) = info.payload().downcast_ref::<&str>() {
// println!("panic payload: {s:?}")
//} else {
// println!("no panic payload")
//};
//if let Some(msg) = info.message() {
// println!("panic msg: {}", msg)
//} else {
// println!("no message");
//}
//if let Some(location) = info.location() {
// println!("location: file {} line {}", location.file(), location.line());
//} else {
// println!("no location");
//};
let fb_size = OFFramebuffer::fb_size();
OFFramebuffer::rectangle(COMMUNISM_RED, 0, 0, fb_size.0, fb_size.1);
let mut y = 0;
OFFramebuffer::put_string(0, y, "---KERNEL FUCKY WUKKY UWU (panic)---", VAPOREON_BLACK);
y += 16;
if let Some(s) = info.payload().downcast_ref::<&str>() {
OFFramebuffer::put_string(0, y, &format!("panic payload: {s:?}"), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0, y, "no panic payload", VAPOREON_BLACK);
};
y += 16;
if let Some(msg) = info.message() {
OFFramebuffer::put_string(0, y, &format!("panic msg: {}", msg), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0, y, "no message", VAPOREON_BLACK);
};
y += 16;
if let Some(location) = info.location() {
OFFramebuffer::put_string(0, y, &format!("location: file {} line {}", location.file(), location.line()), VAPOREON_BLACK);
} else {
OFFramebuffer::put_string(0, y, "no location", VAPOREON_BLACK);
};
}
}
loop {}
}
@ -79,7 +105,7 @@ use alloc::format;
use alloc::vec::Vec;
use core::num::Wrapping;
use core::panic::PanicInfo;
use core::sync::atomic::AtomicBool;
use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use ieee1275::prom_init;
use ieee1275::services::Args;
use crate::colourdefs::{COMMUNISM_RED, VAPOREON_BLACK, VAPOREON_BLUE, VAPOREON_CUM, VAPOREON_DARK};
@ -91,17 +117,13 @@ use crate::windows::{NeedRedrawResult, WINDOW_MANAGER};
#[no_mangle]
#[link_section = ".text"]
pub extern "C" fn ppc_entry(_r3: u32, _r4: u32, entry: extern "C" fn(*mut Args) -> usize) -> isize {
pub extern "C" fn _start(_r3: u32, _r4: u32, entry: extern "C" fn(*mut Args) -> usize) -> isize {
{
let mut prom = unsafe { &mut PROMHNDL };
prom.set_prom(prom_init(entry));
}
{
keyboard::set();
}
kernel_main();
bootstrap::bootstrap();
{
(unsafe { &mut PROMHNDL }).get().exit()
}
@ -136,7 +158,10 @@ pub fn kernel_callback() {
redraw_all();
}
let wm_redraw_status = unsafe { let wm = &mut WINDOW_MANAGER; wm.need_redraw() };
let wm_redraw_status = unsafe {
let wm = &mut WINDOW_MANAGER;
wm.need_redraw()
};
match wm_redraw_status {
NeedRedrawResult::DontNeedRedraw => {}
@ -158,13 +183,19 @@ pub fn kernel_callback() {
} else {
panic!("read error: {:?}", try_read);
}
let terminal_buffer_empty = unsafe { terminal::TERMINAL_QUEUE.is_empty() };
if !terminal_buffer_empty {
unsafe { terminal::dequeue(); }
}
}
#[no_mangle]
pub extern "C" fn kernel_main() -> ! {
use builddate::build_date;
debug!("entry point");
let _ = unsafe { &mut PROMHNDL }.get().write_stdout("we made it!");
loop {}
print!("\n"); // no carriage return cause i like the look of centered vap
print!("\n");
@ -196,8 +227,9 @@ pub extern "C" fn kernel_main() -> ! {
debug!("constructing terminal window");
terminal::construct_terminal_window();
debug!("initialising decrementer exception");
exceptions::decrementer::init_decrementer();
debug!("initialising exceptions");
exceptions::init_exceptions();
debug!("exceptions initialised");
println!("ready!");
println!();

37
src/memory.rs Normal file
View file

@ -0,0 +1,37 @@
use core::alloc::{GlobalAlloc, Layout};
use core::sync::atomic::{AtomicU8, Ordering};
use crate::debug;
struct Allocator {}
#[global_allocator]
static ALLOCATOR: Allocator = Allocator {};
pub static ALLOCATOR_STAGE: AtomicU8 = AtomicU8::new(0);
unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match ALLOCATOR_STAGE.load(Ordering::Relaxed) {
0 => {
panic!("allocating {:?} bytes", layout.size());
crate::bootstrap::ofw_alloc(layout)
}
_ => {
panic!("allocation occurred after allocator stage 0")
}
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
match ALLOCATOR_STAGE.load(Ordering::Relaxed) {
0 => {
crate::bootstrap::ofw_free(ptr, layout)
}
_ => {
panic!("deallocation occurred after allocator stage 0")
}
}
}
}

View file

@ -22,11 +22,6 @@ impl<T: Clone> MessageQueue<T> {
pub fn push(&mut self, item: T) {
let head = self.head.load(core::sync::atomic::Ordering::Relaxed);
let tail = self.tail.load(core::sync::atomic::Ordering::Relaxed);
if head == tail {
// queue is full
panic!("queue is full");
}
self.queue[head] = Some(item);
self.head.store((head + 1) % self.queue.len(), core::sync::atomic::Ordering::Relaxed);
}
@ -94,11 +89,6 @@ impl<T: Copy> NoAllocQueue<T> {
pub fn push(&mut self, item: T) {
let head = self.head.load(core::sync::atomic::Ordering::Relaxed);
let tail = self.tail.load(core::sync::atomic::Ordering::Relaxed);
if head == tail {
// queue is full
panic!("queue is full");
}
self.queue[head] = Some(item);
self.head.store((head + 1) % self.queue.len(), core::sync::atomic::Ordering::Relaxed);
}

View file

@ -7,7 +7,6 @@ use crate::prom::PROMHNDL;
pub fn of_singlevar_get<T>(name: &str, buffer: *mut T) -> Result<[u32; 16], String> {
let mut prom = unsafe { &mut PROMHNDL };
let prom = prom.get();
let name = format!("{}{}", name, '\0');
#[repr(C)]
struct SingleVarArgs {

View file

@ -275,7 +275,23 @@ pub fn queue_str(string: &str) {
let queue = unsafe { &mut TERMINAL_QUEUE };
let mut buf = [0; 80];
for (i, c) in string.as_bytes().iter().enumerate() {
if i >= 80 {
break;
}
buf[i] = *c;
}
queue.push((buf, string.len()));
}
pub unsafe fn dequeue() {
let queue = &mut TERMINAL_QUEUE;
if let Some((buf, len)) = queue.pop() {
let str = core::str::from_utf8(&buf[..*len]).unwrap();
write_string(str);
}
unsafe {
shift_lines_up();
request_terminal_redraw();
}
}