forked from AbleOS/ableos
Compare commits
144 commits
render-api
...
master
Author | SHA1 | Date | |
---|---|---|---|
Able | 6b673bc7e6 | ||
koniifer | 0af4d142a4 | ||
koniifer | 36f0d357cf | ||
koniifer | ccddf36050 | ||
koniifer | da5f1a7a19 | ||
koniifer | 2808bc9e7c | ||
koniifer | d958a103fa | ||
koniifer | ee82bc5705 | ||
Able | 3d53b641bf | ||
koniifer | cea7f1fa5c | ||
Able | 614bef7ec5 | ||
Able | b0f6aa53bd | ||
Able | d5f4ce18a3 | ||
koniifer | 907c0d0dd4 | ||
koniifer | 95b4a921dc | ||
koniifer | b6261d014d | ||
Able | 56ee0fe851 | ||
koniifer | b07bac1f1f | ||
koniifer | dc9273b3c1 | ||
Able | e6d8f5c822 | ||
koniifer | 8ad7542b9c | ||
Able | e40a22fccd | ||
koniifer | cf917927a5 | ||
koniifer | 97ceb12d6e | ||
koniifer | bae58ade61 | ||
koniifer | b21c05e924 | ||
Able | 2f5bc73665 | ||
Able | 0003464099 | ||
koniifer | 77a708d41e | ||
peony | 3409f5051a | ||
Able | 8c7b95277d | ||
koniifer | 7da32b263f | ||
Able | 2439722c88 | ||
koniifer | 3333b1706f | ||
Able | 8808ed5bfe | ||
koniifer | 68d3236cc0 | ||
Able | eea23d967b | ||
Able | d2152537ad | ||
Able | 7723799e76 | ||
koniifer | 8b04b275f3 | ||
Able | 1345f294b8 | ||
Able | 818bcb458f | ||
Able | d2b5f09511 | ||
2676bd7b62 | |||
koniifer | 444fcdb0c4 | ||
koniifer | adbf32d970 | ||
Able | 7f01b0e0f8 | ||
Able | e8edee4ccc | ||
koniifer | ba59233ce7 | ||
Able | f13c682171 | ||
Able | b6b097a872 | ||
koniifer | 6a8d92d2c2 | ||
Able | ab8522fbe1 | ||
Able | a49ac7bca0 | ||
Able | 12883ac926 | ||
Able | 6a319c55b0 | ||
Able | 879bbfa173 | ||
Able | 795f10986f | ||
Able | 85e63eb51c | ||
koniifer | aafe047b51 | ||
koniifer | 404ea22c46 | ||
koniifer | 664334fd00 | ||
Able | 086948d47a | ||
Able | b795215b62 | ||
Able | 16135ae536 | ||
Able | 941eed0ac9 | ||
Able | f4ad4b6856 | ||
koniifer | 9e83707a28 | ||
Able | 6894ef2360 | ||
Able | 69c95c35b5 | ||
Able | 80d363bc59 | ||
Able | 3c3c156eb0 | ||
koniifer | eaace7d9c1 | ||
koniifer | 5af5631755 | ||
Able | fac573837f | ||
koniifer | 6ff65eee41 | ||
koniifer | b35b430047 | ||
koniifer | bcfaf89ed0 | ||
koniifer | 2ba2dcb464 | ||
koniifer | 41d9c0b82a | ||
koniifer | a94332370a | ||
koniifer | 7caa47b9fb | ||
Able | 34101d2e8c | ||
Able | 2bc13cd7d8 | ||
koniifer | 086cc4aef0 | ||
Able | 84f86488c7 | ||
Able | ed7c8f20cb | ||
koniifer | 34cbd9a5e6 | ||
koniifer | 0ebb1f200e | ||
Able | fc06820332 | ||
koniifer | 2a082d8283 | ||
koniifer | 1eee33ce8b | ||
Able | 6fa1c829fd | ||
koniifer | 820c3e459b | ||
koniifer | 3af28f1666 | ||
koniifer | 96c2bd5cd5 | ||
koniifer | ea8eca1089 | ||
koniifer | 7f4a040505 | ||
koniifer | 82f5cdbe21 | ||
koniifer | aac6d61dc6 | ||
koniifer | 3df6f18c85 | ||
koniifer | 07ee8de9f1 | ||
Able | f64f654610 | ||
Able | 7d4b12a103 | ||
Able | 758629df0a | ||
Able | 04a449965b | ||
koniifer | 0bbc76124f | ||
Able | 6ad68dabac | ||
Able | 07c7d52b8c | ||
Able | 2edc8148ca | ||
5f59f05dce | |||
Able | 0bc757164f | ||
Able | f5f68bc2df | ||
Able | 7a256dde68 | ||
Able | 570b566310 | ||
Able | d2488689fe | ||
Able | fe70d81bd0 | ||
Able | cc076d9540 | ||
Able | 3173b63c93 | ||
koniifer | 48027196b1 | ||
koniifer | 78553a3190 | ||
koniifer | df74b09134 | ||
koniifer | 2321efd2e7 | ||
Able | d9caa17f3c | ||
Able | b0ecbfa168 | ||
Able | 1fe20360f6 | ||
Able | fb42351638 | ||
5f2b181f22 | |||
koniifer | 43ea77c18f | ||
Able | 2b2e0c514b | ||
Able | fcca015866 | ||
Able | cc9337348e | ||
Able | 028949559b | ||
Able | 91380539d9 | ||
Able | ec25c0f207 | ||
Able | 1b5cb54a2b | ||
Able | 9686349476 | ||
koniifer | f8c7873978 | ||
Able | 40cc412ab3 | ||
Able | cd369b39d5 | ||
331cbf5da1 | |||
Able | 0594b99a59 | ||
Able | 1855307cd9 | ||
Able | 7426bf479f |
|
@ -1,3 +1,3 @@
|
|||
[alias]
|
||||
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
|
||||
repbuild = "run --manifest-path ./repbuild/Cargo.toml -- "
|
||||
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
||||
|
|
1231
Cargo.lock
generated
1231
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
69
HELP.md
Normal file
69
HELP.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
### What are the requirements?
|
||||
- A machine with [Rustc Tier 1 platform support](https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-1-with-host-tools)
|
||||
- Rustup
|
||||
- QEMU (for executing)
|
||||
- GIT CLI
|
||||
|
||||
### How do I run ableos?
|
||||
- It is recommended to run ableos under QEMU. Here is how:
|
||||
- Install QEMU
|
||||
- Clone ableos
|
||||
- Go to ableos directory
|
||||
- Pull the limine submodule with `git submodule update --init`
|
||||
- Run `cargo repbuild help`
|
||||
|
||||
### How can I contribute?
|
||||
- [Contribute code](#how-do-i-contribute-code)
|
||||
- [Run ableos on your machine](#how-do-i-run-ableos)
|
||||
- Find bugs
|
||||
- Create media showing ableos
|
||||
|
||||
### How do I contribute code?
|
||||
- Start by forking ableos
|
||||
- Write something that runs in the userspace, for example:
|
||||
- System drivers
|
||||
- Programs
|
||||
- Libraries
|
||||
- Patch bugs and improve code in the kernel
|
||||
- Ensure that the code is OK to be maintained by asking in the [discord](https://discord.gg/t5Wt3K4YNA)
|
||||
- When you have finished your changes, you can submit a pull request for review [here](https://git.ablecorp.us/ableos/ableos)
|
||||
|
||||
### repbuild and kernel compile, but QEMU isn't starting
|
||||
- Ensure you have the `qemu-desktop-{arch}` for your OS and target architecture installed
|
||||
- Try running again with `--noaccel` if you have QEMU already
|
||||
|
||||
### I have run using repbuild but it's slow
|
||||
- Ensure release mode is enabled with the `-r` flag
|
||||
- Remove the `--noaccel` flag if you can
|
||||
- If both of these are already done, there may be a problem with thee VM, kernel, your program, or the hblang compiler
|
||||
|
||||
### Compiler is complaining about "reg id leaked"
|
||||
- [Submit](#how-do-i-report-a-compiler-bug) an issue, reg id leaked is a bug
|
||||
|
||||
### My program isn't running
|
||||
- Refer to [here](#i-have-run-using-repbuild-but-its-slow), it may be that your program is simply starting slowly
|
||||
- Ensure that your program has a properly written meta.toml file
|
||||
- Ensure that your program is enabled in [system_config.toml](sysdata/system_config.toml)
|
||||
- Try running again with `--noaccel`, there is a known bug with some systems that prevents programs from starting.
|
||||
|
||||
### Kernel panic??? Huh???
|
||||
- Kernel panics can be caused by improperly using memory (e.g, writing out of bounds)
|
||||
- Kernel panics are most likely to be caused when accessing memory or using `@eca` for kernel ecalls
|
||||
- [Report](#how-do-i-report-an-ableos-bug) a kernel panic
|
||||
|
||||
### I am running in release mode but I have no debug info
|
||||
- Add the `-d` flag for debug info
|
||||
|
||||
### What is `@eca`? How do I use it?
|
||||
- Eca is an ecall. They are similar to syscalls
|
||||
- The `@eca` directive takes the following arguments:
|
||||
- `@eca(ecall_number, reg_1, ..., reg_n)`
|
||||
- The various ecalls have different arguments that are given by register values
|
||||
- Most ecalls are wrapped by `stn`, for example, `random`, `buffer`, and `memory` all make use of ecalls
|
||||
- All ecalls can be found [ecah.rs](kernel/src/holeybytes/ecah.rs)
|
||||
|
||||
### How do I report an ableos bug?
|
||||
- Submit an issue [here](https://git.ablecorp.us/ableos/ableos/issues) or report it in the [discord](https://discord.gg/t5Wt3K4YNA)
|
||||
|
||||
### How do I report a compiler bug?
|
||||
- Submit an issue [here](https://git.ablecorp.us/ableos/holey-bytes/issues) or report it in the [discord](https://discord.gg/t5Wt3K4YNA)
|
12
README.md
12
README.md
|
@ -10,15 +10,7 @@ Donations can be made [here on Liberapay](https://liberapay.com/AbleTheAbove) or
|
|||
<img src="https://img.shields.io/liberapay/patrons/AbleTheAbove.svg?logo=liberapay">
|
||||
|
||||
# Compiling
|
||||
AbleOS should be able to be built on any platform which is supported by
|
||||
[Rustc Tier 1 platform support](https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-1-with-host-tools).
|
||||
|
||||
For running AbleOS, `repbuild` uses QEMU.
|
||||
|
||||
## Steps
|
||||
1. Ensure you have qemu installed
|
||||
2. `git submodule update --init`
|
||||
3. `cargo repbuild run`
|
||||
See [HELP.md](HELP.md)
|
||||
|
||||
# Developing
|
||||
There is a new work in progress developer tool for hblang.
|
||||
There is a new work in progress developer tool for hblang. (see: dev folder)
|
|
@ -1,20 +1,84 @@
|
|||
use logos::Logos;
|
||||
pub mod protocol;
|
||||
|
||||
#[derive(Logos, Debug, PartialEq)]
|
||||
use std::io::Read;
|
||||
|
||||
use {
|
||||
logos::{Lexer, Logos},
|
||||
protocol::Protocol,
|
||||
};
|
||||
|
||||
#[derive(Logos, Debug, PartialEq, Clone)]
|
||||
#[logos(skip r"[ \t\n\f]+")] // Ignore this regex pattern between tokens
|
||||
enum Token {
|
||||
// Tokens can be literal strings, of any length.
|
||||
#[token("protocol")]
|
||||
Protocol,
|
||||
|
||||
#[token(".")]
|
||||
Period,
|
||||
#[token("{")]
|
||||
LBrace,
|
||||
|
||||
// Or regular expressions.
|
||||
#[regex("[a-zA-Z]+")]
|
||||
Text,
|
||||
#[token("}")]
|
||||
RBrace,
|
||||
|
||||
#[token("(")]
|
||||
LParen,
|
||||
|
||||
#[token(")")]
|
||||
RParen,
|
||||
|
||||
#[token(":")]
|
||||
Colon,
|
||||
#[token(";")]
|
||||
SemiColon,
|
||||
|
||||
#[token(",")]
|
||||
Comma,
|
||||
|
||||
#[token("=")]
|
||||
Equal,
|
||||
|
||||
#[token("->")]
|
||||
RArrow,
|
||||
|
||||
#[regex("[a-zA-Z_]+", |lex|{lex.slice().to_string()})]
|
||||
Text(String),
|
||||
|
||||
#[regex("[1234567890]+", |lex|{lex.slice().parse::<u64>().unwrap()})]
|
||||
Number(u64),
|
||||
|
||||
#[regex(r"@[a-zA-Z_]+", |lex|{lex.slice().to_string()})]
|
||||
Decorator(String),
|
||||
|
||||
#[regex(r#"@[a-zA-Z_]+\([a-zA-Z,0-9=]+\)"#, |lex|{lex.slice().to_string()})]
|
||||
DecoratorOption(String),
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut lex = Token::lexer("Create ridiculously fast Lexers.");
|
||||
pub fn build_idl(name: String) {
|
||||
let contents = open_protocol(name);
|
||||
let lex = Token::lexer(&contents);
|
||||
let mut tokens = vec![];
|
||||
for x in lex {
|
||||
match x {
|
||||
Ok(token) => {
|
||||
println!("{:?}", token);
|
||||
tokens.push(token);
|
||||
}
|
||||
Err(err) => println!("{:?}", err),
|
||||
}
|
||||
}
|
||||
build(tokens);
|
||||
}
|
||||
|
||||
fn build(a: Vec<Token>) {
|
||||
for toke in a {
|
||||
println!("{:?}", toke);
|
||||
}
|
||||
}
|
||||
|
||||
fn open_protocol(name: String) -> String {
|
||||
let path = format!("sysdata/idl/{}/src/protocol.aidl", name);
|
||||
let mut file = std::fs::File::open(path).unwrap();
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap();
|
||||
contents
|
||||
}
|
||||
|
|
17
dev/src/idl/protocol.rs
Normal file
17
dev/src/idl/protocol.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
pub enum ProtocolTypes {
|
||||
Byte,
|
||||
}
|
||||
|
||||
pub struct Protocol {}
|
||||
impl Protocol {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn validate_data(&self, data: Vec<u8>) -> bool {
|
||||
if !data.is_empty() && self.is_empty() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
use std::io::Write;
|
||||
|
||||
use idl::build_idl;
|
||||
pub mod idl;
|
||||
|
||||
pub enum Options {
|
||||
|
@ -7,7 +9,7 @@ pub enum Options {
|
|||
New,
|
||||
Run,
|
||||
}
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum DevelopmentType {
|
||||
Program,
|
||||
Library,
|
||||
|
@ -24,7 +26,7 @@ fn main() {
|
|||
|
||||
match subcommand {
|
||||
"build" => {
|
||||
let name = &args[1];
|
||||
let name = &args.pop().unwrap();
|
||||
build(name.to_string())
|
||||
}
|
||||
"new" => {
|
||||
|
@ -70,6 +72,27 @@ pub fn new(development_type: DevelopmentType, name: String) {
|
|||
let readme_contents = format!("# {}", name);
|
||||
readme_file.write_all(readme_contents.as_bytes()).unwrap();
|
||||
|
||||
let contents = format!(
|
||||
"[package]
|
||||
name = \"{}\"
|
||||
authors = [\"\"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = \"1.0.0\"
|
||||
|
||||
[build]
|
||||
command = \"hblang src/main.hb\"
|
||||
",
|
||||
name
|
||||
);
|
||||
|
||||
let toml_path_string = format!("{}/meta.toml", project_folder_path_string);
|
||||
let mut readme_file = std::fs::File::create(toml_path_string.clone()).unwrap();
|
||||
|
||||
readme_file.write_all(contents.as_bytes()).unwrap();
|
||||
|
||||
let src_folder_path_string = format!("{}/src", project_folder_path_string);
|
||||
std::fs::create_dir(src_folder_path_string.clone()).unwrap();
|
||||
|
||||
|
@ -103,8 +126,21 @@ fn run() {
|
|||
|
||||
fn build(name: String) {
|
||||
println!("building {}", name);
|
||||
let mut a = name.split("/");
|
||||
let dev_type = a.next().unwrap();
|
||||
let name = a.next().unwrap().to_string();
|
||||
match dev_type {
|
||||
"programs" => build_program(name),
|
||||
"idl" => build_idl(name),
|
||||
_ => {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_program(_name: String) {}
|
||||
pub fn build_library(_name: String) {}
|
||||
|
||||
fn help() {
|
||||
println!(
|
||||
"==========
|
||||
|
|
|
@ -4,6 +4,3 @@ build-std-features = ["compiler-builtins-mem"]
|
|||
|
||||
[build]
|
||||
target = "./targets/x86_64-ableos.json"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
rustflags = ["-C", "target-feature=+rdrand"]
|
||||
|
|
|
@ -5,8 +5,10 @@ version = "0.2.0"
|
|||
|
||||
|
||||
[dependencies]
|
||||
embedded-graphics = "0.8"
|
||||
hbvm.git = "https://git.ablecorp.us/ableos/holey-bytes"
|
||||
# embedded-graphics = "0.8"
|
||||
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
|
||||
"nightly",
|
||||
] }
|
||||
log = "0.4"
|
||||
spin = "0.9"
|
||||
slab = { version = "0.4", default-features = false }
|
||||
|
@ -14,42 +16,35 @@ uart_16550 = { version = "0.3", features = ["nightly"] }
|
|||
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
hashbrown = { version = "0.14", features = ["nightly"] }
|
||||
|
||||
[dependencies.limine]
|
||||
version = "0.1"
|
||||
#git = "https://github.com/limine-bootloader/limine-rs"
|
||||
hashbrown = { version = "0.15", features = ["nightly"] }
|
||||
limine = "0.1"
|
||||
|
||||
[dependencies.crossbeam-queue]
|
||||
version = "0.3"
|
||||
default-features = false
|
||||
features = ["alloc", "nightly"]
|
||||
|
||||
# [dependencies.clparse]
|
||||
# git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||
# default-features = false
|
||||
|
||||
[dependencies.derive_more]
|
||||
version = "1"
|
||||
default-features = false
|
||||
features = [
|
||||
"add",
|
||||
"add_assign",
|
||||
"constructor",
|
||||
"display",
|
||||
"from",
|
||||
"into",
|
||||
"mul",
|
||||
"mul_assign",
|
||||
"not",
|
||||
"sum",
|
||||
"add",
|
||||
"add_assign",
|
||||
"constructor",
|
||||
"display",
|
||||
"from",
|
||||
"into",
|
||||
"mul",
|
||||
"mul_assign",
|
||||
"not",
|
||||
"sum",
|
||||
]
|
||||
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
x86_64 = "0.15"
|
||||
x2apic = "0.4"
|
||||
virtio-drivers = "0.7"
|
||||
# virtio-drivers = "0.7"
|
||||
|
||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||
sbi = "0.2.0"
|
||||
|
|
|
@ -38,6 +38,7 @@ SECTIONS
|
|||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
*(.got .got.*)
|
||||
} :data
|
||||
|
||||
.bss : {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use {
|
||||
crate::{alloc::string::ToString, device_tree::DeviceTree, kmain::DEVICE_TREE},
|
||||
alloc::string::String,
|
||||
crate::{device_tree::DeviceTree, kmain::DEVICE_TREE},
|
||||
core::arch::asm,
|
||||
xml::XMLElement,
|
||||
};
|
||||
|
@ -28,7 +27,7 @@ fn collect_cpu_info(device_tree: &mut DeviceTree) {
|
|||
cpus.push(cpu);
|
||||
}
|
||||
|
||||
fn cpu_id() -> (String, u64) {
|
||||
fn cpu_id<'a>() -> (&'a str, u64) {
|
||||
let mut cpu_id: u64;
|
||||
unsafe {
|
||||
asm!("mrs {cpu_id}, MIDR_EL1",
|
||||
|
@ -39,11 +38,11 @@ fn cpu_id() -> (String, u64) {
|
|||
let cpu_name = match cpu_id {
|
||||
// the source of these two was a stackoverflow question
|
||||
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
||||
0x410FD034 => "Cortex-A53".to_string(),
|
||||
0x410FD083 => "Cortex-A72".to_string(),
|
||||
0x410FD034 => "Cortex-A53",
|
||||
0x410FD083 => "Cortex-A72",
|
||||
// the source of this one was checking the cpu id :thinking:
|
||||
0x410FD493 => "Neoverse N2".to_string(),
|
||||
_ => "Unknown".to_string(),
|
||||
0x410FD493 => "Neoverse N2",
|
||||
_ => "Unknown",
|
||||
};
|
||||
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use {crate::logger::TERMINAL_LOGGER, core::fmt::Write, spin::Mutex};
|
||||
static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
||||
pub static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
||||
uart: 0x09000000 as *mut u8,
|
||||
});
|
||||
|
||||
struct SerialConsole {
|
||||
pub struct SerialConsole {
|
||||
uart: *mut u8,
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ unsafe impl Send for SerialConsole {}
|
|||
|
||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
SERIAL_CONSOLE.lock().write_fmt(args)?;
|
||||
TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
// TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ use {
|
|||
pub const DOUBLE_FAULT_IX: u16 = 0;
|
||||
|
||||
const STACK_SIZE: usize = 5 * 1024;
|
||||
const STACK_ALIGNMENT: usize = 4096;
|
||||
const STACK_ALIGNMENT: usize = 1;
|
||||
|
||||
pub unsafe fn init() {
|
||||
use x86_64::instructions::{
|
||||
|
@ -39,7 +39,7 @@ static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
|||
let stack_ptr = unsafe {
|
||||
let layout = alloc::alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGNMENT)
|
||||
.expect("Failed to create stack layout");
|
||||
let stack = alloc::alloc::alloc_zeroed(layout);
|
||||
let stack = alloc::alloc::alloc(layout);
|
||||
VirtAddr::from_ptr(stack) + STACK_SIZE as u64
|
||||
};
|
||||
|
||||
|
|
|
@ -1,56 +1,54 @@
|
|||
// TODO: Turn apic keyboard interrupt into a standard ipc message
|
||||
use {
|
||||
core::mem::MaybeUninit,
|
||||
log::trace,
|
||||
spin::{Lazy, Mutex},
|
||||
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
||||
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||
};
|
||||
|
||||
pub unsafe fn init() {
|
||||
trace!("Initialising IDT");
|
||||
IDT.load();
|
||||
Lazy::force(&LAPIC);
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
/// Safety: Using LAPIC or IDT before init() is UB
|
||||
/// Using
|
||||
static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||
|
||||
#[repr(u8)]
|
||||
enum Interrupt {
|
||||
Timer = 32,
|
||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
||||
|
||||
pub enum Interrupt {
|
||||
Timer = 32,
|
||||
ApicErr = u8::MAX - 1,
|
||||
Spurious = u8::MAX,
|
||||
}
|
||||
|
||||
pub(crate) static LAPIC: Lazy<Mutex<LocalApic>> = Lazy::new(|| {
|
||||
let mut lapic = LocalApicBuilder::new()
|
||||
pub unsafe fn init() {
|
||||
trace!("Initializing IDT and LAPIC");
|
||||
|
||||
// Initialize and load the IDT
|
||||
IDT = InterruptDescriptorTable::new();
|
||||
IDT.double_fault
|
||||
.set_handler_fn(double_fault)
|
||||
.set_stack_index(super::gdt::DOUBLE_FAULT_IX);
|
||||
IDT.page_fault.set_handler_fn(page_fault);
|
||||
|
||||
IDT[Interrupt::ApicErr as u8].set_handler_fn(apic_err);
|
||||
IDT[Interrupt::Spurious as u8].set_handler_fn(spurious);
|
||||
IDT[Interrupt::Timer as u8].set_handler_fn(timer);
|
||||
|
||||
IDT.load();
|
||||
|
||||
LAPIC = LocalApicBuilder::new()
|
||||
.timer_vector(Interrupt::Timer as usize)
|
||||
.error_vector(Interrupt::ApicErr as usize)
|
||||
.spurious_vector(Interrupt::Spurious as usize)
|
||||
.set_xapic_base(
|
||||
unsafe { x2apic::lapic::xapic_base() }
|
||||
x2apic::lapic::xapic_base()
|
||||
+ super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed),
|
||||
)
|
||||
.build()
|
||||
.expect("failed to setup Local APIC");
|
||||
unsafe { lapic.enable() };
|
||||
Mutex::new(lapic)
|
||||
});
|
||||
.expect("Failed to setup Local APIC");
|
||||
LAPIC.enable();
|
||||
|
||||
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
||||
let mut idt = InterruptDescriptorTable::new();
|
||||
unsafe {
|
||||
idt.double_fault
|
||||
.set_handler_fn(double_fault)
|
||||
.set_stack_index(super::gdt::DOUBLE_FAULT_IX);
|
||||
}
|
||||
idt.page_fault.set_handler_fn(page_fault);
|
||||
|
||||
idt[Interrupt::ApicErr as u8].set_handler_fn(apic_err);
|
||||
idt[Interrupt::Spurious as u8].set_handler_fn(spurious);
|
||||
idt[Interrupt::Timer as u8].set_handler_fn(timer);
|
||||
|
||||
idt
|
||||
});
|
||||
x86_64::instructions::interrupts::enable();
|
||||
}
|
||||
|
||||
extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
|
||||
panic!("Double fault: error code {error_code} \n{stack_frame:#?}")
|
||||
|
@ -64,13 +62,49 @@ extern "x86-interrupt" fn page_fault(
|
|||
}
|
||||
|
||||
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
||||
unsafe { LAPIC.lock().end_of_interrupt() };
|
||||
// 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) {
|
||||
unsafe { LAPIC.lock().end_of_interrupt() };
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ pub mod graphics;
|
|||
pub(crate) mod interrupts;
|
||||
pub mod logging;
|
||||
pub mod pci;
|
||||
pub mod virtio;
|
||||
// pub mod virtio;
|
||||
|
||||
pub use {logging::log, memory::PAGE_SIZE};
|
||||
|
||||
|
@ -30,9 +30,11 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
|
|||
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
#[cfg(not(target_feature = "avx2"))]
|
||||
unsafe extern "C" fn _kernel_start() -> ! {
|
||||
// Initialise SSE and jump to kernel entrypoint
|
||||
core::arch::asm!(
|
||||
// Initialise SSE, then jump to kernel entrypoint
|
||||
core::arch::naked_asm!(
|
||||
// Initialise SSE
|
||||
"mov rax, cr0",
|
||||
"and ax, 0xfffb",
|
||||
"or ax, 0x2",
|
||||
|
@ -40,16 +42,74 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
"mov rax, cr4",
|
||||
"or ax, 3 << 9",
|
||||
"mov cr4, rax",
|
||||
|
||||
// Jump to the kernel entry point
|
||||
"jmp {}",
|
||||
sym start,
|
||||
options(noreturn),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
#[cfg(target_feature = "avx2")]
|
||||
unsafe extern "C" fn _kernel_start() -> ! {
|
||||
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
|
||||
"or ax, 0x2", // Set CR0.MP (bit 1) for coprocessor monitoring
|
||||
"mov cr0, rax",
|
||||
|
||||
"mov rax, cr4",
|
||||
"or ax, (1 << 9) | (1 << 10)", // Set CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10)
|
||||
"mov cr4, rax",
|
||||
|
||||
// Enable OSXSAVE (required for AVX, AVX2, and XSAVE)
|
||||
"mov rax, cr4",
|
||||
"or eax, 1 << 18", // Set CR4.OSXSAVE (bit 18)
|
||||
"mov cr4, rax",
|
||||
|
||||
// Enable AVX and AVX2 state saving
|
||||
"xor rcx, rcx",
|
||||
"xgetbv",
|
||||
"or eax, 7", // Enable SSE, AVX, and AVX2 state saving
|
||||
"xsetbv",
|
||||
|
||||
// Check for AVX and XSAVE support
|
||||
"mov eax, 1",
|
||||
"cpuid",
|
||||
"and ecx, 0x18000000",
|
||||
"cmp ecx, 0x18000000",
|
||||
"jne {1}", // Jump if AVX/OSXSAVE is not supported
|
||||
|
||||
// Check for BMI2 and AVX2 support
|
||||
"mov eax, 7",
|
||||
"xor ecx, ecx",
|
||||
"cpuid",
|
||||
"and ebx, (1 << 8) | (1 << 5)", // Check BMI2 (bit 8) and AVX2 (bit 5)
|
||||
"cmp ebx, (1 << 8) | (1 << 5)", // Compare to ensure both are supported
|
||||
|
||||
// Check for LZCNT and POPCNT support
|
||||
"mov eax, 1",
|
||||
"cpuid",
|
||||
"and ecx, (1 << 5) | (1 << 23)", // Check LZCNT (bit 5) and POPCNT (bit 23)
|
||||
"cmp ecx, (1 << 5) | (1 << 23)", // Compare to ensure both are supported
|
||||
|
||||
// Jump to the kernel entry point
|
||||
"jmp {0}",
|
||||
sym start,
|
||||
sym oops,
|
||||
)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn oops() -> ! {
|
||||
panic!("your cpu is ancient >:(")
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -128,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();
|
||||
|
@ -166,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);
|
||||
}
|
||||
|
||||
|
@ -189,6 +249,7 @@ unsafe extern "C" fn start() -> ! {
|
|||
/// Spin loop
|
||||
pub fn spin_loop() -> ! {
|
||||
loop {
|
||||
core::hint::spin_loop();
|
||||
x86_64::instructions::hlt()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,12 @@ pub struct PciDeviceInfo {
|
|||
pub full_class: PciFullClass,
|
||||
pub rev_id: u8,
|
||||
}
|
||||
use crate::alloc::string::ToString;
|
||||
|
||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||
pub fn init(device_tree: &mut DeviceTree) {
|
||||
device_tree
|
||||
.devices
|
||||
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
||||
.insert("Unidentified PCI", alloc::vec![]);
|
||||
let mut devices = alloc::vec![];
|
||||
|
||||
for bus in 0..=255 {
|
||||
|
@ -47,7 +46,8 @@ pub fn init(device_tree: &mut DeviceTree) {
|
|||
pci_info.set_attribute("id", id);
|
||||
pci_info.set_attribute("device", device_info.device);
|
||||
pci_info.set_attribute("vendor", vendor);
|
||||
pci_info.set_attribute("class", device_info.full_class.to_string());
|
||||
pci_info.set_attribute("bus", bus);
|
||||
pci_info.set_attribute("class", device_info.full_class);
|
||||
dev.set_child(pci_info);
|
||||
devices.push((dev_type, dev));
|
||||
}
|
||||
|
@ -68,7 +68,8 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
|
||||
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);
|
||||
|
@ -459,9 +460,7 @@ unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
|||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address =
|
||||
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x8000_0000) as u32;
|
||||
|
||||
let address = (bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x8000_0000;
|
||||
// write address
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
|
@ -469,6 +468,20 @@ unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
|||
Port::new(0xCFC).read()
|
||||
}
|
||||
|
||||
unsafe fn pci_config_read_2(bus: u8, device: u8, func: u8, offset: u8) -> (u32, u32) {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
let func = func as u32;
|
||||
let offset = offset as u32;
|
||||
// construct address param
|
||||
let address = (bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x8000_0000;
|
||||
// write address
|
||||
Port::new(0xCF8).write(address);
|
||||
|
||||
// read data
|
||||
(Port::new(0xCFC).read(), address)
|
||||
}
|
||||
|
||||
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||
let bus = bus as u32;
|
||||
let device = device as u32;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use {
|
||||
core::{ptr::NonNull},
|
||||
core::ptr::NonNull,
|
||||
virtio_drivers::{BufferDirection, Hal, PhysAddr},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
//! A tree of hardware devices
|
||||
|
||||
use {
|
||||
crate::alloc::string::ToString,
|
||||
alloc::{string::String, vec::Vec},
|
||||
core::fmt,
|
||||
hashbrown::HashMap,
|
||||
};
|
||||
use {alloc::vec::Vec, core::fmt, hashbrown::HashMap};
|
||||
|
||||
/// A device object.
|
||||
/// TODO define device
|
||||
pub type Device = xml::XMLElement;
|
||||
|
@ -13,38 +9,40 @@ pub type Device = xml::XMLElement;
|
|||
/// A tree of devices
|
||||
// TODO: alphabetize this list
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceTree {
|
||||
pub struct DeviceTree<'a> {
|
||||
/// The device tree
|
||||
pub devices: HashMap<String, Vec<Device>>,
|
||||
pub devices: HashMap<&'a str, Vec<Device>>,
|
||||
}
|
||||
impl DeviceTree {
|
||||
impl<'a> DeviceTree<'a> {
|
||||
/// Build the device tree. Does not populate the device tree
|
||||
pub fn new() -> Self {
|
||||
let mut dt = Self {
|
||||
devices: HashMap::new(),
|
||||
};
|
||||
device_tree!(dt, [
|
||||
"Mice",
|
||||
"Keyboards",
|
||||
"Controllers",
|
||||
"Generic HIDs",
|
||||
"Disk Drives",
|
||||
"CD Drives",
|
||||
"Batteries",
|
||||
"Monitors",
|
||||
"GPUs",
|
||||
"CPUs",
|
||||
"USB",
|
||||
"Serial Ports",
|
||||
"Cameras",
|
||||
"Biometric Devices",
|
||||
]);
|
||||
device_tree!(
|
||||
dt,
|
||||
[
|
||||
"Mice",
|
||||
"Keyboards",
|
||||
"Controllers",
|
||||
"Generic HIDs",
|
||||
"Disk Drives",
|
||||
"CD Drives",
|
||||
"Batteries",
|
||||
"Monitors",
|
||||
"GPUs",
|
||||
"CPUs",
|
||||
"USB",
|
||||
"Serial Ports",
|
||||
"Cameras",
|
||||
"Biometric Devices",
|
||||
]
|
||||
);
|
||||
dt
|
||||
}
|
||||
}
|
||||
use crate::{utils::TAB, device_tree};
|
||||
use crate::tab;
|
||||
impl fmt::Display for DeviceTree {
|
||||
use crate::{device_tree, tab, utils::TAB};
|
||||
impl<'a> fmt::Display for DeviceTree<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f)?;
|
||||
for (device_type, devices) in &self.devices {
|
35
kernel/src/exe_format.rs
Normal file
35
kernel/src/exe_format.rs
Normal file
|
@ -0,0 +1,35 @@
|
|||
enum Sections {
|
||||
Header,
|
||||
Code,
|
||||
Data,
|
||||
Debug,
|
||||
Config,
|
||||
Metadata,
|
||||
}
|
||||
|
||||
// 64 byte header
|
||||
#[repr(packed)]
|
||||
struct AbleOsExecutableHeader {
|
||||
magic_number: [u8; 3],
|
||||
executable_version: u32,
|
||||
|
||||
code_length: u64,
|
||||
data_length: u64,
|
||||
debug_length: u64,
|
||||
config_length: u64,
|
||||
metadata_length: u64,
|
||||
}
|
||||
|
||||
impl AbleOsExecutableHeader {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
magic_number: [0x15, 0x91, 0xD2],
|
||||
executable_version: 0,
|
||||
code_length: 0,
|
||||
config_length: 0,
|
||||
data_length: 0,
|
||||
debug_length: 0,
|
||||
metadata_length: 0,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,41 @@
|
|||
//! Environment call handling routines
|
||||
|
||||
use crate::holeybytes::kernel_services::{block_read, 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 {
|
||||
super::Vm,
|
||||
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||
log::{debug, error, info, trace, warn},
|
||||
hbvm::value::Value,
|
||||
log::{debug, error, info, trace},
|
||||
};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[inline(always)]
|
||||
unsafe fn x86_out<T: x86_64::instructions::port::PortWrite>(address: u16, value: T) {
|
||||
x86_64::instructions::port::Port::new(address).write(value);
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[inline(always)]
|
||||
unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
||||
x86_64::instructions::port::Port::new(address).read()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn handler(vm: &mut Vm) {
|
||||
let ecall_number = vm.registers[2].cast::<u64>();
|
||||
|
||||
// debug!("Ecall number {:?}", ecall_number);
|
||||
//info!("Register dump: {:?}", vm.registers);
|
||||
|
||||
match ecall_number {
|
||||
0 => {
|
||||
// TODO: explode computer
|
||||
|
@ -25,9 +47,9 @@ pub fn handler(vm: &mut Vm) {
|
|||
1 => {
|
||||
// Make buffer
|
||||
|
||||
let bounded = match vm.registers[3].cast::<u64>() {
|
||||
0 => false,
|
||||
1 => true,
|
||||
let bounded = match vm.registers[3] {
|
||||
Value(0) => false,
|
||||
Value(1) => true,
|
||||
_ => {
|
||||
panic!("Bad");
|
||||
}
|
||||
|
@ -36,22 +58,19 @@ pub fn handler(vm: &mut Vm) {
|
|||
let length = vm.registers[4].cast::<u64>();
|
||||
|
||||
let mut buffs = IPC_BUFFERS.lock();
|
||||
let abc;
|
||||
|
||||
match bounded {
|
||||
false => {
|
||||
abc = IpcBuffer::new(false, 0);
|
||||
}
|
||||
true => {
|
||||
abc = IpcBuffer::new(true, length);
|
||||
}
|
||||
};
|
||||
let buff_id = arch::hardware_random_u64();
|
||||
buffs.insert(buff_id, abc);
|
||||
info!("Buffer ID: {}", buff_id);
|
||||
buffs.insert(
|
||||
buff_id,
|
||||
match bounded {
|
||||
false => IpcBuffer::new(false, 0),
|
||||
true => IpcBuffer::new(true, length),
|
||||
},
|
||||
);
|
||||
vm.registers[1] = hbvm::value::Value(buff_id);
|
||||
}
|
||||
2 => {
|
||||
log::error!("Oops, deleting buffers is not implemented.")
|
||||
// Delete buffer
|
||||
}
|
||||
3 => {
|
||||
|
@ -60,7 +79,6 @@ pub fn handler(vm: &mut Vm) {
|
|||
let mem_addr = vm.registers[4].cast::<u64>();
|
||||
let length = vm.registers[5].cast::<u64>() as usize;
|
||||
trace!("IPC address: {:?}", mem_addr);
|
||||
use alloc::vec::Vec;
|
||||
|
||||
match buffer_id {
|
||||
0 => match sds_msg_handler(vm, mem_addr, length) {
|
||||
|
@ -78,174 +96,139 @@ pub fn handler(vm: &mut Vm) {
|
|||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
3 => info!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
3 => {
|
||||
unsafe fn x86_out<T: x86_64::instructions::port::PortWrite>(
|
||||
address: u16,
|
||||
value: T,
|
||||
) {
|
||||
x86_64::instructions::port::Port::new(address).write(value);
|
||||
}
|
||||
unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
||||
x86_64::instructions::port::Port::new(address).read()
|
||||
}
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
let msg_type = msg_vec[0];
|
||||
match msg_type {
|
||||
0 => 'wow: {
|
||||
let size = match msg_vec[0] {
|
||||
0 => 1,
|
||||
1 => 2,
|
||||
2 => 4,
|
||||
_ => {
|
||||
error!("Tried to write more than 32 bits");
|
||||
break 'wow;
|
||||
}
|
||||
0 => unsafe {
|
||||
let size = msg_vec[1];
|
||||
let addr =
|
||||
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
||||
let value = match size {
|
||||
0 => x86_in::<u8>(addr) as u64,
|
||||
1 => x86_in::<u16>(addr) as u64,
|
||||
2 => x86_in::<u32>(addr) as u64,
|
||||
_ => panic!("Trying to read size other than: 8, 16, 32 from port."),
|
||||
};
|
||||
let addr = u16::from_le_bytes(msg_vec[1..3].try_into().unwrap());
|
||||
let value = unsafe {
|
||||
match size {
|
||||
1 => x86_in::<u8>(addr) as u64,
|
||||
2 => x86_in::<u16>(addr) as u64,
|
||||
4 => x86_in::<u32>(addr) as u64,
|
||||
_ => panic!("how?"),
|
||||
}
|
||||
};
|
||||
trace!("Read the value {} from address {}", value, addr);
|
||||
// info!("Read the value {} from address {}", value, addr);
|
||||
vm.registers[1] = hbvm::value::Value(value);
|
||||
}
|
||||
1 => 'wow: {
|
||||
let size = match msg_vec[1] {
|
||||
0 => 1,
|
||||
1 => 2,
|
||||
2 => 4,
|
||||
_ => {
|
||||
error!("Tried to write more than 32 bits");
|
||||
break 'wow;
|
||||
}
|
||||
};
|
||||
let addr = unsafe {
|
||||
u16::from_le_bytes(msg_vec[1..3].try_into().unwrap_unchecked())
|
||||
};
|
||||
trace!("Setting address {}", addr);
|
||||
unsafe {
|
||||
match size {
|
||||
1 => x86_out(addr, msg_vec[3]),
|
||||
2 => x86_out(
|
||||
addr,
|
||||
u16::from_le_bytes(
|
||||
msg_vec[3..5].try_into().unwrap_unchecked(),
|
||||
),
|
||||
),
|
||||
4 => x86_out(
|
||||
addr,
|
||||
u32::from_le_bytes(
|
||||
msg_vec[3..7].try_into().unwrap_unchecked(),
|
||||
),
|
||||
),
|
||||
_ => panic!("How?"),
|
||||
}
|
||||
},
|
||||
1 => unsafe {
|
||||
let size = msg_vec[1];
|
||||
let addr =
|
||||
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
||||
// info!("Setting address {}", addr);
|
||||
|
||||
match size {
|
||||
0 => x86_out(addr, msg_vec[4]),
|
||||
1 => x86_out(
|
||||
addr,
|
||||
u16::from_le_bytes(msg_vec[4..6].try_into().unwrap_unchecked()),
|
||||
),
|
||||
2 => x86_out(
|
||||
addr,
|
||||
u32::from_le_bytes(msg_vec[4..8].try_into().unwrap_unchecked()),
|
||||
),
|
||||
_ => panic!("How?"),
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||
// source of rng
|
||||
4 => {
|
||||
// limit to last 32 bits
|
||||
vm.registers[1] =
|
||||
hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF);
|
||||
let block = block_read(mem_addr, length);
|
||||
block.chunks_mut(8.min(length)).for_each(|chunk| {
|
||||
chunk.clone_from_slice(
|
||||
&crate::arch::hardware_random_u64().to_le_bytes()[..chunk.len()],
|
||||
);
|
||||
});
|
||||
vm.registers[1] = hbvm::value::Value(mem_addr);
|
||||
}
|
||||
// get arch
|
||||
5 => {
|
||||
if cfg!(target_arch = "x86_64") {
|
||||
vm.registers[1] = hbvm::value::Value(0);
|
||||
} else if cfg!(target_arch = "aarch64") {
|
||||
vm.registers[1] = hbvm::value::Value(1);
|
||||
5 => match dt_msg_handler(vm, mem_addr, length) {
|
||||
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 {
|
||||
vm.registers[1] = hbvm::value::Value(u64::MAX)
|
||||
}
|
||||
}
|
||||
// AbleCode™ (get fb ptr)
|
||||
6 => {
|
||||
use {
|
||||
crate::kmain::FB_REQ,
|
||||
limine::{Framebuffer, NonNullPtr},
|
||||
error!("Invalid executable format.");
|
||||
return;
|
||||
};
|
||||
let fb1: &NonNullPtr<Framebuffer> =
|
||||
&FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||
let msg = block_read(mem_addr, length)[0];
|
||||
if msg == b'p' {
|
||||
// ptr
|
||||
let fb_front = fb1.address.as_ptr().unwrap() as *const u8;
|
||||
log::info!("Graphics front ptr {:?}", fb_front);
|
||||
vm.registers[1] = hbvm::value::Value(fb_front as u64);
|
||||
} else if msg == b'w' {
|
||||
// width
|
||||
log::info!("FB Width: {}", fb1.width);
|
||||
vm.registers[1] = hbvm::value::Value(fb1.width);
|
||||
} else if msg == b'h' {
|
||||
// height
|
||||
log::info!("FB Height: {}", fb1.height);
|
||||
vm.registers[1] = hbvm::value::Value(fb1.height);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
match buffs.get_mut(&buffer_id) {
|
||||
Some(buff) => {
|
||||
let mut msg_vec = Vec::with_capacity(length);
|
||||
|
||||
for x in 0..(length as isize) {
|
||||
let xyz = mem_addr as *const u8;
|
||||
let value = unsafe { xyz.offset(x).read() };
|
||||
msg_vec.push(value);
|
||||
}
|
||||
debug!(
|
||||
"Message {:?} has been sent to Buffer({})",
|
||||
msg_vec, buffer_id
|
||||
);
|
||||
buff.push(msg_vec);
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
buff.push(msg_vec.to_vec());
|
||||
debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer_id);
|
||||
}
|
||||
None => {
|
||||
log::error!("Access of non-existent buffer {}", buffer_id)
|
||||
}
|
||||
}
|
||||
drop(buffs);
|
||||
}
|
||||
}
|
||||
}
|
||||
4 => {
|
||||
let buffer_id = vm.registers[3].cast::<u64>();
|
||||
let mut map_ptr = vm.registers[4].cast::<u64>();
|
||||
let map_ptr = vm.registers[4].cast::<u64>();
|
||||
let max_length = vm.registers[5].cast::<u64>();
|
||||
|
||||
let mut buffs = IPC_BUFFERS.lock();
|
||||
let buff: &mut IpcBuffer;
|
||||
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
|
||||
Some(buff) => buff,
|
||||
None => panic!(
|
||||
"Failed to get buffer: id={buffer_id}, ptr={map_ptr}, length={max_length}"
|
||||
),
|
||||
};
|
||||
|
||||
if buffs.get_mut(&buffer_id).is_some() {
|
||||
buff = buffs.get_mut(&buffer_id).unwrap();
|
||||
} else {
|
||||
// info!("AHHH");
|
||||
vm.registers[1] = hbvm::value::Value(0);
|
||||
return;
|
||||
}
|
||||
let pop = buff.pop();
|
||||
if pop.is_err() {
|
||||
return;
|
||||
}
|
||||
let msg = pop.unwrap();
|
||||
if msg.len() > max_length.try_into().unwrap() {
|
||||
let msg = match buff.pop() {
|
||||
Ok(msg) => msg,
|
||||
Err(_) => return,
|
||||
};
|
||||
if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } {
|
||||
info!("{}", max_length);
|
||||
error!("Message is too long to map in.");
|
||||
} else {
|
||||
unsafe {
|
||||
let ptr: *mut u64 = &mut map_ptr;
|
||||
for (index, byte) in msg.iter().enumerate() {
|
||||
ptr.offset(index.try_into().unwrap()).write_bytes(*byte, 1);
|
||||
}
|
||||
let ptr = map_ptr as *mut u8;
|
||||
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
|
||||
}
|
||||
|
||||
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||
|
@ -255,14 +238,8 @@ pub fn handler(vm: &mut Vm) {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let r2 = vm.registers[2].cast::<u64>();
|
||||
unsafe fn x86_in(address: u16) -> u32 {
|
||||
x86_64::instructions::port::Port::new(address).read()
|
||||
}
|
||||
unsafe fn x86_out(address: u16, value: u32) {
|
||||
x86_64::instructions::port::Port::new(address).write(value);
|
||||
}
|
||||
let x = hbvm::value::Value(unsafe { x86_in(r2 as u16) } as u64);
|
||||
info!("Read {:?} from Port {:?}", x, r2);
|
||||
let x = hbvm::value::Value(unsafe { x86_in::<u8>(r2 as u16) } as u64);
|
||||
// info!("Read {:?} from Port {:?}", x, r2);
|
||||
vm.registers[3] = x
|
||||
}
|
||||
}
|
||||
|
@ -272,48 +249,8 @@ pub fn handler(vm: &mut Vm) {
|
|||
}
|
||||
}
|
||||
|
||||
fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
// let message_length = 8 + 8 + 8;
|
||||
// log::info!("Mem Addr 0x{:x?} length {}", mem_addr, length);
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
|
||||
let log_level = msg_vec.last().unwrap();
|
||||
match core::str::from_utf8(&msg_vec[1..]) {
|
||||
Ok(strr) => {
|
||||
// use LogLevel::*;
|
||||
let _ll = match log_level {
|
||||
0 | 48 => error!("{}", strr),
|
||||
1 | 49 => warn!("{}", strr),
|
||||
2 | 50 => info!("{}", strr),
|
||||
3 | 51 => debug!("{}", strr),
|
||||
4 | 52 => trace!("{}", strr),
|
||||
_ => {
|
||||
return Err(LogError::InvalidLogFormat);
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogError {
|
||||
NoMessages,
|
||||
InvalidLogFormat,
|
||||
}
|
||||
|
||||
// use {alloc::vec, log::Record};
|
||||
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
// let mut val = alloc::vec::Vec::new();
|
||||
// for _ in 0..4096 {
|
||||
// val.push(0);
|
||||
// }
|
||||
// info!("Block address: {:?}", val.as_ptr());
|
||||
// vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
||||
// vm.registers[2] = hbvm::value::Value(4096);
|
||||
// Ok(())
|
||||
// }
|
||||
|
|
78
kernel/src/holeybytes/kernel_services/dt_msg_handler.rs
Normal file
78
kernel/src/holeybytes/kernel_services/dt_msg_handler.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use {
|
||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||
alloc::vec::Vec,
|
||||
};
|
||||
pub enum DtError {
|
||||
QueryFailure,
|
||||
}
|
||||
|
||||
pub fn dt_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), DtError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
let query_string = core::str::from_utf8(
|
||||
msg_vec
|
||||
.split_once(|&byte| byte == 0)
|
||||
.unwrap_or((msg_vec, &[]))
|
||||
.0,
|
||||
)
|
||||
.unwrap();
|
||||
log::trace!("Query {}", query_string);
|
||||
|
||||
let ret = query_parse(query_string);
|
||||
log::trace!("Query response {}", ret);
|
||||
|
||||
vm.registers[1] = hbvm::value::Value(ret);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn query_parse(query_string: &str) -> u64 {
|
||||
let query = query_string.split('/').collect::<Vec<&str>>();
|
||||
|
||||
let first_fragment: &str = &query[0];
|
||||
let ret = match first_fragment {
|
||||
"framebuffer" => framebuffer_parse(query),
|
||||
"cpu" => cpu_parse(query),
|
||||
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn cpu_parse(qt_parse_step_two: Vec<&str>) -> u64 {
|
||||
let second_fragment: &str = qt_parse_step_two[1];
|
||||
match second_fragment {
|
||||
// "architecture" => {
|
||||
// return 0;
|
||||
// }
|
||||
_ => {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn framebuffer_parse(qt_parse_step_two: Vec<&str>) -> u64 {
|
||||
use crate::kmain::FB_REQ;
|
||||
let fbs = &mut FB_REQ.get_response().get().unwrap().framebuffers();
|
||||
let second_fragment: &str = qt_parse_step_two[1];
|
||||
match second_fragment {
|
||||
"fb0" => {
|
||||
let fb_front = &fbs[0];
|
||||
let third_fragment: &str = qt_parse_step_two[2];
|
||||
let ret = match third_fragment {
|
||||
"ptr" => {
|
||||
let ptr = fb_front.address.as_ptr().unwrap();
|
||||
ptr as usize as u64
|
||||
}
|
||||
"width" => fb_front.width,
|
||||
"height" => fb_front.height,
|
||||
|
||||
_ => 0,
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
_ => {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
54
kernel/src/holeybytes/kernel_services/logging_service.rs
Normal file
54
kernel/src/holeybytes/kernel_services/logging_service.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use crate::holeybytes::{kernel_services::block_read, Vm};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LogError {
|
||||
InvalidLogFormat,
|
||||
}
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
let str = block_read(strptr, strlen);
|
||||
|
||||
let file_name = "None";
|
||||
let line_number = 0;
|
||||
|
||||
match core::str::from_utf8(&str) {
|
||||
Ok(strr) => {
|
||||
log::logger().log(
|
||||
&Record::builder()
|
||||
.args(format_args!("{}", strr))
|
||||
.level(log_level)
|
||||
.target("Userspace")
|
||||
.file(Some(file_name))
|
||||
.line(Some(line_number))
|
||||
.module_path(Some(&file_name))
|
||||
.build(),
|
||||
);
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
log::error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use {
|
||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||
alloc::alloc::{alloc_zeroed, dealloc},
|
||||
alloc::alloc::{alloc, dealloc},
|
||||
core::alloc::Layout,
|
||||
log::{debug, info},
|
||||
};
|
||||
|
@ -17,13 +17,28 @@ pub enum MemoryQuotaType {
|
|||
}
|
||||
|
||||
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
||||
let ptr = unsafe { alloc_zeroed(Layout::new::<[u8; 4096]>()) };
|
||||
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 8)) };
|
||||
info!("Block address: {:?}", ptr);
|
||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||
vm.registers[2] = hbvm::value::Value(4096);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
||||
let total_size = count * size;
|
||||
src.copy_to_nonoverlapping(dest, size);
|
||||
|
||||
let mut copied = size;
|
||||
|
||||
while copied < total_size {
|
||||
let copy_size = copied.min(total_size - copied);
|
||||
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
|
||||
copied += copy_size;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn memory_msg_handler(
|
||||
vm: &mut Vm,
|
||||
mem_addr: u64,
|
||||
|
@ -32,40 +47,35 @@ pub fn memory_msg_handler(
|
|||
let msg_vec = block_read(mem_addr, length);
|
||||
let msg_type = msg_vec[0];
|
||||
match msg_type {
|
||||
0 => {
|
||||
0 => unsafe {
|
||||
let page_count = msg_vec[1];
|
||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||
|
||||
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
|
||||
let ptr = alloc(Layout::from_size_align_unchecked(
|
||||
page_count as usize * 4096,
|
||||
8,
|
||||
));
|
||||
|
||||
let ptr = unsafe {
|
||||
alloc_zeroed(Layout::from_size_align_unchecked(
|
||||
page_count as usize * 4096,
|
||||
1,
|
||||
))
|
||||
};
|
||||
log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
|
||||
|
||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
||||
}
|
||||
},
|
||||
|
||||
1 => {
|
||||
1 => unsafe {
|
||||
let page_count = msg_vec[1];
|
||||
|
||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
||||
unsafe {
|
||||
dealloc(
|
||||
mptr as *mut u8,
|
||||
Layout::from_size_align_unchecked(page_count as usize * 4096, 1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dealloc(
|
||||
mptr as *mut u8,
|
||||
Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
|
||||
)
|
||||
},
|
||||
2 => {
|
||||
use MemoryQuotaType::*;
|
||||
let quota_type = match msg_vec[0] {
|
||||
let quota_type = match msg_vec[1] {
|
||||
0 => NoQuota,
|
||||
1 => SoftQuota,
|
||||
2 => HardQuota,
|
||||
|
@ -82,10 +92,24 @@ pub fn memory_msg_handler(
|
|||
)
|
||||
}
|
||||
3 => {
|
||||
let page_count = msg_vec[0];
|
||||
let page_count = msg_vec[1];
|
||||
log::debug!(" {} pages", page_count);
|
||||
}
|
||||
4 => unsafe {
|
||||
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
|
||||
let src = u64::from_le_bytes(msg_vec[5..13].try_into().unwrap_unchecked()) as *const u8;
|
||||
let dest = u64::from_le_bytes(msg_vec[13..21].try_into().unwrap_unchecked()) as *mut u8;
|
||||
|
||||
src.copy_to_nonoverlapping(dest, count);
|
||||
},
|
||||
5 => unsafe {
|
||||
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
|
||||
let size = u32::from_le_bytes(msg_vec[5..9].try_into().unwrap_unchecked()) as usize;
|
||||
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
|
||||
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
|
||||
|
||||
memset(dest, src, count, size);
|
||||
},
|
||||
_ => {
|
||||
log::debug!("Unknown memory service message type: {}", msg_type);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use core::slice;
|
||||
|
||||
pub mod dt_msg_handler;
|
||||
pub mod logging_service;
|
||||
pub mod mem_serve;
|
||||
pub mod service_definition_service;
|
||||
|
||||
#[inline(always)]
|
||||
pub fn block_read<'a>(mem_addr: u64, length: usize) -> &'a [u8] {
|
||||
unsafe { slice::from_raw_parts(mem_addr as *const u8, length) }
|
||||
pub fn block_read<'a>(mem_addr: u64, length: usize) -> &'a mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(mem_addr as *mut _, length) }
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use {
|
||||
crate::{
|
||||
arch::hardware_random_u64,
|
||||
holeybytes::{ecah::LogError, kernel_services::block_read, Vm},
|
||||
holeybytes::{kernel_services::block_read, Vm},
|
||||
ipc::{buffer::IpcBuffer, protocol::Protocol},
|
||||
kmain::IPC_BUFFERS,
|
||||
},
|
||||
|
@ -15,28 +15,26 @@ pub static SERVICES: Lazy<Mutex<Services>> = Lazy::new(|| {
|
|||
dt.0.insert(0, Protocol::void());
|
||||
Mutex::new(dt)
|
||||
});
|
||||
|
||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||
#[derive(Debug)]
|
||||
pub enum ServiceError {
|
||||
InvalidFormat,
|
||||
}
|
||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
||||
let msg_vec = block_read(mem_addr, length);
|
||||
if msg_vec.is_empty() {
|
||||
return Err(LogError::NoMessages);
|
||||
}
|
||||
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
||||
|
||||
// info!("Length {}", msg_vec.len());
|
||||
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;
|
||||
let string_vec = block_read(strptr, strlen);
|
||||
let string = core::str::from_utf8(string_vec).expect("Our bytes should be valid utf8");
|
||||
|
||||
use ServiceEventType::*;
|
||||
match sds_event_type {
|
||||
CreateService => {
|
||||
let string =
|
||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||
let ret = sds_create_service(string);
|
||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||
}
|
||||
DeleteService => todo!(),
|
||||
SearchServices => {
|
||||
let string =
|
||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||
let ret = sds_search_service(string);
|
||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||
}
|
||||
|
@ -94,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 {
|
||||
|
|
|
@ -30,30 +30,29 @@ impl Memory {
|
|||
}
|
||||
|
||||
impl hbvm::mem::Memory for Memory {
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
unsafe fn load(
|
||||
&mut self,
|
||||
addr: Address,
|
||||
target: *mut u8,
|
||||
count: usize,
|
||||
) -> Result<(), hbvm::mem::LoadError> {
|
||||
if addr.get() % 4096 == 0 {}
|
||||
core::ptr::copy(addr.get() as *const u8, target, count);
|
||||
core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
unsafe fn store(
|
||||
&mut self,
|
||||
addr: Address,
|
||||
source: *const u8,
|
||||
count: usize,
|
||||
) -> Result<(), hbvm::mem::StoreError> {
|
||||
core::ptr::copy(source, addr.get() as *mut u8, count);
|
||||
core::ptr::copy_nonoverlapping(source, addr.get() as *mut u8, count);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline(always)]
|
||||
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
||||
(addr.get() as *const T).read()
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
mod ecah;
|
||||
mod kernel_services;
|
||||
pub mod kernel_services;
|
||||
mod mem;
|
||||
|
||||
use {
|
||||
alloc::alloc::{alloc_zeroed, dealloc},
|
||||
alloc::alloc::{alloc, dealloc},
|
||||
core::{
|
||||
alloc::Layout,
|
||||
future::Future,
|
||||
|
@ -61,28 +61,22 @@ impl<'p> Future for ExecThread {
|
|||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.vm.run() {
|
||||
Err(err) => {
|
||||
error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers);
|
||||
Poll::Ready(Err(err))
|
||||
}
|
||||
Ok(VmRunOk::End) => Poll::Ready(Ok(())),
|
||||
Ok(VmRunOk::Ecall) => {
|
||||
ecah::handler(&mut self.vm);
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
Ok(VmRunOk::Timer) => {
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
log::error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers,);
|
||||
return Poll::Ready(Err(err));
|
||||
}
|
||||
Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
|
||||
Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm),
|
||||
Ok(VmRunOk::Timer) => (),
|
||||
Ok(VmRunOk::Breakpoint) => {
|
||||
error!(
|
||||
log::error!(
|
||||
"HBVM Debug breakpoint\r\nRegister dump: {:?}",
|
||||
self.vm.registers
|
||||
self.vm.registers,
|
||||
);
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,10 +97,10 @@ impl HandlePageFault for PageFaultHandler {
|
|||
|
||||
#[inline(always)]
|
||||
const fn stack_layout() -> Layout {
|
||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 8) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn allocate_stack() -> *mut u8 {
|
||||
unsafe { alloc_zeroed(stack_layout()) }
|
||||
unsafe { alloc(stack_layout()) }
|
||||
}
|
||||
|
|
|
@ -49,9 +49,7 @@ impl<'a> IpcBuffer<'a> {
|
|||
pub fn push(&mut self, msg: Message) {
|
||||
match &self.buffer {
|
||||
BufferTypes::Unbound(buff) => buff.push(msg),
|
||||
BufferTypes::Bound(buff) => {
|
||||
let _ = buff.push(msg);
|
||||
}
|
||||
BufferTypes::Bound(buff) => buff.push(msg).unwrap(),
|
||||
};
|
||||
}
|
||||
pub fn pop(&mut self) -> Result<Message, IpcError> {
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
use {
|
||||
alloc::{string::String, vec::Vec},
|
||||
hashbrown::HashMap,
|
||||
};
|
||||
use {alloc::vec::Vec, hashbrown::HashMap};
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Type {}
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Funct {
|
||||
takes: Vec<String>,
|
||||
gives: Vec<String>,
|
||||
pub struct Funct<'a> {
|
||||
takes: Vec<&'a str>,
|
||||
gives: Vec<&'a str>,
|
||||
}
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Protocol<'a> {
|
||||
types: HashMap<&'a str, Type>,
|
||||
fns: HashMap<&'a str, Funct>,
|
||||
fns: HashMap<&'a str, Funct<'a>>,
|
||||
}
|
||||
impl<'a> Protocol<'a> {
|
||||
pub fn void() -> Self {
|
||||
|
|
|
@ -8,11 +8,14 @@ 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},
|
||||
log::{debug, info},
|
||||
log::{debug, error, trace},
|
||||
spin::{Lazy, Mutex},
|
||||
};
|
||||
|
||||
|
@ -36,9 +39,9 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
let dt = DEVICE_TREE.lock();
|
||||
|
||||
// TODO(Able): This line causes a deadlock
|
||||
info!("Device Tree: {}", dt);
|
||||
debug!("Device Tree: {}", dt);
|
||||
|
||||
info!("Boot complete. Moving to init_system");
|
||||
trace!("Boot complete. Moving to init_system");
|
||||
|
||||
// TODO: schedule the disk driver from the initramfs
|
||||
// TODO: schedule the filesystem driver from the initramfs
|
||||
|
@ -50,49 +53,73 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||
|
||||
{
|
||||
use crate::alloc::string::ToString;
|
||||
let mut dt = DEVICE_TREE.lock();
|
||||
let mut disp = xml::XMLElement::new("display_0");
|
||||
|
||||
disp.set_attribute("width", fb1.width);
|
||||
disp.set_attribute("height", fb1.height);
|
||||
disp.set_attribute("bits per pixel", fb1.bpp);
|
||||
disp.set_attribute("bpp", fb1.bpp);
|
||||
disp.set_attribute("pitch", fb1.pitch);
|
||||
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||
dt.devices.insert("Displays", alloc::vec![disp]);
|
||||
}
|
||||
log::info!("Graphics initialised");
|
||||
log::info!(
|
||||
debug!("Graphics initialised");
|
||||
debug!(
|
||||
"Graphics front ptr {:?}",
|
||||
fb1.address.as_ptr().unwrap() as *const u8
|
||||
);
|
||||
|
||||
let mut executor = crate::task::Executor::new(256);
|
||||
let bm_take = boot_modules.len();
|
||||
unsafe {
|
||||
for module in boot_modules.into_iter().take(bm_take) {
|
||||
let mut cmd = module.cmd;
|
||||
if cmd.len() > 2 {
|
||||
// // Remove the quotes
|
||||
// cmd.remove(0);
|
||||
// cmd.pop();
|
||||
cmd = &cmd[1..cmd.len()]
|
||||
}
|
||||
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);
|
||||
|
||||
executor.spawn(async move {
|
||||
let mut thr = ExecThread::new(&module.bytes, Address::new(0));
|
||||
if cmd_len > 0 {
|
||||
thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len);
|
||||
}
|
||||
// decode AbleOS Executable format
|
||||
let header = &module.bytes[0..46];
|
||||
let magic_slice = &header[0..3];
|
||||
if magic_slice != [0x15, 0x91, 0xD2] {
|
||||
log::error!("Invalid magic number at the start of executable.");
|
||||
continue;
|
||||
}
|
||||
|
||||
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.");
|
||||
continue;
|
||||
};
|
||||
|
||||
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 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(Box::pin(async move {
|
||||
if let Err(e) = thr.await {
|
||||
log::error!("{e:?}");
|
||||
}
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
info!("Random number: {}", hardware_random_u64());
|
||||
debug!("Random number: {}", hardware_random_u64());
|
||||
|
||||
executor.run();
|
||||
};
|
||||
|
@ -100,6 +127,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)
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
//! Named akern.
|
||||
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
|
||||
#![no_std]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(
|
||||
slice_split_once,
|
||||
exclusive_wrapper,
|
||||
core_intrinsics,
|
||||
abi_x86_interrupt,
|
||||
lazy_get,
|
||||
alloc_error_handler,
|
||||
ptr_sub_ptr,
|
||||
custom_test_frameworks,
|
||||
|
@ -12,8 +15,7 @@
|
|||
pointer_is_aligned_to
|
||||
)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, internal_features, static_mut_refs)]
|
||||
extern crate alloc;
|
||||
|
||||
mod allocator;
|
||||
|
@ -21,6 +23,7 @@ mod arch;
|
|||
mod bootmodules;
|
||||
mod capabilities;
|
||||
mod device_tree;
|
||||
mod exe_format;
|
||||
mod handle;
|
||||
mod holeybytes;
|
||||
mod ipc;
|
||||
|
|
|
@ -36,13 +36,26 @@ impl log::Log for Logger {
|
|||
Level::Debug => "25",
|
||||
Level::Trace => "103",
|
||||
};
|
||||
let module = record.module_path().unwrap_or_default();
|
||||
let line = record.line().unwrap_or_default();
|
||||
crate::arch::log(format_args!(
|
||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
||||
record.args(),
|
||||
))
|
||||
.expect("write to serial console");
|
||||
let module = record
|
||||
.module_path()
|
||||
.unwrap_or_default()
|
||||
.rsplit_once(':')
|
||||
.unwrap_or_default()
|
||||
.1;
|
||||
if module == "" {
|
||||
crate::arch::log(format_args!(
|
||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
|
||||
record.args(),
|
||||
))
|
||||
.expect("write to serial console");
|
||||
} else {
|
||||
let line = record.line().unwrap_or_default();
|
||||
crate::arch::log(format_args!(
|
||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
||||
record.args(),
|
||||
))
|
||||
.expect("write to serial console");
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,15 +4,14 @@
|
|||
/// Used when tab `\t` in hardware is not known and we will default to two spaces
|
||||
pub const TAB: &str = " ";
|
||||
|
||||
|
||||
// NOTE: this only reduces the code duplication in source code not in generated code!
|
||||
// Written by Yours Truly: Munir
|
||||
/// A simple macro to reduce code duplication when we use TAB internally
|
||||
#[macro_export]
|
||||
macro_rules! tab {
|
||||
($num:expr) => {
|
||||
($num:expr) => {
|
||||
TAB.repeat($num)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: this only reduces the code duplication in source code not in generated code!
|
||||
|
@ -22,7 +21,7 @@ macro_rules! tab {
|
|||
macro_rules! device_tree {
|
||||
($devtree:expr, $dev_type_vec:expr) => {
|
||||
for each_device_type in $dev_type_vec {
|
||||
$devtree.devices.insert(each_device_type.to_string(), Vec::new());
|
||||
$devtree.devices.insert(each_device_type, Vec::new());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -50,4 +49,4 @@ macro_rules! cpu_features {
|
|||
$result_vec.push(("rdseed", rdseed));
|
||||
$result_vec.push(("x2apic", x2));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
{
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"panic-strategy": "abort",
|
||||
"disable-redzone": true,
|
||||
"features": "",
|
||||
"code-model": "kernel",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"--gc-sections",
|
||||
"--script=kernel/lds/x86_64.ld"
|
||||
]
|
||||
}
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"panic-strategy": "abort",
|
||||
"disable-redzone": true,
|
||||
"features": "",
|
||||
"code-model": "kernel",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"--gc-sections",
|
||||
"--script=kernel/lds/x86_64.ld"
|
||||
]
|
||||
}
|
||||
}
|
22
kernel/targets/x86_64_v3-ableos.json
Normal file
22
kernel/targets/x86_64_v3-ableos.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"panic-strategy": "abort",
|
||||
"disable-redzone": true,
|
||||
"features": "+sse4.1,+avx,+aes,+fma,+popcnt,+bmi2,+avx2,+lzcnt,+xsave",
|
||||
"code-model": "kernel",
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"--gc-sections",
|
||||
"--script=kernel/lds/x86_64.ld"
|
||||
]
|
||||
}
|
||||
}
|
2
known_bugs.md
Normal file
2
known_bugs.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# i did not know where to put this
|
||||
- memcpy / memset cause crash on debug builds due to ptr misalignment that is not present on release builds
|
|
@ -6,24 +6,15 @@ edition = "2021"
|
|||
[dependencies]
|
||||
str-reader = "0.1"
|
||||
derive_more = { version = "1", default-features = false, features = [
|
||||
"add",
|
||||
"add_assign",
|
||||
"constructor",
|
||||
"display",
|
||||
"from",
|
||||
"into",
|
||||
"mul",
|
||||
"mul_assign",
|
||||
"not",
|
||||
"sum",
|
||||
"display",
|
||||
] }
|
||||
error-stack = "0.5"
|
||||
fatfs = "0.3"
|
||||
fatfs = { version = "0.3", default-features = false, features = [
|
||||
"std",
|
||||
"alloc",
|
||||
] }
|
||||
toml = "0.8"
|
||||
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["rustls-tls", "blocking"]
|
||||
log = "0.4"
|
||||
raw-cpuid = "11"
|
||||
ureq = { version = "2", default-features = false, features = ["tls"] }
|
||||
|
|
|
@ -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,57 +48,79 @@ impl Package {
|
|||
let mut binaries = vec![];
|
||||
|
||||
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
||||
// if count != 0 {
|
||||
println!("{}", name);
|
||||
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) {
|
||||
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);
|
||||
let mut bytes = Vec::new();
|
||||
// compile here
|
||||
|
||||
let _ = hblang::run_compiler(
|
||||
let mut warnings = String::new();
|
||||
|
||||
hblang::run_compiler(
|
||||
&path,
|
||||
Options {
|
||||
fmt: true,
|
||||
in_house_regalloc: true,
|
||||
..Default::default()
|
||||
},
|
||||
&mut bytes,
|
||||
);
|
||||
let _ = hblang::run_compiler(&path, Default::default(), &mut bytes);
|
||||
out,
|
||||
&mut warnings,
|
||||
)?;
|
||||
|
||||
match std::fs::create_dir("target/programs") {
|
||||
Ok(_) => (),
|
||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||
Err(e) => panic!("{}", e),
|
||||
}
|
||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
|
||||
bytes.clear();
|
||||
let _ = hblang::run_compiler(
|
||||
|
||||
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();
|
||||
|
||||
hblang::run_compiler(
|
||||
&path,
|
||||
Options {
|
||||
dump_asm: true,
|
||||
in_house_regalloc: true,
|
||||
..Default::default()
|
||||
},
|
||||
&mut bytes,
|
||||
);
|
||||
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
|
||||
out,
|
||||
&mut warnings,
|
||||
)?;
|
||||
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
|
||||
out.clear();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
// #![allow(unused)]
|
||||
|
||||
mod dev;
|
||||
|
||||
use {
|
||||
core::fmt::Write as _,
|
||||
derive_more::Display,
|
||||
dev::Package,
|
||||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||
std::{
|
||||
// fmt::Display,
|
||||
fs::{self, File},
|
||||
io::{self, Write},
|
||||
path::Path,
|
||||
process::{exit, Command},
|
||||
process::{exit, Command, Stdio},
|
||||
},
|
||||
toml::Value,
|
||||
};
|
||||
|
@ -21,6 +19,9 @@ fn main() -> Result<(), Error> {
|
|||
let mut args = std::env::args();
|
||||
args.next();
|
||||
|
||||
log::set_logger(&hblang::Logger).unwrap();
|
||||
log::set_max_level(log::LevelFilter::Error);
|
||||
|
||||
match args.next().as_deref() {
|
||||
Some("build" | "b") => {
|
||||
let mut release = false;
|
||||
|
@ -35,6 +36,8 @@ fn main() -> Result<(), Error> {
|
|||
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));
|
||||
}
|
||||
|
@ -46,6 +49,7 @@ fn main() -> Result<(), Error> {
|
|||
let mut release = false;
|
||||
let mut debuginfo = false;
|
||||
let mut target = Target::X86_64;
|
||||
let mut do_accel = true;
|
||||
for arg in args {
|
||||
if arg == "-r" || arg == "--release" {
|
||||
release = true;
|
||||
|
@ -55,13 +59,17 @@ fn main() -> Result<(), Error> {
|
|||
target = Target::Riscv64Virt;
|
||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||
target = Target::Aarch64;
|
||||
} else if arg == "--noaccel" {
|
||||
do_accel = false;
|
||||
} else if arg == "avx2" {
|
||||
target = Target::X86_64Avx2;
|
||||
} else {
|
||||
return Err(report!(Error::InvalidSubCom));
|
||||
}
|
||||
}
|
||||
|
||||
build(release, target, debuginfo)?;
|
||||
run(release, target)
|
||||
run(release, target, do_accel)
|
||||
}
|
||||
Some("help" | "h") => {
|
||||
println!(concat!(
|
||||
|
@ -71,8 +79,10 @@ fn main() -> Result<(), Error> {
|
|||
" help (h): Print this message\n",
|
||||
" run (r): Build and run AbleOS in QEMU\n\n",
|
||||
"Options for build and run:\n",
|
||||
" -r: build in release mode",
|
||||
" [target]: sets target"
|
||||
" -r / --release: build in release mode\n",
|
||||
" -d / --debuginfo: build with debug info\n",
|
||||
" --noaccel: run without acceleration (e.g, no kvm)\n",
|
||||
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
|
||||
),);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -195,21 +205,43 @@ TERM_BACKDROP={}
|
|||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||
// let mut real_modules = modules.clone();
|
||||
|
||||
modules.into_iter().for_each(|(_, value)| {
|
||||
if value.is_table() {
|
||||
let path = get_path_without_boot_prefix(
|
||||
value.get("path").expect("You must have `path` as a value"),
|
||||
)
|
||||
.unwrap()
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap();
|
||||
let p = Package::load_from_file(
|
||||
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
||||
);
|
||||
p.build();
|
||||
}
|
||||
});
|
||||
let mut errors = String::new();
|
||||
let mut out = Vec::new();
|
||||
|
||||
modules
|
||||
.into_iter()
|
||||
.map(|(_, value)| -> Result<(), io::Error> {
|
||||
if value.is_table() {
|
||||
let path = get_path_without_boot_prefix(
|
||||
value.get("path").expect("You must have `path` as a value"),
|
||||
)
|
||||
.unwrap()
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap();
|
||||
let p = Package::load_from_file(
|
||||
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
||||
);
|
||||
match p.build(&mut out) {
|
||||
Ok(()) => {}
|
||||
Err(_) => {
|
||||
writeln!(errors, "========= while compiling {} =========", path)
|
||||
.unwrap();
|
||||
errors.push_str(core::str::from_utf8(&out).expect("no"));
|
||||
out.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.for_each(drop);
|
||||
|
||||
if !errors.is_empty() {
|
||||
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
|
||||
std::eprint!("{errors}");
|
||||
continue;
|
||||
}
|
||||
|
||||
modules.into_iter().for_each(|(_key, value)| {
|
||||
if value.is_table() {
|
||||
let path = value.get("path").expect("You must have `path` as a value");
|
||||
|
@ -296,6 +328,9 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
|||
if target == Target::Aarch64 {
|
||||
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
||||
}
|
||||
if target == Target::X86_64Avx2 {
|
||||
com.args(["--target", "targets/x86_64_v3-ableos.json"]);
|
||||
}
|
||||
|
||||
match com.status() {
|
||||
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
||||
|
@ -309,6 +344,10 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
|||
path.push_str("_x86-64");
|
||||
"target/x86_64-ableos"
|
||||
}
|
||||
Target::X86_64Avx2 => {
|
||||
path.push_str("_x86-64");
|
||||
"target/x86_64_v3-ableos"
|
||||
}
|
||||
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
||||
Target::Aarch64 => {
|
||||
path.push_str("_aarch64");
|
||||
|
@ -331,25 +370,68 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
|||
.change_context(Error::Io)
|
||||
}
|
||||
|
||||
fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||
let mut com = match target {
|
||||
Target::X86_64 => Command::new("qemu-system-x86_64"),
|
||||
Target::Riscv64Virt => Command::new("qemu-system-riscv64"),
|
||||
Target::Aarch64 => Command::new("qemu-system-aarch64"),
|
||||
fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
||||
let target_str = match target {
|
||||
Target::X86_64 | Target::X86_64Avx2 => "qemu-system-x86_64",
|
||||
Target::Riscv64Virt => "qemu-system-riscv64",
|
||||
Target::Aarch64 => "qemu-system-aarch64",
|
||||
};
|
||||
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"])
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait_with_output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cpuid = raw_cpuid::CpuId::new();
|
||||
let vmx = cpuid.get_feature_info().unwrap().has_vmx();
|
||||
let svm = cpuid.get_svm_info().is_some();
|
||||
|
||||
if supported.contains("kvm") && (vmx || svm) {
|
||||
"accel=kvm"
|
||||
} else if cpuid
|
||||
.get_processor_brand_string()
|
||||
.filter(|a| a.as_str() == "GenuineIntel")
|
||||
.is_some()
|
||||
&& supported.contains("hax")
|
||||
&& vmx
|
||||
{
|
||||
"accel=hax"
|
||||
} else if supported.contains("whpx") {
|
||||
"accel=whpx"
|
||||
} else {
|
||||
"accel=tcg"
|
||||
}
|
||||
} else {
|
||||
"accel=tcg"
|
||||
};
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
let accel = "accel=tcg";
|
||||
|
||||
match target {
|
||||
Target::X86_64 => {
|
||||
Target::X86_64 | Target::X86_64Avx2 => {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||
"-drive", "file=target/disk.img,format=raw",
|
||||
"-m", "4G",
|
||||
"-smp", "cores=4",
|
||||
"-enable-kvm",
|
||||
"-cpu", "host",
|
||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04"
|
||||
"-device", "vmware-svga",
|
||||
// "-serial", "stdio",
|
||||
"-m", "2G",
|
||||
"-smp", "1",
|
||||
"-parallel", "none",
|
||||
"-monitor", "none",
|
||||
"-machine", accel,
|
||||
"-cpu", "max",
|
||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
]);
|
||||
}
|
||||
Target::Riscv64Virt => {
|
||||
|
@ -393,7 +475,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
|
||||
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||
let (ovmf_url, ovmf_path) = match target {
|
||||
Target::X86_64 => (
|
||||
Target::X86_64 | Target::X86_64Avx2 => (
|
||||
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
|
||||
"target/RELEASEX64_OVMF.fd",
|
||||
),
|
||||
|
@ -415,12 +497,12 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
|||
Ok(_) => return Ok(ovmf_path.to_owned()),
|
||||
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
||||
};
|
||||
let mut bytes = reqwest::blocking::get(ovmf_url)
|
||||
let req = ureq::get(ovmf_url)
|
||||
.call()
|
||||
.map_err(Report::from)
|
||||
.change_context(OvmfFetchError::Fetch)?;
|
||||
|
||||
bytes
|
||||
.copy_to(&mut file)
|
||||
std::io::copy(&mut req.into_reader(), &mut file)
|
||||
.map_err(Report::from)
|
||||
.change_context(OvmfFetchError::Io)?;
|
||||
|
||||
|
@ -442,6 +524,7 @@ impl Context for OvmfFetchError {}
|
|||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Target {
|
||||
X86_64,
|
||||
X86_64Avx2,
|
||||
Riscv64Virt,
|
||||
Aarch64,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-07-27"
|
||||
# old toolchain
|
||||
# channel = "nightly-2024-07-27"
|
||||
channel = "nightly"
|
||||
components = ["rust-src", "llvm-tools"]
|
||||
|
|
BIN
sysdata/assets/able.bmp
Normal file
BIN
sysdata/assets/able.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
sysdata/assets/consolefonts/tamsyn/10x20b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/10x20b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/10x20r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/10x20r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/5x9b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/5x9b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/5x9r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/5x9r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/6x12b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/6x12b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/6x12r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/6x12r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x13b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x13b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x13r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x13r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x14b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x14b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x14r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x14r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x15b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x15b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x15r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x15r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x16b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x16b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x16r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x16r.psf
Normal file
Binary file not shown.
10
sysdata/assets/consolefonts/tamsyn/LICENSE
Normal file
10
sysdata/assets/consolefonts/tamsyn/LICENSE
Normal file
|
@ -0,0 +1,10 @@
|
|||
Tamsyn font is free. You are hereby granted permission to use, copy, modify,
|
||||
and distribute it as you see fit.
|
||||
|
||||
Tamsyn font is provided "as is" without any express or implied warranty.
|
||||
|
||||
The author makes no representations about the suitability of this font for
|
||||
a particular purpose.
|
||||
|
||||
In no event will the author be held liable for damages arising from the use
|
||||
of this font.
|
BIN
sysdata/assets/mini.bmp
Normal file
BIN
sysdata/assets/mini.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
sysdata/assets/mini.qoi
Normal file
BIN
sysdata/assets/mini.qoi
Normal file
Binary file not shown.
BIN
sysdata/assets/wallpaper.qoi
Normal file
BIN
sysdata/assets/wallpaper.qoi
Normal file
Binary file not shown.
BIN
sysdata/empty-background.bmp
Normal file
BIN
sysdata/empty-background.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 B |
|
@ -1,2 +0,0 @@
|
|||
protocol abc {
|
||||
}
|
24
sysdata/idl/log/src/protocol.aidl
Normal file
24
sysdata/idl/log/src/protocol.aidl
Normal file
|
@ -0,0 +1,24 @@
|
|||
@auto_increment
|
||||
enum LogLevel {
|
||||
Error = 0,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
@auto_increment
|
||||
enum LogResult {
|
||||
Err = 0,
|
||||
Ok,
|
||||
}
|
||||
|
||||
struct Log {
|
||||
log_level: LogLevel,
|
||||
}
|
||||
|
||||
@visibility(public)
|
||||
protocol Log {
|
||||
fn log(Log) -> LogResult;
|
||||
fn flush() -> LogResult;
|
||||
}
|
4
sysdata/libraries/horizon_api/examples/horizontal.lui
Normal file
4
sysdata/libraries/horizon_api/examples/horizontal.lui
Normal file
|
@ -0,0 +1,4 @@
|
|||
(horizontal
|
||||
spacing : 10
|
||||
(label "hi")
|
||||
(label "goodbye"))
|
1
sysdata/libraries/horizon_api/examples/label.lui
Normal file
1
sysdata/libraries/horizon_api/examples/label.lui
Normal file
|
@ -0,0 +1 @@
|
|||
(label "hello")
|
3
sysdata/libraries/horizon_api/examples/vertical.lui
Normal file
3
sysdata/libraries/horizon_api/examples/vertical.lui
Normal file
|
@ -0,0 +1,3 @@
|
|||
(vertical
|
||||
(label "hello")
|
||||
(label "hello" color:red))
|
|
@ -1,14 +0,0 @@
|
|||
Element := struct {
|
||||
width: int,
|
||||
height: int,
|
||||
|
||||
x: u16,
|
||||
y: u16,
|
||||
|
||||
id: int,
|
||||
}
|
||||
|
||||
create_element := fn(): Element {
|
||||
return Element.(0, 0, 0, 0, 0)
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
FrameID := struct {
|
||||
|
||||
}
|
|
@ -1,12 +1,49 @@
|
|||
stn := @use("../../stn/src/lib.hb");
|
||||
.{string, memory, buffer, log} := stn
|
||||
|
||||
render := @use("../../../libraries/render/src/lib.hb")
|
||||
|
||||
input := @use("../../intouch/src/lib.hb")
|
||||
|
||||
widgets := @use("widgets/widgets.hb")
|
||||
ui := @use("ui.hb")
|
||||
|
||||
WindowID := struct {
|
||||
host_id: int,
|
||||
window_id: int,
|
||||
}
|
||||
|
||||
create_window := fn(): WindowID {
|
||||
return WindowID.(1, 2)
|
||||
}
|
||||
VoidWindowID := WindowID.(0, 0)
|
||||
|
||||
update_ui := fn(window_id: WindowID): void {
|
||||
return
|
||||
create_window := fn(channel: int): ^render.Surface {
|
||||
// get the horizon buffer
|
||||
// request a new window and provide the callback buffer
|
||||
// wait to recieve a message
|
||||
|
||||
windowing_system_buffer := buffer.search("XHorizon\0")
|
||||
mem_buf := memory.request_page(1)
|
||||
|
||||
if windowing_system_buffer == 0 {
|
||||
return @as(^render.Surface, idk)
|
||||
} else {
|
||||
// ! bad able, stop using string messages :ragey:
|
||||
// msg := "\{01}\0"
|
||||
// msg_length := 2
|
||||
|
||||
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
|
||||
|
||||
x := 0
|
||||
loop if x > 1000 break else x += 1
|
||||
|
||||
ret := buffer.recv([u8; 4096], windowing_system_buffer, mem_buf)
|
||||
if ret == null {
|
||||
log.info("No messages\0")
|
||||
}
|
||||
|
||||
if *mem_buf == 0 {
|
||||
log.info("No messages\0")
|
||||
}
|
||||
|
||||
return @as(^render.Surface, idk)
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
ui_lisp_text_example := "(text id_1)\0";
|
||||
|
||||
|
47
sysdata/libraries/horizon_api/src/ui.hb
Normal file
47
sysdata/libraries/horizon_api/src/ui.hb
Normal file
|
@ -0,0 +1,47 @@
|
|||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{string, log} := stn;
|
||||
.{Vec2} := stn.math
|
||||
|
||||
render := @use("../../../libraries/render/src/lib.hb");
|
||||
.{Surface} := render;
|
||||
.{Font} := render.text
|
||||
|
||||
UI := struct {raw: ^u8, raw_length: uint, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
|
||||
// children: ^^u8,
|
||||
}
|
||||
|
||||
render_ui := fn(surface: Surface, ui: UI): void {
|
||||
if ui.is_dirty {
|
||||
render.clear(ui.surface, render.black)
|
||||
ui.is_dirty = false
|
||||
}
|
||||
pos := Vec2(uint).(0, 0)
|
||||
render.put_surface(surface, ui.surface, pos, false)
|
||||
}
|
||||
|
||||
sexpr_parser := fn(sexpr: ^u8): UI {
|
||||
cursor := sexpr
|
||||
paren_balance := 0
|
||||
loop {
|
||||
if *cursor == 0 {
|
||||
if paren_balance != 0 {
|
||||
log.error("Unbalanced Parens\0")
|
||||
}
|
||||
break
|
||||
} else if *cursor == 40 {
|
||||
log.info("Open paren\0")
|
||||
paren_balance += 1
|
||||
} else if *cursor == 41 {
|
||||
log.info("Closed paren\0")
|
||||
paren_balance -= 1
|
||||
}
|
||||
|
||||
cursor += 1
|
||||
}
|
||||
|
||||
length := string.length(sexpr)
|
||||
|
||||
ui_surface := render.new_surface(100, 100)
|
||||
|
||||
return UI.(sexpr, length, true, ui_surface)
|
||||
}
|
13
sysdata/libraries/horizon_api/src/widgets/image.hb
Normal file
13
sysdata/libraries/horizon_api/src/widgets/image.hb
Normal file
|
@ -0,0 +1,13 @@
|
|||
render := @use("../../../../libraries/render/src/lib.hb");
|
||||
.{Surface} := render
|
||||
|
||||
Image := struct {
|
||||
magic: uint,
|
||||
is_dirty: bool,
|
||||
surface: Surface,
|
||||
}
|
||||
|
||||
image_from_surface := fn(surface: Surface): Image {
|
||||
img := Image.(4, true, surface)
|
||||
return img
|
||||
}
|
46
sysdata/libraries/horizon_api/src/widgets/label.hb
Normal file
46
sysdata/libraries/horizon_api/src/widgets/label.hb
Normal file
|
@ -0,0 +1,46 @@
|
|||
stn := @use("../../../../libraries/stn/src/lib.hb");
|
||||
.{string, log} := stn;
|
||||
.{Vec2} := stn.math
|
||||
|
||||
render := @use("../../../../libraries/render/src/lib.hb");
|
||||
.{Surface, Color} := render;
|
||||
.{Font} := render.text
|
||||
|
||||
Label := struct {
|
||||
magic: uint,
|
||||
is_dirty: bool,
|
||||
surface: Surface,
|
||||
text: ^u8,
|
||||
text_length: uint,
|
||||
bg: Color,
|
||||
fg: Color,
|
||||
}
|
||||
|
||||
set_label_text := fn(label: Label, text: ^u8): void {
|
||||
text_length := string.length(text)
|
||||
|
||||
label.is_dirty = true
|
||||
label.text = text
|
||||
label.text_length = text_length
|
||||
}
|
||||
|
||||
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
|
||||
if label.is_dirty {
|
||||
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)
|
||||
}
|
||||
|
||||
new_label := fn(text: ^u8): Label {
|
||||
text_surface := render.new_surface(1024, 20)
|
||||
text_length := string.length(text)
|
||||
label := Label.(3, true, text_surface, text, text_length, render.black, render.white)
|
||||
return label
|
||||
}
|
||||
|
||||
$set_color := fn(label: Label, bg: Color, fg: Color): void {
|
||||
label.bg = bg
|
||||
label.fg = fg
|
||||
label.is_dirty = true
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
NoWidget := 0
|
||||
|
||||
VerticalWidgetType := 1
|
||||
HorizontalWidgetType := 2
|
||||
|
||||
LabelWidgetType := 3
|
||||
ImageWidgetType := 4
|
36
sysdata/libraries/horizon_api/src/widgets/widgets.hb
Normal file
36
sysdata/libraries/horizon_api/src/widgets/widgets.hb
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Widget types
|
||||
|
||||
// End types
|
||||
stn := @use("../../../../libraries/stn/src/lib.hb");
|
||||
.{string, log} := stn;
|
||||
.{Vec2} := stn.math
|
||||
|
||||
render := @use("../../../../libraries/render/src/lib.hb");
|
||||
.{Surface} := render;
|
||||
.{Font} := render.text
|
||||
|
||||
widget_types := @use("widget_types.hb")
|
||||
label := @use("label.hb")
|
||||
image := @use("image.hb")
|
||||
|
||||
Size := struct {
|
||||
min_width: int,
|
||||
max_width: int,
|
||||
min_height: int,
|
||||
max_height: int,
|
||||
}
|
||||
|
||||
Vertical := packed struct {
|
||||
magic: uint,
|
||||
// array of children, idk
|
||||
// use a vec or linked list or whatever
|
||||
|
||||
children: ^^u8,
|
||||
}
|
||||
|
||||
Horizontal := packed struct {
|
||||
magic: uint,
|
||||
// array of children, idk
|
||||
// use a vec or linked list or whatever
|
||||
children: ^^u8,
|
||||
}
|
21
sysdata/libraries/ignim/src/application.hb
Normal file
21
sysdata/libraries/ignim/src/application.hb
Normal file
|
@ -0,0 +1,21 @@
|
|||
structures := @use("structures.hb")
|
||||
version := @use("version.hb")
|
||||
|
||||
// Refer to here https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkApplicationInfo.html
|
||||
ApplicationInfo := struct {
|
||||
sType: int,
|
||||
pNext: ^int,
|
||||
application_name: ^u8,
|
||||
application_version: int,
|
||||
engine_name: ^u8,
|
||||
engine_version: int,
|
||||
api_version: int,
|
||||
}
|
||||
|
||||
new_application_info := fn(app_name: ^u8, app_version: int, engine_name: ^u8, engine_version: int, api_version: int): ApplicationInfo {
|
||||
app_info_type := structures.ApplicationInfoType
|
||||
|
||||
app_info := ApplicationInfo.(app_info_type, 0, app_name, app_version, engine_name, engine_version, api_version)
|
||||
|
||||
return app_info
|
||||
}
|
14
sysdata/libraries/ignim/src/errors.hb
Normal file
14
sysdata/libraries/ignim/src/errors.hb
Normal file
|
@ -0,0 +1,14 @@
|
|||
OutOfHostMemory := -1
|
||||
OutOfDeviceMemory := -2
|
||||
InitializationFailed := -3
|
||||
DeviceLost := -4
|
||||
MemoryMapFailed := -5
|
||||
|
||||
LayerNotPresent := -6
|
||||
ExtensionNotPresent := -7
|
||||
FeatureNotPresent := -8
|
||||
IncompatibleDriver := -9
|
||||
TooManyObjects := -10
|
||||
FormatNotSupported := -11
|
||||
FragmentedPool := -12
|
||||
Unknown := -13
|
10
sysdata/libraries/ignim/src/extends.hb
Normal file
10
sysdata/libraries/ignim/src/extends.hb
Normal file
|
@ -0,0 +1,10 @@
|
|||
Extent3D := struct {
|
||||
width: int,
|
||||
height: int,
|
||||
depth: int,
|
||||
}
|
||||
|
||||
Extent2D := struct {
|
||||
width: int,
|
||||
height: int,
|
||||
}
|
35
sysdata/libraries/ignim/src/instance.hb
Normal file
35
sysdata/libraries/ignim/src/instance.hb
Normal file
|
@ -0,0 +1,35 @@
|
|||
application := @use("application.hb");
|
||||
.{ApplicationInfo} := application
|
||||
|
||||
structures := @use("structures.hb")
|
||||
errors := @use("errors.hb")
|
||||
|
||||
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkInstanceCreateInfo.html
|
||||
InstanceCreateInfo := struct {
|
||||
sType: int,
|
||||
pNext: int,
|
||||
flags: int,
|
||||
application_info: ^ApplicationInfo,
|
||||
enabled_layer_count: int,
|
||||
ppEnabledLayerNames: int,
|
||||
enabled_extension_count: int,
|
||||
ppEnabledExtensionNames: int,
|
||||
}
|
||||
|
||||
new_create_info := fn(application_info: ^ApplicationInfo): InstanceCreateInfo {
|
||||
create_info_type := structures.InstanceCreateInfoType
|
||||
enabled_layer_count := 0
|
||||
|
||||
create_info := InstanceCreateInfo.(create_info_type, 0, 0, application_info, enabled_layer_count, 0, 0, 0)
|
||||
return create_info
|
||||
}
|
||||
|
||||
// TODO
|
||||
Instance := struct {inner: int}
|
||||
void_instance := fn(): Instance {
|
||||
return Instance.(0)
|
||||
}
|
||||
|
||||
create_instance := fn(create_info: ^InstanceCreateInfo, allocator_callback: int, new_obj: ^Instance): int {
|
||||
return errors.IncompatibleDriver
|
||||
}
|
|
@ -1,7 +1,17 @@
|
|||
VK_VERSION_MAJOR := 1;
|
||||
VK_VERSION_MINOR := 0;
|
||||
application := @use("application.hb")
|
||||
|
||||
init_vulkan := fn(): void {
|
||||
|
||||
return
|
||||
results := @use("results.hb")
|
||||
errors := @use("errors.hb")
|
||||
|
||||
offsets := @use("offset.hb")
|
||||
extends := @use("extends.hb")
|
||||
|
||||
rect := @use("rect.hb")
|
||||
structures := @use("structures.hb")
|
||||
instance := @use("instance.hb")
|
||||
|
||||
version := @use("version.hb")
|
||||
|
||||
init_vulkan := fn(): int {
|
||||
return errors.IncompatibleDriver
|
||||
}
|
10
sysdata/libraries/ignim/src/offset.hb
Normal file
10
sysdata/libraries/ignim/src/offset.hb
Normal file
|
@ -0,0 +1,10 @@
|
|||
Offset3D := struct {
|
||||
x: int,
|
||||
y: int,
|
||||
z: int,
|
||||
}
|
||||
|
||||
Offset2D := struct {
|
||||
x: int,
|
||||
y: int,
|
||||
}
|
7
sysdata/libraries/ignim/src/rect.hb
Normal file
7
sysdata/libraries/ignim/src/rect.hb
Normal file
|
@ -0,0 +1,7 @@
|
|||
offsets := @use("offset.hb")
|
||||
extends := @use("extends.hb")
|
||||
|
||||
Rect2D := struct {
|
||||
offset: offsets.Offset2D,
|
||||
extent: extends.Extent2D,
|
||||
}
|
7
sysdata/libraries/ignim/src/results.hb
Normal file
7
sysdata/libraries/ignim/src/results.hb
Normal file
|
@ -0,0 +1,7 @@
|
|||
// NonErrors
|
||||
Success := 0
|
||||
NotReady := 1
|
||||
Timeout := 2
|
||||
EventSet := 3
|
||||
EventReset := 4
|
||||
Incomplete := 5
|
61
sysdata/libraries/ignim/src/structures.hb
Normal file
61
sysdata/libraries/ignim/src/structures.hb
Normal file
|
@ -0,0 +1,61 @@
|
|||
ApplicationInfoType := 0
|
||||
InstanceCreateInfoType := 1
|
||||
DeviceQueueCreateInfo := 2
|
||||
DeviceCreateInfo := 3
|
||||
SubmitInfo := 4
|
||||
MemoryAllocateInfo := 5
|
||||
MappedMemoryRange := 6
|
||||
BindSparseInfo := 7
|
||||
|
||||
FenceCreateInfo := 8
|
||||
SemaphoreCreateInfo := 9
|
||||
EventCreateInfo := 10
|
||||
QueryPoolCreateInfo := 11
|
||||
|
||||
BufferCreateInfo := 12
|
||||
BufferViewCreateInfo := 13
|
||||
|
||||
ImageCreateInfo := 14
|
||||
ImageViewCreateInfo := 15
|
||||
|
||||
ShaderModuleCreateInfo := 16
|
||||
|
||||
PipelineCacheCreateInfo := 17
|
||||
PipelineShaderStageCreateInfo := 18
|
||||
PipelineVertexInputStateCreateInfo := 19
|
||||
PipelineInputAssemblyStateCreateInfo := 20
|
||||
PipelineTessellationStateCreateInfo := 21
|
||||
PipelineViewportStateCreateInfo := 22
|
||||
PipelineRasterizationStateCreateInfo := 23
|
||||
PipelineMultisampleStateCreateInfo := 24
|
||||
PipelineDepthStencilStateCreateInfo := 25
|
||||
PipelineColorBlendStateCreateInfo := 26
|
||||
PipelineDynamicStateCreateInfo := 27
|
||||
|
||||
GraphicsPipelineCreateInfo := 28
|
||||
ComputePipelineCreateInfo := 29
|
||||
PipelineLayoutCreateInfo := 30
|
||||
SamplerCreateInfo := 31
|
||||
|
||||
DescriptorSetLayoutCreateInfo := 32
|
||||
DescriptorPoolCreateInfo := 33
|
||||
|
||||
DescriptorSetAllocateInfo := 34
|
||||
WriteDescriptorSet := 35
|
||||
CopyDescriptorSet := 36
|
||||
FramebufferCreateInfo := 37
|
||||
|
||||
RenderPassCreateInfo := 38
|
||||
CommandPoolCreateInfo := 39
|
||||
|
||||
CommandBufferAllocateInfo := 40
|
||||
CommandBufferInheritanceInfo := 41
|
||||
CommandBufferBeginInfo := 42
|
||||
|
||||
RenderPassBeginInfo := 43
|
||||
BufferMemoryBarrier := 44
|
||||
ImageMemoryBarrier := 45
|
||||
MemoryBarrier := 46
|
||||
|
||||
LoaderInstanceCreateInfo := 47
|
||||
LoaderDeviceCreateInfo := 48
|
9
sysdata/libraries/ignim/src/version.hb
Normal file
9
sysdata/libraries/ignim/src/version.hb
Normal file
|
@ -0,0 +1,9 @@
|
|||
ApiVersion1_0 := make_api_version(0, 1, 0, 0)
|
||||
|
||||
make_version := fn(major: int, minor: int, patch: int): int {
|
||||
return major << 22 | minor << 12 | patch
|
||||
}
|
||||
|
||||
make_api_version := fn(variant: int, major: int, minor: int, patch: int): int {
|
||||
return variant << 29 | major << 22 | minor << 12 | patch
|
||||
}
|
20
sysdata/libraries/intouch/README.md
Normal file
20
sysdata/libraries/intouch/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# intouch
|
||||
This library is exclusively focused on allowing your to get input regardless of which devices you have.
|
||||
|
||||
Partially modeled after SDL.
|
||||
|
||||
Current goals include
|
||||
- Interfaces
|
||||
- PS/2
|
||||
- Device Types
|
||||
- Keyboard
|
||||
- Mouse
|
||||
|
||||
Longer Term goals
|
||||
- Interfaces
|
||||
- USB
|
||||
- USB-HID
|
||||
- Device Types
|
||||
- Gamepads/controllers
|
||||
- Drawing Tablets
|
||||
- Microphones
|
2
sysdata/libraries/intouch/key_maps/ps2.map
Normal file
2
sysdata/libraries/intouch/key_maps/ps2.map
Normal file
|
@ -0,0 +1,2 @@
|
|||
0x0D -> press Tab
|
||||
0xF0 0x0D -> release Tab
|
18
sysdata/libraries/intouch/src/events.hb
Normal file
18
sysdata/libraries/intouch/src/events.hb
Normal file
|
@ -0,0 +1,18 @@
|
|||
keycodes := @use("keycodes.hb");
|
||||
.{KeyCode} := keycodes
|
||||
|
||||
KeyEvent := packed struct {
|
||||
up: bool,
|
||||
just_triggered: bool,
|
||||
key: KeyCode,
|
||||
}
|
||||
|
||||
MouseEvent := packed struct {
|
||||
x_change: i8,
|
||||
y_change: i8,
|
||||
left: bool,
|
||||
middle: bool,
|
||||
right: bool,
|
||||
}
|
||||
|
||||
GamepadEvent := struct {}
|
121
sysdata/libraries/intouch/src/keycodes.hb
Normal file
121
sysdata/libraries/intouch/src/keycodes.hb
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Originally I was modelling this after the following(1). I have since changed my mind.
|
||||
I am now modelling it as I see fit. This is likely not the final version.
|
||||
|
||||
1) https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
||||
*/
|
||||
|
||||
KeyCode := u32
|
||||
|
||||
// Typically this is not a keycode you will ever recieve.
|
||||
None := KeyCode.(0)
|
||||
|
||||
Escape := KeyCode.(1)
|
||||
/* Alphabet keycodes */
|
||||
|
||||
A := KeyCode.(2)
|
||||
B := KeyCode.(3)
|
||||
C := KeyCode.(4)
|
||||
D := KeyCode.(5)
|
||||
E := KeyCode.(6)
|
||||
F := KeyCode.(7)
|
||||
G := KeyCode.(8)
|
||||
H := KeyCode.(9)
|
||||
I := KeyCode.(10)
|
||||
J := KeyCode.(11)
|
||||
K := KeyCode.(12)
|
||||
L := KeyCode.(13)
|
||||
M := KeyCode.(14)
|
||||
N := KeyCode.(15)
|
||||
O := KeyCode.(16)
|
||||
P := KeyCode.(17)
|
||||
Q := KeyCode.(18)
|
||||
R := KeyCode.(19)
|
||||
S := KeyCode.(20)
|
||||
T := KeyCode.(21)
|
||||
U := KeyCode.(22)
|
||||
V := KeyCode.(23)
|
||||
W := KeyCode.(24)
|
||||
X := KeyCode.(25)
|
||||
Y := KeyCode.(26)
|
||||
Z := KeyCode.(27)
|
||||
|
||||
/* Numeric keycodes*/
|
||||
|
||||
Number0 := KeyCode.(28)
|
||||
Number1 := KeyCode.(29)
|
||||
Number2 := KeyCode.(30)
|
||||
Number3 := KeyCode.(31)
|
||||
Number4 := KeyCode.(32)
|
||||
Number5 := KeyCode.(33)
|
||||
Number6 := KeyCode.(34)
|
||||
Number7 := KeyCode.(35)
|
||||
Number8 := KeyCode.(36)
|
||||
Number9 := KeyCode.(37)
|
||||
|
||||
KeypadNumber0 := KeyCode.(38)
|
||||
KeypadNumber1 := KeyCode.(39)
|
||||
KeypadNumber2 := KeyCode.(40)
|
||||
KeypadNumber3 := KeyCode.(41)
|
||||
KeypadNumber4 := KeyCode.(42)
|
||||
KeypadNumber5 := KeyCode.(43)
|
||||
KeypadNumber6 := KeyCode.(44)
|
||||
KeypadNumber7 := KeyCode.(45)
|
||||
KeypadNumber8 := KeyCode.(46)
|
||||
KeypadNumber9 := KeyCode.(47)
|
||||
|
||||
KeypadPeriod := KeyCode.(48)
|
||||
KeypadDivide := KeyCode.(49)
|
||||
KeypadMultiply := KeyCode.(50)
|
||||
KeypadMinus := KeyCode.(51)
|
||||
KeypadPlus := KeyCode.(52)
|
||||
KeypadEnter := KeyCode.(53)
|
||||
KeypadEquals := KeyCode.(54)
|
||||
|
||||
Delete := KeyCode.(55)
|
||||
/* Locking Keys */
|
||||
NumLock := KeyCode.(56)
|
||||
CapsLock := KeyCode.(57)
|
||||
ScrollLock := KeyCode.(58)
|
||||
|
||||
/* "Alt Gr" key */
|
||||
Mode := KeyCode.(59)
|
||||
|
||||
/* Multi-key compose key */
|
||||
Compose := KeyCode.(60)
|
||||
|
||||
LeftAlt := KeyCode.(61)
|
||||
LeftControl := KeyCode.(62)
|
||||
LeftMeta := KeyCode.(63)
|
||||
LeftShift := KeyCode.(64)
|
||||
/* Left "Windows" key */
|
||||
LeftSuper := KeyCode.(65)
|
||||
|
||||
RightAlt := KeyCode.(66)
|
||||
RightControl := KeyCode.(67)
|
||||
RightMeta := KeyCode.(68)
|
||||
RightShift := KeyCode.(69)
|
||||
/* Right "Windows" key */
|
||||
RightSuper := KeyCode.(70)
|
||||
|
||||
/*
|
||||
This block of any triggers on any press of any of the keys.
|
||||
Typically this is the event to care about.
|
||||
*/
|
||||
AnyNumber0 := KeyCode.(71)
|
||||
AnyNumber1 := KeyCode.(72)
|
||||
AnyNumber2 := KeyCode.(73)
|
||||
AnyNumber3 := KeyCode.(74)
|
||||
AnyNumber4 := KeyCode.(75)
|
||||
AnyNumber5 := KeyCode.(76)
|
||||
AnyNumber6 := KeyCode.(77)
|
||||
AnyNumber7 := KeyCode.(78)
|
||||
AnyNumber8 := KeyCode.(79)
|
||||
AnyNumber9 := KeyCode.(80)
|
||||
|
||||
AnyAlt := KeyCode.(81)
|
||||
AnyControl := KeyCode.(82)
|
||||
AnyMeta := KeyCode.(83)
|
||||
AnyShift := KeyCode.(84)
|
||||
/* Any "Windows" key */
|
||||
AnySuper := KeyCode.(85)
|
36
sysdata/libraries/intouch/src/lib.hb
Normal file
36
sysdata/libraries/intouch/src/lib.hb
Normal file
|
@ -0,0 +1,36 @@
|
|||
stn := @use("../../stn/src/lib.hb");
|
||||
.{log, buffer, memory} := stn
|
||||
keycodes := @use("keycodes.hb")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
recieve_mouse_event := fn(): ?MouseEvent {
|
||||
mevent := MouseEvent.(0, 0, false, false, false)
|
||||
|
||||
buf_id := buffer.search("PS/2 Mouse\0")
|
||||
|
||||
// Read out of the Mouse buffer here
|
||||
buffer.recv(MouseEvent, buf_id, &mevent)
|
||||
|
||||
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
|
||||
return mevent
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
1
sysdata/libraries/pci/README.md
Normal file
1
sysdata/libraries/pci/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# pci
|
93
sysdata/libraries/pci/src/lib.hb
Normal file
93
sysdata/libraries/pci/src/lib.hb
Normal file
|
@ -0,0 +1,93 @@
|
|||
.{string, memory, buffer, log} := @use("../../stn/src/lib.hb")
|
||||
|
||||
PCIAddress := struct {
|
||||
bus: u8,
|
||||
device: u8,
|
||||
function: u8,
|
||||
}
|
||||
|
||||
PCI_ID := struct {
|
||||
vendor: u16,
|
||||
device: u16,
|
||||
inner: int,
|
||||
}
|
||||
|
||||
get_ids := fn(bus: u8, device: u8, function: u8): PCI_ID {
|
||||
res := config_read32(bus, device, function, 0)
|
||||
dev_id := res >> 16
|
||||
dev_id &= 0xFFFF
|
||||
|
||||
vnd_id := res & 0xFFFF
|
||||
return PCI_ID.(dev_id, vnd_id, 0)
|
||||
}
|
||||
|
||||
PciDeviceInfo := struct {
|
||||
header_type: u8,
|
||||
device: u8,
|
||||
bus: u8,
|
||||
device_id: PCI_ID,
|
||||
class: u16,
|
||||
rev_id: u8,
|
||||
}
|
||||
|
||||
calculate_address := fn(bus: u8, device: u8, function: u8, offset: u8): int {
|
||||
address := bus << 16
|
||||
address |= device << 11
|
||||
address |= function << 8
|
||||
address |= offset & 0xFC
|
||||
address |= 0x80000000
|
||||
return address
|
||||
}
|
||||
|
||||
get_header_type := fn(bus: u8, device: u8, function: u8): u8 {
|
||||
res := config_read32(bus, device, function, 0xC)
|
||||
ret := res >> 16
|
||||
ret &= 0xFF
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
check_device := fn(bus: u8, device: u8): PciDeviceInfo {
|
||||
pci_id := get_ids(bus, device, 0)
|
||||
|
||||
if pci_id.vendor == 0xFFFF {
|
||||
log.warn(":|\0")
|
||||
} else {
|
||||
log.info(":)\0")
|
||||
}
|
||||
address := calculate_address(bus, device, 0, 0x8)
|
||||
reg2 := config_read32(bus, device, 0, 0x8)
|
||||
|
||||
class := reg2 >> 16 & 0xFFFF
|
||||
|
||||
header_type := get_header_type(bus, device, 0)
|
||||
|
||||
rev_id := reg2 & 0xFF
|
||||
return PciDeviceInfo.(header_type, device, bus, pci_id, class, rev_id)
|
||||
}
|
||||
|
||||
find_device := fn(vendor_id: int, device_id: int, pci_address: PCIAddress): PCI_ID {
|
||||
pci_id := get_ids(0, 2, 0)
|
||||
|
||||
return pci_id
|
||||
}
|
||||
|
||||
scan_bus := fn(): void {
|
||||
}
|
||||
|
||||
config_read32 := fn(bus: u32, device: u32, func: u32, offset: u32): u32 {
|
||||
// construct address param
|
||||
offset_and := offset & 0xFC
|
||||
|
||||
address := bus << 16
|
||||
address |= device << 11
|
||||
address |= func << 8
|
||||
address |= offset_and
|
||||
address |= 0x80000000
|
||||
|
||||
// write address
|
||||
memory.outl(0xCF8, address)
|
||||
|
||||
// read data
|
||||
return memory.inl(0xCFC)
|
||||
}
|
27
sysdata/libraries/render/TODO.md
Normal file
27
sysdata/libraries/render/TODO.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Images
|
||||
- Animation
|
||||
|
||||
# API
|
||||
- Colour operations:
|
||||
- Alpha Composite
|
||||
- Invert
|
||||
- Surface Operations:
|
||||
- FlipH
|
||||
- Resize
|
||||
- Wrap the colour operations
|
||||
- Tile
|
||||
- Gradient overlay
|
||||
- Draw operations:
|
||||
- Curve raster algorithm
|
||||
- VGA font fast blit
|
||||
- Polygon
|
||||
- Rounded rects
|
||||
|
||||
# Backend
|
||||
- SVGA Driver
|
||||
- Support whatever vulkan stuff able is cooking
|
||||
|
||||
# Bits and bobs on the table
|
||||
- Funny 3D Renderer
|
||||
- stn.memory.swap & kernel message
|
||||
- Make memory.{copy, set} smart
|
49
sysdata/libraries/render/src/image/bmp.hb
Normal file
49
sysdata/libraries/render/src/image/bmp.hb
Normal file
|
@ -0,0 +1,49 @@
|
|||
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
|
||||
.{log} := @use("../../../stn/src/lib.hb")
|
||||
|
||||
BitmapFileHeader := packed struct {
|
||||
magic: u16,
|
||||
size: u32,
|
||||
reserved_1: u16,
|
||||
reserved_2: u16,
|
||||
offset: u32,
|
||||
}
|
||||
|
||||
BitmapInfoHeader := packed struct {
|
||||
size: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
planes: u16,
|
||||
bits: u16,
|
||||
compression: u32,
|
||||
image_size: u32,
|
||||
x_resolution: i32,
|
||||
y_resolution: i32,
|
||||
n_colours: u32,
|
||||
important_colours: u32,
|
||||
}
|
||||
|
||||
BitmapColorHeader := packed struct {
|
||||
red_mask: u32,
|
||||
green_mask: u32,
|
||||
blue_mask: u32,
|
||||
alpha_mask: u32,
|
||||
color_space_type: u32,
|
||||
unused: u32,
|
||||
}
|
||||
|
||||
from := fn(bmp: ^u8): ?Surface {
|
||||
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
||||
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
|
||||
|
||||
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
|
||||
log.error("Invalid BMP image.\0")
|
||||
return null
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
return rhs
|
||||
}
|
31
sysdata/libraries/render/src/image/lib.hb
Normal file
31
sysdata/libraries/render/src/image/lib.hb
Normal file
|
@ -0,0 +1,31 @@
|
|||
.{log} := @use("../../../stn/src/lib.hb");
|
||||
.{Surface} := @use("../lib.hb")
|
||||
bmp := @use("bmp.hb")
|
||||
qoi := @use("qoi.hb")
|
||||
$BMP := 0x4D42
|
||||
$QOI := 0x66696F71
|
||||
|
||||
get_format := fn(file: ^u8): ?uint {
|
||||
if *@as(^u16, @bitcast(file)) == BMP {
|
||||
return BMP
|
||||
} else if *@as(^u32, @bitcast(file)) == QOI {
|
||||
return QOI
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
from := fn(file: ^u8): ?Surface {
|
||||
format := get_format(file)
|
||||
|
||||
if format == null {
|
||||
log.error("Could not detect image format.\0")
|
||||
return null
|
||||
} else if format == BMP {
|
||||
return bmp.from(file)
|
||||
} else if format == QOI {
|
||||
return qoi.from(file)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
101
sysdata/libraries/render/src/image/qoi.hb
Normal file
101
sysdata/libraries/render/src/image/qoi.hb
Normal file
|
@ -0,0 +1,101 @@
|
|||
.{Color, Surface, new_surface} := @use("../lib.hb");
|
||||
.{log} := @use("../../../stn/src/lib.hb")
|
||||
|
||||
/* source:
|
||||
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
||||
|
||||
$QOI_SRGB := 0
|
||||
$QOI_LINEAR := 1
|
||||
$QOI_OP_INDEX := 0x0
|
||||
$QOI_OP_DIFF := 0x40
|
||||
$QOI_OP_LUMA := 0x80
|
||||
$QOI_OP_RUN := 0xC0
|
||||
$QOI_OP_RGB := 0xFE
|
||||
$QOI_OP_RGBA := 0xFF
|
||||
$QOI_MASK_2 := 0xC0
|
||||
$QOI_COLOR_HASH := fn(c: Color): u8 {
|
||||
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
|
||||
}
|
||||
$QOI_MAGIC := 0x716F6966
|
||||
$QOI_PIXELS_MAX := 400000000
|
||||
|
||||
QuiteOkayHeader := packed struct {
|
||||
magic: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
channels: u8,
|
||||
colorspace: u8,
|
||||
}
|
||||
|
||||
be_to_le := fn(big: u32): u32 {
|
||||
return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24
|
||||
}
|
||||
|
||||
from := fn(qoi: ^u8): ?Surface {
|
||||
header := @as(^QuiteOkayHeader, @bitcast(qoi))
|
||||
|
||||
qoi += @sizeof(QuiteOkayHeader)
|
||||
|
||||
width := be_to_le(header.width)
|
||||
height := be_to_le(header.height)
|
||||
|
||||
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
|
||||
log.error("Invalid QOI image.\0")
|
||||
return null
|
||||
}
|
||||
|
||||
surface := new_surface(width, height)
|
||||
index := @as([Color; 64], idk)
|
||||
|
||||
run := 0
|
||||
px := Color.(0, 0, 0, 255)
|
||||
px_pos := 0
|
||||
|
||||
total_pixels := width * height
|
||||
|
||||
loop if px_pos >= total_pixels break else {
|
||||
if run > 0 {
|
||||
run -= 1
|
||||
} else {
|
||||
b1 := *qoi
|
||||
qoi += 1
|
||||
|
||||
if b1 == QOI_OP_RGB {
|
||||
px.r = *qoi
|
||||
px.g = *(qoi + 1)
|
||||
px.b = *(qoi + 2)
|
||||
qoi += 3
|
||||
} else if b1 == QOI_OP_RGBA {
|
||||
px.r = *qoi
|
||||
px.g = *(qoi + 1)
|
||||
px.b = *(qoi + 2)
|
||||
px.a = *(qoi + 3)
|
||||
qoi += 4
|
||||
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
|
||||
px = index[b1 & 0x3F]
|
||||
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
|
||||
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
|
||||
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
|
||||
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
|
||||
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
|
||||
b2 := *qoi
|
||||
vg := (b1 & 0x3F) - 32
|
||||
|
||||
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
|
||||
px.g = px.g + vg & 0xFF
|
||||
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
|
||||
qoi += 1
|
||||
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
|
||||
run = b1 & 0x3F
|
||||
}
|
||||
|
||||
index[QOI_COLOR_HASH(px)] = px
|
||||
};
|
||||
|
||||
*(surface.buf + px_pos) = px
|
||||
|
||||
px_pos += 1
|
||||
}
|
||||
|
||||
return surface
|
||||
}
|
|
@ -1,47 +1,57 @@
|
|||
svga := @use("rel:svga.hb")
|
||||
software := @use("rel:software.hb")
|
||||
software := @use("software.hb")
|
||||
image := @use("image/lib.hb")
|
||||
text := @use("text.hb")
|
||||
|
||||
// default mode
|
||||
mode := software
|
||||
|
||||
init := mode.init
|
||||
doublebuffer := mode.doublebuffer
|
||||
Surface := mode.Surface
|
||||
new_surface := mode.new_surface
|
||||
surface_from_ptr := mode.surface_from_ptr
|
||||
clone_surface := mode.clone_surface
|
||||
free_surface := mode.free_surface
|
||||
index := mode.index
|
||||
indexptr := mode.indexptr
|
||||
|
||||
// Colours
|
||||
Color := mode.Color
|
||||
white := mode.white
|
||||
black := mode.black
|
||||
gray := mode.gray
|
||||
red := mode.red
|
||||
green := mode.green
|
||||
yellow := mode.yellow
|
||||
blue := mode.blue
|
||||
magenta := mode.magenta
|
||||
cyan := mode.cyan
|
||||
light_gray := mode.light_gray
|
||||
light_red := mode.light_red
|
||||
light_green := mode.light_green
|
||||
light_yellow := mode.light_yellow
|
||||
light_blue := mode.light_blue
|
||||
light_magenta := mode.light_magenta
|
||||
light_cyan := mode.light_cyan
|
||||
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
|
||||
$white := Color.(255, 255, 255, 255)
|
||||
$black := Color.(0, 0, 0, 255)
|
||||
$gray := Color.(127, 127, 127, 255)
|
||||
$red := Color.(0, 0, 205, 255)
|
||||
$green := Color.(0, 205, 0, 255)
|
||||
$yellow := Color.(0, 205, 205, 255)
|
||||
$blue := Color.(205, 0, 0, 255)
|
||||
$magenta := Color.(205, 0, 205, 255)
|
||||
$cyan := Color.(205, 205, 0, 255)
|
||||
$light_gray := Color.(229, 229, 229, 255)
|
||||
$light_red := Color.(0, 0, 255, 255)
|
||||
$light_green := Color.(0, 255, 0, 255)
|
||||
$light_yellow := Color.(0, 255, 255, 255)
|
||||
$light_blue := Color.(255, 0, 0, 255)
|
||||
$light_magenta := Color.(255, 0, 255, 255)
|
||||
$light_cyan := Color.(255, 255, 0, 255)
|
||||
|
||||
// Drawing
|
||||
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
|
||||
|
||||
// Display
|
||||
width := mode.width
|
||||
height := mode.height
|
||||
dimensions := mode.dimensions
|
||||
set_height := mode.set_height
|
||||
set_width := mode.set_width
|
||||
set_dimensions := mode.set_dimensions
|
||||
sync := mode.sync
|
||||
|
||||
// Math
|
||||
UVec2 := struct {x: uint, y: uint}
|
||||
IVec2 := struct {x: int, y: int}
|
||||
sync := mode.sync
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue