1
0
Fork 0
forked from AbleOS/ableos

Compare commits

...

10 commits

20 changed files with 495 additions and 16 deletions

View file

@ -1,4 +1,6 @@
{ {
"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"

6
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#86ca959ea3eae1cb32298e135a444820583d24a0" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b"
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#86ca959ea3eae1cb32298e135a444820583d24a0" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a3355a59c0727e58519a94a8f65013beb9c2331b"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]

66
STYLE_GUIDE.md Normal file
View file

@ -0,0 +1,66 @@
# 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 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

@ -22,12 +22,13 @@ 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")] { #[cfg(feature = "ktest")]
{
use crate::ktest; use crate::ktest;
debug!("TESTING"); debug!("TESTING");
ktest::test_main(); ktest::test_main();
loop {}; loop {}
} }
// let kcmd = build_cmd("Kernel Command Line", cmdline); // let kcmd = build_cmd("Kernel Command Line", cmdline);
@ -75,6 +76,7 @@ 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);
@ -131,7 +133,6 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
executor.run(); executor.run();
}; };
crate::arch::spin_loop() crate::arch::spin_loop()
} }

View file

@ -485,7 +485,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", "neoverse-n2", "-cpu", "max",
"-device", "ramfb", "-device", "ramfb",
"-device", "qemu-xhci", "-device", "qemu-xhci",
"-device", "usb-kbd", "-device", "usb-kbd",

View file

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

View file

@ -0,0 +1,79 @@
.{log, panic} := @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 {
return .(0, null)
}
alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
offset := 1
a := 1
loop {
// a = self.state >> offset
// check if the `offset` bit is 1, if it is move to the next offset
if a == 1 {
offset += 1
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

@ -0,0 +1,19 @@
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

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

View file

@ -0,0 +1,25 @@
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

@ -0,0 +1,189 @@
/*
* 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

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

View file

@ -1,4 +1,6 @@
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")

View file

@ -0,0 +1 @@
# alloc_test

View file

@ -0,0 +1,11 @@
[package]
name = "alloc_test"
authors = [""]
[dependants.libraries]
[dependants.binaries]
hblang.version = "1.0.0"
[build]
command = "hblang src/main.hb"

View file

@ -0,0 +1,28 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{allocators, panic, log} := stn
AStruct := struct {
a_field: u8,
}
main := fn(): void {
// 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
}

View file

@ -0,0 +1,11 @@
[package]
name = "hash_test"
authors = [""]
[dependants.libraries]
[dependants.binaries]
hblang.version = "1.0.0"
[build]
command = "hblang src/main.hb"

View file

@ -0,0 +1,31 @@
.{hashers, log, memory, string} := @use("../../../libraries/stn/src/lib.hb")
main := fn(): void {
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)
}
}

View file

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

View file

@ -28,20 +28,26 @@ resolution = "1024x768x24"
# [boot.limine.ableos.modules.horizon] # [boot.limine.ableos.modules.horizon]
# path = "boot:///horizon.hbf" # path = "boot:///horizon.hbf"
[boot.limine.ableos.modules.ps2_mouse_driver] # [boot.limine.ableos.modules.ps2_mouse_driver]
path = "boot:///ps2_mouse_driver.hbf" # 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.sunset_server] # [boot.limine.ableos.modules.sunset_server]
path = "boot:///sunset_server.hbf" # path = "boot:///sunset_server.hbf"
# [boot.limine.ableos.modules.processes] # [boot.limine.ableos.modules.processes]
# path = "boot:///processes.hbf" # path = "boot:///processes.hbf"
# [boot.limine.ableos.modules.alloc_test]
# path = "boot:///alloc_test.hbf"
[boot.limine.ableos.modules.alloc_test]
path = "boot:///hash_test.hbf"