Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

58 changed files with 241 additions and 1388 deletions

View file

@ -1,6 +1,4 @@
{ {
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"rust-analyzer.checkOnSave.allTargets": false, "rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.showUnlinkedFileNotification": false, "rust-analyzer.showUnlinkedFileNotification": false,
"C_Cpp.errorSquiggles": "disabled" "C_Cpp.errorSquiggles": "disabled"

59
Cargo.lock generated
View file

@ -213,12 +213,12 @@ dependencies = [
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
dependencies = [ dependencies = [
"hashbrown", "hashbrown",
"hbbytecode", "hbbytecode",
@ -229,7 +229,7 @@ dependencies = [
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]
@ -392,7 +392,6 @@ dependencies = [
"derive_more", "derive_more",
"hashbrown", "hashbrown",
"hbvm", "hbvm",
"ktest_macro",
"limine", "limine",
"log", "log",
"sbi", "sbi",
@ -405,14 +404,6 @@ dependencies = [
"xml", "xml",
] ]
[[package]]
name = "ktest_macro"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -433,9 +424,9 @@ checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
[[package]] [[package]]
name = "litemap" name = "litemap"
version = "0.7.4" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -512,9 +503,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.92" version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -593,9 +584,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.18" version = "0.23.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e"
dependencies = [ dependencies = [
"log", "log",
"once_cell", "once_cell",
@ -726,9 +717,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.89" version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -809,9 +800,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.14" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@ -842,9 +833,9 @@ dependencies = [
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.4" version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
@ -885,9 +876,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.26.7" version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
@ -1044,9 +1035,9 @@ dependencies = [
[[package]] [[package]]
name = "yoke" name = "yoke"
version = "0.7.5" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
dependencies = [ dependencies = [
"serde", "serde",
"stable_deref_trait", "stable_deref_trait",
@ -1056,9 +1047,9 @@ dependencies = [
[[package]] [[package]]
name = "yoke-derive" name = "yoke-derive"
version = "0.7.5" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1068,18 +1059,18 @@ dependencies = [
[[package]] [[package]]
name = "zerofrom" name = "zerofrom"
version = "0.1.5" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
dependencies = [ dependencies = [
"zerofrom-derive", "zerofrom-derive",
] ]
[[package]] [[package]]
name = "zerofrom-derive" name = "zerofrom-derive"
version = "0.1.5" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -1,77 +0,0 @@
# Style Guide
This style guide has two modes that a guideline may be.
`strict` means that prs will be rejected if they do not follow the guideline.
`loose` means that a pr would be accepted but should later be fixed.
## Empty Functions | loose
Empty functions are typically a sign of an unfinished program or driver.
In cases where there is a clear reason to have an empty function it will be allowed.
For example FakeAlloc is only empty functions because it is a example of an the allocator api.
### Allowed
```rust
/// in example.hb
a := fn(): void {}
```
### Not Allowed
```rust
/// in fat32.hb
a := fn(): void {}
```
## Magic Functions | loose
'Magic functions' are what I am calling small helper functions that do one or two things.
### Example
```rust
a := null
magic_a := fn(){
a = 10
}
```
The exact policy I want to have here is a bit fuzzy. I think that functions like this are nice in certain situations and not in others.
Regardless of if you use them or not, put a comment above the function explaining rational.
## Magic Numbers | loose
The policy on magic numbers is make them const and have a comment above them. Typically linking to a source of information about the magic number.
This helps cut down on magic numbers while making acceptable names and atleast half assed documentation.
Constants are inlined anyways, so its the same thing in the binary.
```rust
// The standard vga port is mapped at 0xB8000
$VGA_PTR := 0xB8000
```
## Tabs Vs Spaces | strict
I prefer for hblang code to use hard tabs.
The rational behind this is that a tab is `1 Indent` which some developers might want to be various different sizes when displayed
Soft tabs do not allow this user/editor specific as soft tabs always become spaces.
Bottom line is this is an accessibility feature.
There are some samples below.
```
\t means hard tab
\n means new line
\0x20 means space
```
### Allowed
```rust
if x == y {\n
\tlog(z)\n
}\n
```
### Not Allowed
```rust
if x == y {\n
\0x20\0x20\0x20\0x20log(z)\n
}\n
```

View file

@ -1,96 +0,0 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1732014248,
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1732328983,
"narHash": "sha256-RHt12f/slrzDpSL7SSkydh8wUE4Nr4r23HlpWywed9E=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "ed8aa5b64f7d36d9338eb1d0a3bb60cf52069a72",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,30 +0,0 @@
{
description = "A devShell example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
in
with pkgs;
{
devShells.default = mkShell {
buildInputs = [
rustToolchain
qemu_full
];
};
}
);
}

View file

@ -3,15 +3,12 @@ edition = "2021"
name = "kernel" name = "kernel"
version = "0.2.0" version = "0.2.0"
[features]
ktest = []
[dependencies] [dependencies]
# embedded-graphics = "0.8" # embedded-graphics = "0.8"
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [ hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"nightly", "nightly",
] } ] }
ktest_macro = { path = "ktest_macro" }
log = "0.4" log = "0.4"
spin = "0.9" spin = "0.9"
slab = { version = "0.4", default-features = false } slab = { version = "0.4", default-features = false }

View file

@ -1,11 +0,0 @@
[package]
edition = "2021"
name = "ktest_macro"
version = "0.1.0"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.37"
syn = { version = "2.0.89", features = ["full"] }

View file

@ -1,86 +0,0 @@
extern crate proc_macro;
extern crate quote;
extern crate syn;
use {
proc_macro::TokenStream,
quote::quote,
syn::{parse::Parse, parse_macro_input, Expr, ItemFn, Token}
};
struct KtestInput {
lhs: Expr,
_comma: Token![,],
rhs: Expr,
}
impl Parse for KtestInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
lhs: input.parse()?,
_comma: input.parse()?,
rhs: input.parse()?,
})
}
}
#[proc_macro]
pub fn ktest_eq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs != #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro]
pub fn ktest_neq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs == #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro_attribute]
pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let test_name = &input.sig.ident;
let test_string = test_name.to_string();
let static_var_name = syn::Ident::new(
&format!("__ktest_{}", test_name).to_uppercase(),
test_name.span(),
);
let block = &input.block;
let out = quote! {
#[cfg(feature = "ktest")]
fn #test_name() -> Result<String, String> {
use crate::alloc::string::ToString;
let name = #test_string.to_string();
#block
return Ok(name);
}
#[cfg(feature = "ktest")]
#[unsafe(link_section = ".note.ktest")]
#[used]
pub static #static_var_name: fn() -> Result<String, String> = #test_name;
};
TokenStream::from(out)
}

View file

@ -6,11 +6,6 @@ SECTIONS
.text.boot : { *(.text.boot) } .text.boot : { *(.text.boot) }
.text : { *(.text) } .text : { *(.text) }
.data : { *(.data) } .data : { *(.data) }
.note.ktest : {
__ktest_start = .;
*(.note.ktest)
__ktest_end = .;
}
.rodata : { *(.rodata) } .rodata : { *(.rodata) }
.bss : { .bss : {
*(COMMON) *(COMMON)

View file

@ -41,13 +41,6 @@ SECTIONS
*(.got .got.*) *(.got .got.*)
} :data } :data
/* Add the .ktest section for test functions */
.note.ktest : {
__ktest_start = .; /* Mark the beginning of the section */
*(.note.ktest) /* Include all items in the .ktest section */
__ktest_end = .; /* Mark the end of the section */
}
.bss : { .bss : {
*(COMMON) *(COMMON)
*(.bss .bss.*) *(.bss .bss.*)

View file

@ -62,7 +62,7 @@ extern "x86-interrupt" fn page_fault(
} }
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) { extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
interrupt(Interrupt::Timer); // interrupt(Interrupt::Timer);
unsafe { unsafe {
LAPIC.end_of_interrupt(); LAPIC.end_of_interrupt();
@ -83,31 +83,28 @@ extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
} }
} }
#[allow(unused_imports)]
fn interrupt(interrupt_type: Interrupt) { fn interrupt(interrupt_type: Interrupt) {
use crate::{arch::INTERRUPT_LIST, kmain::EXECUTOR}; use crate::arch::INTERRUPT_LIST;
// let il = INTERRUPT_LIST.lock(); let il = INTERRUPT_LIST.lock();
// let val = il.list.get(&interrupt_type).unwrap(); let val = il.list.get(&interrupt_type).unwrap();
// use crate::holeybytes::kernel_services::service_definition_service::sds_search_service; use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
// let buffer = sds_search_service(val); let buffer = sds_search_service(val);
// if buffer != 0 { if buffer != 0 {
// use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec}; use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
// let mut buffs = IPC_BUFFERS.lock(); let mut buffs = IPC_BUFFERS.lock();
// match buffs.get_mut(&buffer) { match buffs.get_mut(&buffer) {
// Some(buff) => { Some(buff) => {
// let mut msg_vec = Vec::new(); let mut msg_vec = Vec::new();
// msg_vec.push(0xFF); msg_vec.push(0xFF);
// buff.push(msg_vec.to_vec()); buff.push(msg_vec.to_vec());
// log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer); log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
// } }
// None => { None => {
// log::error!("Access of non-existent buffer {}", buffer) log::error!("Access of non-existent buffer {}", buffer)
// } }
// } }
// }
unsafe { // log::info!("{}", buffer);
EXECUTOR.send_interrupt(interrupt_type as u8);
} }
} }

View file

@ -33,7 +33,7 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
} }
#[inline(always)] #[inline(always)]
pub fn handler(vm: &mut Vm, pid: &usize) { pub fn handler(vm: &mut Vm) {
let ecall_number = vm.registers[2].cast::<u64>(); let ecall_number = vm.registers[2].cast::<u64>();
match ecall_number { match ecall_number {
@ -209,6 +209,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let buffer_id = vm.registers[3].cast::<u64>(); let buffer_id = vm.registers[3].cast::<u64>();
let map_ptr = vm.registers[4].cast::<u64>(); let map_ptr = vm.registers[4].cast::<u64>();
let max_length = vm.registers[5].cast::<u64>(); let max_length = vm.registers[5].cast::<u64>();
let mut buffs = IPC_BUFFERS.lock(); let mut buffs = IPC_BUFFERS.lock();
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) { let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
Some(buff) => buff, Some(buff) => buff,
@ -242,18 +243,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
vm.registers[3] = x vm.registers[3] = x
} }
} }
6 => {
// Wait till interrupt
use crate::kmain::EXECUTOR;
let interrupt_type = vm.registers[3].cast::<u8>();
info!("Interrupt subscribled: {}", interrupt_type);
unsafe {
EXECUTOR.pause(pid.clone());
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.interrupt_subscribe(pid.clone(), interrupt_type);
}
}
_ => { _ => {
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers); log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
} }

