Compare commits
No commits in common. "5f2b181f221826665cd6900b74a2ba42bffe0691" and "2b2e0c514bf8f8a8dd109ee5996de7e1c1f398bf" have entirely different histories.
5f2b181f22
...
2b2e0c514b
1107
Cargo.lock
generated
1107
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["dev", "kernel", "repbuild"]
|
||||
|
||||
# [profile.release]
|
||||
# strip = "symbols"
|
||||
# codegen-units = 1
|
||||
# lto = true
|
||||
# panic = "abort"
|
||||
members = [ "dev","kernel", "repbuild"]
|
||||
|
|
|
@ -5,32 +5,33 @@ version = "0.2.0"
|
|||
|
||||
|
||||
[dependencies]
|
||||
embedded-graphics = "0.8"
|
||||
embedded-graphics = "0.7"
|
||||
hbvm.git = "https://git.ablecorp.us/ableos/holey-bytes"
|
||||
log = "0.4"
|
||||
spin = "0.9"
|
||||
uart_16550 = "0.2"
|
||||
slab = { version = "0.4", default-features = false }
|
||||
uart_16550 = { version = "0.3", features = ["nightly"] }
|
||||
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
hashbrown = { version = "0.14", features = ["nightly"] }
|
||||
able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
hashbrown = "*"
|
||||
kiam = "0.1.1"
|
||||
|
||||
[dependencies.limine]
|
||||
version = "0.1"
|
||||
#git = "https://github.com/limine-bootloader/limine-rs"
|
||||
git = "https://github.com/limine-bootloader/limine-rs"
|
||||
|
||||
[dependencies.crossbeam-queue]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = ["alloc", "nightly"]
|
||||
features = ["alloc"]
|
||||
|
||||
# [dependencies.clparse]
|
||||
# git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
# default-features = false
|
||||
[dependencies.clparse]
|
||||
git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
default-features = false
|
||||
|
||||
[dependencies.derive_more]
|
||||
version = "1"
|
||||
version = "0.99"
|
||||
default-features = false
|
||||
features = [
|
||||
"add",
|
||||
|
@ -47,12 +48,12 @@ features = [
|
|||
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
x86_64 = "0.15"
|
||||
x86_64 = "0.14"
|
||||
x2apic = "0.4"
|
||||
virtio-drivers = "0.7"
|
||||
virtio-drivers = "0.4.0"
|
||||
# rdrand = "*"
|
||||
rdrand = { version = "0.8", default-features = false }
|
||||
|
||||
|
||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||
sbi = "0.2.0"
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
aarch64-cpu = "9"
|
||||
|
|
|
@ -29,7 +29,7 @@ fn collect_cpu_info(device_tree: &mut DeviceTree) {
|
|||
}
|
||||
|
||||
fn cpu_id() -> (String, u64) {
|
||||
let mut cpu_id: u64;
|
||||
let mut cpu_id: u64 = 0;
|
||||
unsafe {
|
||||
asm!("mrs {cpu_id}, MIDR_EL1",
|
||||
cpu_id = out(reg) cpu_id,
|
||||
|
@ -41,8 +41,6 @@ fn cpu_id() -> (String, u64) {
|
|||
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
||||
0x410FD034 => "Cortex-A53".to_string(),
|
||||
0x410FD083 => "Cortex-A72".to_string(),
|
||||
// the source of this one was checking the cpu id :thinking:
|
||||
0x410FD493 => "Neoverse N2".to_string(),
|
||||
_ => "Unknown".to_string(),
|
||||
};
|
||||
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
pub use logging::log;
|
||||
use {
|
||||
crate::{allocator, bootmodules::BootModule, kmain::kmain},
|
||||
alloc::vec::Vec,
|
||||
core::arch::asm,
|
||||
limine::FramebufferRequest,
|
||||
};
|
||||
|
@ -42,7 +41,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0);
|
||||
static MOD_REQ: ModuleRequest = ModuleRequest::new(0);
|
||||
|
||||
let mut bootmodules = Vec::new();
|
||||
let mut bootmodules = alloc::vec::Vec::new();
|
||||
|
||||
if bm.is_some() {
|
||||
let bm = bm.unwrap();
|
||||
|
@ -53,13 +52,18 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
let raw_bytes = core::slice::from_raw_parts(
|
||||
file.base.as_ptr().expect("invalid initrd"),
|
||||
file.length as usize,
|
||||
);
|
||||
)
|
||||
.to_vec();
|
||||
|
||||
let file_path = file.path.to_str().unwrap().to_str();
|
||||
let file_path = alloc::string::String::from_utf8(
|
||||
file.path.to_str().unwrap().to_bytes().to_vec(),
|
||||
);
|
||||
if file_path.is_err() {
|
||||
panic!("invalid file path: {:?}", file_path);
|
||||
}
|
||||
let file_cmd = file.cmdline.to_str().unwrap().to_str();
|
||||
let file_cmd = alloc::string::String::from_utf8(
|
||||
file.cmdline.to_str().unwrap().to_bytes().to_vec(),
|
||||
);
|
||||
if file_cmd.is_err() {
|
||||
panic!("invalid module cmd: {:?}", file_cmd);
|
||||
}
|
||||
|
@ -81,7 +85,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
||||
}
|
||||
|
||||
kmain(
|
||||
crate::kmain::kmain(
|
||||
KFILE_REQ
|
||||
.get_response()
|
||||
.get()
|
||||
|
@ -95,6 +99,8 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
.unwrap_or_default(),
|
||||
bootmodules,
|
||||
);
|
||||
|
||||
spin_loop();
|
||||
}
|
||||
|
||||
pub fn spin_loop() -> ! {
|
||||
|
@ -103,19 +109,8 @@ pub fn spin_loop() -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
/// I am sorry.
|
||||
static mut A_REAL_RANDOM_U64_I_PROMISE: u64 = 0;
|
||||
|
||||
pub fn hardware_random_u64() -> u64 {
|
||||
if let Some(rng) = aarch64_cpu::asm::random::ArmRng::new() {
|
||||
if let Some(rnd) = rng.rndr() {
|
||||
return rnd;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
A_REAL_RANDOM_U64_I_PROMISE += 1;
|
||||
A_REAL_RANDOM_U64_I_PROMISE
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub fn register_dump() {}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
use core::num;
|
||||
|
||||
use {
|
||||
crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress},
|
||||
alloc::boxed::Box,
|
||||
spin::{Mutex, Once},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use spin::{Mutex, Once};
|
||||
use crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress};
|
||||
|
||||
use super::PAGE_SIZE;
|
||||
|
||||
|
@ -30,7 +28,7 @@ impl PageSize {
|
|||
}
|
||||
|
||||
pub struct PageTable {
|
||||
entries: [PageEntry; 512],
|
||||
entries: [PageEntry; 512]
|
||||
}
|
||||
|
||||
impl PageTable {
|
||||
|
@ -74,14 +72,8 @@ impl PageTable {
|
|||
/// flags MUST include one or more of the following:
|
||||
/// Read, Write, Execute
|
||||
/// The valid bit automatically gets added
|
||||
pub fn map(
|
||||
&mut self,
|
||||
vaddr: VirtualAddress,
|
||||
paddr: PhysicalAddress,
|
||||
flags: PageEntryFlags,
|
||||
page_size: PageSize,
|
||||
) {
|
||||
assert!(flags as usize & 0xE != 0);
|
||||
pub fn map(&mut self, vaddr: VirtualAddress, paddr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) {
|
||||
assert!(flags as usize & 0xe != 0);
|
||||
|
||||
let vpn = vaddr.vpns();
|
||||
let ppn = paddr.ppns();
|
||||
|
@ -99,7 +91,7 @@ impl PageTable {
|
|||
}
|
||||
|
||||
let entry = v.addr().as_mut_ptr::<PageEntry>();
|
||||
v = unsafe { entry.add(vpn[i]).as_mut().unwrap() };
|
||||
v = unsafe { entry.add(vpn[i]).as_mut().unwrap() };
|
||||
}
|
||||
|
||||
// When we get here, we should be at VPN[0] and v should be pointing to our entry.
|
||||
|
@ -113,24 +105,14 @@ impl PageTable {
|
|||
}
|
||||
|
||||
/// Identity maps a page of memory
|
||||
pub fn identity_map(
|
||||
&mut self,
|
||||
addr: PhysicalAddress,
|
||||
flags: PageEntryFlags,
|
||||
page_size: PageSize,
|
||||
) {
|
||||
pub fn identity_map(&mut self, addr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) {
|
||||
// log::debug!("identity mapped {addr}");
|
||||
self.map(addr.as_addr().into(), addr, flags, page_size);
|
||||
}
|
||||
|
||||
/// Identity maps a range of contiguous memory
|
||||
/// This assumes that start <= end
|
||||
pub fn identity_map_range(
|
||||
&mut self,
|
||||
start: PhysicalAddress,
|
||||
end: PhysicalAddress,
|
||||
flags: PageEntryFlags,
|
||||
) {
|
||||
pub fn identity_map_range(&mut self, start: PhysicalAddress, end: PhysicalAddress, flags: PageEntryFlags) {
|
||||
log::debug!("start: {start}, end: {end}");
|
||||
let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1);
|
||||
let num_pages = (align_val(end.as_addr(), 12) - mem_addr - 1) / PAGE_SIZE + 1;
|
||||
|
@ -160,7 +142,7 @@ impl PageTable {
|
|||
}
|
||||
|
||||
let entry = v.addr().as_mut_ptr::<PageEntry>();
|
||||
v = unsafe { entry.add(vpn[i]).as_mut().unwrap() };
|
||||
v = unsafe { entry.add(vpn[i]).as_mut().unwrap() };
|
||||
}
|
||||
|
||||
// If we're here this is an unmapped page
|
||||
|
@ -246,7 +228,7 @@ impl PageEntry {
|
|||
}
|
||||
|
||||
fn addr(&self) -> PhysicalAddress {
|
||||
((self.entry() as usize & !0x3FF) << 2).into()
|
||||
((self.entry() as usize & !0x3ff) << 2).into()
|
||||
}
|
||||
|
||||
fn destroy(&mut self) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod memory;
|
||||
|
||||
use {
|
||||
alloc::{boxed::Box, vec::Vec},
|
||||
alloc::boxed::Box,
|
||||
core::{
|
||||
arch::{asm, global_asm},
|
||||
fmt::Write,
|
||||
|
@ -95,7 +95,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
in(reg) satp_value,
|
||||
);
|
||||
|
||||
crate::kmain::kmain("baka=9", Vec::new());
|
||||
crate::kmain::kmain("baka=9", None);
|
||||
}
|
||||
|
||||
/// Spin loop
|
||||
|
@ -105,12 +105,6 @@ pub fn spin_loop() -> ! {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn hardware_random_u64() -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn register_dump() {}
|
||||
|
||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
SERIAL_CONSOLE.get().unwrap().lock().write_fmt(args)
|
||||
}
|
||||
|
|
|
@ -11,9 +11,6 @@ use {
|
|||
|
||||
pub const DOUBLE_FAULT_IX: u16 = 0;
|
||||
|
||||
const STACK_SIZE: usize = 5 * 1024;
|
||||
const STACK_ALIGNMENT: usize = 4096;
|
||||
|
||||
pub unsafe fn init() {
|
||||
use x86_64::instructions::{
|
||||
segmentation::{Segment, CS, SS},
|
||||
|
@ -35,24 +32,24 @@ struct Selectors {
|
|||
|
||||
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||
let mut tss = TaskStateSegment::new();
|
||||
|
||||
let stack_ptr = unsafe {
|
||||
let layout = alloc::alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGNMENT)
|
||||
.expect("Failed to create stack layout");
|
||||
let stack = alloc::alloc::alloc_zeroed(layout);
|
||||
VirtAddr::from_ptr(stack) + STACK_SIZE as u64
|
||||
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = {
|
||||
const SIZE: usize = 5 * 1024;
|
||||
let stack = unsafe {
|
||||
alloc::alloc::alloc_zeroed(
|
||||
alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"),
|
||||
)
|
||||
};
|
||||
VirtAddr::from_ptr(stack) + SIZE
|
||||
};
|
||||
|
||||
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = stack_ptr;
|
||||
tss
|
||||
});
|
||||
|
||||
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||
let mut gdt = GlobalDescriptorTable::new();
|
||||
let sels = Selectors {
|
||||
kcode: gdt.append(Descriptor::kernel_code_segment()),
|
||||
kdata: gdt.append(Descriptor::kernel_data_segment()),
|
||||
tss: gdt.append(Descriptor::tss_segment(&TSS)),
|
||||
kcode: gdt.add_entry(Descriptor::kernel_code_segment()),
|
||||
kdata: gdt.add_entry(Descriptor::kernel_data_segment()),
|
||||
tss: gdt.add_entry(Descriptor::tss_segment(&TSS)),
|
||||
};
|
||||
(gdt, sels)
|
||||
});
|
||||
|
|
|
@ -45,9 +45,9 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||
}
|
||||
idt.page_fault.set_handler_fn(page_fault);
|
||||
|
||||
idt[Interrupt::ApicErr as u8].set_handler_fn(apic_err);
|
||||
idt[Interrupt::Spurious as u8].set_handler_fn(spurious);
|
||||
idt[Interrupt::Timer as u8].set_handler_fn(timer);
|
||||
idt[Interrupt::ApicErr as usize].set_handler_fn(apic_err);
|
||||
idt[Interrupt::Spurious as usize].set_handler_fn(spurious);
|
||||
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
||||
|
||||
idt
|
||||
});
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
//! Logging (as in terms of console / serial output)
|
||||
#![allow(deprecated)]
|
||||
use {core::fmt::Write, spin::Mutex, uart_16550::SerialPort};
|
||||
use {
|
||||
core::fmt::Write,
|
||||
limine::{TerminalRequest, TerminalResponse},
|
||||
spin::{Lazy, Mutex},
|
||||
uart_16550::SerialPort,
|
||||
};
|
||||
|
||||
pub static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use core::arch::x86_64::{_rdrand64_step, _rdseed64_step};
|
||||
|
||||
use {crate::bootmodules::BootModule, core::arch::asm, log::warn};
|
||||
use {
|
||||
crate::bootmodules::BootModule, core::arch::asm, embedded_graphics::pixelcolor::Rgb888,
|
||||
log::warn, rdrand::RdSeed,
|
||||
};
|
||||
pub mod memory;
|
||||
|
||||
mod cpuid;
|
||||
|
@ -142,13 +143,18 @@ unsafe extern "C" fn start() -> ! {
|
|||
let raw_bytes = core::slice::from_raw_parts(
|
||||
file.base.as_ptr().expect("invalid initrd"),
|
||||
file.length as usize,
|
||||
);
|
||||
)
|
||||
.to_vec();
|
||||
|
||||
let file_path = file.path.to_str().unwrap().to_str();
|
||||
let file_path = alloc::string::String::from_utf8(
|
||||
file.path.to_str().unwrap().to_bytes().to_vec(),
|
||||
);
|
||||
if file_path.is_err() {
|
||||
panic!("invalid file path: {:?}", file_path);
|
||||
}
|
||||
let file_cmd = file.cmdline.to_str().unwrap().to_str();
|
||||
let file_cmd = alloc::string::String::from_utf8(
|
||||
file.cmdline.to_str().unwrap().to_bytes().to_vec(),
|
||||
);
|
||||
if file_cmd.is_err() {
|
||||
panic!("invalid module cmd: {:?}", file_cmd);
|
||||
}
|
||||
|
@ -189,20 +195,32 @@ unsafe extern "C" fn start() -> ! {
|
|||
/// Spin loop
|
||||
pub fn spin_loop() -> ! {
|
||||
loop {
|
||||
x86_64::instructions::hlt()
|
||||
x86_64::instructions::hlt();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hardware_random_u64() -> u64 {
|
||||
let mut out: u64 = 0;
|
||||
match unsafe { _rdrand64_step(&mut out) } {
|
||||
1 => out,
|
||||
_ => {
|
||||
use {log::trace, rdrand::RdRand};
|
||||
let gen = RdRand::new();
|
||||
match gen {
|
||||
Ok(gen) => {
|
||||
let ret = gen.try_next_u64().unwrap();
|
||||
trace!("Random {}", ret);
|
||||
return ret;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("RDRand not supported.");
|
||||
// Try rdseed
|
||||
match unsafe { _rdseed64_step(&mut out) } {
|
||||
1 => out,
|
||||
_ => panic!("Neither RDRand or RDSeed are supported"),
|
||||
let gen = RdSeed::new();
|
||||
match gen {
|
||||
Ok(gen) => {
|
||||
let ret = gen.try_next_u64().unwrap();
|
||||
trace!("Random {}", ret);
|
||||
return ret;
|
||||
}
|
||||
Err(err) => {
|
||||
panic!("Neither RDRand or RDSeed are supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +228,6 @@ pub fn hardware_random_u64() -> u64 {
|
|||
|
||||
pub fn get_edid() {}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn register_dump() {
|
||||
let rax: u64;
|
||||
let rbx: u64 = 0;
|
||||
|
|
|
@ -12,8 +12,7 @@ use crate::alloc::string::ToString;
|
|||
|
||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||
pub fn init(device_tree: &mut DeviceTree) {
|
||||
device_tree
|
||||
.devices
|
||||
device_tree.devices
|
||||
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
||||
let mut devices = alloc::vec![];
|
||||
|
||||
|
@ -24,7 +23,6 @@ pub fn init(device_tree: &mut DeviceTree) {
|
|||
let id = device_info.device_id.id;
|
||||
use Vendor::*;
|
||||
let (dev_type, dev_name) = match (vendor, id) {
|
||||
(VMWareInc, 1029) => ("GPUs", "SVGAII PCI GPU"),
|
||||
(Qemu, 4369) => ("GPUs", "QEMU VGA"),
|
||||
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
|
||||
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
|
||||
|
@ -271,7 +269,8 @@ impl Display for Vendor {
|
|||
|
||||
use core::fmt::Display;
|
||||
|
||||
use {crate::device_tree::DeviceTree, x86_64::instructions::port::Port};
|
||||
use x86_64::instructions::port::Port;
|
||||
use crate::device_tree::DeviceTree;
|
||||
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
use {
|
||||
// crate::alloc::string::ToString,
|
||||
alloc::vec::Vec,
|
||||
// clparse::Arguments,
|
||||
// core::fmt::{Debug, Display},
|
||||
// log::trace,
|
||||
// xml::XMLElement,
|
||||
crate::alloc::string::ToString,
|
||||
alloc::{string::String, vec::Vec},
|
||||
clparse::Arguments,
|
||||
core::fmt::{Debug, Display},
|
||||
log::trace,
|
||||
xml::XMLElement,
|
||||
};
|
||||
pub type BootModules<'a> = Vec<BootModule<'a>>;
|
||||
pub type BootModules = Vec<BootModule>;
|
||||
|
||||
pub struct BootModule<'a> {
|
||||
pub path: &'a str,
|
||||
pub bytes: &'a [u8],
|
||||
pub cmd: &'a str,
|
||||
pub struct BootModule {
|
||||
pub path: String,
|
||||
pub bytes: Vec<u8>,
|
||||
pub cmd: String,
|
||||
}
|
||||
impl<'a> BootModule<'a> {
|
||||
pub fn new(path: &'a str, bytes: &'a [u8], cmd: &'a str) -> Self {
|
||||
impl BootModule {
|
||||
pub fn new(path: String, bytes: Vec<u8>, cmd: String) -> Self {
|
||||
Self { path, bytes, cmd }
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn build_cmd<T: Display + Debug>(name: T, cmdline: T) -> XMLElement {
|
||||
// let mut cmdline = cmdline.to_string();
|
||||
// cmdline.pop();
|
||||
// cmdline.remove(0);
|
||||
pub fn build_cmd<T: Display + Debug>(name: T, cmdline: T) -> XMLElement {
|
||||
let mut cmdline = cmdline.to_string();
|
||||
cmdline.pop();
|
||||
cmdline.remove(0);
|
||||
|
||||
// let cmd = Arguments::parse(cmdline.to_string()).unwrap();
|
||||
// trace!("Cmdline: {cmd:?}");
|
||||
let cmd = Arguments::parse(cmdline.to_string()).unwrap();
|
||||
trace!("Cmdline: {cmd:?}");
|
||||
|
||||
// let mut clo = XMLElement::new(name);
|
||||
// for (key, value) in cmd.arguments {
|
||||
// clo.set_attribute(key, value);
|
||||
// }
|
||||
// trace!("command line object: {:?}", clo);
|
||||
// clo
|
||||
// }
|
||||
let mut clo = XMLElement::new(name);
|
||||
for (key, value) in cmd.arguments {
|
||||
clo.set_attribute(key, value);
|
||||
}
|
||||
trace!("command line object: {:?}", clo);
|
||||
clo
|
||||
}
|
||||
|
|
|
@ -1,14 +1,22 @@
|
|||
//! Environment call handling routines
|
||||
|
||||
use crate::holeybytes::kernel_services::{
|
||||
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
|
||||
service_definition_service::sds_msg_handler,
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use crate::{
|
||||
allocator,
|
||||
holeybytes::kernel_services::{
|
||||
block_read,
|
||||
dt_msg_handler::dt_msg_handler,
|
||||
logging_service::log_msg_handler,
|
||||
service_definition_service::{sds_msg_handler, SERVICES},
|
||||
},
|
||||
};
|
||||
|
||||
use {
|
||||
super::Vm,
|
||||
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||
log::{debug, error, info, trace},
|
||||
super::{mem::Memory, Vm},
|
||||
crate::{arch, holeybytes::mem, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||
alloc::string::String,
|
||||
log::{debug, error, info, trace, warn},
|
||||
};
|
||||
|
||||
pub fn handler(vm: &mut Vm) {
|
||||
|
@ -68,11 +76,11 @@ pub fn handler(vm: &mut Vm) {
|
|||
match buffer_id {
|
||||
0 => match sds_msg_handler(vm, mem_addr, length) {
|
||||
Ok(()) => {}
|
||||
Err(err) => log::error!("Improper sds format: {err:?}"),
|
||||
Err(err) => log::error!("Improper sds format"),
|
||||
},
|
||||
1 => match log_msg_handler(vm, mem_addr, length) {
|
||||
Ok(()) => {}
|
||||
Err(_) => log::error!("Improper log format"),
|
||||
Err(err) => log::error!("Improper log format"),
|
||||
},
|
||||
2 => {
|
||||
use crate::holeybytes::kernel_services::mem_serve::memory_msg_handler;
|
||||
|
@ -80,109 +88,77 @@ pub fn handler(vm: &mut Vm) {
|
|||
Ok(_) => {}
|
||||
Err(_) => {}
|
||||
}
|
||||
//
|
||||
}
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
3 => info!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
3 => {
|
||||
unsafe fn x86_out<T: x86_64::instructions::port::PortWrite>(
|
||||
address: u16,
|
||||
value: T,
|
||||
) {
|
||||
x86_64::instructions::port::Port::new(address).write(value);
|
||||
}
|
||||
unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
||||
unsafe fn x86_in(address: u16) -> u8 {
|
||||
x86_64::instructions::port::Port::new(address).read()
|
||||
}
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
unsafe fn x86_out(address: u16, value: u8) {
|
||||
x86_64::instructions::port::Port::new(address).write(value);
|
||||
}
|
||||
|
||||
let mut msg_vec = block_read(mem_addr, length);
|
||||
let msg_type = msg_vec[0];
|
||||
msg_vec.remove(0);
|
||||
match msg_type {
|
||||
0 => 'wow: {
|
||||
let size = match msg_vec[0] {
|
||||
0 => 1,
|
||||
1 => 2,
|
||||
2 => 4,
|
||||
_ => {
|
||||
error!("Tried to write more than 32 bits");
|
||||
break 'wow;
|
||||
}
|
||||
};
|
||||
let addr = u16::from_le_bytes(msg_vec[1..3].try_into().unwrap());
|
||||
let value = unsafe {
|
||||
match size {
|
||||
1 => x86_in::<u8>(addr) as u64,
|
||||
2 => x86_in::<u16>(addr) as u64,
|
||||
4 => x86_in::<u32>(addr) as u64,
|
||||
_ => panic!("how?"),
|
||||
}
|
||||
};
|
||||
0 => {
|
||||
let mut addr = msg_vec[0] as u16;
|
||||
msg_vec.remove(0);
|
||||
|
||||
let addr2 = msg_vec[0] as u16;
|
||||
msg_vec.remove(0);
|
||||
|
||||
addr = ((addr) << 8) | addr2;
|
||||
|
||||
let value = unsafe { x86_in(addr) };
|
||||
|
||||
trace!("Read the value {} from address {}", value, addr);
|
||||
vm.registers[1] = hbvm::value::Value(value);
|
||||
vm.registers[1] = hbvm::value::Value(value as u64);
|
||||
}
|
||||
1 => 'wow: {
|
||||
let size = match msg_vec[1] {
|
||||
0 => 1,
|
||||
1 => 2,
|
||||
2 => 4,
|
||||
_ => {
|
||||
error!("Tried to write more than 32 bits");
|
||||
break 'wow;
|
||||
}
|
||||
};
|
||||
let addr = unsafe {
|
||||
u16::from_le_bytes(msg_vec[1..3].try_into().unwrap_unchecked())
|
||||
};
|
||||
trace!("Setting address {}", addr);
|
||||
unsafe {
|
||||
match size {
|
||||
1 => x86_out(addr, msg_vec[3]),
|
||||
2 => x86_out(
|
||||
addr,
|
||||
u16::from_le_bytes(
|
||||
msg_vec[3..5].try_into().unwrap_unchecked(),
|
||||
),
|
||||
),
|
||||
4 => x86_out(
|
||||
addr,
|
||||
u32::from_le_bytes(
|
||||
msg_vec[3..7].try_into().unwrap_unchecked(),
|
||||
),
|
||||
),
|
||||
_ => panic!("How?"),
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let mut addr = msg_vec[0] as u16;
|
||||
msg_vec.remove(0);
|
||||
|
||||
let addr2 = msg_vec[0] as u16;
|
||||
msg_vec.remove(0);
|
||||
|
||||
addr = ((addr) << 8) | addr2;
|
||||
|
||||
let value = msg_vec[0];
|
||||
msg_vec.remove(0);
|
||||
trace!("Setting the address {} to {}", addr, value);
|
||||
unsafe { x86_out(addr, value) };
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||
// source of rng
|
||||
4 => {
|
||||
// limit to last 32 bits
|
||||
vm.registers[1] =
|
||||
hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
5 => match dt_msg_handler(vm, mem_addr, length) {
|
||||
Ok(()) => {}
|
||||
Err(_) => log::error!("Improper dt query"),
|
||||
Err(err) => log::error!("Improper dt query"),
|
||||
},
|
||||
|
||||
buffer_id => {
|
||||
let mut buffs = IPC_BUFFERS.lock();
|
||||
match buffs.get_mut(&buffer_id) {
|
||||
Some(buff) => {
|
||||
let mut msg_vec = Vec::with_capacity(length);
|
||||
use alloc::vec;
|
||||
let mut msg_vec = vec![];
|
||||
|
||||
for x in 0..(length as isize) {
|
||||
let xyz = mem_addr as *const u8;
|
||||
let value = unsafe { xyz.offset(x).read() };
|
||||
msg_vec.push(value);
|
||||
}
|
||||
debug!(
|
||||
buff.push(msg_vec.clone());
|
||||
info!(
|
||||
"Message {:?} has been sent to Buffer({})",
|
||||
msg_vec, buffer_id
|
||||
);
|
||||
buff.push(msg_vec);
|
||||
}
|
||||
None => {
|
||||
log::error!("Access of non-existent buffer {}", buffer_id)
|
||||
|
@ -198,12 +174,12 @@ pub fn handler(vm: &mut Vm) {
|
|||
let max_length = vm.registers[5].cast::<u64>();
|
||||
|
||||
let mut buffs = IPC_BUFFERS.lock();
|
||||
let buff: &mut IpcBuffer;
|
||||
let mut buff: &mut IpcBuffer;
|
||||
|
||||
if buffs.get_mut(&buffer_id).is_some() {
|
||||
buff = buffs.get_mut(&buffer_id).unwrap();
|
||||
} else {
|
||||
// info!("AHHH");
|
||||
info!("AHHH");
|
||||
vm.registers[1] = hbvm::value::Value(0);
|
||||
return;
|
||||
}
|
||||
|
@ -223,7 +199,7 @@ pub fn handler(vm: &mut Vm) {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||
info!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||
}
|
||||
}
|
||||
5 => {
|
||||
|
@ -241,19 +217,13 @@ pub fn handler(vm: &mut Vm) {
|
|||
vm.registers[3] = x
|
||||
}
|
||||
}
|
||||
// 5
|
||||
_ => {
|
||||
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogError {
|
||||
NoMessages,
|
||||
InvalidLogFormat,
|
||||
}
|
||||
|
||||
// use {alloc::vec, log::Record};
|
||||
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
// let mut val = alloc::vec::Vec::new();
|
||||
// for _ in 0..4096 {
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
use {
|
||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||
alloc::{
|
||||
borrow::ToOwned,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
},
|
||||
log::debug,
|
||||
};
|
||||
pub enum DtError {
|
||||
QueryFailure,
|
||||
}
|
||||
|
||||
pub fn dt_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), DtError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
let mut msg_vec = block_read(mem_addr, length);
|
||||
let mut bytes: Vec<u8> = Vec::new();
|
||||
for byte in msg_vec {
|
||||
if *byte == 0 {
|
||||
if byte == 0 {
|
||||
break;
|
||||
}
|
||||
bytes.push(*byte)
|
||||
bytes.push(byte)
|
||||
}
|
||||
let query_string = String::from_utf8(bytes).unwrap();
|
||||
log::trace!("Query {}", query_string);
|
||||
|
@ -60,7 +62,10 @@ fn cpu_parse(qt_parse_step_two: Vec<String>) -> u64 {
|
|||
}
|
||||
|
||||
fn framebuffer_parse(qt_parse_step_two: Vec<String>) -> u64 {
|
||||
use crate::kmain::FB_REQ;
|
||||
use {
|
||||
crate::kmain::FB_REQ,
|
||||
limine::{Framebuffer, NonNullPtr},
|
||||
};
|
||||
let fbs = &FB_REQ.get_response().get().unwrap().framebuffers();
|
||||
|
||||
let second_fragment: &str = &qt_parse_step_two[1];
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
use crate::holeybytes::{kernel_services::block_read, Vm};
|
||||
use crate::logger::TermLogger;
|
||||
|
||||
use {
|
||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||
alloc::string::String,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogError {
|
||||
InvalidLogFormat,
|
||||
}
|
||||
use log::Record;
|
||||
use {alloc::vec, log::Record};
|
||||
|
||||
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
pub fn log_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
let mut msg_vec = block_read(mem_addr, length);
|
||||
|
||||
let log_level = msg_vec.last().unwrap();
|
||||
let log_level = msg_vec.pop().unwrap();
|
||||
|
||||
let file_name = "None";
|
||||
let line_number = 0;
|
||||
|
||||
match core::str::from_utf8(&msg_vec[..msg_vec.len()]) {
|
||||
match String::from_utf8(msg_vec) {
|
||||
Ok(strr) => {
|
||||
use log::Level::*;
|
||||
let log_level = match log_level {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use {
|
||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||
alloc::alloc::{alloc_zeroed, dealloc},
|
||||
core::alloc::Layout,
|
||||
crate::holeybytes::{
|
||||
kernel_services::{block_read, mem_serve},
|
||||
Vm,
|
||||
},
|
||||
alloc::alloc::alloc_zeroed,
|
||||
log::{debug, info},
|
||||
};
|
||||
|
||||
|
@ -16,10 +18,13 @@ pub enum MemoryQuotaType {
|
|||
KillQuota = 3,
|
||||
}
|
||||
|
||||
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
||||
let ptr = unsafe { alloc_zeroed(Layout::new::<[u8; 4096]>()) };
|
||||
info!("Block address: {:?}", ptr);
|
||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||
fn alloc_page(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), MemoryServiceError> {
|
||||
let mut val = alloc::vec::Vec::new();
|
||||
for _ in 0..4096 {
|
||||
val.push(0);
|
||||
}
|
||||
info!("Block address: {:?}", val.as_ptr());
|
||||
vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
||||
vm.registers[2] = hbvm::value::Value(4096);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -29,39 +34,34 @@ pub fn memory_msg_handler(
|
|||
mem_addr: u64,
|
||||
length: usize,
|
||||
) -> Result<(), MemoryServiceError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
let mut msg_vec = block_read(mem_addr, length);
|
||||
let msg_type = msg_vec[0];
|
||||
|
||||
msg_vec.remove(0);
|
||||
match msg_type {
|
||||
0 => {
|
||||
let page_count = msg_vec[1];
|
||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||
let page_count = msg_vec[0];
|
||||
msg_vec.remove(0);
|
||||
|
||||
let mptr_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||
|
||||
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
|
||||
|
||||
let ptr = unsafe {
|
||||
alloc_zeroed(Layout::from_size_align_unchecked(
|
||||
page_count as usize * 4096,
|
||||
1,
|
||||
))
|
||||
};
|
||||
|
||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
||||
let mut val = alloc::vec::Vec::new();
|
||||
for _ in 0..(page_count as isize * 4096) {
|
||||
val.push(0);
|
||||
}
|
||||
vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
||||
log::debug!("Kernel ptr: {:x}", val.as_ptr() as u64);
|
||||
}
|
||||
|
||||
1 => {
|
||||
let page_count = msg_vec[1];
|
||||
let page_count = msg_vec[0];
|
||||
msg_vec.remove(0);
|
||||
|
||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||
let mptr_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
||||
unsafe {
|
||||
dealloc(
|
||||
mptr as *mut u8,
|
||||
Layout::from_size_align_unchecked(page_count as usize * 4096, 1),
|
||||
)
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
use MemoryQuotaType::*;
|
||||
|
@ -72,10 +72,19 @@ pub fn memory_msg_handler(
|
|||
3 => KillQuota,
|
||||
_ => NoQuota,
|
||||
};
|
||||
let hid_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||
msg_vec.remove(0);
|
||||
let hid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||
let hid: u64 = u64::from_le_bytes(hid_raw);
|
||||
let pid_raw: [u8; 8] = msg_vec[10..18].try_into().unwrap();
|
||||
let pid: u64 = u64::from_le_bytes(pid_raw);
|
||||
for _ in 0..8 {
|
||||
msg_vec.remove(0);
|
||||
}
|
||||
|
||||
let pid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||
let pid: u64 = u64::from_le_bytes(hid_raw);
|
||||
for _ in 0..8 {
|
||||
msg_vec.remove(0);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Setting HID-{:x}:PID-{:x}'s quota type to {:?}",
|
||||
hid, pid, quota_type
|
||||
|
@ -84,6 +93,7 @@ pub fn memory_msg_handler(
|
|||
3 => {
|
||||
let page_count = msg_vec[0];
|
||||
log::debug!(" {} pages", page_count);
|
||||
msg_vec.remove(0);
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
use core::slice;
|
||||
use alloc::{vec, vec::Vec};
|
||||
|
||||
pub mod dt_msg_handler;
|
||||
pub mod logging_service;
|
||||
pub mod mem_serve;
|
||||
pub mod service_definition_service;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn block_read<'a>(mem_addr: u64, length: usize) -> &'a [u8] {
|
||||
unsafe { slice::from_raw_parts(mem_addr as *const u8, length) }
|
||||
pub fn block_read(mem_addr: u64, length: usize) -> Vec<u8> {
|
||||
let mut msg_vec = vec![];
|
||||
|
||||
for x in 0..(length as isize) {
|
||||
let xyz = mem_addr as *const u8;
|
||||
let value = unsafe { xyz.offset(x).read() };
|
||||
msg_vec.push(value);
|
||||
}
|
||||
msg_vec
|
||||
}
|
||||
|
|
|
@ -1,42 +1,45 @@
|
|||
use {
|
||||
crate::{
|
||||
alloc::string::ToString,
|
||||
arch::hardware_random_u64,
|
||||
holeybytes::{kernel_services::block_read, Vm},
|
||||
ipc::{buffer::IpcBuffer, protocol::Protocol},
|
||||
ipc::{
|
||||
buffer::IpcBuffer,
|
||||
protocol::{self, Protocol},
|
||||
},
|
||||
kmain::IPC_BUFFERS,
|
||||
},
|
||||
alloc::string::String,
|
||||
hashbrown::HashMap,
|
||||
log::{info, trace},
|
||||
spin::{lazy::Lazy, Mutex},
|
||||
};
|
||||
pub struct Services<'a>(HashMap<u64, Protocol<'a>>);
|
||||
pub struct Services(HashMap<u64, Protocol>);
|
||||
pub static SERVICES: Lazy<Mutex<Services>> = Lazy::new(|| {
|
||||
let mut dt = Services(HashMap::new());
|
||||
dt.0.insert(0, Protocol::void());
|
||||
Mutex::new(dt)
|
||||
});
|
||||
#[derive(Debug)]
|
||||
pub enum ServiceError {
|
||||
InvalidFormat,
|
||||
}
|
||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
let mut msg_vec = block_read(mem_addr, length);
|
||||
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
||||
msg_vec.remove(0);
|
||||
|
||||
// info!("Length {}", msg_vec.len());
|
||||
|
||||
use ServiceEventType::*;
|
||||
match sds_event_type {
|
||||
CreateService => {
|
||||
let string =
|
||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||
let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8");
|
||||
let ret = sds_create_service(string);
|
||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||
}
|
||||
DeleteService => todo!(),
|
||||
SearchServices => {
|
||||
let string =
|
||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||
let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8");
|
||||
let ret = sds_search_service(string);
|
||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||
}
|
||||
|
@ -78,16 +81,16 @@ impl From<u8> for ServiceEventType {
|
|||
}
|
||||
}
|
||||
|
||||
fn sds_create_service(protocol: &'static str) -> u64 {
|
||||
fn sds_create_service(protocol: String) -> u64 {
|
||||
let buff_id = hardware_random_u64();
|
||||
let mut services = SERVICES.lock();
|
||||
let mut buffers = IPC_BUFFERS.lock();
|
||||
|
||||
let protocol_ = Protocol::from(protocol);
|
||||
let protocol_ = Protocol::from(protocol.clone());
|
||||
let mut buff = IpcBuffer::new(false, 0);
|
||||
|
||||
services.0.insert(buff_id, protocol_.clone());
|
||||
buff.protocol = protocol_;
|
||||
buff.protocol = protocol_.clone();
|
||||
buffers.insert(buff_id, buff);
|
||||
|
||||
trace!("BufferID({}) => {}", buff_id, protocol);
|
||||
|
@ -95,13 +98,13 @@ fn sds_create_service(protocol: &'static str) -> u64 {
|
|||
buff_id
|
||||
}
|
||||
|
||||
fn sds_search_service(protocol: &str) -> u64 {
|
||||
let services = SERVICES.lock();
|
||||
let compare = Protocol::from(protocol);
|
||||
fn sds_search_service(protocol: String) -> u64 {
|
||||
let mut services = SERVICES.lock();
|
||||
let compare = Protocol::from(protocol.clone());
|
||||
for (bid, protocol_canidate) in &services.0 {
|
||||
trace!("BID-{bid} protocol_canidate {:?}", protocol_canidate);
|
||||
if protocol_canidate == &compare {
|
||||
trace!("BufferID({}) => {}", bid, protocol);
|
||||
trace!("BufferID({}) => {}", bid, protocol.clone());
|
||||
return *bid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use hbvm::mem::Address;
|
||||
|
||||
fn calc_start_of_page(ptr: u64) -> u64 {
|
||||
let _page_aligned = false;
|
||||
let mut page_aligned = false;
|
||||
if ptr % 4096 == 0 {
|
||||
// page_aligned = true;
|
||||
return ptr / 4096;
|
||||
|
@ -21,11 +21,11 @@ pub struct Memory {
|
|||
|
||||
impl Memory {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn read_device(_addr: Address) {
|
||||
//unsafe {
|
||||
//
|
||||
// x86_64::instructions::port::Port::new(addr.get()).read()
|
||||
//}
|
||||
fn read_device(addr: Address) {
|
||||
unsafe {
|
||||
//
|
||||
// x86_64::instructions::port::Port::new(addr.get()).read()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ impl hbvm::mem::Memory for Memory {
|
|||
target: *mut u8,
|
||||
count: usize,
|
||||
) -> Result<(), hbvm::mem::LoadError> {
|
||||
use log::{error, info};
|
||||
if addr.get() % 4096 == 0 {}
|
||||
core::ptr::copy(addr.get() as *const u8, target, count);
|
||||
Ok(())
|
||||
|
@ -55,6 +56,6 @@ impl hbvm::mem::Memory for Memory {
|
|||
|
||||
#[inline]
|
||||
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
||||
(addr.get() as *const T).read()
|
||||
(addr.get() as *const T).read_unaligned()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,86 +3,86 @@ mod kernel_services;
|
|||
mod mem;
|
||||
|
||||
use {
|
||||
alloc::alloc::{alloc_zeroed, dealloc},
|
||||
core::{
|
||||
alloc::Layout,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
},
|
||||
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||
alloc::boxed::Box,
|
||||
core::{default, future::Future, marker::PhantomData, ptr::NonNull, task::Poll},
|
||||
hbvm::{
|
||||
mem::{softpaging::HandlePageFault, Address},
|
||||
mem::{
|
||||
softpaging::{icache::ICache, HandlePageFault, SoftPagedMem},
|
||||
Address, Memory,
|
||||
},
|
||||
VmRunError, VmRunOk,
|
||||
},
|
||||
log::error,
|
||||
log::{debug, error, info, trace, warn},
|
||||
};
|
||||
|
||||
const STACK_SIZE: usize = 1024 * 1024;
|
||||
const TIMER_QUOTIENT: usize = 1000;
|
||||
const TIMER_QUOTIENT: usize = 100;
|
||||
type Vm = hbvm::Vm<mem::Memory, TIMER_QUOTIENT>;
|
||||
|
||||
pub struct ExecThread {
|
||||
pub struct ExecThread<'p> {
|
||||
vm: Vm,
|
||||
stack_bottom: *mut u8,
|
||||
_phantom: PhantomData<&'p [u8]>,
|
||||
}
|
||||
|
||||
unsafe impl Send for ExecThread {}
|
||||
|
||||
impl ExecThread {
|
||||
unsafe impl<'p> Send for ExecThread<'p> {}
|
||||
impl<'p> ExecThread<'p> {
|
||||
pub fn set_arguments(&mut self, ptr: u64, length: u64) {
|
||||
self.vm.registers[1] = hbvm::value::Value(ptr);
|
||||
self.vm.registers[2] = hbvm::value::Value(length);
|
||||
}
|
||||
|
||||
pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self {
|
||||
let mut vm = Vm::new(
|
||||
mem::Memory {},
|
||||
Address::new(program.as_ptr() as u64 + entrypoint.get()),
|
||||
);
|
||||
|
||||
let stack_bottom = allocate_stack();
|
||||
pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self {
|
||||
let mut vm = unsafe {
|
||||
Vm::new(
|
||||
mem::Memory {},
|
||||
Address::new(program.as_ptr() as u64 + entrypoint.get()),
|
||||
)
|
||||
};
|
||||
|
||||
let stack_bottom = unsafe { allocate_stack().as_ptr() };
|
||||
vm.write_reg(254, (stack_bottom as usize + STACK_SIZE - 1) as u64);
|
||||
|
||||
ExecThread { vm, stack_bottom }
|
||||
ExecThread {
|
||||
vm,
|
||||
stack_bottom,
|
||||
_phantom: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Drop for ExecThread {
|
||||
impl<'p> Drop for ExecThread<'p> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { dealloc(self.stack_bottom, stack_layout()) };
|
||||
unsafe { alloc::alloc::dealloc(self.stack_bottom, stack_layout()) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Future for ExecThread {
|
||||
impl<'p> Future for ExecThread<'p> {
|
||||
type Output = Result<(), VmRunError>;
|
||||
|
||||
#[inline(always)]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
fn poll(
|
||||
mut self: core::pin::Pin<&mut Self>,
|
||||
cx: &mut core::task::Context<'_>,
|
||||
) -> Poll<Self::Output> {
|
||||
match self.vm.run() {
|
||||
Err(err) => {
|
||||
error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers);
|
||||
Poll::Ready(Err(err))
|
||||
}
|
||||
Ok(VmRunOk::End) => Poll::Ready(Ok(())),
|
||||
Ok(VmRunOk::Ecall) => {
|
||||
ecah::handler(&mut self.vm);
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
Ok(VmRunOk::Timer) => {
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
log::error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers,);
|
||||
return Poll::Ready(Err(err));
|
||||
}
|
||||
Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
|
||||
Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm),
|
||||
Ok(VmRunOk::Timer) => (),
|
||||
Ok(VmRunOk::Breakpoint) => {
|
||||
error!(
|
||||
log::error!(
|
||||
"HBVM Debug breakpoint\r\nRegister dump: {:?}",
|
||||
self.vm.registers
|
||||
self.vm.registers,
|
||||
);
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,22 +91,33 @@ impl HandlePageFault for PageFaultHandler {
|
|||
fn page_fault(
|
||||
&mut self,
|
||||
reason: hbvm::mem::MemoryAccessReason,
|
||||
_pagetable: &mut hbvm::mem::softpaging::paging::PageTable,
|
||||
pagetable: &mut hbvm::mem::softpaging::paging::PageTable,
|
||||
vaddr: hbvm::mem::Address,
|
||||
size: hbvm::mem::softpaging::PageSize,
|
||||
dataptr: *mut u8,
|
||||
) -> bool {
|
||||
error!("REASON: {reason} vaddr: {vaddr} size: {size:?} Dataptr {dataptr:p}");
|
||||
) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
log::error!(
|
||||
"REASON: {reason} \
|
||||
vaddr: {vaddr} \
|
||||
size: {size:?} \
|
||||
Dataptr {dataptr:p}",
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const fn stack_layout() -> Layout {
|
||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
||||
const fn stack_layout() -> core::alloc::Layout {
|
||||
unsafe { alloc::alloc::Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn allocate_stack() -> *mut u8 {
|
||||
unsafe { alloc_zeroed(stack_layout()) }
|
||||
fn allocate_stack() -> NonNull<u8> {
|
||||
let layout = stack_layout();
|
||||
match NonNull::new(unsafe { alloc::alloc::alloc_zeroed(layout) }) {
|
||||
Some(ptr) => ptr,
|
||||
None => alloc::alloc::handle_alloc_error(layout),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ pub enum BufferTypes {
|
|||
Bound(ArrayQueue<Message>),
|
||||
}
|
||||
/// Interproccess buffer
|
||||
pub struct IpcBuffer<'a> {
|
||||
pub protocol: Protocol<'a>,
|
||||
pub struct IpcBuffer {
|
||||
pub protocol: Protocol,
|
||||
pub buffer: BufferTypes,
|
||||
}
|
||||
|
||||
impl<'a> IpcBuffer<'a> {
|
||||
impl IpcBuffer {
|
||||
pub fn new(bounded: bool, length: u64) -> Self {
|
||||
log::debug!(
|
||||
"New IPCBuffer\r
|
||||
|
@ -24,7 +24,7 @@ impl<'a> IpcBuffer<'a> {
|
|||
length
|
||||
);
|
||||
match (bounded, length) {
|
||||
(false, ..) => {
|
||||
(false, a) => {
|
||||
let buftype = BufferTypes::Unbound(SegQueue::new());
|
||||
|
||||
Self {
|
||||
|
@ -48,9 +48,9 @@ impl<'a> IpcBuffer<'a> {
|
|||
}
|
||||
pub fn push(&mut self, msg: Message) {
|
||||
match &self.buffer {
|
||||
BufferTypes::Unbound(buff) => buff.push(msg),
|
||||
BufferTypes::Unbound(buff) => buff.push(msg.clone()),
|
||||
BufferTypes::Bound(buff) => {
|
||||
let _ = buff.push(msg);
|
||||
let _ = buff.push(msg.clone());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use {
|
||||
alloc::{string::String, vec::Vec},
|
||||
hashbrown::HashMap,
|
||||
log::info,
|
||||
};
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Type {}
|
||||
|
@ -10,11 +11,11 @@ pub struct Funct {
|
|||
gives: Vec<String>,
|
||||
}
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Protocol<'a> {
|
||||
types: HashMap<&'a str, Type>,
|
||||
fns: HashMap<&'a str, Funct>,
|
||||
pub struct Protocol {
|
||||
types: HashMap<String, Type>,
|
||||
fns: HashMap<String, Funct>,
|
||||
}
|
||||
impl<'a> Protocol<'a> {
|
||||
impl Protocol {
|
||||
pub fn void() -> Self {
|
||||
Self {
|
||||
types: HashMap::new(),
|
||||
|
@ -27,8 +28,8 @@ impl<'a> Protocol<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Protocol<'a> {
|
||||
fn from(value: &'a str) -> Self {
|
||||
impl From<String> for Protocol {
|
||||
fn from(value: alloc::string::String) -> Self {
|
||||
let mut hm_t = HashMap::new();
|
||||
hm_t.insert(value, Type {});
|
||||
Self {
|
||||
|
|
|
@ -2,25 +2,27 @@
|
|||
|
||||
use {
|
||||
crate::{
|
||||
arch::hardware_random_u64,
|
||||
bootmodules::BootModules,
|
||||
//bootmodules::build_cmd,
|
||||
arch::{hardware_random_u64, logging::SERIAL_CONSOLE},
|
||||
bootmodules::{build_cmd, BootModules},
|
||||
capabilities,
|
||||
device_tree::DeviceTree,
|
||||
holeybytes::ExecThread,
|
||||
ipc::buffer::IpcBuffer,
|
||||
ipc::buffer::{self, IpcBuffer},
|
||||
},
|
||||
alloc::format,
|
||||
hashbrown::HashMap,
|
||||
hbvm::mem::Address,
|
||||
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
||||
log::{debug, info},
|
||||
log::{debug, info, trace},
|
||||
spin::{Lazy, Mutex},
|
||||
xml::XMLElement,
|
||||
};
|
||||
|
||||
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||
pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
||||
debug!("Entered kmain");
|
||||
|
||||
// let kcmd = build_cmd("Kernel Command Line", cmdline);
|
||||
// trace!("Cmdline: {kcmd:?}");
|
||||
let kcmd = build_cmd("Kernel Command Line", cmdline);
|
||||
trace!("Cmdline: {kcmd:?}");
|
||||
|
||||
// for (i, bm) in boot_modules.iter().enumerate() {
|
||||
// let name = format!("module-{}", i);
|
||||
|
@ -66,18 +68,17 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
fb1.address.as_ptr().unwrap() as *const u8
|
||||
);
|
||||
|
||||
let mut executor = crate::task::Executor::new(256);
|
||||
let mut executor = crate::task::Executor::default();
|
||||
let bm_take = boot_modules.len();
|
||||
unsafe {
|
||||
for module in boot_modules.into_iter().take(bm_take) {
|
||||
let mut cmd = module.cmd;
|
||||
if cmd.len() > 2 {
|
||||
// // Remove the quotes
|
||||
// cmd.remove(0);
|
||||
// cmd.pop();
|
||||
cmd = &cmd[1..cmd.len()]
|
||||
// Remove the quotes
|
||||
cmd.remove(0);
|
||||
cmd.pop();
|
||||
}
|
||||
let cmd_len = cmd.len() as u64;
|
||||
let cmd_len = cmd.as_bytes().len() as u64;
|
||||
|
||||
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||
|
||||
|
@ -86,10 +87,11 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
if cmd_len > 0 {
|
||||
thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len);
|
||||
}
|
||||
|
||||
if let Err(e) = thr.await {
|
||||
log::error!("{e:?}");
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
info!("Random number: {}", hardware_random_u64());
|
||||
|
@ -106,7 +108,8 @@ pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
|||
});
|
||||
pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||
|
||||
pub type IpcBuffers<'a> = HashMap<u64, IpcBuffer<'a>>;
|
||||
use alloc::vec::Vec;
|
||||
pub type IpcBuffers = HashMap<u64, IpcBuffer>;
|
||||
pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
|
||||
let mut bufs = HashMap::new();
|
||||
let log_buffer = IpcBuffer::new(false, 0);
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
//! The ableOS kernel.
|
||||
//! Named akern.
|
||||
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
|
||||
|
||||
#![no_std]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(
|
||||
abi_x86_interrupt,
|
||||
alloc_error_handler,
|
||||
inline_const,
|
||||
panic_info_message,
|
||||
pointer_is_aligned,
|
||||
ptr_sub_ptr,
|
||||
custom_test_frameworks,
|
||||
naked_functions,
|
||||
pointer_is_aligned_to
|
||||
)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
|
||||
#![allow(dead_code)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
extern crate alloc;
|
||||
|
||||
mod allocator;
|
||||
|
@ -40,7 +42,6 @@ pub const VERSION: Version = Version {
|
|||
};
|
||||
|
||||
#[panic_handler]
|
||||
#[cfg(target_os = "none")]
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
arch::register_dump();
|
||||
|
||||
|
@ -53,8 +54,10 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
|||
));
|
||||
}
|
||||
|
||||
let msg = info.message();
|
||||
let _ = crate::arch::log(format_args!("{msg}\r\n"));
|
||||
if let Some(msg) = info.message() {
|
||||
let _ = crate::arch::log(format_args!("{msg}\r\n"));
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![allow(deprecated)]
|
||||
// TODO: Add a logger api with logger levels and various outputs
|
||||
pub static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||
|
||||
|
@ -10,11 +9,7 @@ use {
|
|||
|
||||
pub fn init() -> Result<(), SetLoggerError> {
|
||||
log::set_logger(&crate::logger::Logger)?;
|
||||
if cfg!(debug_assertions) {
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
} else {
|
||||
log::set_max_level(log::LevelFilter::Info);
|
||||
}
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
|
||||
Lazy::force(&TERMINAL_LOGGER);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! The Memory Manager
|
||||
|
||||
use {alloc::collections::VecDeque, derive_more::*};
|
||||
use alloc::collections::VecDeque;
|
||||
use derive_more::*;
|
||||
|
||||
pub use crate::arch::PAGE_SIZE;
|
||||
pub const MAX_ORDER: usize = 10;
|
||||
|
@ -43,7 +44,7 @@ pub const MAX_ORDER: usize = 10;
|
|||
Sum,
|
||||
UpperHex,
|
||||
)]
|
||||
#[display("0x{:x}", _0)]
|
||||
#[display(fmt = "0x{:x}", _0)]
|
||||
#[from(forward)]
|
||||
pub struct VirtualAddress(usize);
|
||||
|
||||
|
@ -54,11 +55,11 @@ impl VirtualAddress {
|
|||
pub fn vpns(&self) -> [usize; 3] {
|
||||
[
|
||||
// [20:12]
|
||||
(self.0 >> 12) & 0x1FF,
|
||||
(self.0 >> 12) & 0x1ff,
|
||||
// [29:21]
|
||||
(self.0 >> 21) & 0x1FF,
|
||||
(self.0 >> 21) & 0x1ff,
|
||||
// [38:30]
|
||||
(self.0 >> 30) & 0x1FF,
|
||||
(self.0 >> 30) & 0x1ff,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -113,7 +114,7 @@ impl VirtualAddress {
|
|||
Sum,
|
||||
UpperHex,
|
||||
)]
|
||||
#[display("0x{:x}", _0)]
|
||||
#[display(fmt = "0x{:x}", _0)]
|
||||
#[from(forward)]
|
||||
pub struct PhysicalAddress(usize);
|
||||
|
||||
|
@ -124,11 +125,11 @@ impl PhysicalAddress {
|
|||
pub fn ppns(&self) -> [usize; 3] {
|
||||
[
|
||||
// [20:12]
|
||||
(self.0 >> 12) & 0x1FF,
|
||||
(self.0 >> 12) & 0x1ff,
|
||||
// [29:21]
|
||||
(self.0 >> 21) & 0x1FF,
|
||||
(self.0 >> 21) & 0x1ff,
|
||||
// [55:30]
|
||||
(self.0 >> 30) & 0x3FFFFFF,
|
||||
(self.0 >> 30) & 0x3ffffff,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use {
|
||||
alloc::{boxed::Box, sync::Arc},
|
||||
alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake},
|
||||
core::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
||||
task::{Context, Poll, Waker},
|
||||
},
|
||||
crossbeam_queue::SegQueue,
|
||||
kiam::when,
|
||||
slab::Slab,
|
||||
spin::RwLock,
|
||||
};
|
||||
|
||||
static SPAWN_QUEUE: RwLock<Option<SpawnQueue>> = RwLock::new(None);
|
||||
pub fn spawn(future: impl Future<Output = ()> + Send + 'static) {
|
||||
match &*SPAWN_QUEUE.read() {
|
||||
Some(s) => s.push(Task::new(future)),
|
||||
None => panic!("no task executor is running"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn yield_now() -> impl Future<Output = ()> {
|
||||
struct YieldNow(bool);
|
||||
impl Future for YieldNow {
|
||||
type Output = ();
|
||||
|
||||
#[inline(always)]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.0 {
|
||||
Poll::Ready(())
|
||||
|
@ -29,150 +40,101 @@ pub fn yield_now() -> impl Future<Output = ()> {
|
|||
YieldNow(false)
|
||||
}
|
||||
|
||||
pub struct Executor<F: Future<Output = ()> + Send> {
|
||||
tasks: Slab<Task<F>>,
|
||||
task_queue: Arc<TaskQueue>,
|
||||
#[derive(Default)]
|
||||
pub struct Executor {
|
||||
tasks: Slab<Task>,
|
||||
queue: TaskQueue,
|
||||
to_spawn: SpawnQueue,
|
||||
wakers: BTreeMap<TaskId, Waker>,
|
||||
}
|
||||
|
||||
impl<F: Future<Output = ()> + Send> Executor<F> {
|
||||
pub fn new(size: usize) -> Self {
|
||||
Self {
|
||||
tasks: Slab::with_capacity(size),
|
||||
task_queue: Arc::new(TaskQueue::new()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn spawn(&mut self, future: F) {
|
||||
self.task_queue
|
||||
.queue
|
||||
.push(self.tasks.insert(Task::new(future)));
|
||||
impl Executor {
|
||||
pub fn spawn(&mut self, future: impl Future<Output = ()> + Send + 'static) {
|
||||
self.queue
|
||||
.push(TaskId(self.tasks.insert(Task::new(future))));
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let mut task_batch = [0; 32];
|
||||
let mut batch_len = 0;
|
||||
{
|
||||
let mut global_spawner = SPAWN_QUEUE.write();
|
||||
if global_spawner.is_some() {
|
||||
panic!("Task executor is already running");
|
||||
}
|
||||
|
||||
*global_spawner = Some(Arc::clone(&self.to_spawn));
|
||||
}
|
||||
|
||||
loop {
|
||||
self.task_queue.batch_pop(&mut task_batch, &mut batch_len);
|
||||
when! {
|
||||
let Some(id) = self
|
||||
.to_spawn
|
||||
.pop()
|
||||
.map(|t| TaskId(self.tasks.insert(t)))
|
||||
.or_else(|| self.queue.pop())
|
||||
=> {
|
||||
let Some(task) = self.tasks.get_mut(id.0) else {
|
||||
panic!("Attempted to get task from empty slot: {}", id.0);
|
||||
};
|
||||
|
||||
if batch_len == 0 {
|
||||
if self.task_queue.is_empty() {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| {
|
||||
Waker::from(Arc::new(TaskWaker {
|
||||
id,
|
||||
queue: Arc::clone(&self.queue),
|
||||
}))
|
||||
}));
|
||||
|
||||
for &id in &task_batch[..batch_len] {
|
||||
if let Some(task) = self.tasks.get_mut(id) {
|
||||
let waker = task
|
||||
.waker
|
||||
.get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue)));
|
||||
|
||||
let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) };
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
if let Poll::Ready(()) = task.poll(&mut cx) {
|
||||
self.tasks.remove(id);
|
||||
self.task_queue.free_tasks.push(id);
|
||||
match task.poll(&mut cx) {
|
||||
Poll::Ready(()) => {
|
||||
self.tasks.remove(id.0);
|
||||
self.wakers.remove(&id);
|
||||
}
|
||||
Poll::Pending => (),
|
||||
}
|
||||
}
|
||||
},
|
||||
self.tasks.is_empty() => break,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
*SPAWN_QUEUE.write() = None;
|
||||
}
|
||||
}
|
||||
|
||||
struct Task<F: Future<Output = ()> + Send> {
|
||||
future: Pin<Box<F>>,
|
||||
waker: Option<TaskWaker>,
|
||||
struct Task {
|
||||
future: Pin<Box<dyn Future<Output = ()> + Send>>,
|
||||
}
|
||||
|
||||
impl<F: Future<Output = ()> + Send> Task<F> {
|
||||
#[inline(always)]
|
||||
pub fn new(future: F) -> Self {
|
||||
impl Task {
|
||||
pub fn new(future: impl Future<Output = ()> + Send + 'static) -> Self {
|
||||
log::trace!("New task scheduled");
|
||||
Self {
|
||||
future: Box::pin(future),
|
||||
waker: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
|
||||
self.future.as_mut().poll(cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct TaskId(usize);
|
||||
|
||||
type TaskQueue = Arc<SegQueue<TaskId>>;
|
||||
type SpawnQueue = Arc<SegQueue<Task>>;
|
||||
|
||||
struct TaskWaker {
|
||||
id: usize,
|
||||
task_queue: Arc<TaskQueue>,
|
||||
id: TaskId,
|
||||
queue: TaskQueue,
|
||||
}
|
||||
|
||||
impl TaskWaker {
|
||||
#[inline(always)]
|
||||
fn new(id: usize, task_queue: Arc<TaskQueue>) -> Self {
|
||||
Self { id, task_queue }
|
||||
impl Wake for TaskWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
log::trace!("Woke Task-{:?}", self.id);
|
||||
self.wake_by_ref();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn wake(&self) {
|
||||
self.task_queue.queue.push(self.id);
|
||||
}
|
||||
|
||||
fn into_raw_waker(waker: &TaskWaker) -> RawWaker {
|
||||
let ptr = waker as *const TaskWaker;
|
||||
RawWaker::new(ptr.cast(), &VTABLE)
|
||||
}
|
||||
}
|
||||
|
||||
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw);
|
||||
|
||||
unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
|
||||
let waker = &*(ptr as *const TaskWaker);
|
||||
TaskWaker::into_raw_waker(waker)
|
||||
}
|
||||
|
||||
unsafe fn wake_raw(ptr: *const ()) {
|
||||
let waker = &*(ptr as *const TaskWaker);
|
||||
waker.wake();
|
||||
}
|
||||
|
||||
unsafe fn wake_by_ref_raw(ptr: *const ()) {
|
||||
let waker = &*(ptr as *const TaskWaker);
|
||||
waker.wake();
|
||||
}
|
||||
|
||||
unsafe fn drop_raw(_: *const ()) {}
|
||||
|
||||
struct TaskQueue {
|
||||
queue: SegQueue<usize>,
|
||||
next_task: usize,
|
||||
free_tasks: SegQueue<usize>,
|
||||
}
|
||||
|
||||
impl TaskQueue {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
queue: SegQueue::new(),
|
||||
next_task: 0,
|
||||
free_tasks: SegQueue::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn batch_pop(&self, output: &mut [usize], len: &mut usize) {
|
||||
*len = 0;
|
||||
while let Some(id) = self.queue.pop() {
|
||||
output[*len] = id;
|
||||
*len += 1;
|
||||
if *len == output.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.queue.is_empty()
|
||||
fn wake_by_ref(self: &Arc<Self>) {
|
||||
self.queue.push(self.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,26 +4,15 @@ version = "0.2.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
str-reader = "0.1"
|
||||
derive_more = { version = "1", default-features = false, features = [
|
||||
"add",
|
||||
"add_assign",
|
||||
"constructor",
|
||||
"display",
|
||||
"from",
|
||||
"into",
|
||||
"mul",
|
||||
"mul_assign",
|
||||
"not",
|
||||
"sum",
|
||||
] }
|
||||
error-stack = "0.5"
|
||||
str-reader = "0.1.2"
|
||||
derive_more = "0.99"
|
||||
error-stack = "0.4"
|
||||
fatfs = "0.3"
|
||||
toml = "0.8"
|
||||
toml = "0.5.2"
|
||||
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.12"
|
||||
version = "0.11"
|
||||
default-features = false
|
||||
features = ["rustls-tls", "blocking"]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![allow(unused)]
|
||||
use std::{
|
||||
fmt::format,
|
||||
fs::{read_to_string, File},
|
||||
|
@ -86,17 +85,9 @@ impl Package {
|
|||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||
Err(e) => panic!("{}", e),
|
||||
}
|
||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
|
||||
bytes.clear();
|
||||
let _ = hblang::run_compiler(
|
||||
&path,
|
||||
Options {
|
||||
dump_asm: true,
|
||||
..Default::default()
|
||||
},
|
||||
&mut bytes,
|
||||
);
|
||||
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
|
||||
let path = format!("target/programs/{}.hbf", self.name);
|
||||
let mut file = File::create(path).unwrap();
|
||||
file.write_all(&bytes).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// #![allow(unused)]
|
||||
|
||||
mod dev;
|
||||
|
||||
use {
|
||||
|
@ -8,7 +6,7 @@ use {
|
|||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||
std::{
|
||||
// fmt::Display,
|
||||
fmt::Display,
|
||||
fs::{self, File},
|
||||
io::{self, Write},
|
||||
path::Path,
|
||||
|
@ -24,13 +22,10 @@ fn main() -> Result<(), Error> {
|
|||
match args.next().as_deref() {
|
||||
Some("build" | "b") => {
|
||||
let mut release = false;
|
||||
let mut debuginfo = false;
|
||||
let mut target = Target::X86_64;
|
||||
for arg in args {
|
||||
if arg == "-r" || arg == "--release" {
|
||||
release = true;
|
||||
} else if arg == "-d" || arg == "--debuginfo" {
|
||||
debuginfo = true;
|
||||
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||
target = Target::Riscv64Virt;
|
||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||
|
@ -40,17 +35,14 @@ fn main() -> Result<(), Error> {
|
|||
}
|
||||
}
|
||||
|
||||
build(release, target, debuginfo).change_context(Error::Build)
|
||||
build(release, target).change_context(Error::Build)
|
||||
}
|
||||
Some("run" | "r") => {
|
||||
let mut release = false;
|
||||
let mut debuginfo = false;
|
||||
let mut target = Target::X86_64;
|
||||
for arg in args {
|
||||
if arg == "-r" || arg == "--release" {
|
||||
release = true;
|
||||
} else if arg == "-d" || arg == "--debuginfo" {
|
||||
debuginfo = true;
|
||||
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||
target = Target::Riscv64Virt;
|
||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||
|
@ -60,7 +52,7 @@ fn main() -> Result<(), Error> {
|
|||
}
|
||||
}
|
||||
|
||||
build(release, target, debuginfo)?;
|
||||
build(release, target)?;
|
||||
run(release, target)
|
||||
}
|
||||
Some("help" | "h") => {
|
||||
|
@ -195,7 +187,7 @@ TERM_BACKDROP={}
|
|||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||
// let mut real_modules = modules.clone();
|
||||
|
||||
modules.into_iter().for_each(|(_, value)| {
|
||||
modules.into_iter().for_each(|(key, value)| {
|
||||
if value.is_table() {
|
||||
let path = get_path_without_boot_prefix(
|
||||
value.get("path").expect("You must have `path` as a value"),
|
||||
|
@ -244,7 +236,7 @@ TERM_BACKDROP={}
|
|||
let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?;
|
||||
|
||||
let mut f = fs.root_dir().create_file("limine.cfg")?;
|
||||
let _ = f.write(limine_str.as_bytes())?;
|
||||
let a = f.write(limine_str.as_bytes())?;
|
||||
drop(f);
|
||||
|
||||
io::copy(
|
||||
|
@ -278,7 +270,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
|
|||
.expect("Copy failed");
|
||||
}
|
||||
|
||||
fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||
fn build(release: bool, target: Target) -> Result<(), Error> {
|
||||
let fs = get_fs().change_context(Error::Io)?;
|
||||
let mut com = Command::new("cargo");
|
||||
com.current_dir("kernel");
|
||||
|
@ -286,9 +278,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
|||
if release {
|
||||
com.arg("-r");
|
||||
}
|
||||
if debuginfo {
|
||||
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
|
||||
}
|
||||
|
||||
if target == Target::Riscv64Virt {
|
||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||
|
@ -370,7 +359,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-M", "virt",
|
||||
"-cpu", "neoverse-n2",
|
||||
"-cpu", "cortex-a72",
|
||||
"-device", "ramfb",
|
||||
"-device", "qemu-xhci",
|
||||
"-device", "usb-kbd",
|
||||
|
@ -429,11 +418,11 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
|||
|
||||
#[derive(Debug, Display)]
|
||||
enum OvmfFetchError {
|
||||
#[display("Failed to fetch OVMF package")]
|
||||
#[display(fmt = "Failed to fetch OVMF package")]
|
||||
Fetch,
|
||||
#[display("No OVMF package available")]
|
||||
#[display(fmt = "No OVMF package available")]
|
||||
Empty,
|
||||
#[display("IO Error")]
|
||||
#[display(fmt = "IO Error")]
|
||||
Io,
|
||||
}
|
||||
|
||||
|
@ -446,28 +435,26 @@ enum Target {
|
|||
Aarch64,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Debug, Display)]
|
||||
enum Error {
|
||||
#[display("Failed to build the kernel")]
|
||||
#[display(fmt = "Failed to build the kernel")]
|
||||
Build,
|
||||
#[display("Missing or invalid subcommand (available: build, run)")]
|
||||
#[display(fmt = "Missing or invalid subcommand (available: build, run)")]
|
||||
InvalidSubCom,
|
||||
#[display("IO Error")]
|
||||
#[display(fmt = "IO Error")]
|
||||
Io,
|
||||
#[display("Failed to spawn a process")]
|
||||
#[display(fmt = "Failed to spawn a process")]
|
||||
ProcessSpawn,
|
||||
#[display("Failed to fetch UEFI firmware")]
|
||||
#[display(fmt = "Failed to fetch UEFI firmware")]
|
||||
OvmfFetch,
|
||||
#[display("Failed to assemble Holey Bytes code")]
|
||||
#[display(fmt = "Failed to assemble Holey Bytes code")]
|
||||
Assembler,
|
||||
#[display("QEMU Error: {}", "fmt_qemu_err(*_0)")]
|
||||
#[display(fmt = "QEMU Error: {}", "fmt_qemu_err(*_0)")]
|
||||
Qemu(Option<i32>),
|
||||
}
|
||||
|
||||
impl Context for Error {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn fmt_qemu_err(e: Option<i32>) -> impl Display {
|
||||
struct W(Option<i32>);
|
||||
impl Display for W {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-07-27"
|
||||
channel = "nightly-2024-05-17"
|
||||
components = ["rust-src", "llvm-tools"]
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
OutOfHostMemory := -1
|
||||
OutOfDeviceMemory := -2
|
||||
InitializationFailed := -3
|
||||
DeviceLost := -4
|
||||
MemoryMapFailed := -5
|
||||
// the 0- thing is scuffed
|
||||
|
||||
LayerNotPresent := -6
|
||||
ExtensionNotPresent := -7
|
||||
FeatureNotPresent := -8
|
||||
IncompatibleDriver := -9
|
||||
TooManyObjects := -10
|
||||
FormatNotSupported := -11
|
||||
FragmentedPool := -12
|
||||
Unknown := -13
|
||||
OutOfHostMemory := 0 - 1
|
||||
OutOfDeviceMemory := 0 - 2
|
||||
InitializationFailed := 0 - 3
|
||||
DeviceLost := 0 - 4
|
||||
MemoryMapFailed := 0 - 5
|
||||
|
||||
LayerNotPresent := 0 - 6
|
||||
ExtensionNotPresent := 0 - 7
|
||||
FeatureNotPresent := 0 - 8
|
||||
IncompatibleDriver := 0 - 9
|
||||
TooManyObjects := 0 - 10
|
||||
FormatNotSupported := 0 - 11
|
||||
FragmentedPool := 0 - 12
|
||||
Unknown := 0 - 13
|
|
@ -1,9 +0,0 @@
|
|||
Rendering interface for SVGA and Software renderers
|
||||
|
||||
# TODO:
|
||||
|
||||
- SVGA Driver
|
||||
- needs pci driver
|
||||
- needs init (requiring program)
|
||||
- Double Buffer mode for Software renderer
|
||||
- needs init (requiring program)
|
|
@ -1,47 +0,0 @@
|
|||
svga := @use("rel:svga.hb")
|
||||
software := @use("rel:software.hb")
|
||||
|
||||
// default mode
|
||||
mode := software
|
||||
|
||||
init := mode.init
|
||||
doublebuffer := mode.doublebuffer
|
||||
|
||||
// Colours
|
||||
Color := mode.Color
|
||||
white := mode.white
|
||||
black := mode.black
|
||||
gray := mode.gray
|
||||
red := mode.red
|
||||
green := mode.green
|
||||
yellow := mode.yellow
|
||||
blue := mode.blue
|
||||
magenta := mode.magenta
|
||||
cyan := mode.cyan
|
||||
light_gray := mode.light_gray
|
||||
light_red := mode.light_red
|
||||
light_green := mode.light_green
|
||||
light_yellow := mode.light_yellow
|
||||
light_blue := mode.light_blue
|
||||
light_magenta := mode.light_magenta
|
||||
light_cyan := mode.light_cyan
|
||||
|
||||
// Drawing
|
||||
put_pixel := mode.put_pixel
|
||||
put_rect := mode.put_rect
|
||||
put_filled_rect := mode.put_filled_rect
|
||||
put_line := mode.put_line
|
||||
clear := mode.clear
|
||||
|
||||
// Display
|
||||
width := mode.width
|
||||
height := mode.height
|
||||
dimensions := mode.dimensions
|
||||
set_height := mode.set_height
|
||||
set_width := mode.set_width
|
||||
set_dimensions := mode.set_dimensions
|
||||
sync := mode.sync
|
||||
|
||||
// Math
|
||||
UVec2 := struct {x: uint, y: uint}
|
||||
IVec2 := struct {x: int, y: int}
|
|
@ -1,261 +0,0 @@
|
|||
.{math, memory} := @use("../../stn/src/lib.hb");
|
||||
.{dt_get} := @use("../../dt_api/src/lib.hb");
|
||||
.{IVec2} := @use("rel:lib.hb")
|
||||
|
||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
||||
white := Color.(255, 255, 255, 255)
|
||||
black := Color.(0, 0, 0, 255)
|
||||
gray := Color.(127, 127, 127, 255)
|
||||
red := Color.(0, 0, 205, 255)
|
||||
green := Color.(0, 205, 0, 255)
|
||||
yellow := Color.(0, 205, 205, 255)
|
||||
blue := Color.(205, 0, 0, 255)
|
||||
magenta := Color.(205, 0, 205, 255)
|
||||
cyan := Color.(205, 205, 0, 255)
|
||||
light_gray := Color.(229, 229, 229, 255)
|
||||
light_red := Color.(0, 0, 255, 255)
|
||||
light_green := Color.(0, 255, 0, 255)
|
||||
light_yellow := Color.(0, 255, 255, 255)
|
||||
light_blue := Color.(255, 0, 0, 255)
|
||||
light_magenta := Color.(255, 0, 255, 255)
|
||||
light_cyan := Color.(255, 255, 0, 255)
|
||||
|
||||
// might not work for some resolutions, but needs to be comptime because...
|
||||
copy_pixels := 0xC000 >> 2
|
||||
|
||||
ctx := @as(Context, idk)
|
||||
|
||||
// some of these are redudant holdovers from fb_driver
|
||||
// will keep them for future work if necessary
|
||||
Context := struct {
|
||||
fb: ^Color,
|
||||
bb: ^Color,
|
||||
buf: ^Color,
|
||||
width: int,
|
||||
height: int,
|
||||
partitions: int,
|
||||
pixels: int,
|
||||
bb_pages: int,
|
||||
double_buffer: bool,
|
||||
}
|
||||
|
||||
init := fn(): void {
|
||||
width := dt_get("framebuffer/fb0/width\0")
|
||||
height := dt_get("framebuffer/fb0/height\0")
|
||||
// width := 1024
|
||||
// height := 768
|
||||
pixels := width * height
|
||||
bytes := pixels << 2
|
||||
partitions := pixels / copy_pixels
|
||||
pages := 1 + bytes >> 12
|
||||
back_buffer := create_back_buffer(pages)
|
||||
ctx = Context.{
|
||||
fb: dt_get("framebuffer/fb0/ptr\0"),
|
||||
bb: back_buffer,
|
||||
buf: back_buffer,
|
||||
width,
|
||||
height,
|
||||
partitions,
|
||||
pixels,
|
||||
bb_pages: pages,
|
||||
double_buffer: true,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
doublebuffer := fn(enable: bool): void {
|
||||
if enable {
|
||||
ctx.buf = ctx.bb
|
||||
} else {
|
||||
ctx.buf = ctx.fb
|
||||
}
|
||||
ctx.double_buffer = enable
|
||||
return
|
||||
}
|
||||
|
||||
create_back_buffer := fn(pages: int): ^Color {
|
||||
if pages <= 0xFF {
|
||||
return @bitcast(@inline(memory.request_page, pages))
|
||||
}
|
||||
ptr := @inline(memory.request_page, 255)
|
||||
remaining := pages - 0xFF
|
||||
loop if remaining <= 0 break else {
|
||||
if remaining < 0xFF {
|
||||
memory.request_page(remaining)
|
||||
} else {
|
||||
memory.request_page(0xFF)
|
||||
}
|
||||
remaining -= 0xFF
|
||||
}
|
||||
return @bitcast(ptr)
|
||||
}
|
||||
|
||||
clear := fn(color: Color): void {
|
||||
cursor := ctx.buf
|
||||
boundary := cursor + 512
|
||||
loop if cursor == boundary break else {
|
||||
*cursor = color
|
||||
cursor += 1
|
||||
}
|
||||
boundary += 512 * 7
|
||||
loop if cursor == boundary break else {
|
||||
*@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(ctx.buf))
|
||||
cursor += 512
|
||||
}
|
||||
boundary += copy_pixels - 4096
|
||||
loop if cursor == boundary break else {
|
||||
*@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(ctx.buf))
|
||||
cursor += 4096
|
||||
}
|
||||
boundary += (ctx.partitions - 1) * copy_pixels
|
||||
loop if cursor == boundary break else {
|
||||
*@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(ctx.buf))
|
||||
cursor += @sizeof([u8; copy_pixels])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
sync := fn(): void {
|
||||
if ctx.double_buffer {
|
||||
bb := ctx.buf
|
||||
fb := ctx.fb
|
||||
boundary := bb + ctx.pixels
|
||||
loop if bb == boundary break else {
|
||||
*@as(^[Color; copy_pixels], @bitcast(fb)) = *@as(^[Color; copy_pixels], @bitcast(bb))
|
||||
bb += copy_pixels
|
||||
fb += copy_pixels
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
width := fn(): int {
|
||||
return ctx.width
|
||||
}
|
||||
|
||||
height := fn(): int {
|
||||
return ctx.height
|
||||
}
|
||||
|
||||
screenidx := fn(x: int, y: int): int {
|
||||
return x + ctx.width * y
|
||||
}
|
||||
|
||||
put_pixel := fn(pos: IVec2, color: Color): void {
|
||||
*(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color
|
||||
return
|
||||
}
|
||||
|
||||
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||
x := pos.x
|
||||
y := pos.y
|
||||
end := pos + tr
|
||||
loop if x == end.x break else {
|
||||
loop if y == end.y break else {
|
||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||
y += 1
|
||||
}
|
||||
x += 1
|
||||
y = pos.y
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||
x := pos.x
|
||||
y := pos.y
|
||||
end := pos + tr
|
||||
loop if y == end.y break else {
|
||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
||||
*(ctx.buf + @inline(screenidx, x + tr.x, y)) = color
|
||||
y += 1
|
||||
}
|
||||
y = pos.y
|
||||
loop if x == end.x break else {
|
||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
||||
*(ctx.buf + @inline(screenidx, x, y + tr.y)) = color
|
||||
x += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
dx := p1.x - p0.x
|
||||
dy := p1.y - p0.y
|
||||
yi := 1
|
||||
if dy < 0 {
|
||||
yi = -1
|
||||
dy = -dy
|
||||
}
|
||||
D := 2 * dy - dx
|
||||
y := p0.y
|
||||
x := p0.x
|
||||
loop if x == p1.x break else {
|
||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||
if D > 0 {
|
||||
y += yi
|
||||
D += 2 * (dy - dx)
|
||||
} else {
|
||||
D += 2 * dy
|
||||
}
|
||||
x += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
dx := p1.x - p0.x
|
||||
dy := p1.y - p0.y
|
||||
xi := 1
|
||||
if dy < 0 {
|
||||
xi = -1
|
||||
dx = -dx
|
||||
}
|
||||
D := 2 * dx - dy
|
||||
x := p0.x
|
||||
y := p0.y
|
||||
loop if y == p1.y break else {
|
||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||
if D > 0 {
|
||||
x += xi
|
||||
D += 2 * (dx - dy)
|
||||
} else {
|
||||
D += 2 * dx
|
||||
}
|
||||
y += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) {
|
||||
if p0.x > p1.x {
|
||||
@inline(put_line_low, p1, p0, color)
|
||||
} else {
|
||||
@inline(put_line_low, p0, p1, color)
|
||||
}
|
||||
} else {
|
||||
if p0.y > p1.y {
|
||||
@inline(put_line_high, p1, p0, color)
|
||||
} else {
|
||||
@inline(put_line_high, p0, p1, color)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
set_height := fn(new: int): void {
|
||||
return
|
||||
}
|
||||
|
||||
set_width := fn(new: int): void {
|
||||
return
|
||||
}
|
||||
|
||||
dimensions := fn(): IVec2 {
|
||||
return .(ctx.width, ctx.height)
|
||||
}
|
||||
|
||||
set_dimensions := fn(new: IVec2): void {
|
||||
return
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
.{IVec2} := @use("rel:lib.hb")
|
||||
// .{pci, memory, string, log} := @use("../../stn/src/lib.hb");
|
||||
|
||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
||||
white := Color.(255, 255, 255, 255)
|
||||
black := Color.(0, 0, 0, 255)
|
||||
gray := Color.(127, 127, 127, 255)
|
||||
red := Color.(0, 0, 205, 255)
|
||||
green := Color.(0, 205, 0, 255)
|
||||
yellow := Color.(0, 205, 205, 255)
|
||||
blue := Color.(205, 0, 0, 255)
|
||||
magenta := Color.(205, 0, 205, 255)
|
||||
cyan := Color.(205, 205, 0, 255)
|
||||
light_gray := Color.(229, 229, 229, 255)
|
||||
light_red := Color.(0, 0, 255, 255)
|
||||
light_green := Color.(0, 255, 0, 255)
|
||||
light_yellow := Color.(0, 255, 255, 255)
|
||||
light_blue := Color.(255, 0, 0, 255)
|
||||
light_magenta := Color.(255, 0, 255, 255)
|
||||
light_cyan := Color.(255, 255, 0, 255)
|
||||
|
||||
clear := fn(color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
width := fn(): int {
|
||||
return 0
|
||||
}
|
||||
|
||||
height := fn(): int {
|
||||
return 0
|
||||
}
|
||||
|
||||
dimensions := fn(): IVec2 {
|
||||
return .(0, 0)
|
||||
}
|
||||
|
||||
put_pixel := fn(position: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
// do not use, use line() instead
|
||||
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||
return
|
||||
}
|
||||
|
||||
set_height := fn(new: int): void {
|
||||
return
|
||||
}
|
||||
|
||||
set_width := fn(new: int): void {
|
||||
return
|
||||
}
|
||||
|
||||
set_dimensions := fn(new: IVec2): void {
|
||||
return
|
||||
}
|
||||
|
||||
sync := fn(): void {
|
||||
return
|
||||
}
|
||||
|
||||
init := fn(): void {
|
||||
return
|
||||
}
|
|
@ -4,20 +4,21 @@ receive_message := fn(buffer_id: int, memory_map_location: ^u8, length: int): ^u
|
|||
return @eca(^u8, 4, buffer_id, memory_map_location, length)
|
||||
}
|
||||
|
||||
send_message := fn(msg: ^u8, buffer_id: int): void {
|
||||
msg_length := @inline(string.length, msg)
|
||||
@eca(i32, 3, buffer_id, msg, msg_length)
|
||||
send_message := fn(buffer_id: int): void {
|
||||
message := "Hello there\0"
|
||||
message_length := string.length(message)
|
||||
@eca(i32, 3, buffer_id, message, message_length)
|
||||
return
|
||||
}
|
||||
|
||||
create := fn(msg: ^u8): int {
|
||||
msg_length := @inline(string.length, msg);
|
||||
msg_length := string.length(msg);
|
||||
*msg = 0
|
||||
return @eca(int, 3, 0, msg, msg_length)
|
||||
}
|
||||
|
||||
search := fn(msg: ^u8): int {
|
||||
msg_length := @inline(string.length, msg);
|
||||
msg_length := string.length(msg);
|
||||
*msg = 3
|
||||
|
||||
return @eca(int, 3, 0, msg, msg_length)
|
||||
|
|
|
@ -3,5 +3,3 @@ log := @use("rel:log.hb")
|
|||
memory := @use("rel:memory.hb")
|
||||
buffer := @use("rel:buffer.hb")
|
||||
math := @use("rel:math.hb")
|
||||
random := @use("rel:random.hb")
|
||||
pci := @use("rel:pci.hb")
|
|
@ -2,7 +2,7 @@ string := @use("rel:string.hb")
|
|||
buffer := @use("rel:buffer.hb")
|
||||
|
||||
log := fn(message: ^u8, level: u8): void {
|
||||
message_length := @inline(string.length, message);
|
||||
message_length := string.length(message);
|
||||
*(message + message_length) = level
|
||||
@eca(i32, 3, 1, message, message_length + 1)
|
||||
return
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
shift := 31
|
||||
|
||||
// following only work for: int
|
||||
abs := fn(x: int): int {
|
||||
mask := x >> shift
|
||||
mask := x >> 31
|
||||
return (x ^ mask) - mask
|
||||
}
|
||||
min := fn(a: int, b: int): int {
|
||||
c := a - b
|
||||
return b + (c & c >> shift)
|
||||
}
|
||||
max := fn(a: int, b: uint): int {
|
||||
c := a - b
|
||||
return a - (c & c >> shift)
|
||||
return b + (a - b & a - b >> 31)
|
||||
}
|
|
@ -17,38 +17,19 @@ release_page := fn(ptr: ^u8, page_count: u8): void {
|
|||
return @eca(void, 3, 2, msg, 12)
|
||||
}
|
||||
|
||||
outb := fn(addr: u16, value: u8): void {
|
||||
msg := "\0\0\0\0\0";
|
||||
*@as(^u8, msg) = @as(u8, 1);
|
||||
*@as(^u8, msg + 1) = @as(u8, 0);
|
||||
*@as(^u16, @bitcast(msg + 2)) = addr;
|
||||
*@as(^u8, msg + 4) = value
|
||||
@eca(void, 3, 3, msg, 5)
|
||||
outb := fn(addr_high: u8, addr_low: u8, value: u8): void {
|
||||
msg := "\0\0\0\0";
|
||||
*msg = 1;
|
||||
*(msg + 1) = addr_high;
|
||||
*(msg + 2) = addr_low;
|
||||
*(msg + 3) = value
|
||||
@eca(void, 3, 3, msg, 4)
|
||||
return
|
||||
}
|
||||
|
||||
inb := fn(addr: u16): u8 {
|
||||
inb := fn(addr_high: u8, addr_low: u8): u8 {
|
||||
msg := "\0\0\0\0";
|
||||
*@as(^u8, msg) = @as(u8, 0);
|
||||
*@as(^u8, msg + 1) = @as(u8, 0);
|
||||
*@as(^u16, @bitcast(msg + 2)) = addr
|
||||
return @eca(u8, 3, 3, msg, 4)
|
||||
}
|
||||
|
||||
outl := fn(addr: u16, value: u32): void {
|
||||
msg := "\0\0\0\0\0\0\0\0";
|
||||
*@as(^u8, msg) = @as(u8, 1);
|
||||
*@as(^u8, msg + 1) = @as(u8, 2);
|
||||
*@as(^u16, @bitcast(msg + 2)) = addr;
|
||||
*@as(^u32, @bitcast(msg + 4)) = value
|
||||
@eca(void, 3, 3, msg, 8)
|
||||
return
|
||||
}
|
||||
|
||||
inl := fn(addr: u16): u32 {
|
||||
msg := "\0\0\0\0";
|
||||
*@as(^u8, msg) = @as(u8, 0);
|
||||
*@as(^u8, msg + 1) = @as(u8, 2);
|
||||
*@as(^u16, @bitcast(msg + 2)) = addr
|
||||
return @eca(u32, 3, 3, msg, 4)
|
||||
*(msg + 1) = addr_high;
|
||||
*(msg + 2) = addr_low
|
||||
return @eca(u8, 3, 3, msg, 3)
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
.{inl, outl} := @use("rel:memory.hb")
|
||||
|
||||
config_read := fn(bus: u8, device: u8, func: u8, offset: u8): u32 {
|
||||
lbus := @as(u32, bus)
|
||||
ldevice := @as(u32, device)
|
||||
lfunc := @as(u32, func)
|
||||
loffset := @as(u32, offset)
|
||||
|
||||
address := lbus << 16 | ldevice << 11 | lfunc << 8 | loffset & 0xFC | @as(u32, 0x80000000)
|
||||
|
||||
outl(0xCF8, address)
|
||||
return inl(0xCFC)
|
||||
}
|
||||
|
||||
config_write := fn(bus: u8, device: u8, func: u8, offset: u8, value: u32): void {
|
||||
lbus := @as(u32, bus)
|
||||
ldevice := @as(u32, device)
|
||||
lfunc := @as(u32, func)
|
||||
loffset := @as(u32, offset)
|
||||
|
||||
address := lbus << 16 | ldevice << 11 | lfunc << 8 | loffset & 0xFC | @as(u32, 0x80000000)
|
||||
|
||||
outl(0xCF8, address)
|
||||
outl(0xCFC, value)
|
||||
}
|
||||
|
||||
get_header_type := fn(bus: u8, device: u8, func: u8): u8 {
|
||||
return @as(u8, config_read(bus, device, func, 0xC) >> 16 & 0xFF)
|
||||
}
|
||||
|
||||
Ids := struct {vendor: u16, device: u16}
|
||||
|
||||
get_ids := fn(bus: u8, device: u8, func: u8): Ids {
|
||||
res := config_read(bus, device, func, 0)
|
||||
return .(@as(u16, res >> 16 & 0xFFFF), @as(u16, res & 0xFFFF))
|
||||
}
|
||||
|
||||
PciDeviceInfo := struct {header_type: u8, device: u8, bus: u8, device_id: Ids, full_class: u16, rev_id: u8}
|
||||
|
||||
check_device := fn(bus: u8, device: u8): PciDeviceInfo {
|
||||
ids := get_ids(bus, device, 0)
|
||||
if ids.vendor == 0xFFFF {
|
||||
return .(0, 0, 0, .(0, 0), 0, 0)
|
||||
}
|
||||
reg2 := config_read(bus, device, 0, 0x8)
|
||||
class := @as(u16, reg2 >> 16 & 0xFFFF)
|
||||
header_type := get_header_type(bus, device, 0)
|
||||
|
||||
return .(header_type, device, bus, ids, class, @as(u8, reg2 & 0xFF))
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
integer := fn(): int {
|
||||
return @eca(int, 3, 4)
|
||||
}
|
||||
|
||||
integer_range := fn(min: int, max: int): int {
|
||||
return @eca(int, 3, 4) % (max - min + 1) + min
|
||||
}
|
|
@ -1,34 +1,42 @@
|
|||
length := fn(ptr: ^u8): int {
|
||||
len := 0
|
||||
loop if *(ptr + len) == 0 break else len += 1
|
||||
loop if *ptr == 0 break else {
|
||||
len += 1
|
||||
ptr += 1
|
||||
}
|
||||
return len
|
||||
}
|
||||
|
||||
display_int := fn(num: int, p: ^u8): ^u8 {
|
||||
i := 0
|
||||
if num == 0 {
|
||||
*p = 48
|
||||
set(p, 48)
|
||||
return p
|
||||
}
|
||||
loop if num == 0 break else {
|
||||
*(p + i) = num % 10 + 48
|
||||
loop {
|
||||
if num == 0 break
|
||||
set(p + i, num % 10 + 48)
|
||||
num /= 10
|
||||
i += 1
|
||||
}
|
||||
@inline(reverse, p);
|
||||
*(p + i) = 0
|
||||
reverse(p)
|
||||
//null terminate
|
||||
set(p + i, 0)
|
||||
return p
|
||||
}
|
||||
|
||||
reverse := fn(s: ^u8): void {
|
||||
//reverse a string, don't remove digits
|
||||
len := 0
|
||||
loop if *(s + len) == 0 break else len += 1
|
||||
loop {
|
||||
if *(s + len) == 0 break
|
||||
len += 1
|
||||
}
|
||||
i := 0
|
||||
j := len - 1
|
||||
temp := 0
|
||||
loop if i >= j break else {
|
||||
temp = *(s + i);
|
||||
loop {
|
||||
if i >= j break
|
||||
temp := *(s + i);
|
||||
*(s + i) = *(s + j);
|
||||
*(s + j) = temp
|
||||
i += 1
|
||||
|
@ -36,3 +44,8 @@ reverse := fn(s: ^u8): void {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
set := fn(change: ^u8, new: int): void {
|
||||
*change = new
|
||||
return
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "serial_driver"
|
||||
name = "a_serial_driver"
|
||||
authors = ["Able"]
|
||||
|
||||
[dependants.libraries]
|
|
@ -1,10 +1,11 @@
|
|||
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{log, string, memory, buffer} := stn
|
||||
|
||||
serial_print := fn(ptr: ^u8): void {
|
||||
letter := 0
|
||||
loop if *ptr == 0 break else {
|
||||
letter = *ptr
|
||||
memory.outb(0xF803, letter)
|
||||
memory.outb(3, 248, letter)
|
||||
ptr += 1
|
||||
}
|
||||
return
|
||||
|
@ -12,8 +13,8 @@ serial_print := fn(ptr: ^u8): void {
|
|||
|
||||
serial_println := fn(ptr: ^u8): void {
|
||||
serial_print(ptr)
|
||||
memory.outb(0xF803, 12)
|
||||
memory.outb(0xF803, 13)
|
||||
memory.outb(3, 248, 12)
|
||||
memory.outb(3, 248, 13)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -25,7 +26,7 @@ main := fn(): int {
|
|||
mem := memory.request_page(1)
|
||||
|
||||
loop {
|
||||
ptr := @eca(int, 4, a, mem, 0x1000)
|
||||
ptr := @eca(int, 4, a, mem, 4096)
|
||||
if ptr == 0 {
|
||||
serial_println("No message\0")
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{log, string, memory, buffer} := stn
|
||||
|
||||
main := fn(): int {
|
||||
// shuts down ableOS
|
||||
// memory.outb(0xF400, 0)
|
||||
//memory.outb(0, 244, 0)
|
||||
|
||||
a := memory.inb(0x4600)
|
||||
b := memory.inb(0x4700)
|
||||
a := memory.inb(0, 70)
|
||||
b := memory.inb(0, 71)
|
||||
|
||||
c := buffer.search("XNumber\0")
|
||||
|
||||
|
|
2
sysdata/programs/fb_driver/README.md
Normal file
2
sysdata/programs/fb_driver/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Framebuffer Driver
|
||||
A simple framebuffer driver.
|
7
sysdata/programs/fb_driver/UNTESTED_FUNCTIONS
Normal file
7
sysdata/programs/fb_driver/UNTESTED_FUNCTIONS
Normal file
|
@ -0,0 +1,7 @@
|
|||
color.blend
|
||||
|
||||
lib.composite
|
||||
lib.screen2rect
|
||||
lib.rect2screen
|
||||
|
||||
draw.tri_line
|
11
sysdata/programs/fb_driver/meta.toml
Normal file
11
sysdata/programs/fb_driver/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "fb_driver"
|
||||
authors = ["able", "aurlex"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
27
sysdata/programs/fb_driver/src/color.hb
Normal file
27
sysdata/programs/fb_driver/src/color.hb
Normal file
|
@ -0,0 +1,27 @@
|
|||
ColorBGRA := struct {b: u8, g: u8, r: u8, a: u8}
|
||||
|
||||
/* ALL the colo(u)rs you will ever need.
|
||||
they dont work though, cause hblang bug (reg id leaked, again) */
|
||||
WHITE := ColorBGRA.{b: 255, g: 255, r: 255, a: 255}
|
||||
BLACK := ColorBGRA.{b: 0, g: 0, r: 0, a: 255}
|
||||
GRAY := ColorBGRA.{b: 127, g: 127, r: 127, a: 255}
|
||||
RED := ColorBGRA.{b: 0, g: 0, r: 205, a: 255}
|
||||
GREEN := ColorBGRA.{b: 0, g: 205, r: 0, a: 255}
|
||||
YELLOW := ColorBGRA.{b: 0, g: 205, r: 205, a: 255}
|
||||
BLUE := ColorBGRA.{b: 205, g: 0, r: 0, a: 255}
|
||||
MAGENTA := ColorBGRA.{b: 205, g: 0, r: 205, a: 255}
|
||||
CYAN := ColorBGRA.{b: 205, g: 205, r: 0, a: 255}
|
||||
LIGHTGRAY := ColorBGRA.{b: 229, g: 229, r: 229, a: 255}
|
||||
LIGHTRED := ColorBGRA.{b: 0, g: 0, r: 255, a: 255}
|
||||
LIGHTGREEN := ColorBGRA.{b: 0, g: 255, r: 0, a: 255}
|
||||
LIGHTYELLOW := ColorBGRA.{b: 0, g: 255, r: 255, a: 255}
|
||||
LIGHTBLUE := ColorBGRA.{b: 255, g: 0, r: 0, a: 255}
|
||||
LIGHTMAGENTA := ColorBGRA.{b: 255, g: 0, r: 255, a: 255}
|
||||
LIGHTCYAN := ColorBGRA.{b: 255, g: 255, r: 0, a: 255}
|
||||
|
||||
// i have no clue if this works. please don't me ask how it works. -aurlex
|
||||
blend := fn(fg: ColorBGRA, bg: ColorBGRA): ColorBGRA {
|
||||
s := fg + bg
|
||||
m := s - ((fg ^ bg) & 16843008) & 16843008
|
||||
return (m >> 8 | 16777216 * (s < fg)) * 255 | s - m
|
||||
}
|
113
sysdata/programs/fb_driver/src/draw.hb
Normal file
113
sysdata/programs/fb_driver/src/draw.hb
Normal file
|
@ -0,0 +1,113 @@
|
|||
.{draw_pixel, screenidx, Transform, Point, Rect, Buffer, FB_WIDTH} := @use("rel:lib.hb")
|
||||
ColorBGRA := @use("rel:color.hb").ColorBGRA
|
||||
math := @use("../../../libraries/stn/src/lib.hb").math
|
||||
|
||||
/* draws a filled rectangle to the screen
|
||||
will be optimised later */
|
||||
rect_fill := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA): void {
|
||||
n := 0
|
||||
loop if n == tr.height * tr.width break else {
|
||||
*(buffer.write + screenidx(.(n % tr.width + pos.x, n / tr.width + pos.y))) = color
|
||||
n += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
/* draws a wireframe rectangle to the screen
|
||||
will also be optimised later */
|
||||
rect_line := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA, thickness: int): void {
|
||||
t := 0
|
||||
y := 0
|
||||
x := 0
|
||||
loop if t == thickness break else {
|
||||
y = pos.y
|
||||
x = pos.x
|
||||
loop if y == pos.y + tr.height break else {
|
||||
*(buffer.write + pos.x + t + FB_WIDTH * y) = color;
|
||||
*(buffer.write + pos.x + tr.width - t + FB_WIDTH * y) = color
|
||||
y += 1
|
||||
}
|
||||
loop if x == pos.x + tr.width break else {
|
||||
*(buffer.write + x + (pos.y + t) * FB_WIDTH) = color;
|
||||
*(buffer.write + x + (pos.y + tr.height - t) * FB_WIDTH) = color
|
||||
x += 1
|
||||
}
|
||||
t += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// do not use, use line() instead
|
||||
line_low := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
|
||||
dx := p1.x - p0.x
|
||||
dy := p1.y - p0.y
|
||||
yi := 1
|
||||
if dy < 0 {
|
||||
yi = 0 - 1
|
||||
dy = 0 - dy
|
||||
}
|
||||
D := 2 * dy - dx
|
||||
y := p0.y
|
||||
x := p0.x
|
||||
loop if x == p1.x break else {
|
||||
*(buffer.write + x + y * FB_WIDTH) = color
|
||||
if D > 0 {
|
||||
y += yi
|
||||
D += 2 * (dy - dx)
|
||||
} else {
|
||||
D += 2 * dy
|
||||
}
|
||||
x += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
// do not use, use line() instead
|
||||
line_high := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
|
||||
dx := p1.x - p0.x
|
||||
dy := p1.y - p0.y
|
||||
xi := 1
|
||||
if dy < 0 {
|
||||
xi = 0 - 1
|
||||
dx = 0 - dx
|
||||
}
|
||||
D := 2 * dx - dy
|
||||
x := p0.x
|
||||
y := p0.y
|
||||
loop if y == p1.y break else {
|
||||
*(buffer.write + x + y * FB_WIDTH) = color
|
||||
if D > 0 {
|
||||
x += xi
|
||||
D += 2 * (dx - dy)
|
||||
} else {
|
||||
D += 2 * dx
|
||||
}
|
||||
y += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/* implementation of Bresenham's line algorithm
|
||||
TODO: thickness, might need better math library */
|
||||
line := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA, thickness: int): void {
|
||||
if math.abs(p1.y - p0.y) < math.abs(p1.x - p0.x) {
|
||||
if p0.x > p1.x {
|
||||
line_low(buffer, p1, p0, color)
|
||||
} else {
|
||||
line_low(buffer, p0, p1, color)
|
||||
}
|
||||
} else {
|
||||
if p0.y > p1.y {
|
||||
line_high(buffer, p1, p0, color)
|
||||
} else {
|
||||
line_high(buffer, p0, p1, color)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// theoretically draws a wireframe polygon to the screen. untested.
|
||||
tri_line := fn(buffer: Buffer, p0: Point, p1: Point, p2: Point, color: ColorBGRA, thickness: int): void {
|
||||
line(buffer, p0, p1, color, thickness)
|
||||
line(buffer, p1, p2, color, thickness)
|
||||
line(buffer, p2, p0, color, thickness)
|
||||
return
|
||||
}
|
26
sysdata/programs/fb_driver/src/examples/amogus.hb
Normal file
26
sysdata/programs/fb_driver/src/examples/amogus.hb
Normal file
|
@ -0,0 +1,26 @@
|
|||
.{rect_line} := @use("../draw.hb");
|
||||
.{present, create_buffer, clear} := @use("../lib.hb")
|
||||
|
||||
/* expected result:
|
||||
the impostor travels left and loops around the screen */
|
||||
|
||||
example := fn(): void {
|
||||
// Creates a back buffer, which we write to, to avoid screen flickering
|
||||
buffer := create_buffer()
|
||||
x := 0
|
||||
loop {
|
||||
// draw all our shapes to the back buffer
|
||||
rect_line(buffer, .(200 - x, 80), .(430, 380), .(0, 0, 255, 0), 1)
|
||||
rect_line(buffer, .(630 - x, 120), .(120, 300), .(0, 0, 255, 0), 1)
|
||||
rect_line(buffer, .(200 - x, 460), .(160, 270), .(0, 0, 255, 0), 1)
|
||||
rect_line(buffer, .(470 - x, 460), .(160, 270), .(0, 0, 255, 0), 1)
|
||||
rect_line(buffer, .(140 - x, 140), .(340, 250), .(255, 255, 0, 0), 1)
|
||||
/* push the back buffer to the front buffer
|
||||
this displays our image to the screen */
|
||||
present(buffer)
|
||||
// erase our old image
|
||||
clear(buffer, .(0, 0, 0, 0))
|
||||
x += 1
|
||||
}
|
||||
return
|
||||
}
|
27
sysdata/programs/fb_driver/src/examples/colors.hb
Normal file
27
sysdata/programs/fb_driver/src/examples/colors.hb
Normal file
|
@ -0,0 +1,27 @@
|
|||
.{clear, create_buffer, present} := @use("../lib.hb");
|
||||
.{ColorBGRA} := @use("../color.hb")
|
||||
|
||||
/* expected result:
|
||||
the screen fades from green to cyan
|
||||
then wraps back to green
|
||||
note that this may happen too fast for you to notice... */
|
||||
|
||||
example := fn(): void {
|
||||
// creates a back buffer, which we write to, to avoid screen flickering
|
||||
buffer := create_buffer()
|
||||
color := ColorBGRA.(0, 255, 0, 255)
|
||||
/* have to explicitly say 0 is a u8, or we do something crazy to the colors.
|
||||
looks like a compiler bug */
|
||||
n := @as(i8, @as(u8, 0)) - 1
|
||||
loop {
|
||||
clear(buffer, color)
|
||||
present(buffer)
|
||||
/* because for some reason just comparing doesnt work.
|
||||
also looks like a compiler bug */
|
||||
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
||||
n = 0 - n
|
||||
}
|
||||
color.b += n
|
||||
}
|
||||
return
|
||||
}
|
19
sysdata/programs/fb_driver/src/examples/front_buffer.hb
Normal file
19
sysdata/programs/fb_driver/src/examples/front_buffer.hb
Normal file
|
@ -0,0 +1,19 @@
|
|||
.{front_buffer_ptr, front_buffer_copy, get_front_buffer, Buffer} := @use("../lib.hb");
|
||||
|
||||
example := fn(): void {
|
||||
// you can get the raw frontbuffer pointer using
|
||||
raw_buffer := front_buffer_ptr
|
||||
// this buffer is the one that you write individual pixels to
|
||||
|
||||
// you can gete the copy frontbuffer pointer using
|
||||
copy_buffer := copy_buffer_ptr
|
||||
/* this buffer is used for massive writing
|
||||
operations by taking advantage of
|
||||
static copying */
|
||||
|
||||
// you can construct a buffer like so
|
||||
buffer := Buffer.{write: raw_buffer, copy: copy_buffer}
|
||||
// this is the operation that get_front_buffer does
|
||||
same_buffer := get_front_buffer()
|
||||
return
|
||||
}
|
25
sysdata/programs/fb_driver/src/examples/lines.hb
Normal file
25
sysdata/programs/fb_driver/src/examples/lines.hb
Normal file
|
@ -0,0 +1,25 @@
|
|||
.{line} := @use("../draw.hb");
|
||||
.{clear, create_buffer, present, FB_WIDTH, FB_HEIGHT, Point} := @use("../lib.hb")
|
||||
|
||||
/* expected result:
|
||||
a 3d-looking blue set of lines
|
||||
created on a blue background */
|
||||
|
||||
example := fn(): void {
|
||||
// creates a back buffer, which we write to, to avoid screen flickering
|
||||
buffer := create_buffer()
|
||||
// fill the screen in blue
|
||||
clear(buffer, .(100, 50, 0, 255))
|
||||
p0 := Point.(0, 0 - 1)
|
||||
p1 := Point.(0, FB_HEIGHT - 1)
|
||||
loop if p0.y >= FB_HEIGHT break else {
|
||||
// draw a line between p0 and p1
|
||||
line(buffer, p0, p1, .(255, 180, 100, 255), 3)
|
||||
p0.y += FB_HEIGHT >> 6
|
||||
p1.x += FB_WIDTH >> 6
|
||||
}
|
||||
/* push the back buffer to the front buffer
|
||||
this displays our image to the screen */
|
||||
present(buffer)
|
||||
return
|
||||
}
|
32
sysdata/programs/fb_driver/src/examples/square.hb
Normal file
32
sysdata/programs/fb_driver/src/examples/square.hb
Normal file
|
@ -0,0 +1,32 @@
|
|||
.{rect_line} := @use("../draw.hb");
|
||||
.{clear, create_buffer, present, Point, FB_HEIGHT, FB_WIDTH} := @use("../lib.hb")
|
||||
|
||||
/* expected result:
|
||||
the white outline of a square bounces around the screen */
|
||||
|
||||
example := fn(): void {
|
||||
// creates a back buffer, which we write to, to avoid screen flickering
|
||||
buffer := create_buffer()
|
||||
vel := Point.{x: 1, y: 1}
|
||||
pos := Point.{x: 100, y: 100}
|
||||
loop {
|
||||
// draw the square at our current position
|
||||
rect_line(buffer, pos, .(100, 100), .(255, 255, 255, 255), 3)
|
||||
/* push the back buffer to the front buffer
|
||||
this displays our image to the screen */
|
||||
present(buffer)
|
||||
// erase our old image
|
||||
clear(buffer, .(0, 0, 0, 0))
|
||||
|
||||
// bounce the square if it touches the screen edges
|
||||
if pos.x == 0 | pos.x == FB_WIDTH - 100 {
|
||||
vel.x = 0 - vel.x
|
||||
}
|
||||
if pos.y == 0 | pos.y == FB_HEIGHT - 100 {
|
||||
vel.y = 0 - vel.y
|
||||
}
|
||||
|
||||
pos += vel
|
||||
}
|
||||
return
|
||||
}
|
20
sysdata/programs/fb_driver/src/examples/strobe.hb
Normal file
20
sysdata/programs/fb_driver/src/examples/strobe.hb
Normal file
|
@ -0,0 +1,20 @@
|
|||
.{clear, create_buffer, present} := @use("../lib.hb")
|
||||
|
||||
/* expected result: (EPILEPSY WARNING)
|
||||
the screen rapidly flashes red then black */
|
||||
|
||||
example := fn(): void {
|
||||
// creates a back buffer, which we write to, to avoid screen flickering
|
||||
buffer := create_buffer()
|
||||
loop {
|
||||
// screen go red
|
||||
clear(buffer, .(0, 0, 255, 0))
|
||||
// show the red
|
||||
present(buffer)
|
||||
// screen go black
|
||||
clear(buffer, .(0, 255, 255, 0))
|
||||
// show the black
|
||||
present(buffer)
|
||||
}
|
||||
return
|
||||
}
|
100
sysdata/programs/fb_driver/src/lib.hb
Normal file
100
sysdata/programs/fb_driver/src/lib.hb
Normal file
|
@ -0,0 +1,100 @@
|
|||
.{memory, log, math} := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{ColorBGRA, blend} := @use("rel:color.hb")
|
||||
|
||||
FB_WIDTH := 1024
|
||||
FB_HEIGHT := 768
|
||||
FB_PIXELS := FB_WIDTH * FB_HEIGHT
|
||||
FB_BYTES := FB_PIXELS << 2
|
||||
// actual enforced max copy size is (1 << 16) - 1, but this was faster
|
||||
MAX_COPY_SIZE := 6144
|
||||
// see stn.math.min, cant use here due to compiler bug (reg id leaked)
|
||||
COPY_PIXELS := MAX_COPY_SIZE + (FB_BYTES - MAX_COPY_SIZE & FB_BYTES - MAX_COPY_SIZE >> 31) >> 2
|
||||
PARTITIONS := FB_PIXELS / COPY_PIXELS
|
||||
TOTAL_PAGES := 1 + FB_BYTES >> 12
|
||||
|
||||
Buffer := struct {write: ^ColorBGRA, copy: ^[ColorBGRA; COPY_PIXELS]}
|
||||
Point := struct {x: int, y: int}
|
||||
Transform := struct {width: int, height: int}
|
||||
Rect := struct {p1: Point, p2: Point}
|
||||
|
||||
front_buffer_ptr := @as(^ColorBGRA, @bitcast(0 - 140734267129856))
|
||||
front_buffer_copy := @as(^[ColorBGRA; COPY_PIXELS], @bitcast(front_buffer_ptr))
|
||||
|
||||
get_front_buffer := fn(): Buffer {
|
||||
// trying to return front_buffer_ptr or front_buffer_copy causes reg id leak
|
||||
return Buffer.{write: @as(^ColorBGRA, @bitcast(0 - 140734267129856)), copy: @as(^[ColorBGRA; COPY_PIXELS], @bitcast(0 - 140734267129856))}
|
||||
}
|
||||
/* this is separate to create_raw_buffer because returning a Buffer from
|
||||
create_raw_buffer causes reg id leak */
|
||||
create_buffer := fn(): Buffer {
|
||||
ptr := create_raw_buffer()
|
||||
ptr_copy := @as(^[ColorBGRA; COPY_PIXELS], @bitcast(ptr))
|
||||
// same here, bitcasting inside the struct literal causes reg id leak
|
||||
buffer := Buffer.{write: ptr, copy: ptr_copy}
|
||||
return buffer
|
||||
}
|
||||
create_raw_buffer := fn(): ^ColorBGRA {
|
||||
// helps to trace allocation bugs
|
||||
log.info("Creating buffer. This will allocate.\0")
|
||||
if TOTAL_PAGES <= 255 {
|
||||
return @bitcast(memory.request_page(TOTAL_PAGES))
|
||||
}
|
||||
ptr := memory.request_page(255)
|
||||
remaining := TOTAL_PAGES - 255
|
||||
loop if remaining <= 0 break else {
|
||||
if remaining < 255 {
|
||||
memory.request_page(remaining)
|
||||
} else {
|
||||
memory.request_page(255)
|
||||
}
|
||||
remaining -= 255
|
||||
}
|
||||
return @bitcast(ptr)
|
||||
}
|
||||
// sets the buffer to the color. very fast.
|
||||
clear := fn(buffer: Buffer, color: ColorBGRA): void {
|
||||
n := 0
|
||||
// write the first pixel chunk
|
||||
loop if n >= COPY_PIXELS break else {
|
||||
*(buffer.write + n) = color
|
||||
n += 1
|
||||
}
|
||||
n = 1
|
||||
// copy that pixel chunk through the buffer, taking advantage of memory copying
|
||||
loop if n >= PARTITIONS break else {
|
||||
*(buffer.copy + n) = *buffer.copy
|
||||
n += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
// only required to be called when using a back buffer. if using single-buffered rendering, do not call this.
|
||||
present := fn(buffer: Buffer): void {
|
||||
offset := 0
|
||||
// copy chunks of the read buffer to the front buffer
|
||||
loop if offset >= PARTITIONS break else {
|
||||
*(front_buffer_copy + offset) = *(buffer.copy + offset)
|
||||
offset += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
// composites the contents of buffer1 into buffer2, accounting for alpha transparency
|
||||
// i dont know if it works. i have not tested it. it probably doesnt work
|
||||
composite := fn(buffer1: Buffer, buffer2: Buffer): void {
|
||||
n := 0
|
||||
loop if n == FB_PIXELS break else {
|
||||
bg := *(buffer2.write + n);
|
||||
*(buffer2.write + n) = blend(*(buffer1.write + n), bg)
|
||||
n += 1
|
||||
}
|
||||
return
|
||||
}
|
||||
// really need to be able to inline this please - aurlex
|
||||
screenidx := fn(pos: Point): int {
|
||||
return pos.x + FB_WIDTH * pos.y
|
||||
}
|
||||
point2rect := fn(pos: Point, tr: Transform): Rect {
|
||||
return .(pos, .(pos.x + tr.x, pos.y + tr.y))
|
||||
}
|
||||
rect2point := fn(rect: Rect): struct {point: Point, transform: Transform} {
|
||||
return .(.(0, 0), .(0, 0))
|
||||
}
|
7
sysdata/programs/fb_driver/src/main.hb
Normal file
7
sysdata/programs/fb_driver/src/main.hb
Normal file
|
@ -0,0 +1,7 @@
|
|||
// change "lines.hb" to another example to see it onscreen
|
||||
example := @use("examples/square.hb").example
|
||||
|
||||
main := fn(): int {
|
||||
example()
|
||||
return 0
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
/* expected result:
|
||||
the impostor travels left and loops around the screen */
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
x := 0
|
||||
loop {
|
||||
render.put_rect(.(200 - x, 80), .(430, 380), render.red)
|
||||
render.put_rect(.(630 - x, 120), .(120, 300), render.red)
|
||||
render.put_rect(.(200 - x, 460), .(160, 270), render.red)
|
||||
render.put_rect(.(470 - x, 460), .(160, 270), render.red)
|
||||
render.put_rect(.(140 - x, 140), .(340, 250), render.cyan)
|
||||
render.sync()
|
||||
render.clear(render.black)
|
||||
x += 1
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
/* expected result:
|
||||
the screen fades from cyan to green
|
||||
then wraps back to cyan
|
||||
note that this may happen too fast for you to notice... */
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
color := render.light_cyan
|
||||
n := @as(u8, 1)
|
||||
loop {
|
||||
render.clear(color)
|
||||
render.sync()
|
||||
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
||||
n = -n
|
||||
}
|
||||
color.b += n
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
/* expected result:
|
||||
a 3d-looking set of blue lines
|
||||
created on a blue background */
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
render.clear(.(100, 50, 0, 255))
|
||||
width := render.width()
|
||||
height := render.height()
|
||||
p0 := render.IVec2.(0, 0)
|
||||
p1 := render.IVec2.(0, height)
|
||||
loop if p0.y >= height break else {
|
||||
render.put_line(p0, p1, .(255, 180, 100, 255))
|
||||
render.put_line(.(width, height) - p0, .(width, height) - p1, .(255, 180, 100, 255))
|
||||
p0.y += height >> 6
|
||||
p1.x += width >> 6
|
||||
}
|
||||
render.sync()
|
||||
return
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
.{random} := @use("../../../../libraries/stn/src/lib.hb")
|
||||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
render.doublebuffer(false)
|
||||
render.clear(render.black)
|
||||
loop {
|
||||
x := random.integer_range(0, 1024)
|
||||
y := random.integer_range(0, 768)
|
||||
r := random.integer_range(0, 255)
|
||||
g := random.integer_range(0, 75)
|
||||
b := random.integer_range(0, 155)
|
||||
render.put_pixel(.(x, y), .(b, g, r, 255))
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
/* expected result:
|
||||
the white outline of a square bounces around the screen */
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
vel := render.IVec2.(1, 1)
|
||||
pos := render.IVec2.(100, 100)
|
||||
width := render.width()
|
||||
height := render.height()
|
||||
loop {
|
||||
render.put_rect(pos, .(100, 100), render.white)
|
||||
render.sync()
|
||||
render.clear(render.black)
|
||||
|
||||
if pos.x == 0 | pos.x == width - 100 {
|
||||
vel.x = -vel.x
|
||||
}
|
||||
if pos.y == 0 | pos.y == height - 100 {
|
||||
vel.y = -vel.y
|
||||
}
|
||||
|
||||
pos += vel
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
/* expected result: (EPILEPSY WARNING)
|
||||
the screen rapidly flashes red then black */
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
loop {
|
||||
render.clear(render.red)
|
||||
render.sync()
|
||||
render.clear(render.yellow)
|
||||
render.sync()
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
render.mode = render.svga
|
||||
|
||||
example := fn(): void {
|
||||
render.init()
|
||||
return
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
.{example} := @use("./examples/colors.hb")
|
||||
|
||||
main := fn(): void {
|
||||
@inline(example)
|
||||
return
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
.{string, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{string, memory, buffer} := stn
|
||||
|
||||
frame_buffer := @as(^u8, @bitcast(0 - 140734267129856))
|
||||
|
||||
log_info := fn(): void {
|
||||
a := buffer.search("XNumber\0")
|
||||
if a == 0 {
|
||||
} else {
|
||||
msg := "XABC\0"
|
||||
msg_length := @inline(string.length, msg)
|
||||
msg_length := string.length(msg)
|
||||
@eca(void, 3, a, msg, msg_length)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.{log, string, memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{log, string, memory, buffer} := stn
|
||||
|
||||
service_search := fn(): void {
|
||||
a := "\{01}\0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "render_example"
|
||||
authors = ["koniifer"]
|
||||
name = "time_driver"
|
||||
authors = ["SamBuckley"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
22
sysdata/programs/time_driver/src/main.hb
Normal file
22
sysdata/programs/time_driver/src/main.hb
Normal file
|
@ -0,0 +1,22 @@
|
|||
stn := @use("../../../libraries/stn/src/lib.hb")
|
||||
log := stn.log
|
||||
mem := stn.memory
|
||||
s := stn.string
|
||||
page := 0
|
||||
|
||||
main := fn(): void {
|
||||
page += mem.request_page(1)
|
||||
port_str := "\0\0\{47}\0"
|
||||
a := @eca(u8, 3, 3, port_str, 4)
|
||||
|
||||
n := 5000000
|
||||
loop {
|
||||
if n == 0 break
|
||||
n -= 1
|
||||
stack_reclamation_edge_case := 0
|
||||
}
|
||||
td := s.display_int(a, page)
|
||||
log.debug(td)
|
||||
|
||||
return
|
||||
}
|
|
@ -19,27 +19,31 @@ resolution = "1024x768x24"
|
|||
|
||||
# [boot.limine.ableos.modules.tests]
|
||||
# path = "boot:///tests.hbf"
|
||||
# [boot.limine.ableos.modules.a_serial_driver]
|
||||
# path = "boot:///a_serial_driver.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.0serial_driver]
|
||||
# path = "boot:///serial_driver.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.diskio_driver]
|
||||
# path = "boot:///diskio_driver.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.render_example]
|
||||
# path = "boot:///render_example.hbf"
|
||||
# [boot.limine.ableos.modules.fb_driver]
|
||||
# path = "boot:///fb_driver.hbf"
|
||||
|
||||
|
||||
# [boot.limine.ableos.modules.serial_driver_test]
|
||||
# path = "boot:///serial_driver_test.hbf"
|
||||
|
||||
|
||||
# [boot.limine.ableos.modules.horizon]
|
||||
# path = "boot:///horizon.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.horizon_testing_program]
|
||||
# path = "boot:///horizon_testing_program.hbf"
|
||||
|
||||
|
||||
# [boot.limine.ableos.modules.dt_buffer_test]
|
||||
# path = "boot:///dt_buffer_test.hbf"
|
||||
|
||||
|
||||
[boot.limine.ableos.modules.svga_driver]
|
||||
path = "boot:///svga_driver.hbf"
|
||||
|
|
Loading…
Reference in a new issue