1
0
Fork 0
forked from AbleOS/ableos

Compare commits

...

69 commits

Author SHA1 Message Date
peony 5028062e39 Merge branch 'master' of https://git.ablecorp.us/AbleOS/ableos 2024-11-24 13:32:27 +01:00
peony f7f9fece4f Merged once more 2024-11-24 13:31:57 +01:00
able b505622601 Merge pull request 'Ktest + Nix Flake' (#20) from FunkyEgg/ableos:master into master
Reviewed-on: https://git.ablecorp.us/AbleOS/ableos/pulls/20
2024-11-23 21:13:23 -06:00
funky 80ae717dd9 Introduced kernel testing system ktest
This commit also fixed a small issue with panic handler formatting
2024-11-24 11:21:39 +11:00
funky ab8b2309ae Nix Flake Support
nix-shell is broken on both my systems, so better be safe than sorry.
2024-11-24 11:12:24 +11:00
koniifer 7b7e02976d random change 2024-11-23 18:06:48 +00:00
koniifer c1c02ffefd silly string 2024-11-23 16:51:39 +00:00
peony f4ceab972c Merge branch 'master' of https://git.ablecorp.us/AbleOS/ableos 2024-11-23 17:13:04 +01:00
able 8602ceb0d3 nightly revert 2024-11-23 04:59:32 -06:00
peony 96c07e137b Removed error.error because its in #aos-geeral. 2024-11-18 20:47:46 +01:00
peony d78878a12f Compiler error 2024-11-18 20:29:51 +01:00
Able 6b673bc7e6 labels now have bg/fg color 2024-11-18 09:19:04 -06:00
peony 8f265ebf40 PS/2 literally almost work 2024-11-17 22:59:05 +01:00
peony 3d5a8f6f10 End meeeee 2024-11-17 22:38:07 +01:00
peony f11122e58e Merge master 2024-11-17 21:31:51 +01:00
peony 2fdede7199 PS/2 workkkk 2024-11-17 21:30:58 +01:00
koniifer 0af4d142a4 bad process spawning, compiler updates 2024-11-17 20:29:32 +00:00
peony 13422dfd9f Merge branch 'master' of https://git.ablecorp.us/AbleOS/ableos 2024-11-17 19:11:33 +01:00
peony 90a97cd160 more work 2024-11-17 19:11:13 +01:00
peony 23b45b1887 Driver workkkk 2024-11-17 17:57:06 +01:00
koniifer 36f0d357cf arm cpuid fix 2024-11-17 10:52:13 +00:00
peony cf37eaf086 Merge branch 'master' of https://git.ablecorp.us/AbleOS/ableos 2024-11-17 11:17:59 +01:00
peony 284aa5a5e6 PS/2 is so close 2024-11-17 11:17:32 +01:00
koniifer ccddf36050 fix 2024-11-17 10:11:14 +00:00
peony 11976b752f PS/2 driver going well (it still doesn't work) 2024-11-16 22:56:00 +01:00
peony 98b15d4c10 Merge master 2024-11-16 21:52:45 +01:00
peony f5c6d7d822 PS/2 driver refactoring and poassibly completion process 2024-11-16 21:51:55 +01:00
koniifer da5f1a7a19 compiler update 2024-11-16 20:42:16 +00:00
koniifer 2808bc9e7c various fixes, update to latest rust nightly 2024-11-16 16:34:45 +00:00
koniifer d958a103fa fix 2024-11-16 09:34:17 +00:00
koniifer ee82bc5705 minor changes 2024-11-16 09:30:53 +00:00
Able 3d53b641bf interrupt work 2024-11-16 02:51:58 -06:00
peony efcd6c0631 Uuugh, jesus this sucks 2024-11-15 22:55:44 +01:00
peony b795aced8e Merge branch 'master' of https://git.ablecorp.us/AbleOS/ableos 2024-11-15 20:48:23 +01:00
peony 08099b0877 Barely any PS/2 driver work 2024-11-15 20:47:11 +01:00
koniifer cea7f1fa5c use new register allocator by default 2024-11-15 19:46:36 +00:00
Able 614bef7ec5 ok now there is colors 2024-11-14 18:40:44 -06:00
Able b0f6aa53bd Mouse updates 2024-11-14 18:33:29 -06:00
Able d5f4ce18a3 push changes 2024-11-14 18:09:54 -06:00
koniifer 907c0d0dd4 multi-client support and demo 2024-11-14 21:28:21 +00:00
koniifer 95b4a921dc improve & optimise window decoration code 2024-11-14 16:43:23 +00:00
koniifer b6261d014d bad frame synchronisation implementation 2024-11-13 23:08:20 +00:00
Able 56ee0fe851 misc 2024-11-13 14:17:15 -06:00
koniifer b07bac1f1f broken 2024-11-13 17:03:31 +00:00
peony a1bfd8e85f Driver not work 2024-11-12 22:36:43 +01:00
koniifer dc9273b3c1 various opts and keeping on top of compiler changes 2024-11-12 20:14:37 +00:00
Able e6d8f5c822 todo changes 2024-11-11 17:49:11 -06:00
koniifer 8ad7542b9c sunset work, stn changes, and fiddling with kernel logging clutter 2024-11-11 21:48:43 +00:00
Able e40a22fccd Commit 2024-11-11 01:23:14 -06:00
koniifer cf917927a5 incomplete sunset redesign 2024-11-11 01:03:01 +00:00
peony edfb588060 Merge main. 2024-11-10 21:26:54 +01:00
peony cc4a32afaa PS/2 work 2024-11-10 21:24:19 +01:00
koniifer 97ceb12d6e double skill issue 2024-11-10 20:07:03 +00:00
koniifer bae58ade61 skill issue fix 2024-11-10 20:04:49 +00:00
koniifer b21c05e924 compiler bugfix 2024-11-10 19:37:37 +00:00
Able 2f5bc73665 The List 2024-11-10 13:13:38 -06:00
Able 0003464099 sunsetting sunset 2024-11-10 13:00:41 -06:00
koniifer 77a708d41e sunrising sunset 2024-11-10 18:57:48 +00:00
peony be6a095c14 Cargo stuff 2024-11-10 19:14:20 +01:00
peony 3409f5051a Circle rendering support (janky) (#18)
circle rendering
Reviewed-on: https://git.ablecorp.us/AbleOS/ableos/pulls/18
Co-authored-by: peony <peony@email.com>
Co-committed-by: peony <peony@email.com>
2024-11-10 09:03:14 -06:00
peony aac1164d55 More git stuff 2024-11-10 15:45:01 +01:00
peony 89d08d8a62 Alighning with master. 2024-11-10 15:44:17 +01:00
peony 8f5833955f Circle test. (Precision issues) 2024-11-10 15:42:41 +01:00
peony 4c0adbe15d Circle rendring. 2024-11-10 15:19:55 +01:00
peony 3708acc077 Revert to mainline 2024-11-10 15:09:41 +01:00
peony b5b122f451 Complete revert to mainline, I think? 2024-11-10 15:04:59 +01:00
Able 8c7b95277d reorg 2024-11-10 06:18:23 -06:00
peony 39ebaa03ba Uuuugh 2024-10-14 14:35:41 +02:00
peony de8000f596 Fixed software renderer; added vline,hline,trirect 2024-10-13 23:15:10 +02:00
72 changed files with 1976 additions and 415 deletions

126
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "aarch64-cpu"
@ -13,9 +13,9 @@ dependencies = [
[[package]]
name = "allocator-api2"
version = "0.2.19"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f"
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
[[package]]
name = "anyhow"
@ -65,15 +65,6 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
dependencies = [
"allocator-api2",
]
[[package]]
name = "byteorder"
version = "1.5.0"
@ -82,9 +73,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.1.37"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
dependencies = [
"shlex",
]
@ -208,12 +199,6 @@ dependencies = [
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.1"
@ -228,24 +213,23 @@ dependencies = [
[[package]]
name = "hbbytecode"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
[[package]]
name = "hblang"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
dependencies = [
"hashbrown 0.15.1",
"hashbrown",
"hbbytecode",
"hbvm",
"log",
"regalloc2",
]
[[package]]
name = "hbvm"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
dependencies = [
"hbbytecode",
]
@ -396,7 +380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown 0.15.1",
"hashbrown",
]
[[package]]
@ -406,8 +390,9 @@ dependencies = [
"aarch64-cpu",
"crossbeam-queue",
"derive_more",
"hashbrown 0.15.1",
"hashbrown",
"hbvm",
"ktest_macro",
"limine",
"log",
"sbi",
@ -420,6 +405,14 @@ dependencies = [
"xml",
]
[[package]]
name = "ktest_macro"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -428,9 +421,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.162"
version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "limine"
@ -440,9 +433,9 @@ checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
[[package]]
name = "litemap"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "lock_api"
@ -519,9 +512,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "proc-macro2"
version = "1.0.89"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
@ -553,19 +546,6 @@ dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "regalloc2"
version = "0.10.2"
source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#21c43e3ee182824e92e2b25f1d3c03ed47f9c02b"
dependencies = [
"allocator-api2",
"bumpalo",
"hashbrown 0.14.5",
"log",
"rustc-hash",
"smallvec",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
@ -602,12 +582,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "rustc-hash"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -619,9 +593,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.16"
version = "0.23.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
dependencies = [
"log",
"once_cell",
@ -675,18 +649,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.214"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.214"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
@ -752,9 +726,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
dependencies = [
"proc-macro2",
"quote",
@ -824,9 +798,9 @@ dependencies = [
[[package]]
name = "uart_16550"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d"
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
dependencies = [
"bitflags 2.6.0",
"rustversion",
@ -835,9 +809,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.13"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "unicode-xid"
@ -868,9 +842,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.5.3"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
dependencies = [
"form_urlencoded",
"idna",
@ -911,9 +885,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "webpki-roots"
version = "0.26.6"
version = "0.26.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
dependencies = [
"rustls-pki-types",
]
@ -1070,9 +1044,9 @@ dependencies = [
[[package]]
name = "yoke"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
@ -1082,9 +1056,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
version = "0.7.4"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
@ -1094,18 +1068,18 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",

96
flake.lock Normal file
View file

@ -0,0 +1,96 @@
{
"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
}

30
flake.nix Normal file
View file

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

View file

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

@ -0,0 +1,29 @@
extern crate proc_macro;
extern crate quote;
extern crate syn;
use {
proc_macro::TokenStream,
quote::quote,
syn::{parse_macro_input, ItemFn}
};
#[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 static_var_name = syn::Ident::new(
&format!("__ktest_{}", test_name),
test_name.span(),
);
let out = quote! {
// #[cfg(feature = "ktest")]
#input
// #[cfg(feature = "ktest")]
#[unsafe(link_section = ".note.ktest")]
#[used]
pub static #static_var_name: fn() = #test_name;
};
TokenStream::from(out)
}

View file

@ -38,7 +38,15 @@ SECTIONS
.data : {
*(.data .data.*)
*(.got .got.*)
} :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 : {
*(COMMON)

View file

@ -14,3 +14,29 @@ arch_cond!(
riscv64: "riscv64",
x86_64: "x86_64",
);
#[cfg(target_arch = "x86_64")]
use {crate::arch::interrupts::Interrupt, alloc::string::String};
#[cfg(target_arch = "x86_64")]
pub struct InterruptList {
list: HashMap<Interrupt, String>,
}
#[cfg(target_arch = "x86_64")]
use hashbrown::HashMap;
#[cfg(target_arch = "x86_64")]
impl InterruptList {
pub fn new() -> Self {
Self {
list: HashMap::new(),
}
}
}
#[cfg(target_arch = "x86_64")]
use spin::{Lazy, Mutex};
#[cfg(target_arch = "x86_64")]
pub static INTERRUPT_LIST: Lazy<Mutex<InterruptList>> = Lazy::new(|| {
let mut il = InterruptList::new();
use crate::alloc::string::ToString;
il.list.insert(Interrupt::Timer, "PS/2 Mouse".to_string());
Mutex::new(il)
});

View file

@ -11,7 +11,9 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
#[repr(u8)]
enum Interrupt {
#[derive(Debug, Eq, Hash, PartialEq)]
pub enum Interrupt {
Timer = 32,
ApicErr = u8::MAX - 1,
Spurious = u8::MAX,
@ -60,17 +62,49 @@ extern "x86-interrupt" fn page_fault(
}
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
// interrupt(Interrupt::Timer);
unsafe {
LAPIC.end_of_interrupt();
}
}
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
interrupt(Interrupt::ApicErr);
panic!("Internal APIC error");
}
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
interrupt(Interrupt::Spurious);
unsafe {
LAPIC.end_of_interrupt();
}
}
fn interrupt(interrupt_type: Interrupt) {
use crate::arch::INTERRUPT_LIST;
let il = INTERRUPT_LIST.lock();
let val = il.list.get(&interrupt_type).unwrap();
use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
let buffer = sds_search_service(val);
if buffer != 0 {
use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
let mut buffs = IPC_BUFFERS.lock();
match buffs.get_mut(&buffer) {
Some(buff) => {
let mut msg_vec = Vec::new();
msg_vec.push(0xFF);
buff.push(msg_vec.to_vec());
log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
}
None => {
log::error!("Access of non-existent buffer {}", buffer)
}
}
// log::info!("{}", buffer);
}
}

View file

@ -33,7 +33,7 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
#[cfg(not(target_feature = "avx2"))]
unsafe extern "C" fn _kernel_start() -> ! {
// Initialise SSE, then jump to kernel entrypoint
core::arch::asm!(
core::arch::naked_asm!(
// Initialise SSE
"mov rax, cr0",
"and ax, 0xfffb",
@ -46,7 +46,6 @@ unsafe extern "C" fn _kernel_start() -> ! {
// Jump to the kernel entry point
"jmp {}",
sym start,
options(noreturn),
)
}
@ -54,7 +53,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
#[naked]
#[cfg(target_feature = "avx2")]
unsafe extern "C" fn _kernel_start() -> ! {
core::arch::asm!(
core::arch::naked_asm!(
// Enable protected mode and configure control registers
"mov rax, cr0",
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
@ -100,7 +99,6 @@ unsafe extern "C" fn _kernel_start() -> ! {
"jmp {0}",
sym start,
sym oops,
options(noreturn),
)
}
@ -111,7 +109,7 @@ unsafe extern "C" fn oops() -> ! {
unsafe extern "C" fn start() -> ! {
logging::init();
crate::logger::init().expect("failed to set logger");
log::info!("Initialising AKern {}", crate::VERSION);
log::debug!("Initialising AKern {}", crate::VERSION);
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
memory::init_pt(VirtAddr::new(
@ -190,7 +188,7 @@ unsafe extern "C" fn start() -> ! {
// TODO: Add in rdseed and rdrand as sources for randomness
let _rand = xml::XMLElement::new("Random");
log::trace!("Getting boot modules");
log::debug!("Getting boot modules");
let bm = MOD_REQ.get_response().get();
let mut bootmodules = alloc::vec::Vec::new();
@ -228,7 +226,7 @@ unsafe extern "C" fn start() -> ! {
break;
}
}
log::info!("Boot module count: {:?}", bootmodules.len());
log::debug!("Boot module count: {:?}", bootmodules.len());
assert_eq!(bm.module_count, bootmodules.len() as u64);
}

View file

@ -69,7 +69,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
}
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
log::debug!("pci device-({}) addr {} is {}", device, addr, reg2);
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
let pci_class = PciFullClass::from_u16(class);
let header_type = get_header_type(bus, device, 0);

View file

@ -1,8 +1,17 @@
//! 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 {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address};
use crate::{
holeybytes::{
kernel_services::{
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
service_definition_service::sds_msg_handler,
},
ExecThread,
},
kmain::EXECUTOR,
task::Executor,
};
use {
@ -58,10 +67,10 @@ pub fn handler(vm: &mut Vm) {
true => IpcBuffer::new(true, length),
},
);
info!("Buffer ID: {}", buff_id);
vm.registers[1] = hbvm::value::Value(buff_id);
}
2 => {
log::error!("Oops, deleting buffers is not implemented.")
// Delete buffer
}
3 => {
@ -143,6 +152,43 @@ pub fn handler(vm: &mut Vm) {
Ok(()) => {}
Err(_) => log::error!("Improper dt query"),
},
6 => unsafe {
let program = block_read(mem_addr, length);
// decode AbleOS Executable format
let header = &program[0..46];
let magic_slice = &header[0..3];
if magic_slice != [0x15, 0x91, 0xD2] {
log::error!("Invalid magic number at the start of executable.");
return;
}
let executable_format_version =
u32::from_le_bytes(header[3..7].try_into().unwrap());
let offset = if executable_format_version == 0 {
47
} else {
error!("Invalid executable format.");
return;
};
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::debug!("{code_length} + {data_length} = {end}");
let thr = ExecThread::new(&program[offset..end], Address::new(0));
vm.registers[1] = Value(
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.spawn(Box::pin(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
})) as u64,
);
log::debug!("spawned a process");
},
buffer_id => {
let mut buffs = IPC_BUFFERS.lock();
@ -182,7 +228,7 @@ pub fn handler(vm: &mut Vm) {
} else {
unsafe {
let ptr = map_ptr as *mut u8;
ptr.copy_from(msg.as_ptr(), msg.len());
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
}
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);

View file

@ -9,7 +9,20 @@ use 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);
let log_level = msg_vec[0];
use log::Level::*;
let log_level = match msg_vec[0] {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
if log_level > log::max_level() {
return Ok(());
}
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
@ -20,18 +33,6 @@ pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(),
match core::str::from_utf8(&str) {
Ok(strr) => {
use log::Level::*;
let log_level = match log_level {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
log::logger().log(
&Record::builder()
.args(format_args!("{}", strr))

View file

@ -25,42 +25,16 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
}
#[inline(always)]
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
const BLOCK_SIZE: usize = 64;
let mut remaining = count * size;
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
let total_size = count * size;
src.copy_to_nonoverlapping(dest, size);
if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
let mut copied = size;
let mut buffer = [0u8; BLOCK_SIZE];
let mut buffer_size = size;
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
buffer
.as_mut_ptr()
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
buffer_size *= 2;
}
let buffer_ptr = buffer.as_ptr() as *const u64;
while (dest as usize) & 7 != 0 && remaining >= 8 {
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
dest = dest.add(1);
remaining -= 1;
}
while core::intrinsics::likely(remaining >= 8) {
*(dest as *mut u64) = *buffer_ptr;
dest = dest.add(8);
remaining -= 8;
}
if remaining > 0 {
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
while copied < total_size {
let copy_size = copied.min(total_size - copied);
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
copied += copy_size;
}
}

View file

@ -92,8 +92,7 @@ fn sds_create_service(protocol: &'static str) -> u64 {
// let a: protocol::Protocol = protocol.into();
buff_id
}
fn sds_search_service(protocol: &str) -> u64 {
pub fn sds_search_service(protocol: &str) -> u64 {
let services = SERVICES.lock();
let compare = Protocol::from(protocol);
for (bid, protocol_canidate) in &services.0 {

View file

@ -1,5 +1,5 @@
mod ecah;
mod kernel_services;
pub mod kernel_services;
mod mem;
use {

View file

@ -8,7 +8,10 @@ use {
device_tree::DeviceTree,
holeybytes::ExecThread,
ipc::buffer::IpcBuffer,
task::Executor,
},
alloc::boxed::Box,
core::cell::LazyCell,
hashbrown::HashMap,
hbvm::mem::Address,
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
@ -19,6 +22,14 @@ use {
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
debug!("Entered kmain");
#[cfg(feature = "ktest")] {
use crate::ktest;
debug!("TESTING");
ktest::test_main();
loop {};
}
// let kcmd = build_cmd("Kernel Command Line", cmdline);
// trace!("Cmdline: {kcmd:?}");
@ -65,13 +76,24 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
fb1.address.as_ptr().unwrap() as *const u8
);
let mut executor = crate::task::Executor::new(256);
unsafe {
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
for module in boot_modules.iter() {
let cmd = module.cmd.trim_matches('"');
let cmd_len = cmd.len() as u64;
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
log::info!(
"Starting {}",
module
.path
.split('/')
.last()
.unwrap()
.split('.')
.next()
.unwrap()
);
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
// decode AbleOS Executable format
let header = &module.bytes[0..46];
@ -92,17 +114,17 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::info!("{code_length} + {data_length} = {end}");
log::debug!("{code_length} + {data_length} = {end}");
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
if cmd_len > 0 {
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
}
executor.spawn(async move {
executor.spawn(Box::pin(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
})
}));
}
debug!("Random number: {}", hardware_random_u64());
@ -113,6 +135,10 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
crate::arch::spin_loop()
}
// ! SAFETY: this is not threadsafe at all, like even a little bit.
// ! SERIOUSLY
pub static mut EXECUTOR: LazyCell<Executor> = LazyCell::new(|| Executor::new());
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
let dt = DeviceTree::new();
Mutex::new(dt)
@ -130,10 +156,3 @@ pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
Mutex::new(bufs)
});
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

38
kernel/src/ktest.rs Normal file
View file

@ -0,0 +1,38 @@
pub use ktest_macro::ktest;
use log::debug;
extern "C" {
static __ktest_start: fn();
static __ktest_end: fn();
}
// TODO: Get test_fn linker name (may require no_mangle in macro)
// More info on tests (run the rest even if panic)
// Implement ktest for arm and riscv (Later problems, see below)
// Allow for arch specific tests (Leave for now)
// Allow for ktest test name attr
// Usefull message at the end of testing
pub fn test_main() {
unsafe {
let mut current_test = &__ktest_start as *const fn();
let mut current = 1;
let test_end = &__ktest_end as *const fn();
while current_test < test_end {
let test_fn = *current_test;
debug!("Running test {}", current);
test_fn();
debug!("Test {} passed", current);
current_test = current_test.add(1);
current += 1;
}
}
}
#[ktest]
pub fn trivial_assertion() {
assert_eq!(1, 1);
}

View file

@ -2,20 +2,19 @@
//! 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]
#![no_main]
#![feature(
slice_split_once,
exclusive_wrapper,
new_uninit,
core_intrinsics,
abi_x86_interrupt,
lazy_get,
alloc_error_handler,
ptr_sub_ptr,
custom_test_frameworks,
naked_functions,
pointer_is_aligned_to
pointer_is_aligned_to,
)]
#![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features)]
#![allow(dead_code, internal_features, static_mut_refs)]
extern crate alloc;
mod allocator;
@ -33,6 +32,10 @@ mod memory;
mod task;
mod utils;
// #[cfg(feature = "tests")]
mod ktest;
use alloc::string::ToString;
use versioning::Version;
/// Kernel's version
@ -56,15 +59,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
));
}
let msg = info.message();
let msg = info.message().to_string().replace("\n", "\r\n");
let _ = crate::arch::log(format_args!("{msg}\r\n"));
loop {}
}
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

@ -29,24 +29,24 @@ pub fn yield_now() -> impl Future<Output = ()> {
YieldNow(false)
}
pub struct Executor<F: Future<Output = ()> + Send> {
tasks: Slab<Task<F>>,
pub struct Executor {
tasks: Slab<Task>,
task_queue: Arc<TaskQueue>,
}
impl<F: Future<Output = ()> + Send> Executor<F> {
pub fn new(size: usize) -> Self {
impl Executor {
pub fn new() -> Self {
Self {
tasks: Slab::with_capacity(size),
tasks: Slab::new(),
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)));
pub fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) -> usize {
let id = self.tasks.insert(Task::new(future));
self.task_queue.queue.push(id);
id
}
pub fn run(&mut self) {
@ -83,17 +83,17 @@ impl<F: Future<Output = ()> + Send> Executor<F> {
}
}
struct Task<F: Future<Output = ()> + Send> {
future: Pin<Box<F>>,
struct Task {
future: Pin<Box<dyn Future<Output = ()> + Send>>,
waker: Option<TaskWaker>,
}
impl<F: Future<Output = ()> + Send> Task<F> {
impl Task {
#[inline(always)]
pub fn new(future: F) -> Self {
pub fn new(future: Pin<Box<dyn Future<Output = ()> + Send>>) -> Self {
Self {
future: Box::pin(future),
waker: None,
future,
waker: None,
}
}

View file

@ -1,6 +1,6 @@
{
"arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
"disable-redzone": true,
"env": "",
"executables": true,

View file

@ -1,5 +1,6 @@
#![allow(unused)]
use std::{
collections::HashMap,
fmt::format,
fs::{read_to_string, File},
io::{BufWriter, Write},
@ -13,6 +14,7 @@ pub struct Package {
name: String,
binaries: Vec<String>,
build_cmd: String,
args: HashMap<String, String>,
}
impl Package {
@ -46,36 +48,46 @@ impl Package {
let mut binaries = vec![];
for (count, (name, table)) in bin_table.into_iter().enumerate() {
// if count != 0 {
binaries.push(name.clone());
// }
}
let build_table = data.get("build").unwrap();
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
build_cmd.remove(0);
// build_cmd.pop();
let mut args: HashMap<String, String> = match build_table.get("args") {
None => HashMap::new(),
Some(v) => v
.as_table()
.unwrap()
.into_iter()
.map(|(k, v)| (k.clone(), v.to_string()))
.collect::<HashMap<String, String>>(),
};
Self {
name,
binaries,
build_cmd,
args,
}
}
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
let path = format!("sysdata/programs/{}/{}", self.name, file);
// compile here
let mut warnings = String::new();
hblang::run_compiler(
&path,
Options {
fmt: true,
in_house_regalloc: true,
..Default::default()
},
out,
&mut warnings,
)?;
match std::fs::create_dir("target/programs") {
@ -87,9 +99,11 @@ impl Package {
hblang::run_compiler(
&path,
Options {
in_house_regalloc: true,
..Default::default()
},
out,
&mut warnings,
)?;
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
out.clear();
@ -98,9 +112,11 @@ impl Package {
&path,
Options {
dump_asm: true,
in_house_regalloc: true,
..Default::default()
},
out,
&mut warnings,
)?;
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
out.clear();

View file

@ -27,6 +27,7 @@ fn main() -> Result<(), Error> {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
for arg in args {
if arg == "-r" || arg == "--release" {
release = true;
@ -38,17 +39,42 @@ fn main() -> Result<(), Error> {
target = Target::Aarch64;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo).change_context(Error::Build)
build(release, target, debuginfo, tests).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") => {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
let mut do_accel = true;
for arg in args {
if arg == "-r" || arg == "--release" {
@ -63,12 +89,14 @@ fn main() -> Result<(), Error> {
do_accel = false;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo)?;
build(release, target, debuginfo, tests)?;
run(release, target, do_accel)
}
Some("help" | "h") => {
@ -82,6 +110,7 @@ fn main() -> Result<(), Error> {
" -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\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"
),);
Ok(())
@ -310,7 +339,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, debuginfo: bool, tests: bool) -> Result<(), Error> {
let fs = get_fs().change_context(Error::Io)?;
let mut com = Command::new("cargo");
com.current_dir("kernel");
@ -322,6 +351,10 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
}
if tests {
com.args(["--features", "ktest"]);
}
if target == Target::Riscv64Virt {
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
}
@ -378,6 +411,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
};
let (mut com, mut com2) = (Command::new(target_str), Command::new(target_str));
let ovmf_path = fetch_ovmf(target);
#[cfg(target_arch = "x86_64")]
let accel = if do_accel {
let supported = String::from_utf8(
com2.args(["--accel", "help"])
@ -413,6 +447,8 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
} else {
"accel=tcg"
};
#[cfg(not(target_arch = "x86_64"))]
let accel = "accel=tcg";
match target {
Target::X86_64 | Target::X86_64Avx2 => {
@ -470,6 +506,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
}
}
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
let (ovmf_url, ovmf_path) = match target {
Target::X86_64 | Target::X86_64Avx2 => (

View file

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

View file

@ -3,7 +3,7 @@ stn := @use("../../../../libraries/stn/src/lib.hb");
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Surface, Color} := render;
.{Font} := render.text
Label := struct {
@ -12,6 +12,8 @@ Label := struct {
surface: Surface,
text: ^u8,
text_length: uint,
bg: Color,
fg: Color,
}
set_label_text := fn(label: Label, text: ^u8): void {
@ -24,8 +26,8 @@ set_label_text := fn(label: Label, text: ^u8): void {
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
if label.is_dirty {
render.clear(label.surface, render.black)
render.put_text(label.surface, font, .(0, 0), render.white, label.text)
render.clear(label.surface, label.bg)
render.put_text(label.surface, font, .(0, 0), label.fg, label.text)
}
render.put_surface(surface, label.surface, pos, false)
}
@ -33,6 +35,12 @@ render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: V
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)
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,13 +1,9 @@
keycodes := @use("keycodes.hb");
.{KeyCode} := keycodes
KeyEvent := struct {
// 0 if down
// 1 if up
up: u8,
// 0 if not just triggered
// 1 if just triggered
just_triggered: u8,
KeyEvent := packed struct {
up: bool,
just_triggered: bool,
key: KeyCode,
}

View file

@ -6,6 +6,17 @@ events := @use("events.hb");
.{KeyEvent, MouseEvent} := events
recieve_key_event := fn(): ?KeyEvent {
kevent := KeyEvent.(false, false, 0)
buf_id := buffer.search("PS/2 Keyboard\0")
// Read out of the Keyboard buffer here
buffer.recv(KeyEvent, buf_id, &kevent)
if kevent.just_triggered {
return kevent
}
return null
}
@ -15,7 +26,7 @@ recieve_mouse_event := fn(): ?MouseEvent {
buf_id := buffer.search("PS/2 Mouse\0")
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, @bitcast(&mevent))
buffer.recv(MouseEvent, buf_id, &mevent)
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
return mevent

View file

@ -1,7 +1,4 @@
# Images
- General over image format
- Support formats:
- PNG
- Animation
# API

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
.{log} := @use("../../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
magic: u16,
@ -41,7 +41,7 @@ from := fn(bmp: ^u8): ?Surface {
return null
}
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height)
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
rhs := new_surface(info_header.width, info_header.height)
put_surface(rhs, lhs, .(0, 0), true)

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
.{log} := @use("../../../stn/src/lib.hb")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
@ -13,7 +13,7 @@ $QOI_OP_RUN := 0xC0
$QOI_OP_RGB := 0xFE
$QOI_OP_RGBA := 0xFF
$QOI_MASK_2 := 0xC0
QOI_COLOR_HASH := fn(c: Color): u8 {
$QOI_COLOR_HASH := fn(c: Color): u8 {
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
}
$QOI_MAGIC := 0x716F6966
@ -89,7 +89,7 @@ from := fn(qoi: ^u8): ?Surface {
run = b1 & 0x3F
}
index[@inline(QOI_COLOR_HASH, px)] = px
index[QOI_COLOR_HASH(px)] = px
};
*(surface.buf + px_pos) = px

View file

@ -38,14 +38,20 @@ $light_cyan := Color.(255, 255, 0, 255)
put_pixel := mode.put_pixel
put_rect := mode.put_rect
put_filled_rect := mode.put_filled_rect
put_trirect := mode.put_trirect
put_circle := mode.put_circle
put_filled_circle := mode.put_filled_circle
put_textured_circle := mode.put_textured_circle
put_line := mode.put_line
put_vline := mode.put_vline
put_hline := mode.put_hline
clear := mode.clear
put_surface := mode.put_surface
put_text := mode.put_text
// thanks peony for these three!
put_trirect := mode.put_trirect
put_vline := mode.put_vline
put_hline := mode.put_hline
//put_trirect := mode.put_trirect
//put_vline := mode.put_vline
//put_hline := mode.put_hline
// Display
sync := mode.sync

View file

@ -10,19 +10,21 @@ Surface := struct {
buf: ^Color,
width: uint,
height: uint,
size: uint,
}
new_surface := fn(width: uint, height: uint): Surface {
return .(
@inline(memory.alloc, Color, width * height),
memory.alloc(Color, width * height),
width,
height,
width * height,
)
}
clone_surface := fn(surface: ^Surface): Surface {
new := new_surface(surface.width, surface.height)
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
memory.copy(Color, surface.buf, new.buf, @intcast(surface.size))
return new
}
@ -33,42 +35,38 @@ init := fn(doublebuffer: bool): Surface {
if doublebuffer {
return new_surface(width, height)
} else {
return .(framebuffer, width, height)
return .(framebuffer, width, height, width * height)
}
}
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
$clear := fn(surface: Surface, color: Color): void {
memory.set(Color, &color, surface.buf, surface.width * surface.height)
}
sync := fn(surface: Surface): void {
if surface.buf == framebuffer {
return
}
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
$sync := fn(surface: Surface): void {
memory.copy(Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
}
index := fn(surface: Surface, x: uint, y: uint): uint {
$index := fn(surface: Surface, x: uint, y: uint): uint {
return x + surface.width * y
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + @inline(index, surface, x, y)
$indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + index(surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
*@inline(indexptr, surface, pos.x, pos.y) = color
return
$put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
return *indexptr(surface, pos.x, pos.y) = color
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
top_start_idx := indexptr(surface, pos.x, pos.y)
bottom_start_idx := indexptr(surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, tr.x)
@inline(memory.set, Color, &color, bottom_start_idx, tr.x)
memory.set(Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, bottom_start_idx, tr.x)
top_start_idx += surface.width
bottom_start_idx -= surface.width
@ -76,16 +74,16 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color:
}
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, top_start_idx, tr.x)
}
return
}
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
start_idx := indexptr(surface, pos.x, pos.y)
end_idx := indexptr(surface, pos.x, pos.y + tr.y)
right_start_idx := indexptr(surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
@ -94,8 +92,8 @@ put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color):
right_start_idx += surface.width
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
memory.set(Color, &color, indexptr(surface, pos.x, pos.y), @bitcast(tr.x + 1))
memory.set(Color, &color, indexptr(surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return
}
@ -112,7 +110,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
y := p0.y
x := p0.x
loop if x == p1.x break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
@ -136,7 +134,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Col
x := p0.x
y := p0.y
loop if y == p1.y break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
@ -169,8 +167,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
src_top_cursor := top.buf
src_bottom_cursor := top.buf + top.width * (top.height - 1)
dst_top_idx := @inline(indexptr, surface, pos.x, pos.y)
dst_bottom_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
dst_top_idx := indexptr(surface, pos.x, pos.y)
dst_bottom_idx := indexptr(surface, pos.x, pos.y + top.height - 1)
dst_increment := surface.width
@ -184,8 +182,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
rows_to_copy := top.height
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
@inline(memory.copy, Color, src_bottom_cursor, dst_bottom_idx, top.width)
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
memory.copy(Color, src_bottom_cursor, dst_bottom_idx, top.width)
dst_top_idx += dst_increment
dst_bottom_idx -= dst_increment
@ -195,7 +193,7 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
}
return
@ -233,7 +231,7 @@ put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): vo
y := y0
loop if y == y1 break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
y += 1
}
@ -247,10 +245,95 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
x0 = x1
x1 = tmp
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
// x0 = math.min(x0, x1)
memory.set(Color, &color, indexptr(surface, x0, y), @bitcast(x1 - x0 - 1))
return
}
put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - @intcast(2 * radius);
*indexptr(surface, pos.x + radius, pos.y) = color;
*indexptr(surface, pos.x - radius, pos.y) = color;
*indexptr(surface, pos.x, pos.y + radius) = color;
*indexptr(surface, pos.x, pos.y - radius) = color
loop if y < x break else {
x += 1
if error > 0 {
y -= 1
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
};
*indexptr(surface, pos.x + x, pos.y + y) = color;
*indexptr(surface, pos.x + y, pos.y + x) = color;
*indexptr(surface, pos.x - x, pos.y + y) = color;
*indexptr(surface, pos.x - y, pos.y + x) = color;
*indexptr(surface, pos.x + x, pos.y - y) = color;
*indexptr(surface, pos.x + y, pos.y - x) = color;
*indexptr(surface, pos.x - x, pos.y - y) = color;
*indexptr(surface, pos.x - y, pos.y - x) = color
}
return
}
put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - @intcast(2 * radius)
put_hline(surface, pos.y - x, pos.x - radius, pos.x + radius, color);
*indexptr(surface, pos.x, pos.y + radius) = color;
*indexptr(surface, pos.x, pos.y - radius) = color
loop if y < x break else {
x += 1
if error > 0 {
put_hline(surface, pos.y + y, pos.x - x, pos.x + x, color)
put_hline(surface, pos.y - y, pos.x - x, pos.x + x, color)
y -= 1
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
}
put_hline(surface, pos.y + x, pos.x - y, pos.x + y, color)
put_hline(surface, pos.y - x, pos.x - y, pos.x + y, color)
}
return
}
put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
x := 0
y := radius
error := @as(int, 3) - @intcast(2 * radius)
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y), indexptr(surface, pos.x - y, pos.y), 2 * y);
*indexptr(surface, pos.x, pos.y + y) = *indexptr(source, source_pos.x, source_pos.y + y);
*indexptr(surface, pos.x, pos.y - y) = *indexptr(source, source_pos.x, source_pos.y - y)
loop if y < x break else {
x += 1
if error > 0 {
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y + y), indexptr(surface, pos.x - x, pos.y + y), 2 * x)
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y - y), indexptr(surface, pos.x - x, pos.y - y), 2 * x)
y -= 1
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
}
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y + x), indexptr(surface, pos.x - y, pos.y + x), 2 * y)
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y - x), indexptr(surface, pos.x - y, pos.y - x), 2 * y)
}
return
}
utf8_len_table := [u8].(0, 0, 2, 3)
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
@ -280,7 +363,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
str += 1
continue
}
glyph_data = @inline(get_glyph, font, *str)
glyph_data = get_glyph(font, *str)
} else {
if *str < UNC_TABLE_SIZE {
glyph_index := *(font.unicode + *str)
@ -352,7 +435,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
cursor.y += next_line_y
}
dest := @inline(indexptr, surface, cursor.x, cursor.y)
dest := indexptr(surface, cursor.x, cursor.y)
rows := font.height
loop if rows == 0 break else {

View file

@ -74,16 +74,16 @@ font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
return font
}
get_glyph := fn(font: Font, index: u8): ^u8 {
$get_glyph := fn(font: Font, index: u8): ^u8 {
return font.data + @as(uint, index) * font.bytes_per_glyph
}
UNC_TABLE_SIZE := 1 << 16
$UNC_TABLE_SIZE := 1 << 16
init_unicode := fn(font: ^Font): void {
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
@inline(memory.set, u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
memory.set(u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
table := font.data + font.num_glyphs * font.bytes_per_glyph
curr_glyph := @as(u16, 0)
@ -121,8 +121,6 @@ init_unicode := fn(font: ^Font): void {
next_byte := *table
if (next_byte & 0xC0) != 0x80 {
valid = false
}
if valid == false {
break
}
unicode = unicode << 6 | next_byte & 0x3F

View file

@ -1,27 +1,35 @@
string := @use("string.hb")
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): void {
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
}
write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void {
return @eca(3, buffer_id, msg, @sizeof(Expr))
}
recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void {
return @eca(4, buffer_id, memory_map_location, length)
}
write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void {
return @eca(3, buffer_id, msg, length)
}
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
create := fn(msg: ^u8): int {
create := fn(msg: ^u8): uint {
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}
search := fn(msg: ^u8): int {
$create_nameless := fn(): uint {
return @eca(1, 0)
}
$delete_buffer := fn(buffer_id: uint): void {
return @eca(2, buffer_id)
}
search := fn(msg: ^u8): uint {
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}

View file

@ -7,6 +7,7 @@ math := @use("math.hb")
random := @use("random.hb")
file := @use("file_io.hb")
dt := @use("dt.hb")
process := @use("process.hb")
panic := fn(message: ?^u8): never {
log.error("Error: Panic Called, Message:\0")

View file

@ -1,29 +1,24 @@
abs := fn($Expr: type, x: Expr): Expr {
mask := x >> @bitcast(@sizeof(Expr) - 1)
return (x ^ mask) - mask
$abs := fn($Expr: type, x: Expr): Expr {
return (x ^ x >> @sizeof(Expr) - 1) - (x >> @sizeof(Expr) - 1)
}
min := fn($Expr: type, a: Expr, b: Expr): Expr {
c := a - b
return b + (c & c >> @bitcast(@sizeof(Expr) - 1))
$min := fn($Expr: type, a: Expr, b: Expr): Expr {
return b + (a - b & a - b >> @sizeof(Expr) - 1)
}
max := fn($Expr: type, a: Expr, b: Expr): Expr {
c := a - b
return a - (c & c >> @bitcast(@sizeof(Expr) - 1))
$max := fn($Expr: type, a: Expr, b: Expr): Expr {
return a - (a - b & a - b >> @sizeof(Expr) - 1)
}
signum := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
} else if x < @as(Expr, @intcast(0)) {
return -1
} else {
return 0
$sign := fn($Expr: type, x: Expr): i8 {
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
}
}
signincl := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
}
return -1
return result
}
Vec2 := fn($Expr: type): type {
@ -40,7 +35,7 @@ $TABLE_SIZE := @as(i32, 256)
sin := fn(theta: f32): f32 {
si := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
d := theta - @floatcast(@itf(si)) * 2.0 * PI / @itf(TABLE_SIZE)
d := theta - @floatcast(@itf(si)) * 2.0 * PI / @floatcast(@itf(TABLE_SIZE))
ci := si + TABLE_SIZE / 4 & TABLE_SIZE - 1
si &= TABLE_SIZE - 1
return SIN_TABLE[@bitcast(si)] + (SIN_TABLE[@bitcast(ci)] - 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
@ -48,10 +43,10 @@ sin := fn(theta: f32): f32 {
cos := fn(theta: f32): f32 {
ci := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
d := theta - @floatcast(@itf(ci)) * 2.0 * PI / @itf(TABLE_SIZE)
d := theta - @floatcast(@itf(ci)) * 2.0 * PI / @floatcast(@itf(TABLE_SIZE))
si := ci + TABLE_SIZE / 4 & TABLE_SIZE - 1
ci &= TABLE_SIZE - 1
return SIN_TABLE[@bitcast(si)] + (SIN_TABLE[@bitcast(ci)] - 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
return SIN_TABLE[@bitcast(si)] - (SIN_TABLE[@bitcast(ci)] + 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
}
tan := fn(theta: f32): f32 {

View file

@ -1,24 +1,29 @@
PAGE_SIZE := 4096
MAX_ALLOC := 0xFF
MAX_FREE := 0xFF
$PAGE_SIZE := 4096
$MAX_ALLOC := 0xFF
$MAX_FREE := 0xFF
dangling := fn($Expr: type): ^Expr {
$uninit := fn($Expr: type): ?Expr {
return null
}
$dangling := fn($Expr: type): ^Expr {
return @bitcast(@alignof(Expr))
}
calc_pages := fn($Expr: type, num: uint): uint {
$calc_pages := fn($Expr: type, num: uint): uint {
return 1 + @sizeof(Expr) * num / PAGE_SIZE
}
// ! will be replaced, don't get attached
alloc := fn($Expr: type, num: uint): ^Expr {
pages := @inline(calc_pages, Expr, num)
pages := calc_pages(Expr, num)
if pages <= MAX_ALLOC {
return @bitcast(request_page(@intcast(pages)))
}
ptr := request_page(0xFF)
ptr := request_page(MAX_ALLOC)
remaining := pages - MAX_ALLOC
loop if remaining < MAX_ALLOC break else {
_ = request_page(@intcast(MAX_ALLOC))
_ = request_page(MAX_ALLOC)
remaining -= MAX_ALLOC
}
_ = request_page(@intcast(remaining))
@ -26,46 +31,46 @@ alloc := fn($Expr: type, num: uint): ^Expr {
}
// ! stub
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
$free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
return
}
RqPageMsg := packed struct {a: u8, count: u8}
request_page := fn(count: u8): ^u8 {
$request_page := fn(count: u8): ^u8 {
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
}
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
release_page := fn(ptr: ^u8, count: u8): void {
$release_page := fn(ptr: ^u8, count: u8): void {
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
}
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
outb := fn(addr: u16, value: u8): void {
$outb := fn(addr: u16, value: u8): void {
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
}
InbMsg := packed struct {a: u8, b: u8, addr: u16}
inb := fn(addr: u16): u8 {
$inb := fn(addr: u16): u8 {
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
}
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
outl := fn(addr: u16, value: u32): void {
$outl := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
}
InlMsg := packed struct {a: u8, b: u8, addr: u16}
inl := fn(addr: u16): u32 {
$inl := fn(addr: u16): u32 {
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
}
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}

View file

@ -0,0 +1,12 @@
// ! will be rewritten to take a file object when filesystem is exist
// returns PID
$spawn := fn(proc_exe: ^u8, length: uint): uint {
return @eca(3, 6, proc_exe, length)
}
/* TODO:
- Spawn an empty process
- Call a function to load bytes into that process from a function
Or
- Manually fill the bytes in
- Execute the process via a run type command */

View file

@ -1,7 +1,15 @@
any := fn($Expr: type): Expr {
$any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
}
range := fn($Expr: type, min: Expr, max: Expr): Expr {
return @inline(any, Expr) % (max - min) + @intcast(1) + min
$range := fn($Expr: type, min: Expr, max: Expr): Expr {
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

@ -0,0 +1,6 @@
subscribe_to_interrupt := fn(interrupt_number: u8): bool {
return false
}
// Pauses execution until the interrupt occures
sleep_until_interrupt := fn(interrupt_number: u8): void {
}

View file

@ -4,118 +4,213 @@ length := fn(ptr: ^u8): uint {
}
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
is_negative := num < 0
if is_negative num = -num
ptr := p
negative := num < 0
if negative {
num = -num
}
if radix == 2 {
*ptr = 48
ptr += 1;
*ptr = 98
ptr += 1
} else if radix == 16 {
*ptr = 48
ptr += 1;
*ptr = 120
ptr += 1
} else if radix == 8 {
*ptr = 48
ptr += 1;
*ptr = 111
ptr += 1
}
digits_start := ptr
if num == 0 {
*ptr = 48
ptr += 1
} else {
loop if num == 0 break else {
digit := num % @bitcast(radix)
if digit < 10 {
*ptr = @intcast(digit) + 48
} else {
*ptr = @intcast(digit) + 55
}
ptr += 1
num /= @bitcast(radix)
}
*ptr = 0x30;
*(ptr + 1) = 0
return p
}
if negative {
*ptr = 45
loop if num == 0 break else {
remainder := num % @bitcast(radix)
num /= @bitcast(radix);
*ptr = @intcast(remainder + 0x30)
if remainder > 9 {
*ptr = @intcast(remainder - 10 + 0x41)
}
ptr += 1
};
}
*ptr = 0
@inline(reverse, digits_start)
if is_negative {
*ptr = 0x2D
ptr += 1
}
// ! it gets broked when you do this ??
// *ptr = 0
@inline(reverse, p)
return p
}
reverse := fn(s: ^u8): void {
i := 0
j := @inline(length, s) - 1
j := s + @inline(length, s) - 1
temp := @as(u8, 0)
loop if i >= j break else {
temp = *(s + i);
*(s + i) = *(s + j);
*(s + j) = temp
i += 1
loop if s < j {
temp = *s;
*s = *j;
*j = temp
s += 1
j -= 1
}
return
} else return
}
equals := fn(lhs: ^u8, rhs: ^u8): bool {
if lhs == rhs {
return true
}
i := 0
loop if *(lhs + i) != *(rhs + i) {
loop if *lhs != *rhs {
return false
} else if *lhs == 0 {
return true
} else {
i += 1
lhs += 1
rhs += 1
}
}
contains := fn(haystack: ^u8, needle: ^u8): bool {
haystack_len := @inline(length, haystack)
needle_len := @inline(length, needle)
if needle_len == 0 {
return true
}
if haystack_len < needle_len {
return false
clear := fn(ptr: ^u8): void {
loop if *ptr == 0 break else {
*ptr = 0
ptr += 1
}
}
max_start := haystack_len - needle_len
split_once := fn(haystack: ^u8, needle: u8): ?^u8 {
loop if *haystack == needle return haystack else if *haystack == 0 return null else haystack += 1
}
pos := 0
loop if pos > max_start break else {
is_match := true
offset := 0
split_once_str := fn(haystack: ^u8, needle: ^u8): ?^u8 {
if *needle == 0 return null
loop if offset >= needle_len break else {
if *(haystack + pos + offset) != *(needle + offset) {
is_match = false
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
}
}
if is_match == false {
break
}
offset += 1
}
haystack += 1
}
}
if is_match {
return true
}
pos += 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
}
return false
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,63 @@
.{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
.{new_surface, Color} := @use("../../render/src/lib.hb")
// ! in the future this should be safely handled
channel := Channel.(0, 0)
find_server := fn(): void {
log.info("client: locating server\0")
channel2 := await_channel()
channel.server = channel2.server
channel.client = channel2.client
log.info("client: server located\0")
}
new := fn(props: WindowProps): ?Window {
send_header(message.syn, channel.server)
response := await_message(Channel, channel.client)
if response.header.kind != message.ack {
return null
}
log.info("client: recv ack\0")
send_message(WindowProps, message.props, props, response.body.server)
windowdata := await_message(WindowData, response.body.client)
if windowdata.header.kind != message.ack {
return null
}
log.info("client: recv windowdata\0")
surface := new_surface(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
return .(windowdata.body, surface)
}
quit := fn(client: Window): void {
send_header(message.quit, client.data.channel.server)
}
connected := fn(client: Window): bool {
return true
}
shutdown_server := fn(client: Window): bool {
return false
}
update_props := fn(client: Window): bool {
return false
}
update_permissions := fn(client: Window): bool {
return false
}
send_frame := fn(client: Window): bool {
send_header(message.frame_ready, client.data.channel.server)
response := await_message(uint, client.data.channel.client)
if response.header.kind != message.ack {
return false
}
// ! FOR NOW, server will ALWAYS be local,
// ! so we can send pointer to surface.
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
return true
}

View file

@ -0,0 +1,97 @@
.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb");
.{Surface} := @use("../../render/src/lib.hb")
$BUFFER_SERVER := "sunset_server\0"
$BUFFER_CLIENT := "sunset_client\0"
Channel := packed struct {
client: uint,
server: uint,
}
client := @use("./client.hb")
server := @use("./server.hb")
message := @use("./message.hb")
permissions := @use("./permissions.hb")
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
}
$send_header := fn(kind: MessageKind, buffer_id: uint): void {
buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
}
$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
buffer.recv(?Message(Expr), buffer_id, &response)
return response
}
$recv_header := fn(buffer_id: uint): ?MessageHeader {
response := @as(?MessageHeader, null)
buffer.recv(?MessageHeader, buffer_id, &response)
return response
}
await_channel := fn(): Channel {
channel := Channel.(0, 0)
loop if channel.server != 0 break else {
channel.server = buffer.search(BUFFER_SERVER)
}
loop if channel.client != 0 break else {
channel.client = buffer.search(BUFFER_CLIENT)
}
return channel
}
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
loop {
buffer.recv(?Message(Expr), buffer_id, &response)
if response != null {
return @as(Message(Expr), response)
}
}
}
await_header := fn(buffer_id: uint): MessageHeader {
response := @as(?MessageHeader, null)
loop {
buffer.recv(?MessageHeader, buffer_id, &response)
if response != null {
return @as(?MessageHeader, response)
}
}
}
MessageKind := u8
MessageHeader := packed struct {
kind: MessageKind,
}
Message := fn($Expr: type): type {
return packed struct {
header: MessageHeader,
body: Expr,
}
}
WindowProps := struct {
position: Vec2(uint),
dimensions: Vec2(uint),
// ! replace with owned string type later
title: ^u8,
}
WindowData := struct {
props: WindowProps,
channel: Channel,
permissions: uint,
}
Window := struct {
data: WindowData,
surface: Surface,
}

View file

@ -0,0 +1,8 @@
// ! all values in this file are subject to change.
$syn := 1
$ack := 2
$refused := 3
$quit := 4
$props := 5
$shutdown := 6
$frame_ready := 7

View file

@ -0,0 +1,5 @@
$none := 0b0
$exclusive_framebuffer := 0b1
$shutdown := 0b100
$default := none

View file

@ -0,0 +1,135 @@
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("../../render/src/lib.hb");
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb")
WindowServer := struct {
window_count: uint,
channel: Channel,
// ! replace this with a collection when we get an allocator
windows: [?Window; 10],
font: text.Font,
}
// ! in the future this should be safely handled
server := @as(WindowServer, idk)
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
start := fn(): void {
font := text.font_from_psf2(@bitcast(&psf), false)
if font == null {
log.error("server: failed to load asset\0")
return
}
server = .(
0,
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
.(null, null, null, null, null, null, null, null, null, null),
@as(text.Font, font),
)
log.info("server: started server\0")
}
incoming := fn(): bool {
msg := recv_header(server.channel.server)
if msg == null {
return true
}
if msg.kind == message.syn {
log.info("server: recv syn\0")
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
send_message(Channel, message.ack, channel, server.channel.client)
props := await_message(WindowProps, channel.server)
if props.header.kind != message.props {
return true
}
log.info("server: recv props\0")
// ! do inspection of requested props here
data := WindowData.(props.body, channel, permissions.default)
send_message(WindowData, message.ack, data, channel.client)
surface := new_window_decorations(data.props.dimensions)
// decorations
{
title := data.props.title
title_length := string.length(title)
deco_length := title_length * 10
// draw the window tab bar
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
// Draw the window tab
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
// Draw the outside box
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
}
server.windows[server.window_count] = .(data, surface)
server.window_count += 1
}
return true
}
$DECO_WIDTH := 2
$DECO_HEIGHT_TOP := 20
$DECO_HEIGHT_BOTTOM := 1
$DECO_COLOUR := Color.(100, 200, 255, 255)
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
return new_surface(
dimensions.x + DECO_WIDTH,
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
)
}
// ! compositor code. this currently disallows tearing.
collect_frames := fn(): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
header := recv_header(window.data.channel.server)
if header == null {
i += 1
continue
}
if header.kind != message.frame_ready {
i += 1
continue
}
send_header(message.ack, window.data.channel.client)
ptr := await_message(^Color, window.data.channel.server)
if ptr.header.kind != message.ack {
return
}
put_surface(
window.surface,
Surface.(
ptr.body,
window.data.props.dimensions.x,
window.data.props.dimensions.y,
window.data.props.dimensions.x * window.data.props.dimensions.y,
),
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
false,
)
i += 1
}
}
render_clients := fn(screen: Surface): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
put_surface(screen, window.surface, window.data.props.position, false)
i += 1
}
}

View file

@ -56,23 +56,13 @@ main := fn(): int {
loop {
// Clear the screen
render.clear(screen, render.black)
render.put_surface(screen, wallpaper, .(0, 0), false)
// TODO: Read the window buffer here
{
// ret := buffer.recv([u8; 4096], win_buff, mem_buf)
// for some reason this null check causes the compiler to spin forever
// if ret == null {
// log.info("No messages\0")
// } else {
// log.info("Handle Messages\0")
// }
}
// get input events from drivers via intouch
// key_event := intouch.recieve_key_event();
// log.info("before mouse event check\0");
if false {
// Scroll bar :ThumbsUp:
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
@ -82,18 +72,35 @@ main := fn(): int {
render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
}
{
// osu dots
render.put_rect(screen, .(400, 100), .(100, 100), render.red)
render.put_rect(screen, .(100, 100 + 300), .(100, 100), render.red)
}
{
pos := Vec2(uint).(1, screen.height - 21)
render_label_to_surface(screen, text_label, font, pos)
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), render.white)
}
// Screen border
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
// get input events from drivers via intouch
if false {
key_event := intouch.recieve_key_event()
if key_event != null {
log.info("Key event \0")
}
}
{
mouse_event := intouch.recieve_mouse_event()
//
if mouse_event != null {
// log.warn("Mouse event recieved\0")
// log.warn("Mouse event received\0")
change_x := @as(i16, mouse_event.x_change)
change_x = change_x << 8
@ -130,15 +137,9 @@ main := fn(): int {
}
}
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
// render mouse
lum := render.indexptr(screen, mouse_x, mouse_y)
if lum.r / 3 + lum.g / 3 + lum.b / 3 < 128 {
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
} else {
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
}
// Send events to focused window
}

View file

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

View file

@ -0,0 +1,7 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
main := fn(): void {
log.info("Hello, World!\0")
loop {
}
}

View file

@ -0,0 +1,19 @@
.{process, log, string, memory} := @use("../../../libraries/stn/src/lib.hb")
exe := @embed("./hello_world_and_spin.hbf")
main := fn(): void {
buf := "\0\0\0\0\0\0\0"
loop {
log.info(
string.display_int(
@bitcast(process.spawn(@bitcast(&exe), 356)),
buf,
10,
),
)
// spin so we don't spawn 10 quattuordecillion processes
i := 0
loop if i == 1000000 break else i += 1
}
}

View file

@ -0,0 +1,23 @@
# Unified PS/2 Driver
Te entire thing is held together inspite
## !!Assumptions!!
Anyone who works on this should work to keep this list as small as possible/remove as many of these as possible.
- Bit 5 of the response form 0x64 indicates which port the data is coming from. (Not true on all systems)
- A parity or timeout error never occurs.
- PS/2 controller exists.
- Both PS/2 ports being broken doesn't need handling.
- One PS/2 port being broken doesn't need special attention.
- PS/2 controller doesn't need to perform a self-check.
- These DeviceIDs never exist:
- 0xFFFD
- 0xFFFE
- 0xFFFF
- 0x01xx
- 0x03xx
- 0x04xx
- Literally all PS/2 keyboards can be handeled the exact same way. We have the capability for detecting different keyboard types, I just don't bother with it because that would litreally take months to get working.
- The device doesn't send any data while we're waiting for an `ACK`.
Supporting mice in the keyboard port and vice versa was a ***bad*** idea, but I do not regret it because it means we're "superior" to real world operating systems.

View file

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

View file

@ -0,0 +1,26 @@
//Do not question.
$bit0 := fn(value: u8): bool {
return (value & 0x1) > 0
}
$bit1 := fn(value: u8): bool {
return (value & 0x2) > 0
}
$bit2 := fn(value: u8): bool {
return (value & 0x4) > 0
}
$bit3 := fn(value: u8): bool {
return (value & 0x8) > 0
}
$bit4 := fn(value: u8): bool {
return (value & 0x10) > 0
}
$bit5 := fn(value: u8): bool {
return (value & 0x20) > 0
}
$bit6 := fn(value: u8): bool {
return (value & 0x40) > 0
}
$bit7 := fn(value: u8): bool {
return (value & 0x80) > 0
}

View file

@ -0,0 +1,95 @@
.{memory, log} := @use("../../../libraries/stn/src/lib.hb");
.{bit0, bit1, bit5, bit6, bit7} := @use("bits.hb");
.{Port, PORT_AT_STARTUP} := @use("port.hb")
port1 := @as(Port, PORT_AT_STARTUP)
port2 := @as(Port, PORT_AT_STARTUP)
$disable_port1 := fn(): void memory.outb(0x64, 0xAD)
$enable_port1 := fn(): void memory.outb(0x64, 0xAE)
$disable_port2 := fn(): void memory.outb(0x64, 0xA7)
$enable_port2 := fn(): void memory.outb(0x64, 0xA8)
test_port1 := fn(): bool {
memory.outb(0x64, 0xAB)
loop if has_input(get_info()) break
input := get_input()
return input == 0x0
}
test_port2 := fn(): bool {
memory.outb(0x64, 0xA9)
loop if has_input(get_info()) break
input := get_input()
return input == 0x0
}
get_config_byte := fn(): u8 {
memory.outb(0x64, 0x20)
loop if has_input(get_info()) break
return get_input()
}
Info := struct {d: u8}
$get_info := fn(): Info return .(memory.inb(0x64))
//inline when can
has_input := fn(info: Info): bool return bit0(info.d)
can_send := fn(info: Info): bool return bit1(info.d) == false
timed_out := fn(info: Info): bool return bit6(info.d)
check_parity := fn(info: Info): bool return bit7(info.d)
get_port := fn(info: Info): ^Port {
if bit5(info.d) {
return &port2
} else {
return &port1
}
}
send_byte := fn(port: ^Port, byte: u8): void {
if port == &port2 {
memory.outb(0x64, 0xD4)
}
loop if can_send(get_info()) break
memory.outb(0x60, byte)
}
$get_input := fn(): u8 return memory.inb(0x60)
$write_out := fn(data: u8): void memory.outb(0x60, data)
flush_input := fn(): void {
loop if has_input(get_info()) == false break else get_info()
}
init := fn(): void {
disable_port1()
disable_port2()
//Disables ports to make sure that they won't interfere with the setup process.
flush_input()
enable_port2()
port2.exists = bit5(@inline(get_config_byte)) == false
disable_port2()
flush_input()
port1.exists = test_port1()
if port2.exists {
port2.exists = test_port2()
}
if (port1.exists | port2.exists) == false {
log.error("No ports detected! No input will be processed! Cannot handle this!\0")
}
if port1.exists {
log.info("Port 1 exists.\0")
enable_port1()
}
if port2.exists {
log.info("Port 2 exists.\0")
enable_port2()
}
}

View file

@ -0,0 +1,15 @@
DeviceID := struct {value: u16}
$MOUSE_3_BUTTON := DeviceID.(0x0)
$MOUSE_SCROLLWHEEL := DeviceID.(0x3)
$MOUSE_5_BUTTON := DeviceID.(0x4)
$KEYBOARD_SPACESAVER := DeviceID.(0x84AB)
$KEYBOARD_122_KEY := DeviceID.(0x86AB)
$KEYBOARD_JAPANESE_G := DeviceID.(0x90AB)
$KEYBOARD_JAPANESE_P := DeviceID.(0x91AB)
$KEYBOARD_JAPANESE_A := DeviceID.(0x92AB)
$KEYBOARD_NCD_SUN := DeviceID.(0xA1AC)
$MOUSE_INIT_1 := DeviceID.(0xFFFD)
$MOUSE_INIT_2 := DeviceID.(0xFFFE)
$NO_DEVICE := DeviceID.(0xFFFF)

View file

@ -0,0 +1,152 @@
.{memory, log, buffer, string} := @use("../../../libraries/stn/src/lib.hb");
.{MouseEvent} := @use("../../../libraries/intouch/src/lib.hb").events;
.{bit0, bit1, bit2, bit3, bit4} := @use("bits.hb")
devices := @use("devices.hb")
controller := @use("controller.hb");
.{Info, Port} := controller
mouse := @use("mouse.hb")
format_page := memory.dangling(u8)
mouse_buffer := 0
keyboard_buffer := 0
info := Info.(0)
send_command := fn(port: ^Port, byte: u8): void {
tries := 3
loop if tries == 0 break else {
controller.send_byte(port, byte)
loop {
info = controller.get_info()
if controller.has_input(info) == false {
continue
}
input := controller.get_input()
if controller.get_port(info) != port {
if check_complete(port) == false {
port.packet[port.packet_length] = input
port.packet_length += 1
}
continue
}
if input == 0xFA {
return
} else {
break
}
}
tries -= 1
}
}
enable_streaming := fn(port: ^Port): void {
@inline(send_command, port, 0xF4)
}
process := fn(port: ^controller.Port): void {
if port.device.value < devices.MOUSE_5_BUTTON.value {
event := MouseEvent.(0, 0, false, false, false)
event.left = bit0(port.packet[0])
event.right = bit1(port.packet[0])
event.middle = bit2(port.packet[0])
event.x_change = @intcast(port.packet[1])
event.y_change = @intcast(port.packet[2])
buffer.write(MouseEvent, mouse_buffer, &event)
} else if port.device == devices.MOUSE_INIT_1 {
port.device.value = port.packet[0]
if port.device != devices.MOUSE_SCROLLWHEEL {
enable_streaming(port)
return
}
port.device = devices.MOUSE_INIT_2
} else if port.device == devices.MOUSE_INIT_2 {
port.device.value = port.packet[0]
} else if port.device == devices.NO_DEVICE {
if port.packet_length == 1 {
port.device.value = port.packet[0]
enable_streaming(port)
//TODO: Upgrade mouse.
} else {
port.device.value = port.packet[1] | port.packet[0] << 8
enable_streaming(port)
}
log.info("Identified device!\0")
log.info(string.display_int(port.device.value, format_page, 16))
} else {
log.info("KEY PRESSED\0")
}
}
check_complete := fn(port: ^controller.Port): bool {
last_value := port.packet[port.packet_length - 1]
if port.device == devices.NO_DEVICE {
if last_value == 0 | last_value == 3 | last_value == 4 {
return true
} else if port.packet_length == 2 {
return true
}
} else if port.device == devices.MOUSE_3_BUTTON {
if port.packet_length == 3 return true
} else if port.device == devices.MOUSE_SCROLLWHEEL | port.device == devices.MOUSE_5_BUTTON {
if port.packet_length == 4 return true
} else {
if port.packet[0] == 0xE1 {
if port.packet_length == 6 {
return true
}
} else if port.packet[0] != 0xE0 {
return true
} else if port.packet_length == 2 & port.packet[1] != 0x2A & port.packet[1] != 0xB7 {
return true
} else if port.packet_length == 4 {
return true
}
}
return false
}
main := fn(): void {
mouse_buffer = buffer.create("PS/2 Mouse\0")
format_page = memory.alloc(u8, 1024)
controller.init()
if controller.port1.exists {
//log.info("Port 1 exists.\0")
controller.send_byte(@bitcast(0), 0xF4)
}
if controller.port2.exists {
//controller.send_byte(&controller.port2, 0xF4)
}
loop {
info = controller.get_info()
if controller.timed_out(info) {
log.error("Timeout error! Cannot handle these!\0")
}
if controller.check_parity(info) {
log.error("Parity error! Cannot handle these!\0")
}
/*
if controller.has_input(info) {
port := controller.get_port(info)
if port.packet_length > 0 & check_complete(port) {
process(port)
}
input := controller.get_input()
/*if input == 0xAA & port.can_hot_plug {
port.device = devices.NO_DEVICE
controller.send_byte(port, 0xF4)
}*/
port.packet[port.packet_length] = input
port.packet_length += 1
if check_complete(port) {
process(port)
port.packet_length = 0
}
}*/
}
}

View file

@ -0,0 +1,21 @@
Button := struct {id: u8}
$LEFT_BUTTON := Button.(1)
$RIGHT_BUTTON := Button.(2)
$MIDDLE_BUTTON := Button.(4)
$BUTTON4 := Button.(8)
$BUTTON5 := Button.(16)
SampleRate := struct {value: u8}
$SR10 := SampleRate.(10)
$SR20 := SampleRate.(20)
$SR40 := SampleRate.(40)
$SR60 := SampleRate.(60)
$SR80 := SampleRate.(80)
$SR100 := SampleRate.(100)
$SR200 := SampleRate.(200)
Resolution := struct {value: u8}
$RES_1COUNT_PER_MM := Resolution.(0)
$RES_2COUNT_PER_MM := Resolution.(1)
$RES_4COUNT_PER_MM := Resolution.(2)
$RES_8COUNT_PER_MM := Resolution.(3)

View file

@ -0,0 +1,21 @@
.{DeviceID, NO_DEVICE} := @use("devices.hb")
State := struct {s: u8}
$Recive := State.(0)
$Reboot := State.(1)
Port := packed struct {
exists: bool,
device: DeviceID,
packet: [u8; 8],
packet_length: u8,
can_hot_plug: bool,
}
$PORT_AT_STARTUP := Port.(
true,
NO_DEVICE,
.(0, 0, 0, 0, 0, 0, 0, 0),
0,
true,
)

View file

@ -1,4 +1,8 @@
.{memory, log, buffer} := @use("../../../libraries/stn/src/lib.hb")
stn := @use("../../../libraries/stn/src/lib.hb");
.{memory, log, buffer} := stn
intouch := @use("../../../libraries/intouch/src/lib.hb");
.{KeyEvent} := intouch
send_byte := fn(byte: u8): u8 {
memory.outb(96, byte)
@ -6,23 +10,31 @@ send_byte := fn(byte: u8): u8 {
}
main := fn(): int {
buf := buffer.create("XKeyboard\0")
buf := buffer.create("PS/2 Keyboard\0")
_ = send_byte(238)
log.info("PS/2 Driver Loaded\0")
if send_byte(238) == 238 {
log.info("PS/2 Keyboard Echoed\0")
}
if send_byte(244) == 250 {
log.info("Enabled scanning\0")
}
prev_input := 250
loop {
loop if (memory.inb(0x64) & 0x20) == 0x20 break
input := memory.inb(96)
if input == prev_input {
continue
}
prev_input = input
buffer.write(u8, &input, buf)
kevent := KeyEvent.(false, true, input)
buffer.write(KeyEvent, buf, &kevent)
}
return 0
}

View file

@ -145,7 +145,7 @@ main := fn(): int {
event.x_change = x_change
event.y_change = y_change
buffer.write(MouseEvent, &event, mouse_buffer)
buffer.write(MouseEvent, mouse_buffer, &event)
}
return 0

View file

@ -10,12 +10,12 @@ example := fn(): void {
color := render.light_cyan
n := @as(u8, 1)
loop {
// ! dead code elimination bug
render.clear(screen, color)
render.sync(screen)
if (color.b & 255) == 255 | (color.b & 255) == 0 {
if color.b == 255 | color.b == 0 {
n = -n
}
color.b += n
}
return
}

View file

@ -0,0 +1,35 @@
.{Vec2, sin, cos, PI} := @use("../../../../libraries/stn/src/lib.hb").math
render := @use("../../../../libraries/render/src/lib.hb")
able_bmp := @embed("../../../../assets/able.bmp")
mini_bmp := @embed("../../../../assets/mini.bmp")
/* expected result:
two textured circles rotating
around one yellow filled circle
with a blue line showing their
'orbit' */
example := fn(): void {
able := render.image.from(@bitcast(&able_bmp))
mini := render.image.from(@bitcast(&mini_bmp))
if able == null | mini == null {
return
}
angle := 0.0
screen := render.init(true)
loop {
render.clear(screen, render.black)
render.put_filled_circle(screen, .(screen.width / 2, screen.height / 2), 128, render.light_yellow)
render.put_circle(screen, .(screen.width / 2, screen.height / 2), 256, render.light_blue)
render.put_textured_circle(screen, able, .(able.width / 2, able.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle) * 256)), screen.height / 2 + @intcast(@fti(cos(angle) * 256))), able.width / 2 - 1)
render.put_textured_circle(screen, mini, .(mini.width / 2, mini.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle + PI) * 256)), screen.height / 2 + @intcast(@fti(cos(angle + PI) * 256))), mini.width / 2 - 1)
render.sync(screen)
angle += 0.01
}
return
}

View file

@ -46,7 +46,7 @@ example := fn(): void {
bottom := buf + msg_len
@inline(memory.copy, u8, msg, buf, msg_len)
memory.copy(u8, msg, buf, msg_len)
cursor := bottom
draw_window(window, font, buf, cursor)

View file

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

View file

@ -0,0 +1,29 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
bmp := @embed("../../../assets/mini.bmp")
main := fn(): void {
sunset.client.find_server()
image := render.image.bmp.from(@bitcast(&bmp))
if image == null {
log.error("got no image\0")
return
}
window := sunset.client.new(.(.(100, 100), .(200, 200), "Hello,\0"))
if window == null {
log.error("got no window\0")
return
}
x := 0
loop {
render.clear(window.surface, render.black)
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
_ = sunset.client.send_frame(window)
x += 1
}
}

View file

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

View file

@ -0,0 +1,29 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
bmp := @embed("../../../assets/able.bmp")
main := fn(): void {
sunset.client.find_server()
image := render.image.bmp.from(@bitcast(&bmp))
if image == null {
log.error("got no image\0")
return
}
window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0"))
if window == null {
log.error("got no window\0")
return
}
x := 0
loop {
render.clear(window.surface, render.black)
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 40), false)
_ = sunset.client.send_frame(window)
x += 1
}
}

View file

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

View file

@ -0,0 +1,99 @@
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
intouch := @use("../../../libraries/intouch/src/lib.hb")
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{new_label, render_label_to_surface, set_label_text, set_color} := horizon_api.widgets.label
stn := @use("../../../libraries/stn/src/lib.hb");
.{Vec2} := stn.math
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
img := @embed("../../../assets/wallpaper.qoi")
main := fn(): int {
sunset.server.start()
screen := render.init(true)
render.clear(screen, render.black)
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
wallpaper := render.image.from(@bitcast(&img))
if wallpaper == null {
// stn.panic("Wallpaper not loaded\0")
return 1
}
mouse_x := 100
mouse_y := 100
text_label := new_label("Hi\0")
set_color(text_label, sunset.server.DECO_COLOUR, render.black)
loop {
mouse_event := intouch.recieve_mouse_event()
if mouse_event != null {
change_x := @as(i16, mouse_event.x_change)
change_x = change_x << 8
change_x = change_x >> 8
mouse_x += change_x
if mouse_x <= 0 {
mouse_x = 0
}
if mouse_x >= screen.width - 20 {
mouse_x = @intcast(screen.width - 21)
}
change_y := @as(i16, mouse_event.y_change)
change_y = change_y << 8
change_y = change_y >> 8
mouse_y -= change_y
if mouse_y < 0 {
mouse_y = 1
}
if mouse_y >= screen.height - 20 {
mouse_y = @intcast(screen.height - 21)
}
if mouse_event.left {
set_label_text(text_label, "LEFT CLICK\0")
}
if mouse_event.middle {
set_label_text(text_label, "MIDDLE CLICK\0")
}
if mouse_event.right {
set_label_text(text_label, "RIGHT CLICK\0")
}
}
{
render.clear(screen, render.black)
render.put_surface(screen, wallpaper, .(0, 0), false)
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), sunset.server.DECO_COLOUR)
}
if sunset.server.incoming() {
sunset.server.collect_frames()
sunset.server.render_clients(screen)
}
{
pos := Vec2(uint).(1, screen.height - 21)
render_label_to_surface(screen, text_label, font, pos)
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), sunset.server.DECO_COLOUR)
}
// Mouse cursor
{
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR_DARKER)
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR)
}
render.sync(screen)
}
return 0
}

View file

@ -25,11 +25,20 @@ resolution = "1024x768x24"
# [boot.limine.ableos.modules.render_example]
# path = "boot:///render_example.hbf"
[boot.limine.ableos.modules.horizon]
path = "boot:///horizon.hbf"
# [boot.limine.ableos.modules.horizon]
# path = "boot:///horizon.hbf"
[boot.limine.ableos.modules.ps2_mouse_driver]
path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_mouse_driver]
# path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_keyboard_driver]
# path = "boot:///ps2_keyboard_driver.hbf"
[boot.limine.ableos.modules.ps2_driver]
path = "boot:///ps2_driver.hbf"
# [boot.limine.ableos.modules.sunset_client]
# path = "boot:///sunset_client.hbf"
# [boot.limine.ableos.modules.sunset_server]
# path = "boot:///sunset_server.hbf"

40
todo.md Normal file
View file

@ -0,0 +1,40 @@
@konii
Windowing System
Rendering
@able
Windowing System
Interrupt Forwarding
@peony
PS/2
XYZ
@kodin
AIDL AbleOS Interface Description Language
UI-SEXPR lispy ui decl language
@morshy
Simple Userland Allocator
@funky
Kernel Testing Framework (A rust framework for testing the kernel)
@unassigned
FileIO (Fat32)
DiskIO (Undecided Disk type)
Proper Memory Protection
Channels (Two buffers bundled together to form two way communication)
Userland Testing Framework (An hblang framework for testing the userspace)
PCI/E (Honestly I have no fucking clue whats going on with PCI or why userland cant properly read it)
Kernel Reimpl (Do not you dare think about this yet its only here as an option to show goals)
AbleOS Compiler Collection
acc-asm
hblang^2 (hblang compiler in hblang)