View file

@ -65,12 +65,7 @@ impl<'p> Future for ExecThread {
return Poll::Ready(Err(err)); return Poll::Ready(Err(err));
} }
Ok(VmRunOk::End) => return Poll::Ready(Ok(())), Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
Ok(VmRunOk::Ecall) => ecah::handler( Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm),
&mut self.vm,
cx.ext()
.downcast_ref()
.expect("PID did not exist in Context"),
),
Ok(VmRunOk::Timer) => (), Ok(VmRunOk::Timer) => (),
Ok(VmRunOk::Breakpoint) => { Ok(VmRunOk::Breakpoint) => {
log::error!( log::error!(

View file

@ -22,18 +22,6 @@ use {
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
debug!("Entered kmain"); debug!("Entered kmain");
#[cfg(feature = "ktest")]
{
use {
crate::ktest,
log::info,
};
info!("Running tests");
ktest::test_main();
loop {}
}
// let kcmd = build_cmd("Kernel Command Line", cmdline); // let kcmd = build_cmd("Kernel Command Line", cmdline);
// trace!("Cmdline: {kcmd:?}"); // trace!("Cmdline: {kcmd:?}");
@ -79,7 +67,6 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
"Graphics front ptr {:?}", "Graphics front ptr {:?}",
fb1.address.as_ptr().unwrap() as *const u8 fb1.address.as_ptr().unwrap() as *const u8
); );
log::info!("Started AbleOS");
unsafe { unsafe {
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR); let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
@ -125,7 +112,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
if cmd_len > 0 { if cmd_len > 0 {
thr.set_arguments(cmd.as_ptr() as u64, cmd_len); thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
} }
executor.spawn(Box::pin(async { executor.spawn(Box::pin(async move {
if let Err(e) = thr.await { if let Err(e) = thr.await {
log::error!("{e:?}"); log::error!("{e:?}");
} }
@ -136,6 +123,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
executor.run(); executor.run();
}; };
crate::arch::spin_loop() crate::arch::spin_loop()
} }
@ -160,3 +148,10 @@ pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
Mutex::new(bufs) Mutex::new(bufs)
}); });
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

View file

@ -1,51 +0,0 @@
pub use ktest_macro::*;
use {
alloc::string::String,
log::{error, info},
};
extern "C" {
static __ktest_start: fn() -> Result<String, String>;
static __ktest_end: fn() -> Result<String, String>;
}
// TODO: Implement ktest for arm and riscv (Later problems, see below)
// Allow for arch specific tests (Leave for now)
// Should panic tests
// Test specific panic handler
pub fn test_main() {
unsafe {
let mut current_test = &__ktest_start as *const fn() -> Result<String, String>;
let test_end = &__ktest_end as *const fn() -> Result<String, String>;
let mut pass = 0;
let mut fail = 0;
while current_test < test_end {
let test_fn = *current_test;
let test_name = test_fn();
match test_name {
Ok(name) => {
info!("Test: {} passed", name);
pass += 1;
},
Err(name) => {
error!("Test: {} failed", name);
fail += 1;
}
}
current_test = current_test.add(1);
}
info!("{}/{} tests passed", pass, pass + fail);
}
}
#[ktest]
pub fn trivial_assertion() {
ktest_eq!(1, 1);
ktest_neq!(0, 1);
}

View file

@ -2,7 +2,6 @@
//! Named akern. //! 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 //! 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] #![no_std]
#![no_main]
#![feature( #![feature(
slice_split_once, slice_split_once,
exclusive_wrapper, exclusive_wrapper,
@ -10,12 +9,12 @@
abi_x86_interrupt, abi_x86_interrupt,
lazy_get, lazy_get,
alloc_error_handler, alloc_error_handler,
local_waker,
context_ext,
ptr_sub_ptr, ptr_sub_ptr,
custom_test_frameworks,
naked_functions, naked_functions,
pointer_is_aligned_to pointer_is_aligned_to
)] )]
#![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features, static_mut_refs)] #![allow(dead_code, internal_features, static_mut_refs)]
extern crate alloc; extern crate alloc;
@ -34,9 +33,6 @@ mod memory;
mod task; mod task;
mod utils; mod utils;
#[allow(improper_ctypes, non_upper_case_globals)]
mod ktest;
use versioning::Version; use versioning::Version;
/// Kernel's version /// Kernel's version
@ -49,7 +45,6 @@ pub const VERSION: Version = Version {
#[panic_handler] #[panic_handler]
#[cfg(target_os = "none")] #[cfg(target_os = "none")]
fn panic(info: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
use alloc::string::ToString;
arch::register_dump(); arch::register_dump();
if let Some(loc) = info.location() { if let Some(loc) = info.location() {
@ -61,7 +56,15 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
)); ));
} }
let msg = info.message().to_string().replace("\n", "\r\n"); let msg = info.message();
let _ = crate::arch::log(format_args!("{msg}\r\n")); let _ = crate::arch::log(format_args!("{msg}\r\n"));
loop {} loop {}
} }
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

@ -3,8 +3,7 @@ use {
core::{ core::{
future::Future, future::Future,
pin::Pin, pin::Pin,
sync::atomic::{AtomicBool, Ordering}, task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
task::{Context, ContextBuilder, Poll, RawWaker, RawWakerVTable, Waker},
}, },
crossbeam_queue::SegQueue, crossbeam_queue::SegQueue,
slab::Slab, slab::Slab,
@ -15,6 +14,7 @@ pub fn yield_now() -> impl Future<Output = ()> {
impl Future for YieldNow { impl Future for YieldNow {
type Output = (); type Output = ();
#[inline(always)]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 { if self.0 {
Poll::Ready(()) Poll::Ready(())
@ -29,164 +29,150 @@ pub fn yield_now() -> impl Future<Output = ()> {
YieldNow(false) YieldNow(false)
} }
pub trait Process: Future<Output = ()> + Send {}
impl<T: Future<Output = ()> + Send> Process for T {}
pub struct Executor { pub struct Executor {
tasks: Slab<Task>, tasks: Slab<Task>,
task_queue: Arc<SegQueue<usize>>, task_queue: Arc<TaskQueue>,
interrupt_lookup: [Option<usize>; u8::MAX as usize],
} }
impl Executor { impl Executor {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
tasks: Slab::new(), tasks: Slab::new(),
task_queue: Arc::new(SegQueue::new()), task_queue: Arc::new(TaskQueue::new()),
interrupt_lookup: [None; u8::MAX as usize],
} }
} }
pub fn spawn(&mut self, future: Pin<Box<dyn Process>>) -> usize { #[inline]
pub fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) -> usize {
let id = self.tasks.insert(Task::new(future)); let id = self.tasks.insert(Task::new(future));
self.task_queue.push(id); self.task_queue.queue.push(id);
id id
} }
pub fn pause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(true);
}
}
pub fn unpause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(false);
self.task_queue.push(id);
}
}
pub fn interrupt_subscribe(&mut self, pid: usize, interrupt_type: u8) {
self.interrupt_lookup[interrupt_type as usize] = Some(pid);
}
pub fn run(&mut self) { pub fn run(&mut self) {
let mut task_batch = [0; 32]; let mut task_batch = [0; 32];
loop { let mut batch_len = 0;
let mut batch_len = 0;
while let Some(id) = self.task_queue.pop() { loop {
task_batch[batch_len] = id; self.task_queue.batch_pop(&mut task_batch, &mut batch_len);
batch_len += 1;
if batch_len == task_batch.len() { if batch_len == 0 {
if self.task_queue.is_empty() {
break; break;
} else {
continue;
} }
} }
if batch_len == 0 { for &id in &task_batch[..batch_len] {
// break;
continue;
}
for &(mut id) in &task_batch[..batch_len] {
if let Some(task) = self.tasks.get_mut(id) { if let Some(task) = self.tasks.get_mut(id) {
if task.is_paused() { let waker = task
continue; .waker
} .get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue)));
let waker = create_waker(id, Arc::clone(&self.task_queue)); let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) };
let mut cx = ContextBuilder::from_waker(&waker).ext(&mut id).build(); let mut cx = Context::from_waker(&waker);
if let Poll::Ready(()) = task.poll(&mut cx) { if let Poll::Ready(()) = task.poll(&mut cx) {
self.tasks.remove(id); self.tasks.remove(id);
self.interrupt_lookup.map(|pid| { self.task_queue.free_tasks.push(id);
if let Some(pid) = pid {
if pid == id {
return None;
}
}
return pid;
});
} }
} }
} }
} }
} }
pub fn send_interrupt(&self, interrupt: u8) {
let id = self.interrupt_lookup[interrupt as usize];
if let Some(id) = id {
self.unpause(id);
}
}
} }
struct Task { struct Task {
future: Pin<Box<dyn Process>>, future: Pin<Box<dyn Future<Output = ()> + Send>>,
paused: AtomicBool, waker: Option<TaskWaker>,
} }
impl Task { impl Task {
fn new(future: Pin<Box<dyn Process>>) -> Self { #[inline(always)]
pub fn new(future: Pin<Box<dyn Future<Output = ()> + Send>>) -> Self {
Self { Self {
future, future,
paused: AtomicBool::new(false), waker: None,
} }
} }
#[inline(always)]
fn poll(&mut self, cx: &mut Context) -> Poll<()> { fn poll(&mut self, cx: &mut Context) -> Poll<()> {
self.future.as_mut().poll(cx) self.future.as_mut().poll(cx)
} }
fn is_paused(&self) -> bool {
self.paused.load(Ordering::Acquire)
}
fn set_paused(&self, paused: bool) {
self.paused.store(paused, Ordering::Release)
}
} }
fn create_waker(task_id: usize, task_queue: Arc<SegQueue<usize>>) -> Waker {
let data = Box::new(TaskWaker {
task_id,
task_queue,
});
let raw_waker = RawWaker::new(Box::into_raw(data) as *const (), &VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
#[derive(Clone)]
struct TaskWaker { struct TaskWaker {
task_id: usize, id: usize,
task_queue: Arc<SegQueue<usize>>, task_queue: Arc<TaskQueue>,
} }
impl TaskWaker { impl TaskWaker {
#[inline(always)]
fn new(id: usize, task_queue: Arc<TaskQueue>) -> Self {
Self { id, task_queue }
}
#[inline(always)]
fn wake(&self) { fn wake(&self) {
self.task_queue.push(self.task_id); 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); const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw);
unsafe fn clone_raw(ptr: *const ()) -> RawWaker { unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
let task_waker = Box::from_raw(ptr as *mut TaskWaker); let waker = &*(ptr as *const TaskWaker);
let raw_waker = RawWaker::new(Box::into_raw(task_waker.clone()) as *const (), &VTABLE); TaskWaker::into_raw_waker(waker)
raw_waker
} }
unsafe fn wake_raw(ptr: *const ()) { unsafe fn wake_raw(ptr: *const ()) {
let task_waker = Box::from_raw(ptr as *mut TaskWaker); let waker = &*(ptr as *const TaskWaker);
task_waker.wake(); waker.wake();
} }
unsafe fn wake_by_ref_raw(ptr: *const ()) { unsafe fn wake_by_ref_raw(ptr: *const ()) {
let task_waker = &*(ptr as *const TaskWaker); let waker = &*(ptr as *const TaskWaker);
task_waker.wake(); waker.wake();
} }
unsafe fn drop_raw(ptr: *const ()) { unsafe fn drop_raw(_: *const ()) {}
drop(Box::from_raw(ptr as *mut TaskWaker));
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()
}
} }

View file

@ -27,7 +27,6 @@ fn main() -> Result<(), Error> {
let mut release = false; let mut release = false;
let mut debuginfo = false; let mut debuginfo = false;
let mut target = Target::X86_64; let mut target = Target::X86_64;
let mut tests = false;
for arg in args { for arg in args {
if arg == "-r" || arg == "--release" { if arg == "-r" || arg == "--release" {
release = true; release = true;
@ -39,42 +38,17 @@ fn main() -> Result<(), Error> {
target = Target::Aarch64; target = Target::Aarch64;
} else if arg == "avx2" { } else if arg == "avx2" {
target = Target::X86_64Avx2; target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else { } else {
return Err(report!(Error::InvalidSubCom)); return Err(report!(Error::InvalidSubCom));
} }
} }
build(release, target, debuginfo, tests).change_context(Error::Build) build(release, target, debuginfo).change_context(Error::Build)
} }
// Some("test" | "t") => {
// 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" {
// target = Target::Aarch64;
// } else if arg == "avx2" {
// target = Target::X86_64Avx2;
// } else {
// return Err(report!(Error::InvalidSubCom));
// }
// }
// test(release, target, debuginfo).change_context(Error::Build)
// }
Some("run" | "r") => { Some("run" | "r") => {
let mut release = false; let mut release = false;
let mut debuginfo = false; let mut debuginfo = false;
let mut target = Target::X86_64; let mut target = Target::X86_64;
let mut tests = false;
let mut do_accel = true; let mut do_accel = true;
for arg in args { for arg in args {
if arg == "-r" || arg == "--release" { if arg == "-r" || arg == "--release" {
@ -89,14 +63,12 @@ fn main() -> Result<(), Error> {
do_accel = false; do_accel = false;
} else if arg == "avx2" { } else if arg == "avx2" {
target = Target::X86_64Avx2; target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else { } else {
return Err(report!(Error::InvalidSubCom)); return Err(report!(Error::InvalidSubCom));
} }
} }
build(release, target, debuginfo, tests)?; build(release, target, debuginfo)?;
run(release, target, do_accel) run(release, target, do_accel)
} }
Some("help" | "h") => { Some("help" | "h") => {
@ -110,7 +82,6 @@ fn main() -> Result<(), Error> {
" -r / --release: build in release mode\n", " -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\n", " -d / --debuginfo: build with debug info\n",
" --noaccel: run without acceleration (e.g, no kvm)\n", " --noaccel: run without acceleration (e.g, no kvm)\n",
" --ktest: Enables tests via ktest\n",
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target" "[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
),); ),);
Ok(()) Ok(())
@ -339,7 +310,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
.expect("Copy failed"); .expect("Copy failed");
} }
fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<(), Error> { fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
let fs = get_fs().change_context(Error::Io)?; let fs = get_fs().change_context(Error::Io)?;
let mut com = Command::new("cargo"); let mut com = Command::new("cargo");
com.current_dir("kernel"); com.current_dir("kernel");
@ -351,10 +322,6 @@ fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<
com.env("RUSTFLAGS", "-Cdebug-assertions=true"); com.env("RUSTFLAGS", "-Cdebug-assertions=true");
} }
if tests {
com.args(["--features", "ktest"]);
}
if target == Target::Riscv64Virt { if target == Target::Riscv64Virt {
com.args(["--target", "targets/riscv64-virt-ableos.json"]); com.args(["--target", "targets/riscv64-virt-ableos.json"]);
} }
@ -460,10 +427,6 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
// "-serial", "stdio", // "-serial", "stdio",
"-m", "2G", "-m", "2G",
"-smp", "1", "-smp", "1",
"-audiodev",
"pa,id=speaker",
"-machine",
"pcspk-audiodev=speaker",
"-parallel", "none", "-parallel", "none",
"-monitor", "none", "-monitor", "none",
"-machine", accel, "-machine", accel,
@ -489,7 +452,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip] #[rustfmt::skip]
com.args([ com.args([
"-M", "virt", "-M", "virt",
"-cpu", "max", "-cpu", "neoverse-n2",
"-device", "ramfb", "-device", "ramfb",
"-device", "qemu-xhci", "-device", "qemu-xhci",
"-device", "usb-kbd", "-device", "usb-kbd",
@ -510,7 +473,6 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
} }
} }
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> { fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
let (ovmf_url, ovmf_path) = match target { let (ovmf_url, ovmf_path) = match target {
Target::X86_64 | Target::X86_64Avx2 => ( Target::X86_64 | Target::X86_64Avx2 => (

View file

@ -1,5 +1,5 @@
[toolchain] [toolchain]
# old toolchain # old toolchain
# channel = "nightly-2024-07-27" # channel = "nightly-2024-07-27"
channel = "nightly-2024-11-20" channel = "nightly"
components = ["rust-src", "llvm-tools"] components = ["rust-src", "llvm-tools"]

View file

@ -26,6 +26,12 @@ create_window := fn(channel: int): ^render.Surface {
if windowing_system_buffer == 0 { if windowing_system_buffer == 0 {
return @as(^render.Surface, idk) return @as(^render.Surface, idk)
} else { } else {
// ! bad able, stop using string messages :ragey:
// msg := "\{01}\0"
// msg_length := 2
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
x := 0 x := 0
loop if x > 1000 break else x += 1 loop if x > 1000 break else x += 1

View file

@ -14,27 +14,14 @@ Label := struct {
text_length: uint, text_length: uint,
bg: Color, bg: Color,
fg: Color, fg: Color,
}
new_label := fn(text: ^u8): Self { set_label_text := fn(label: Label, text: ^u8): void {
text_surface := render.new_surface(1024, 20) text_length := string.length(text)
text_length := string.length(text)
label := Self.(3, true, text_surface, text, text_length, render.black, render.white)
return label
}
set_label_text := fn(self: Self, text: ^u8): void { label.is_dirty = true
text_length := string.length(text) label.text = text
label.text_length = text_length
self.is_dirty = true
self.text = text
self.text_length = text_length
}
$set_color := fn(self: Self, bg: Color, fg: Color): void {
self.bg = bg
self.fg = fg
self.is_dirty = true
}
} }
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void { render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
@ -44,3 +31,16 @@ render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: V
} }
render.put_surface(surface, label.surface, pos, false) render.put_surface(surface, label.surface, pos, false)
} }
new_label := fn(text: ^u8): Label {
text_surface := render.new_surface(1024, 20)
text_length := string.length(text)
label := Label.(3, true, text_surface, text, text_length, render.black, render.white)
return label
}
$set_color := fn(label: Label, bg: Color, fg: Color): void {
label.bg = bg
label.fg = fg
label.is_dirty = true
}

View file

@ -1,4 +0,0 @@
AllocReturn := struct {
byte_count: uint,
ptr: ?^u8,
}

View file

@ -1,90 +0,0 @@
.{log, panic, memory} := @use("../lib.hb")
alloc_return := @use("alloc_return.hb")
/* the block size is 64 bytes, 64 blocks of 64 bytes.
this will very quickly lead to exhaustion of free blocks.
*/
BlockAlloc := struct {
// hi
state: uint,
ptr: ?^u8,
$init := fn(): Self {
alloc_page_ptr := memory.request_page(1)
state := 0xFFFFFFFFFFFFFFFF
return .(state, alloc_page_ptr)
}
alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
offset := 0
state_2 := 0
loop {
xyz := self.state & 1
abc := if xyz == 1 {
true
} else {
false
}
// check if the `offset` bit is 1, if it is move to the next offset
if abc {
offset += 1
return .(0, null)
} else {
log.info("Already Allocated\0")
}
// else {
// // self it to 1 and return the ptr to the allocation
// self.state |= a
// // return ptr + offset * 64
// if self.ptr != null {
// return .(64, self.ptr + offset * 64)
// } else {
// // panic.panic("Allocator is not inited.\0")
// // return .(0, null)
// }
// }
// there are only 64 blocks
if offset >= 64 {
return .(0, null)
}
}
}
dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
// size := size_of(alloc_type)*count
size := 64
// get the size alligned to the nearest block
// rounded_size := nearest_block_size_rounded_up(size)
rounded_size := 64
state_bit_start := {
// Do math here to figure out what starting ptr corresponds to what bit
3
}
offset := 0
loop {
if rounded_size > 0 {
// set state_bit_start+offset to 0
// at the end move to the next one
offset += 1
} else {
break
}
rounded_size -= 64
}
return void
}
$deinit := fn(self: Self): void {
self.state = 0
self.ptr = null
}
}
// request a kernel page
// ptr := memory.alloc(1)

View file

@ -1,19 +0,0 @@
alloc_return := @use("alloc_return.hb")
FakeAlloc := struct {
$init := fn(): Self {
return .()
}
$alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
return .(0, null)
}
$dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
return void
}
// Nothing to clean up here
$deinit := fn(self: Self): void {
return void
}
}

View file

@ -1,2 +0,0 @@
.{BlockAlloc} := @use("block_alloc.hb");
.{FakeAlloc} := @use("fake_alloc.hb")

View file

@ -1,25 +0,0 @@
allocators := @use("alloc/alloc.hb")
AStruct := struct {
a_field: u8,
}
main := fn():void{
alloc := allocators.FakeAlloc.init()
astruct := alloc.alloc(AStruct, 2)
if astruct.ptr != null{
panic("FakeAlloc actually allocated.")
}
alloc.dealloc(astruct_ptr, AStruct, 2)
alloc.deinit()
balloc := allocators.BlockAlloc.init()
bstruct_ptr := balloc.alloc(AStruct, 2)
if bstruct_ptr == null {
panic("BlockAlloc actually didn't allocate.")
}
balloc.dealloc(bstruct_ptr, AStruct, 2)
balloc.deinit()
}

View file

@ -1,189 +0,0 @@
/*
* This code is an implementation of the FoldHash algorithm from https://github.com/orlp/foldhash,
* originally written by Orson Peters under the zlib license.
*
* Changes to the original code were made to meet the simplicity requirements of this implementation.
* Behaviour aims to be equivalent but not identical to the original code.
*
* Copyright (c) 2024 Orson Peters
*
* This software is provided 'as-is', without any express or implied warranty. In
* no event will the authors be held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software for any purpose, including
* commercial applications, and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
* that you wrote the original software. If you use this software in a product,
* an acknowledgment in the product documentation would be appreciated but is
* not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/;
.{math, random} := @use("../lib.hb")
$ARBITRARY0 := 0x243F6A8885A308D3
$ARBITRARY1 := 0x13198A2E03707344
$ARBITRARY2 := 0xA4093822299F31D0
$ARBITRARY3 := 0x82EFA98EC4E6C89
$ARBITRARY4 := 0x452821E638D01377
$ARBITRARY5 := 0xBE5466CF34E90C6C
$ARBITRARY6 := 0xC0AC29B7C97C50DD
$ARBITRARY7 := 0x3F84D5B5B5470917
$ARBITRARY8 := 0x9216D5D98979FB1B
$ARBITRARY9 := 0xD1310BA698DFB5AC
$FIXED_GLOBAL_SEED := [uint].(ARBITRARY4, ARBITRARY5, ARBITRARY6, ARBITRARY7)
global_seed := 0
u128 := packed struct {a: uint, b: uint}
$folded_multiply := fn(x: uint, y: uint): uint {
lx := @as(u32, @intcast(x))
ly := @as(u32, @intcast(y))
hx := x >> 32
hy := y >> 32
afull := lx * hy
bfull := hx * ly
return afull ^ (bfull << 32 | bfull >> 32)
}
hash_bytes_medium := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, fold_seed: uint): uint {
lo := bytes
end := bytes + len
hi := end - 16
loop if lo >= hi break else {
a := *@as(^uint, @bitcast(lo))
b := *@as(^uint, @bitcast(lo + 8))
c := *@as(^uint, @bitcast(hi))
d := *@as(^uint, @bitcast(hi + 8))
s0 = folded_multiply(a ^ s0, c ^ fold_seed)
s1 = folded_multiply(b ^ s1, d ^ fold_seed)
hi -= 16
lo += 16
}
return s0 ^ s1
}
hash_bytes_long := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, s2: uint, s3: uint, fold_seed: uint): uint {
$chunk_size := 64
chunks := len / chunk_size
remainder := len % chunk_size
ptr := bytes
i := 0
loop if i >= chunks break else {
a := *@as(^uint, @bitcast(ptr))
b := *@as(^uint, @bitcast(ptr + 8))
c := *@as(^uint, @bitcast(ptr + 16))
d := *@as(^uint, @bitcast(ptr + 24))
e := *@as(^uint, @bitcast(ptr + 32))
f := *@as(^uint, @bitcast(ptr + 40))
g := *@as(^uint, @bitcast(ptr + 48))
h := *@as(^uint, @bitcast(ptr + 56))
s0 = folded_multiply(a ^ s0, e ^ fold_seed)
s1 = folded_multiply(b ^ s1, f ^ fold_seed)
s2 = folded_multiply(c ^ s2, g ^ fold_seed)
s3 = folded_multiply(d ^ s3, h ^ fold_seed)
ptr += chunk_size
i += 1
}
s0 ^= s2
s1 ^= s3
if remainder > 0 {
remainder_start := bytes + len - math.max(uint, remainder, 16)
return hash_bytes_medium(remainder_start, math.max(uint, remainder, 16), s0, s1, fold_seed)
}
return s0 ^ s1
}
FoldHasher := struct {
accumulator: uint,
original_seed: uint,
sponge: u128,
sponge_len: u8,
fold_seed: uint,
expand_seed: uint,
expand_seed2: uint,
expand_seed3: uint,
$new := fn(seed: uint): Self {
return .(
seed,
seed,
.(0, 0),
0,
FIXED_GLOBAL_SEED[0],
FIXED_GLOBAL_SEED[1],
FIXED_GLOBAL_SEED[2],
FIXED_GLOBAL_SEED[3],
)
}
default := fn(): Self {
if global_seed == 0 {
// ! consider this "secure enough" for now
global_seed = random.any(uint)
}
return Self.new(global_seed)
}
write := fn(self: ^Self, bytes: ^u8, len: uint): void {
s0 := self.accumulator
s1 := self.expand_seed
if len <= 16 {
if len >= 8 {
s0 ^= *@bitcast(bytes)
s1 ^= *@bitcast(bytes + len - 8)
} else if len >= 4 {
s0 ^= *@as(^u32, @bitcast(bytes))
s1 ^= *@as(^u32, @bitcast(bytes + len - 4))
} else if len > 0 {
lo := *bytes
mid := *(bytes + len / 2)
hi := *(bytes + len - 1)
s0 ^= lo
s1 ^= @as(uint, hi) << 8 | mid
}
self.accumulator = folded_multiply(s0, s1)
} else if len < 256 {
self.accumulator = hash_bytes_medium(bytes, len, s0, s1, self.fold_seed)
} else {
self.accumulator = hash_bytes_long(
bytes,
len,
s0,
s1,
self.expand_seed2,
self.expand_seed3,
self.fold_seed,
)
}
}
finish := fn(self: ^Self): uint {
if self.sponge_len > 0 {
return folded_multiply(self.sponge.b ^ self.accumulator, self.sponge.a ^ self.fold_seed)
} else {
return self.accumulator
}
}
reset := fn(self: ^Self): void {
self.accumulator = self.original_seed
self.sponge = .(0, 0)
self.sponge_len = 0
}
}

View file

@ -1,2 +0,0 @@
//! NON CRYPTOGRAPHIC HASHER
foldhash := @use("foldhash.hb")

View file

@ -1,6 +1,4 @@
acs := @use("acs.hb") acs := @use("acs.hb")
allocators := @use("alloc/lib.hb")
hashers := @use("hash/lib.hb")
string := @use("string.hb") string := @use("string.hb")
log := @use("log.hb") log := @use("log.hb")
memory := @use("memory.hb") memory := @use("memory.hb")
@ -10,7 +8,6 @@ random := @use("random.hb")
file := @use("file_io.hb") file := @use("file_io.hb")
dt := @use("dt.hb") dt := @use("dt.hb")
process := @use("process.hb") process := @use("process.hb")
sleep := @use("sleep.hb")
panic := fn(message: ?^u8): never { panic := fn(message: ?^u8): never {
log.error("Error: Panic Called, Message:\0") log.error("Error: Panic Called, Message:\0")

View file

@ -10,16 +10,6 @@ $max := fn($Expr: type, a: Expr, b: Expr): Expr {
$sign := fn($Expr: type, x: Expr): i8 { $sign := fn($Expr: type, x: Expr): i8 {
return @bitcast(x > 0) - @bitcast(x < 0) return @bitcast(x > 0) - @bitcast(x < 0)
} }
$log := fn($Expr: type, base: uint, x: Expr): uint {
// if x <= 0 {}
// if base <= 1 {}
result := 0
loop if x < base break else {
x /= base
result += 1
}
return result
}
Vec2 := fn($Expr: type): type { Vec2 := fn($Expr: type): type {
return struct {x: Expr, y: Expr} return struct {x: Expr, y: Expr}

View file

@ -1,15 +1,7 @@
$any := fn($Expr: type): Expr { any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
} }
$range := fn($Expr: type, min: Expr, max: Expr): Expr { range := fn($Expr: type, min: Expr, max: Expr): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) % (max - min) + *@bitcast(&1) + min return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) % (max - min) + *@bitcast(&1) + min
} }
$fill := fn($Expr: type, ptr: ^Expr): void {
return @eca(3, 4, ptr, @sizeof(Expr))
}
$fill_buffer := fn(buf: ^u8, len: uint): void {
return @eca(3, 4, buf, len)
}

View file

@ -3,5 +3,4 @@ subscribe_to_interrupt := fn(interrupt_number: u8): bool {
} }
// Pauses execution until the interrupt occures // Pauses execution until the interrupt occures
sleep_until_interrupt := fn(interrupt_number: u8): void { sleep_until_interrupt := fn(interrupt_number: u8): void {
@eca(6, interrupt_number)
} }

View file

@ -61,156 +61,3 @@ equals := fn(lhs: ^u8, rhs: ^u8): bool {
rhs += 1 rhs += 1
} }
} }
clear := fn(ptr: ^u8): void {
loop if *ptr == 0 break else {
*ptr = 0
ptr += 1
}
}
split_once := fn(haystack: ^u8, needle: u8): ?^u8 {
loop if *haystack == needle return haystack else if *haystack == 0 return null else haystack += 1
}
split_once_str := fn(haystack: ^u8, needle: ^u8): ?^u8 {
if *needle == 0 return null
loop if *haystack == 0 return null else {
if *haystack == *needle {
h := haystack
n := needle
loop {
n += 1
h += 1
if *n == 0 {
return haystack
} else if *h == 0 | *h != *n {
break
}
}
}
haystack += 1
}
}
Split := struct {
str: ^u8,
needle: u8,
done: bool,
}
split := fn(iter: ^u8, needle: u8): Split {
return .(
iter,
needle,
false,
)
}
iter_split := fn(iter: ^Split): ?^u8 {
if iter.done | *iter.str == 0 {
return null
}
next := split_once(iter.str + 1, iter.needle)
if next == null {
iter.done = true
return iter.str
}
s := iter.str
iter.str = next + 1
return s
}
SplitStr := struct {
str: ^u8,
needle: ^u8,
done: bool,
}
split_str := fn(iter: ^u8, needle: ^u8): SplitStr {
return .(
iter,
needle,
false,
)
}
iter_split_str := fn(iter: ^SplitStr): ?^u8 {
if iter.done | *iter.str == 0 {
return null
}
next := split_once_str(iter.str, iter.needle)
if next == null {
iter.done = true
return iter.str
}
s := iter.str
iter.str = next + length(iter.needle)
return s
}
find_once := fn(haystack: ^u8, needle: u8): ?uint {
return @bitcast(@inline(split_once, haystack, needle) - haystack)
}
find_once_str := fn(haystack: ^u8, needle: ^u8): ?uint {
return @bitcast(@inline(split_once_str, haystack, needle) - haystack)
}
count := fn(haystack: ^u8, needle: ^u8): uint {
c := 0
loop if *haystack == needle {
c += 1
haystack += 1
} else if *haystack == 0 return c else haystack += 1
}
count_str := fn(haystack: ^u8, needle: ^u8): uint {
if *needle == 0 return 0
c := 0
loop if *haystack == 0 return c else {
if *haystack == *needle {
h := haystack
n := needle
loop {
n += 1
h += 1
if *n == 0 {
c += 1
break
} else if *h == 0 | *h != *n {
break
}
}
}
haystack += 1
}
}
left_trim := fn(str: ^u8, sub: ^u8): ^u8 {
original := str
if *str == *sub {
loop if *sub == 0 {
return str
} else if *str != *sub {
return original
} else if *str == 0 {
return original
} else {
str += 1
sub += 1
}
}
return str
}

View file

@ -0,0 +1 @@
# dt_buffer_test

View file

@ -1,6 +1,6 @@
[package] [package]
name = "sdoom" name = "dt_buffer_test"
authors = [""] authors = ["able"]
[dependants.libraries] [dependants.libraries]

View file

@ -0,0 +1,13 @@
.{dt} := @use("../../../libraries/stn/src/lib.hb")
main := fn(): void {
dt.get(void, "framebuffer/fb0/width\0")
dt.get(void, "cpu/cpu0/architecture\0")
// Checking if the first detected serial port is memory mapped or port mapped
// 0 -> memory mapped
// 1 -> port mapped
dt.get(void, "serial_ports/sp0/mapping\0")
return
}

View file

@ -1 +0,0 @@
# pcspkr

View file

@ -1,45 +0,0 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{memory, buffer, log, string, math} := stn;
.{inb, outb} := memory
$PIT_CLOCK := 1193180
play_sound := fn(frequency: u32): void {
div := 0
div = PIT_CLOCK / frequency
memory.outb(0x43, 0xB6)
memory.outb(0x42, @intcast(div))
memory.outb(0x42, @intcast(div >> 8))
tmp := inb(0x61)
if tmp != (tmp | 3) {
outb(0x61, tmp | 3)
}
}
no_sound := fn(): void {
tmp := memory.inb(0x61) & 0xFC
memory.outb(0x61, tmp)
}
beep := fn(): void {
play_sound(1000)
idx := 0
loop {
if idx >= 1000000 {
idx += 1
} else {
break
}
}
no_sound()
}
main := fn(): int {
no_sound()
beep()
return 0
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "pcspkr" name = "processes"
authors = [""] authors = ["koniifer"]
[dependants.libraries] [dependants.libraries]

View file

@ -1,8 +1,8 @@
.{process, log, string, memory} := @use("../../../../../libraries/stn/src/lib.hb") .{process, log, string, memory} := @use("../../../libraries/stn/src/lib.hb")
exe := @embed("./assets/hello_world_and_spin.hbf") exe := @embed("./hello_world_and_spin.hbf")
test := fn(): uint { main := fn(): void {
buf := "\0\0\0\0\0\0\0" buf := "\0\0\0\0\0\0\0"
loop { loop {
log.info( log.info(
@ -16,5 +16,4 @@ test := fn(): uint {
i := 0 i := 0
loop if i == 1000000 break else i += 1 loop if i == 1000000 break else i += 1
} }
return 0
} }

View file

@ -1 +1 @@
.{example: main} := @use("./examples/orbit.hb") .{example: main} := @use("./examples/text.hb")

View file

@ -1,4 +0,0 @@
# sdoom
SDoom stands for simple doom.
This is not a full implementation of doom and is instead a doom style renderer.

View file

@ -1,53 +0,0 @@
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
stn := @use("../../../libraries/stn/src/lib.hb");
.{log} := stn;
.{Vec2} := stn.math
Player := struct {
x: i8,
y: i8,
$new := fn(x: i8, y: i8): Self {
return Self.(x, y)
}
}
GameState := struct {
player: Player,
$new := fn(): Self {
p := Player.new(0, 0)
return Self.(p)
}
}
main := fn(): void {
sunset.client.find_server()
window := sunset.client.new(.(.(600, 400), .(200, 200), "SDoom\0"))
if window == null {
log.error("got no window\0")
return
}
game_state := GameState.new()
loop {
render.clear(window.surface, render.black)
width := 100
idx := 1
loop {
if idx >= width {
break
}
render.put_vline(window.surface, idx, 10, 100, render.white)
idx += 1
}
_ = sunset.client.send_frame(window)
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "test" name = "serial_driver_test"
authors = ["koniifer", "able"] authors = ["able"]
[dependants.libraries] [dependants.libraries]

View file

@ -0,0 +1,20 @@
.{string, buffer} := @use("../../../libraries/stn/src/lib.hb")
log_info := fn(): void {
a := buffer.search("XNumber\0")
if a == 0 {
} else {
msg := "XABC\0"
// inline is broked
// msg_length := @inline(string.length, msg)
msg_length := 5
@as(void, @eca(3, a, msg, msg_length))
}
return
}
main := fn(): int {
log_info()
return 0
}

View file

@ -13,7 +13,7 @@ main := fn(): void {
return return
} }
window := sunset.client.new(.(.(400, 100), .(400, 240), "Sunset!\0")) window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0"))
if window == null { if window == null {
log.error("got no window\0") log.error("got no window\0")

View file

@ -3,7 +3,7 @@ render := @use("../../../libraries/render/src/lib.hb")
intouch := @use("../../../libraries/intouch/src/lib.hb") intouch := @use("../../../libraries/intouch/src/lib.hb")
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb"); horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{set_color, render_label_to_surface, Label} := horizon_api.widgets.label .{new_label, render_label_to_surface, set_label_text, set_color} := horizon_api.widgets.label
stn := @use("../../../libraries/stn/src/lib.hb"); stn := @use("../../../libraries/stn/src/lib.hb");
.{Vec2} := stn.math .{Vec2} := stn.math
@ -13,9 +13,6 @@ img := @embed("../../../assets/wallpaper.qoi")
main := fn(): int { main := fn(): int {
sunset.server.start() sunset.server.start()
defer {
stn.log.info("Sunset Server Exit\0")
}
screen := render.init(true) screen := render.init(true)
render.clear(screen, render.black) render.clear(screen, render.black)
@ -31,8 +28,8 @@ main := fn(): int {
mouse_x := 100 mouse_x := 100
mouse_y := 100 mouse_y := 100
text_label := Label.new_label("Hi\0") text_label := new_label("Hi\0")
text_label.set_color(sunset.server.DECO_COLOUR, render.black) set_color(text_label, sunset.server.DECO_COLOUR, render.black)
loop { loop {
mouse_event := intouch.recieve_mouse_event() mouse_event := intouch.recieve_mouse_event()
@ -62,13 +59,13 @@ main := fn(): int {
} }
if mouse_event.left { if mouse_event.left {
text_label.set_label_text("LEFT CLICK\0") set_label_text(text_label, "LEFT CLICK\0")
} }
if mouse_event.middle { if mouse_event.middle {
text_label.set_label_text("MIDDLE CLICK\0") set_label_text(text_label, "MIDDLE CLICK\0")
} }
if mouse_event.right { if mouse_event.right {
text_label.set_label_text("RIGHT CLICK\0") set_label_text(text_label, "RIGHT CLICK\0")
} }
} }
{ {

View file

@ -1,7 +0,0 @@
stn := @use("./tests/stn/lib.hb")
serial_driver := @use("./tests/serial_driver.hb")
main := fn(): uint {
// return serial_driver.test()
return stn.process.test()
}

View file

@ -1,18 +0,0 @@
.{string, buffer} := @use("../../../../libraries/stn/src/lib.hb")
log_info := fn(): void {
a := buffer.search("XNumber\0")
if a == 0 {
} else {
msg := "XABC\0"
msg_length := string.length(msg)
@eca(3, a, msg, msg_length)
}
return
}
test := fn(): uint {
log_info()
return 0
}

View file

@ -1,30 +0,0 @@
stn := @use("../../../../../libraries/stn/src/lib.hb");
.{allocators, panic, log} := stn
AStruct := struct {
a_field: u8,
}
test := fn(): uint {
// alloc := allocators.FakeAlloc.init()
// astruct := alloc.alloc(AStruct, 2)
// if astruct.ptr != null{
// panic.panic("FakeAlloc actually allocated.")
// }
// alloc.dealloc(&astruct.ptr, AStruct, 2)
// alloc.deinit()
balloc := allocators.BlockAlloc.init()
// defer {
// balloc.deinit()
// }
bstruct := balloc.alloc(AStruct, 2)
// if bstruct.ptr == null {
// log.info("Hi\0")
// // panic.panic("BlockAlloc actually didn't allocate.")
// } else {
// log.info("Allocator functioned.\0")
// }
// balloc.dealloc(bstruct_ptr, AStruct, 2)
return 0
}

View file

@ -1,18 +0,0 @@
.{dt, memory, string, log} := @use("../../../../../libraries/stn/src/lib.hb")
test := fn(): uint {
buffer := memory.request_page(1)
log.info(string.display_int(dt.get(int, "framebuffer/fb0/width\0"), buffer, 10))
string.clear(buffer)
log.info(string.display_int(dt.get(int, "cpu/cpu0/architecture\0"), buffer, 10))
string.clear(buffer)
// 0 -> memory mapped
// 1 -> port mapped
log.info(string.display_int(dt.get(int, "serial_ports/sp0/mapping\0"), buffer, 10))
return 0
}

View file

@ -1,32 +0,0 @@
.{hashers, log, memory, string} := @use("../../../../../libraries/stn/src/lib.hb")
test := fn(): uint {
buffer := memory.request_page(1)
target := "abcdefghijklmnop\0"
strings := [^u8].("abcdefshijklmnop\0", "abcdefghijklnnop\0", "abcdefshijklmnop\0", "abcdefghijklmnop\0", "abcdefghijflmnop\0", "dbcdefghijklmnop\0", "abcdefghijklmnop\0")
len := @sizeof(@TypeOf(strings)) / @sizeof(^u8)
strlen := string.length(target)
// hasher := hashers.foldhash.FoldHasher.new(1)
hasher := hashers.foldhash.FoldHasher.default()
hasher.write(target, strlen)
correct := hasher.finish()
log.warn("target:\0")
log.warn(target)
i := 0
loop if i == len break else {
defer i += 1
hasher.reset()
hasher.write(strings[i], strlen)
d := hasher.finish()
if d == correct {
log.warn("match found\0")
}
log.info(strings[i])
log.debug(string.display_int(@bitcast(d), buffer, 16))
string.clear(buffer)
}
return 0
}

View file

@ -1,5 +0,0 @@
hashers := @use("./hashers.hb")
allocators := @use("./allocators.hb")
sleep := @use("./sleep.hb")
dt := @use("./dt.hb")
process := @use("./process.hb")

View file

@ -1,8 +0,0 @@
.{sleep, log} := @use("../../../../../libraries/stn/src/lib.hb")
test := fn(): uint {
log.info("BEFORE\0")
sleep.sleep_until_interrupt(32)
log.info("AFTER\0")
return 0
}

View file

@ -34,20 +34,14 @@ path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_keyboard_driver] # [boot.limine.ableos.modules.ps2_keyboard_driver]
# path = "boot:///ps2_keyboard_driver.hbf" # path = "boot:///ps2_keyboard_driver.hbf"
# [boot.limine.ableos.modules.sunset_client] [boot.limine.ableos.modules.sunset_client]
# path = "boot:///sunset_client.hbf" path = "boot:///sunset_client.hbf"
# [boot.limine.ableos.modules.sunset_client_2] [boot.limine.ableos.modules.sunset_client_2]
# path = "boot:///sunset_client_2.hbf" path = "boot:///sunset_client_2.hbf"
[boot.limine.ableos.modules.sdoom]
path = "boot:///sdoom.hbf"
[boot.limine.ableos.modules.sunset_server] [boot.limine.ableos.modules.sunset_server]
path = "boot:///sunset_server.hbf" path = "boot:///sunset_server.hbf"
# [boot.limine.ableos.modules.pcspkr] # [boot.limine.ableos.modules.processes]
# path = "boot:///pcspkr.hbf" # path = "boot:///processes.hbf"
# [boot.limine.ableos.modules.test]
# path = "boot:///test.hbf"