forked from AbleOS/ableos
Compare commits
No commits in common. "use-flake-instead-of-shell.nix" and "master" have entirely different histories.
use-flake-
...
master
|
@ -1,3 +1,2 @@
|
||||||
[alias]
|
[alias]
|
||||||
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
|
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
|
||||||
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1 @@
|
||||||
target/
|
target/
|
||||||
.direnv
|
|
||||||
|
|
1184
Cargo.lock
generated
1184
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,3 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["dev", "kernel", "repbuild"]
|
members = ["kernel", "repbuild"]
|
||||||
|
|
||||||
# [profile.release]
|
|
||||||
# strip = "symbols"
|
|
||||||
# codegen-units = 1
|
|
||||||
# lto = true
|
|
||||||
# panic = "abort"
|
|
||||||
|
|
12
README.md
12
README.md
|
@ -1,8 +1,6 @@
|
||||||
# AbleOS
|
# AbleOS
|
||||||
An UNIX-unlike micro-kernel written in rust with an embedded bytecode virtual machine.
|
An UNIX-unlike micro-kernel written in rust with an embedded bytecode virtual machine.
|
||||||
|
|
||||||
Please note that a custom target directory is not supported and support will not be added.
|
|
||||||
|
|
||||||
# Community
|
# Community
|
||||||
[Discord](https://discord.gg/JrKVukDtgs)
|
[Discord](https://discord.gg/JrKVukDtgs)
|
||||||
|
|
||||||
|
@ -16,11 +14,5 @@ AbleOS should be able to be built on any platform which is supported by
|
||||||
For running AbleOS, `repbuild` uses QEMU.
|
For running AbleOS, `repbuild` uses QEMU.
|
||||||
|
|
||||||
## Steps
|
## Steps
|
||||||
1. Ensure you have qemu installed
|
1. `git submodule update --init`
|
||||||
2. `git submodule update --init`
|
2. `cargo repbuild`
|
||||||
3. `cargo repbuild run`
|
|
||||||
|
|
||||||
# Developing
|
|
||||||
There is a new work in progress developer tool for hblang.
|
|
||||||
|
|
||||||
There is also a flake you can run by typing `nix develop .`.
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "dev"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
logos = "0.14.1"
|
|
|
@ -1,6 +0,0 @@
|
||||||
# dev
|
|
||||||
`dev` is an ableOS specific tool meant to help the development of ableOS.
|
|
||||||
|
|
||||||
At the current stage changes are not welcome. If you have feature suggestions ping me on discord `@abletheabove`.
|
|
||||||
|
|
||||||
Run `cargo dev help` to see usage.
|
|
|
@ -1,84 +0,0 @@
|
||||||
pub mod protocol;
|
|
||||||
|
|
||||||
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("{")]
|
|
||||||
LBrace,
|
|
||||||
|
|
||||||
#[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 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
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
152
dev/src/main.rs
152
dev/src/main.rs
|
@ -1,152 +0,0 @@
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use idl::build_idl;
|
|
||||||
pub mod idl;
|
|
||||||
|
|
||||||
pub enum Options {
|
|
||||||
Build,
|
|
||||||
Clean,
|
|
||||||
New,
|
|
||||||
Run,
|
|
||||||
}
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
pub enum DevelopmentType {
|
|
||||||
Program,
|
|
||||||
Library,
|
|
||||||
IDL,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let mut args: Vec<String> = std::env::args().collect();
|
|
||||||
args.remove(0);
|
|
||||||
args.reverse();
|
|
||||||
|
|
||||||
let binding = args.pop().unwrap_or("help".to_string());
|
|
||||||
let subcommand = binding.as_str();
|
|
||||||
|
|
||||||
match subcommand {
|
|
||||||
"build" => {
|
|
||||||
let name = &args.pop().unwrap();
|
|
||||||
build(name.to_string())
|
|
||||||
}
|
|
||||||
"new" => {
|
|
||||||
let binding = args.pop().unwrap();
|
|
||||||
let dev_type = binding.as_str();
|
|
||||||
let name = args.pop().unwrap();
|
|
||||||
use DevelopmentType::*;
|
|
||||||
match dev_type {
|
|
||||||
"lib" | "library" => new(Library, name),
|
|
||||||
"prog" | "program" => new(Program, name),
|
|
||||||
"idl" => {
|
|
||||||
new(IDL, name);
|
|
||||||
// idl::main();
|
|
||||||
panic!("IDL is not finalized yet.")
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
"run" => run(),
|
|
||||||
"help" => help(),
|
|
||||||
_ => {
|
|
||||||
println!("Error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(development_type: DevelopmentType, name: String) {
|
|
||||||
let (folder_hierarchy, entry_name) = match development_type {
|
|
||||||
DevelopmentType::Program => ("programs", "main.hb"),
|
|
||||||
DevelopmentType::Library => ("libraries", "lib.hb"),
|
|
||||||
DevelopmentType::IDL => ("idl", "protocol.aidl"),
|
|
||||||
};
|
|
||||||
let project_folder_path_string = format!("sysdata/{folder_hierarchy}/{name}");
|
|
||||||
|
|
||||||
if std::path::Path::new(&project_folder_path_string).exists() {
|
|
||||||
panic!("Project already exists.")
|
|
||||||
}
|
|
||||||
|
|
||||||
std::fs::create_dir(project_folder_path_string.clone()).unwrap();
|
|
||||||
let readme_path_string = format!("{}/README.md", project_folder_path_string);
|
|
||||||
let mut readme_file = std::fs::File::create(readme_path_string.clone()).unwrap();
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
let full_path_string = format!("{src_folder_path_string}/{entry_name}");
|
|
||||||
let mut file = std::fs::File::create(full_path_string.clone()).unwrap();
|
|
||||||
let file_contents = match development_type {
|
|
||||||
DevelopmentType::Program => "main := fn(): int {
|
|
||||||
return 0
|
|
||||||
}"
|
|
||||||
.to_string(),
|
|
||||||
DevelopmentType::Library => "".to_string(),
|
|
||||||
DevelopmentType::IDL => format!(
|
|
||||||
"protocol {} {{
|
|
||||||
}}",
|
|
||||||
name
|
|
||||||
)
|
|
||||||
.to_owned(),
|
|
||||||
}
|
|
||||||
.to_string();
|
|
||||||
file.write_all(file_contents.as_bytes()).unwrap();
|
|
||||||
|
|
||||||
println!("New project created.");
|
|
||||||
if development_type == DevelopmentType::Program {
|
|
||||||
println!("You should add your project into the ableOS system configuration in sysdata/system_config.toml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run() {
|
|
||||||
println!("Running is not supported on a non-ableOS platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
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!(
|
|
||||||
"==========
|
|
||||||
= Help =
|
|
||||||
==========
|
|
||||||
Subcommands
|
|
||||||
- new Usage: `cargo dev new library name` or `cargo dev new program name`"
|
|
||||||
)
|
|
||||||
}
|
|
57
flake.lock
57
flake.lock
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1726560853,
|
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 0,
|
|
||||||
"narHash": "sha256-6H95HGJHhEZtyYA3rIQpvamMKAGoa8Yh2rFV29QnuGw=",
|
|
||||||
"path": "/nix/store/nra828scc8qs92b9pxra5csqzffb6hpl-source",
|
|
||||||
"type": "path"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
62
flake.nix
62
flake.nix
|
@ -1,62 +0,0 @@
|
||||||
{
|
|
||||||
description = "ableos flake";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs =
|
|
||||||
{
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
flake-utils,
|
|
||||||
}:
|
|
||||||
flake-utils.lib.eachDefaultSystem (
|
|
||||||
system:
|
|
||||||
let
|
|
||||||
# legacyPackages is a misnomer, it's just using your system packages
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
devShell = pkgs.mkShell rec {
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
clang
|
|
||||||
llvmPackages.bintools
|
|
||||||
rustup
|
|
||||||
qemu_full
|
|
||||||
# OMVFFull
|
|
||||||
# OMVF
|
|
||||||
];
|
|
||||||
extraCmds = '''';
|
|
||||||
RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain.toml;
|
|
||||||
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
|
||||||
LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
|
|
||||||
shellHook = ''
|
|
||||||
export REPBUILD_QEMU_FIRMWARE_PATH=${pkgs.OVMF.fd}/FV/OVMF.fd
|
|
||||||
|
|
||||||
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
|
|
||||||
export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
|
|
||||||
'';
|
|
||||||
# Add precompiled library to rustc search path
|
|
||||||
RUSTFLAGS = (
|
|
||||||
builtins.map (a: "-L ${a}/lib") [
|
|
||||||
# add libraries here (e.g. pkgs.libvmi)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
# Add glibc, clang, glib and other headers to bindgen search path
|
|
||||||
BINDGEN_EXTRA_CLANG_ARGS =
|
|
||||||
# Includes with normal include path
|
|
||||||
(builtins.map (a: ''-I"${a}/include"'') [
|
|
||||||
# add dev libraries here (e.g. pkgs.libvmi.dev)
|
|
||||||
pkgs.glibc.dev
|
|
||||||
])
|
|
||||||
# Includes with special directory paths
|
|
||||||
++ [
|
|
||||||
''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
|
|
||||||
''-I"${pkgs.glib.dev}/include/glib-2.0"''
|
|
||||||
"-I${pkgs.glib.out}/lib/glib-2.0/include/"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -5,32 +5,33 @@ version = "0.2.0"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embedded-graphics = "0.8"
|
embedded-graphics = "0.7"
|
||||||
hbvm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
hbvm.git = "https://git.ablecorp.us/ableos/holey-bytes"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
spin = "0.9"
|
spin = "0.9"
|
||||||
|
uart_16550 = "0.2"
|
||||||
slab = { version = "0.4", default-features = false }
|
slab = { version = "0.4", default-features = false }
|
||||||
uart_16550 = { version = "0.3", features = ["nightly"] }
|
|
||||||
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
versioning.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"
|
able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
hashbrown = { version = "0.14", features = ["nightly"] }
|
hashbrown = "*"
|
||||||
|
kiam = "0.1.1"
|
||||||
|
|
||||||
[dependencies.limine]
|
[dependencies.limine]
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
#git = "https://github.com/limine-bootloader/limine-rs"
|
git = "https://github.com/limine-bootloader/limine-rs"
|
||||||
|
|
||||||
[dependencies.crossbeam-queue]
|
[dependencies.crossbeam-queue]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc", "nightly"]
|
features = ["alloc"]
|
||||||
|
|
||||||
# [dependencies.clparse]
|
[dependencies.clparse]
|
||||||
# git = "https://git.ablecorp.us/ableos/ableos_userland"
|
git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
# default-features = false
|
default-features = false
|
||||||
|
|
||||||
[dependencies.derive_more]
|
[dependencies.derive_more]
|
||||||
version = "1"
|
version = "0.99"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = [
|
features = [
|
||||||
"add",
|
"add",
|
||||||
|
@ -47,12 +48,12 @@ features = [
|
||||||
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
x86_64 = "0.15"
|
x86_64 = "0.14"
|
||||||
x2apic = "0.4"
|
x2apic = "0.4"
|
||||||
virtio-drivers = "0.7"
|
virtio-drivers = "0.4.0"
|
||||||
|
# rdrand = "*"
|
||||||
|
rdrand = { version = "0.8", default-features = false }
|
||||||
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||||
sbi = "0.2.0"
|
sbi = "0.2.0"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
|
||||||
aarch64-cpu = "9"
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ fn collect_cpu_info(device_tree: &mut DeviceTree) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cpu_id() -> (String, u64) {
|
fn cpu_id() -> (String, u64) {
|
||||||
let mut cpu_id: u64;
|
let mut cpu_id: u64 = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mrs {cpu_id}, MIDR_EL1",
|
asm!("mrs {cpu_id}, MIDR_EL1",
|
||||||
cpu_id = out(reg) cpu_id,
|
cpu_id = out(reg) cpu_id,
|
||||||
|
@ -41,8 +41,6 @@ fn cpu_id() -> (String, u64) {
|
||||||
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
||||||
0x410FD034 => "Cortex-A53".to_string(),
|
0x410FD034 => "Cortex-A53".to_string(),
|
||||||
0x410FD083 => "Cortex-A72".to_string(),
|
0x410FD083 => "Cortex-A72".to_string(),
|
||||||
// the source of this one was checking the cpu id :thinking:
|
|
||||||
0x410FD493 => "Neoverse N2".to_string(),
|
|
||||||
_ => "Unknown".to_string(),
|
_ => "Unknown".to_string(),
|
||||||
};
|
};
|
||||||
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use {crate::logger::TERMINAL_LOGGER, core::fmt::Write, spin::Mutex};
|
use {crate::logger::TERMINAL_LOGGER, core::fmt::Write, spin::Mutex};
|
||||||
pub static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
const SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
||||||
uart: 0x09000000 as *mut u8,
|
uart: 0x09000000 as *mut u8,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,12 +17,9 @@ impl core::fmt::Write for SerialConsole {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Sync for SerialConsole {}
|
|
||||||
unsafe impl Send for SerialConsole {}
|
|
||||||
|
|
||||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||||
SERIAL_CONSOLE.lock().write_fmt(args)?;
|
SERIAL_CONSOLE.lock().write_fmt(args)?;
|
||||||
// TERMINAL_LOGGER.lock().write_fmt(args)?;
|
TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
pub use logging::log;
|
pub use logging::log;
|
||||||
use {
|
use {
|
||||||
crate::{allocator, bootmodules::BootModule, kmain::kmain},
|
crate::{allocator, bootmodules::BootModule, kmain::kmain},
|
||||||
alloc::vec::Vec,
|
|
||||||
core::arch::asm,
|
core::arch::asm,
|
||||||
limine::FramebufferRequest,
|
limine::FramebufferRequest,
|
||||||
};
|
};
|
||||||
|
@ -42,7 +41,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0);
|
static KFILE_REQ: KernelFileRequest = KernelFileRequest::new(0);
|
||||||
static MOD_REQ: ModuleRequest = ModuleRequest::new(0);
|
static MOD_REQ: ModuleRequest = ModuleRequest::new(0);
|
||||||
|
|
||||||
let mut bootmodules = Vec::new();
|
let mut bootmodules = alloc::vec::Vec::new();
|
||||||
|
|
||||||
if bm.is_some() {
|
if bm.is_some() {
|
||||||
let bm = bm.unwrap();
|
let bm = bm.unwrap();
|
||||||
|
@ -53,13 +52,18 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
let raw_bytes = core::slice::from_raw_parts(
|
let raw_bytes = core::slice::from_raw_parts(
|
||||||
file.base.as_ptr().expect("invalid initrd"),
|
file.base.as_ptr().expect("invalid initrd"),
|
||||||
file.length as usize,
|
file.length as usize,
|
||||||
);
|
)
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
let file_path = file.path.to_str().unwrap().to_str();
|
let file_path = alloc::string::String::from_utf8(
|
||||||
|
file.path.to_str().unwrap().to_bytes().to_vec(),
|
||||||
|
);
|
||||||
if file_path.is_err() {
|
if file_path.is_err() {
|
||||||
panic!("invalid file path: {:?}", file_path);
|
panic!("invalid file path: {:?}", file_path);
|
||||||
}
|
}
|
||||||
let file_cmd = file.cmdline.to_str().unwrap().to_str();
|
let file_cmd = alloc::string::String::from_utf8(
|
||||||
|
file.cmdline.to_str().unwrap().to_bytes().to_vec(),
|
||||||
|
);
|
||||||
if file_cmd.is_err() {
|
if file_cmd.is_err() {
|
||||||
panic!("invalid module cmd: {:?}", file_cmd);
|
panic!("invalid module cmd: {:?}", file_cmd);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +85,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
kmain(
|
crate::kmain::kmain(
|
||||||
KFILE_REQ
|
KFILE_REQ
|
||||||
.get_response()
|
.get_response()
|
||||||
.get()
|
.get()
|
||||||
|
@ -95,6 +99,8 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
bootmodules,
|
bootmodules,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
spin_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spin_loop() -> ! {
|
pub fn spin_loop() -> ! {
|
||||||
|
@ -103,19 +109,8 @@ pub fn spin_loop() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// I am sorry.
|
|
||||||
static mut A_REAL_RANDOM_U64_I_PROMISE: u64 = 0;
|
|
||||||
|
|
||||||
pub fn hardware_random_u64() -> u64 {
|
pub fn hardware_random_u64() -> u64 {
|
||||||
if let Some(rng) = aarch64_cpu::asm::random::ArmRng::new() {
|
0
|
||||||
if let Some(rnd) = rng.rndr() {
|
|
||||||
return rnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
A_REAL_RANDOM_U64_I_PROMISE += 1;
|
|
||||||
A_REAL_RANDOM_U64_I_PROMISE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_dump() {}
|
pub fn register_dump() {}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
use core::num;
|
use core::num;
|
||||||
|
|
||||||
use {
|
use alloc::boxed::Box;
|
||||||
crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress},
|
use spin::{Mutex, Once};
|
||||||
alloc::boxed::Box,
|
use crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress};
|
||||||
spin::{Mutex, Once},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::PAGE_SIZE;
|
use super::PAGE_SIZE;
|
||||||
|
|
||||||
|
@ -30,7 +28,7 @@ impl PageSize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PageTable {
|
pub struct PageTable {
|
||||||
entries: [PageEntry; 512],
|
entries: [PageEntry; 512]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PageTable {
|
impl PageTable {
|
||||||
|
@ -74,14 +72,8 @@ impl PageTable {
|
||||||
/// flags MUST include one or more of the following:
|
/// flags MUST include one or more of the following:
|
||||||
/// Read, Write, Execute
|
/// Read, Write, Execute
|
||||||
/// The valid bit automatically gets added
|
/// The valid bit automatically gets added
|
||||||
pub fn map(
|
pub fn map(&mut self, vaddr: VirtualAddress, paddr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) {
|
||||||
&mut self,
|
assert!(flags as usize & 0xe != 0);
|
||||||
vaddr: VirtualAddress,
|
|
||||||
paddr: PhysicalAddress,
|
|
||||||
flags: PageEntryFlags,
|
|
||||||
page_size: PageSize,
|
|
||||||
) {
|
|
||||||
assert!(flags as usize & 0xE != 0);
|
|
||||||
|
|
||||||
let vpn = vaddr.vpns();
|
let vpn = vaddr.vpns();
|
||||||
let ppn = paddr.ppns();
|
let ppn = paddr.ppns();
|
||||||
|
@ -113,24 +105,14 @@ impl PageTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identity maps a page of memory
|
/// Identity maps a page of memory
|
||||||
pub fn identity_map(
|
pub fn identity_map(&mut self, addr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) {
|
||||||
&mut self,
|
|
||||||
addr: PhysicalAddress,
|
|
||||||
flags: PageEntryFlags,
|
|
||||||
page_size: PageSize,
|
|
||||||
) {
|
|
||||||
// log::debug!("identity mapped {addr}");
|
// log::debug!("identity mapped {addr}");
|
||||||
self.map(addr.as_addr().into(), addr, flags, page_size);
|
self.map(addr.as_addr().into(), addr, flags, page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Identity maps a range of contiguous memory
|
/// Identity maps a range of contiguous memory
|
||||||
/// This assumes that start <= end
|
/// This assumes that start <= end
|
||||||
pub fn identity_map_range(
|
pub fn identity_map_range(&mut self, start: PhysicalAddress, end: PhysicalAddress, flags: PageEntryFlags) {
|
||||||
&mut self,
|
|
||||||
start: PhysicalAddress,
|
|
||||||
end: PhysicalAddress,
|
|
||||||
flags: PageEntryFlags,
|
|
||||||
) {
|
|
||||||
log::debug!("start: {start}, end: {end}");
|
log::debug!("start: {start}, end: {end}");
|
||||||
let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1);
|
let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1);
|
||||||
let num_pages = (align_val(end.as_addr(), 12) - mem_addr - 1) / PAGE_SIZE + 1;
|
let num_pages = (align_val(end.as_addr(), 12) - mem_addr - 1) / PAGE_SIZE + 1;
|
||||||
|
@ -246,7 +228,7 @@ impl PageEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn addr(&self) -> PhysicalAddress {
|
fn addr(&self) -> PhysicalAddress {
|
||||||
((self.entry() as usize & !0x3FF) << 2).into()
|
((self.entry() as usize & !0x3ff) << 2).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destroy(&mut self) {
|
fn destroy(&mut self) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
mod memory;
|
mod memory;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
alloc::{boxed::Box, vec::Vec},
|
alloc::boxed::Box,
|
||||||
core::{
|
core::{
|
||||||
arch::{asm, global_asm},
|
arch::{asm, global_asm},
|
||||||
fmt::Write,
|
fmt::Write,
|
||||||
|
@ -45,7 +45,7 @@ extern "C" {
|
||||||
static USABLE_MEMORY_SIZE: usize;
|
static USABLE_MEMORY_SIZE: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static SERIAL_CONSOLE: Once<Mutex<MmioSerialPort>> = Once::new();
|
static SERIAL_CONSOLE: Once<Mutex<MmioSerialPort>> = Once::new();
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn _kernel_start() -> ! {
|
unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
|
@ -95,7 +95,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
in(reg) satp_value,
|
in(reg) satp_value,
|
||||||
);
|
);
|
||||||
|
|
||||||
crate::kmain::kmain("baka=9", Vec::new());
|
crate::kmain::kmain("baka=9", None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spin loop
|
/// Spin loop
|
||||||
|
@ -105,12 +105,6 @@ pub fn spin_loop() -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hardware_random_u64() -> u64 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_dump() {}
|
|
||||||
|
|
||||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||||
SERIAL_CONSOLE.get().unwrap().lock().write_fmt(args)
|
SERIAL_CONSOLE.get().unwrap().lock().write_fmt(args)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,6 @@ use {
|
||||||
|
|
||||||
pub const DOUBLE_FAULT_IX: u16 = 0;
|
pub const DOUBLE_FAULT_IX: u16 = 0;
|
||||||
|
|
||||||
const STACK_SIZE: usize = 5 * 1024;
|
|
||||||
const STACK_ALIGNMENT: usize = 1;
|
|
||||||
|
|
||||||
pub unsafe fn init() {
|
pub unsafe fn init() {
|
||||||
use x86_64::instructions::{
|
use x86_64::instructions::{
|
||||||
segmentation::{Segment, CS, SS},
|
segmentation::{Segment, CS, SS},
|
||||||
|
@ -35,24 +32,24 @@ struct Selectors {
|
||||||
|
|
||||||
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
static TSS: Lazy<TaskStateSegment> = Lazy::new(|| {
|
||||||
let mut tss = TaskStateSegment::new();
|
let mut tss = TaskStateSegment::new();
|
||||||
|
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = {
|
||||||
let stack_ptr = unsafe {
|
const SIZE: usize = 5 * 1024;
|
||||||
let layout = alloc::alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGNMENT)
|
let stack = unsafe {
|
||||||
.expect("Failed to create stack layout");
|
alloc::alloc::alloc_zeroed(
|
||||||
let stack = alloc::alloc::alloc(layout);
|
alloc::alloc::Layout::from_size_align(SIZE, 1).expect("stack pointer"),
|
||||||
VirtAddr::from_ptr(stack) + STACK_SIZE as u64
|
)
|
||||||
|
};
|
||||||
|
VirtAddr::from_ptr(stack) + SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
tss.interrupt_stack_table[usize::from(DOUBLE_FAULT_IX)] = stack_ptr;
|
|
||||||
tss
|
tss
|
||||||
});
|
});
|
||||||
|
|
||||||
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
static GDT: Lazy<(GlobalDescriptorTable, Selectors)> = Lazy::new(|| {
|
||||||
let mut gdt = GlobalDescriptorTable::new();
|
let mut gdt = GlobalDescriptorTable::new();
|
||||||
let sels = Selectors {
|
let sels = Selectors {
|
||||||
kcode: gdt.append(Descriptor::kernel_code_segment()),
|
kcode: gdt.add_entry(Descriptor::kernel_code_segment()),
|
||||||
kdata: gdt.append(Descriptor::kernel_data_segment()),
|
kdata: gdt.add_entry(Descriptor::kernel_data_segment()),
|
||||||
tss: gdt.append(Descriptor::tss_segment(&TSS)),
|
tss: gdt.add_entry(Descriptor::tss_segment(&TSS)),
|
||||||
};
|
};
|
||||||
(gdt, sels)
|
(gdt, sels)
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,52 +1,56 @@
|
||||||
|
// TODO: Turn apic keyboard interrupt into a standard ipc message
|
||||||
use {
|
use {
|
||||||
core::mem::MaybeUninit,
|
|
||||||
log::trace,
|
log::trace,
|
||||||
|
spin::{Lazy, Mutex},
|
||||||
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
||||||
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safety: Using LAPIC or IDT before init() is UB
|
pub unsafe fn init() {
|
||||||
/// Using
|
trace!("Initialising IDT");
|
||||||
static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
IDT.load();
|
||||||
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
Lazy::force(&LAPIC);
|
||||||
|
x86_64::instructions::interrupts::enable();
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Interrupt {
|
enum Interrupt {
|
||||||
Timer = 32,
|
Timer = 32,
|
||||||
|
|
||||||
ApicErr = u8::MAX - 1,
|
ApicErr = u8::MAX - 1,
|
||||||
Spurious = u8::MAX,
|
Spurious = u8::MAX,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn init() {
|
pub(crate) static LAPIC: Lazy<Mutex<LocalApic>> = Lazy::new(|| {
|
||||||
trace!("Initializing IDT and LAPIC");
|
let mut lapic = LocalApicBuilder::new()
|
||||||
|
|
||||||
// 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)
|
.timer_vector(Interrupt::Timer as usize)
|
||||||
.error_vector(Interrupt::ApicErr as usize)
|
.error_vector(Interrupt::ApicErr as usize)
|
||||||
.spurious_vector(Interrupt::Spurious as usize)
|
.spurious_vector(Interrupt::Spurious as usize)
|
||||||
.set_xapic_base(
|
.set_xapic_base(
|
||||||
x2apic::lapic::xapic_base()
|
unsafe { x2apic::lapic::xapic_base() }
|
||||||
+ super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed),
|
+ super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed),
|
||||||
)
|
)
|
||||||
.build()
|
.build()
|
||||||
.expect("Failed to setup Local APIC");
|
.expect("failed to setup Local APIC");
|
||||||
LAPIC.enable();
|
unsafe { lapic.enable() };
|
||||||
|
Mutex::new(lapic)
|
||||||
|
});
|
||||||
|
|
||||||
x86_64::instructions::interrupts::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 usize].set_handler_fn(apic_err);
|
||||||
|
idt[Interrupt::Spurious as usize].set_handler_fn(spurious);
|
||||||
|
idt[Interrupt::Timer as usize].set_handler_fn(timer);
|
||||||
|
|
||||||
|
idt
|
||||||
|
});
|
||||||
|
|
||||||
extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
|
extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
|
||||||
panic!("Double fault: error code {error_code} \n{stack_frame:#?}")
|
panic!("Double fault: error code {error_code} \n{stack_frame:#?}")
|
||||||
|
@ -60,9 +64,7 @@ extern "x86-interrupt" fn page_fault(
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
||||||
unsafe {
|
unsafe { LAPIC.lock().end_of_interrupt() };
|
||||||
LAPIC.end_of_interrupt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
||||||
|
@ -70,7 +72,5 @@ extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
||||||
unsafe {
|
unsafe { LAPIC.lock().end_of_interrupt() };
|
||||||
LAPIC.end_of_interrupt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
//! Logging (as in terms of console / serial output)
|
//! Logging (as in terms of console / serial output)
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
use {core::fmt::Write, spin::Mutex, uart_16550::SerialPort};
|
use {
|
||||||
|
core::fmt::Write,
|
||||||
|
limine::{TerminalRequest, TerminalResponse},
|
||||||
|
spin::{Lazy, Mutex},
|
||||||
|
uart_16550::SerialPort,
|
||||||
|
};
|
||||||
|
|
||||||
pub static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
pub static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use core::arch::x86_64::{_rdrand64_step, _rdseed64_step};
|
use {
|
||||||
|
crate::bootmodules::BootModule, core::arch::asm, embedded_graphics::pixelcolor::Rgb888,
|
||||||
use {crate::bootmodules::BootModule, core::arch::asm, log::warn};
|
log::warn, rdrand::RdSeed,
|
||||||
|
};
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
|
||||||
mod cpuid;
|
mod cpuid;
|
||||||
|
@ -142,13 +143,18 @@ unsafe extern "C" fn start() -> ! {
|
||||||
let raw_bytes = core::slice::from_raw_parts(
|
let raw_bytes = core::slice::from_raw_parts(
|
||||||
file.base.as_ptr().expect("invalid initrd"),
|
file.base.as_ptr().expect("invalid initrd"),
|
||||||
file.length as usize,
|
file.length as usize,
|
||||||
);
|
)
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
let file_path = file.path.to_str().unwrap().to_str();
|
let file_path = alloc::string::String::from_utf8(
|
||||||
|
file.path.to_str().unwrap().to_bytes().to_vec(),
|
||||||
|
);
|
||||||
if file_path.is_err() {
|
if file_path.is_err() {
|
||||||
panic!("invalid file path: {:?}", file_path);
|
panic!("invalid file path: {:?}", file_path);
|
||||||
}
|
}
|
||||||
let file_cmd = file.cmdline.to_str().unwrap().to_str();
|
let file_cmd = alloc::string::String::from_utf8(
|
||||||
|
file.cmdline.to_str().unwrap().to_bytes().to_vec(),
|
||||||
|
);
|
||||||
if file_cmd.is_err() {
|
if file_cmd.is_err() {
|
||||||
panic!("invalid module cmd: {:?}", file_cmd);
|
panic!("invalid module cmd: {:?}", file_cmd);
|
||||||
}
|
}
|
||||||
|
@ -189,20 +195,32 @@ unsafe extern "C" fn start() -> ! {
|
||||||
/// Spin loop
|
/// Spin loop
|
||||||
pub fn spin_loop() -> ! {
|
pub fn spin_loop() -> ! {
|
||||||
loop {
|
loop {
|
||||||
x86_64::instructions::hlt()
|
x86_64::instructions::hlt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hardware_random_u64() -> u64 {
|
pub fn hardware_random_u64() -> u64 {
|
||||||
let mut out: u64 = 0;
|
use {log::trace, rdrand::RdRand};
|
||||||
match unsafe { _rdrand64_step(&mut out) } {
|
let gen = RdRand::new();
|
||||||
1 => out,
|
match gen {
|
||||||
_ => {
|
Ok(gen) => {
|
||||||
|
let ret = gen.try_next_u64().unwrap();
|
||||||
|
trace!("Random {}", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
warn!("RDRand not supported.");
|
warn!("RDRand not supported.");
|
||||||
// Try rdseed
|
// Try rdseed
|
||||||
match unsafe { _rdseed64_step(&mut out) } {
|
let gen = RdSeed::new();
|
||||||
1 => out,
|
match gen {
|
||||||
_ => panic!("Neither RDRand or RDSeed are supported"),
|
Ok(gen) => {
|
||||||
|
let ret = gen.try_next_u64().unwrap();
|
||||||
|
trace!("Random {}", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
panic!("Neither RDRand or RDSeed are supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +228,6 @@ pub fn hardware_random_u64() -> u64 {
|
||||||
|
|
||||||
pub fn get_edid() {}
|
pub fn get_edid() {}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn register_dump() {
|
pub fn register_dump() {
|
||||||
let rax: u64;
|
let rax: u64;
|
||||||
let rbx: u64 = 0;
|
let rbx: u64 = 0;
|
||||||
|
|
|
@ -12,8 +12,7 @@ use crate::alloc::string::ToString;
|
||||||
|
|
||||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||||
pub fn init(device_tree: &mut DeviceTree) {
|
pub fn init(device_tree: &mut DeviceTree) {
|
||||||
device_tree
|
device_tree.devices
|
||||||
.devices
|
|
||||||
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
||||||
let mut devices = alloc::vec![];
|
let mut devices = alloc::vec![];
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ pub fn init(device_tree: &mut DeviceTree) {
|
||||||
let id = device_info.device_id.id;
|
let id = device_info.device_id.id;
|
||||||
use Vendor::*;
|
use Vendor::*;
|
||||||
let (dev_type, dev_name) = match (vendor, id) {
|
let (dev_type, dev_name) = match (vendor, id) {
|
||||||
(VMWareInc, 1029) => ("GPUs", "SVGAII PCI GPU"),
|
|
||||||
(Qemu, 4369) => ("GPUs", "QEMU VGA"),
|
(Qemu, 4369) => ("GPUs", "QEMU VGA"),
|
||||||
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
|
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
|
||||||
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
|
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
|
||||||
|
@ -47,7 +45,6 @@ pub fn init(device_tree: &mut DeviceTree) {
|
||||||
pci_info.set_attribute("id", id);
|
pci_info.set_attribute("id", id);
|
||||||
pci_info.set_attribute("device", device_info.device);
|
pci_info.set_attribute("device", device_info.device);
|
||||||
pci_info.set_attribute("vendor", vendor);
|
pci_info.set_attribute("vendor", vendor);
|
||||||
pci_info.set_attribute("bus", bus);
|
|
||||||
pci_info.set_attribute("class", device_info.full_class.to_string());
|
pci_info.set_attribute("class", device_info.full_class.to_string());
|
||||||
dev.set_child(pci_info);
|
dev.set_child(pci_info);
|
||||||
devices.push((dev_type, dev));
|
devices.push((dev_type, dev));
|
||||||
|
@ -69,8 +66,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
|
let reg2 = unsafe { pci_config_read(bus, device, 0, 0x8) };
|
||||||
log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
|
|
||||||
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
|
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
|
||||||
let pci_class = PciFullClass::from_u16(class);
|
let pci_class = PciFullClass::from_u16(class);
|
||||||
let header_type = get_header_type(bus, device, 0);
|
let header_type = get_header_type(bus, device, 0);
|
||||||
|
@ -273,7 +269,8 @@ impl Display for Vendor {
|
||||||
|
|
||||||
use core::fmt::Display;
|
use core::fmt::Display;
|
||||||
|
|
||||||
use {crate::device_tree::DeviceTree, x86_64::instructions::port::Port};
|
use x86_64::instructions::port::Port;
|
||||||
|
use crate::device_tree::DeviceTree;
|
||||||
|
|
||||||
#[allow(non_camel_case_types, dead_code)]
|
#[allow(non_camel_case_types, dead_code)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
@ -461,7 +458,9 @@ unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||||
let func = func as u32;
|
let func = func as u32;
|
||||||
let offset = offset as u32;
|
let offset = offset as u32;
|
||||||
// construct address param
|
// construct address param
|
||||||
let address = (bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x8000_0000;
|
let address =
|
||||||
|
((bus << 16) | (device << 11) | (func << 8) | (offset & 0xFC) | 0x8000_0000) as u32;
|
||||||
|
|
||||||
// write address
|
// write address
|
||||||
Port::new(0xCF8).write(address);
|
Port::new(0xCF8).write(address);
|
||||||
|
|
||||||
|
@ -469,20 +468,6 @@ unsafe fn pci_config_read(bus: u8, device: u8, func: u8, offset: u8) -> u32 {
|
||||||
Port::new(0xCFC).read()
|
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) {
|
unsafe fn pci_config_write(bus: u8, device: u8, func: u8, offset: u8, value: u32) {
|
||||||
let bus = bus as u32;
|
let bus = bus as u32;
|
||||||
let device = device as u32;
|
let device = device as u32;
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
use {
|
use {
|
||||||
// crate::alloc::string::ToString,
|
crate::alloc::string::ToString,
|
||||||
alloc::vec::Vec,
|
alloc::{string::String, vec::Vec},
|
||||||
// clparse::Arguments,
|
clparse::Arguments,
|
||||||
// core::fmt::{Debug, Display},
|
core::fmt::{Debug, Display},
|
||||||
// log::trace,
|
log::trace,
|
||||||
// xml::XMLElement,
|
xml::XMLElement,
|
||||||
};
|
};
|
||||||
pub type BootModules<'a> = Vec<BootModule<'a>>;
|
pub type BootModules = Vec<BootModule>;
|
||||||
|
|
||||||
pub struct BootModule<'a> {
|
pub struct BootModule {
|
||||||
pub path: &'a str,
|
pub path: String,
|
||||||
pub bytes: &'a [u8],
|
pub bytes: Vec<u8>,
|
||||||
pub cmd: &'a str,
|
pub cmd: String,
|
||||||
}
|
}
|
||||||
impl<'a> BootModule<'a> {
|
impl BootModule {
|
||||||
pub fn new(path: &'a str, bytes: &'a [u8], cmd: &'a str) -> Self {
|
pub fn new(path: String, bytes: Vec<u8>, cmd: String) -> Self {
|
||||||
Self { path, bytes, cmd }
|
Self { path, bytes, cmd }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn build_cmd<T: Display + Debug>(name: T, cmdline: T) -> XMLElement {
|
pub fn build_cmd<T: Display + Debug>(name: T, cmdline: T) -> XMLElement {
|
||||||
// let mut cmdline = cmdline.to_string();
|
let mut cmdline = cmdline.to_string();
|
||||||
// cmdline.pop();
|
cmdline.pop();
|
||||||
// cmdline.remove(0);
|
cmdline.remove(0);
|
||||||
|
|
||||||
// let cmd = Arguments::parse(cmdline.to_string()).unwrap();
|
let cmd = Arguments::parse(cmdline.to_string()).unwrap();
|
||||||
// trace!("Cmdline: {cmd:?}");
|
trace!("Cmdline: {cmd:?}");
|
||||||
|
|
||||||
// let mut clo = XMLElement::new(name);
|
let mut clo = XMLElement::new(name);
|
||||||
// for (key, value) in cmd.arguments {
|
for (key, value) in cmd.arguments {
|
||||||
// clo.set_attribute(key, value);
|
clo.set_attribute(key, value);
|
||||||
// }
|
}
|
||||||
// trace!("command line object: {:?}", clo);
|
trace!("command line object: {:?}", clo);
|
||||||
// clo
|
clo
|
||||||
// }
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ use {
|
||||||
core::fmt,
|
core::fmt,
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A device object.
|
/// A device object.
|
||||||
/// TODO define device
|
/// TODO define device
|
||||||
pub type Device = xml::XMLElement;
|
pub type Device = xml::XMLElement;
|
||||||
|
@ -24,9 +23,7 @@ impl DeviceTree {
|
||||||
let mut dt = Self {
|
let mut dt = Self {
|
||||||
devices: HashMap::new(),
|
devices: HashMap::new(),
|
||||||
};
|
};
|
||||||
device_tree!(
|
device_tree!(dt, [
|
||||||
dt,
|
|
||||||
[
|
|
||||||
"Mice",
|
"Mice",
|
||||||
"Keyboards",
|
"Keyboards",
|
||||||
"Controllers",
|
"Controllers",
|
||||||
|
@ -41,12 +38,12 @@ impl DeviceTree {
|
||||||
"Serial Ports",
|
"Serial Ports",
|
||||||
"Cameras",
|
"Cameras",
|
||||||
"Biometric Devices",
|
"Biometric Devices",
|
||||||
]
|
]);
|
||||||
);
|
|
||||||
dt
|
dt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
use crate::{device_tree, tab, utils::TAB};
|
use crate::{utils::TAB, device_tree};
|
||||||
|
use crate::tab;
|
||||||
impl fmt::Display for DeviceTree {
|
impl fmt::Display for DeviceTree {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
|
@ -1,35 +0,0 @@
|
||||||
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,21 +1,27 @@
|
||||||
//! Environment call handling routines
|
//! Environment call handling routines
|
||||||
|
|
||||||
use crate::holeybytes::kernel_services::{
|
use core::borrow::Borrow;
|
||||||
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
|
|
||||||
service_definition_service::sds_msg_handler,
|
use crate::{
|
||||||
|
allocator,
|
||||||
|
holeybytes::kernel_services::{
|
||||||
|
block_read,
|
||||||
|
service_definition_service::{sds_msg_handler, SERVICES},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
super::Vm,
|
super::{mem::Memory, Vm},
|
||||||
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
crate::{arch, holeybytes::mem, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||||
log::{debug, error, info, trace},
|
alloc::string::String,
|
||||||
|
log::{debug, error, info, trace, warn},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn handler(vm: &mut Vm) {
|
pub fn handler(vm: &mut Vm) {
|
||||||
let ecall_number = vm.registers[2].cast::<u64>();
|
let ecall_number = vm.registers[2].cast::<u64>();
|
||||||
// log::info!("eca called :pensive:");
|
|
||||||
// debug!("Ecall number {:?}", ecall_number);
|
// debug!("Ecall number {:?}", ecall_number);
|
||||||
//info!("Register dump: {:?}", vm.registers);
|
// trace!("Register dump: {:?}", vm.registers);
|
||||||
|
|
||||||
match ecall_number {
|
match ecall_number {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -51,7 +57,7 @@ pub fn handler(vm: &mut Vm) {
|
||||||
};
|
};
|
||||||
let buff_id = arch::hardware_random_u64();
|
let buff_id = arch::hardware_random_u64();
|
||||||
buffs.insert(buff_id, abc);
|
buffs.insert(buff_id, abc);
|
||||||
info!("Buffer ID: {}", buff_id);
|
debug!("Buffer ID: {}", buff_id);
|
||||||
vm.registers[1] = hbvm::value::Value(buff_id);
|
vm.registers[1] = hbvm::value::Value(buff_id);
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
|
@ -68,11 +74,11 @@ pub fn handler(vm: &mut Vm) {
|
||||||
match buffer_id {
|
match buffer_id {
|
||||||
0 => match sds_msg_handler(vm, mem_addr, length) {
|
0 => match sds_msg_handler(vm, mem_addr, length) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(err) => log::error!("Improper sds format: {err:?}"),
|
Err(err) => log::error!("Improper sds format"),
|
||||||
},
|
},
|
||||||
1 => match log_msg_handler(vm, mem_addr, length) {
|
1 => match log_msg_handler(vm, mem_addr, length) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => log::error!("Improper log format"),
|
Err(err) => log::error!("Improper log format"),
|
||||||
},
|
},
|
||||||
2 => {
|
2 => {
|
||||||
use crate::holeybytes::kernel_services::mem_serve::memory_msg_handler;
|
use crate::holeybytes::kernel_services::mem_serve::memory_msg_handler;
|
||||||
|
@ -80,84 +86,25 @@ pub fn handler(vm: &mut Vm) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_) => {}
|
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 => unsafe {
|
|
||||||
let size = msg_vec[1];
|
|
||||||
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
|
||||||
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."),
|
|
||||||
};
|
|
||||||
// info!("Read the value {} from address {}", value, addr);
|
|
||||||
vm.registers[1] = hbvm::value::Value(value);
|
|
||||||
},
|
|
||||||
1 => unsafe {
|
|
||||||
let size = msg_vec[1];
|
|
||||||
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
5 => match dt_msg_handler(vm, mem_addr, length) {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(_) => log::error!("Improper dt query"),
|
|
||||||
},
|
|
||||||
buffer_id => {
|
buffer_id => {
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
let mut buffs = IPC_BUFFERS.lock();
|
||||||
|
|
||||||
match buffs.get_mut(&buffer_id) {
|
match buffs.get_mut(&buffer_id) {
|
||||||
Some(buff) => {
|
Some(buff) => {
|
||||||
let mut msg_vec = Vec::with_capacity(length);
|
let mut msg_vec = vec![];
|
||||||
|
|
||||||
for x in 0..(length as isize) {
|
for x in 0..(length as isize) {
|
||||||
let xyz = mem_addr as *const u8;
|
let xyz = mem_addr as *const u8;
|
||||||
let value = unsafe { xyz.offset(x).read() };
|
let value = unsafe { xyz.offset(x).read() };
|
||||||
msg_vec.push(value);
|
msg_vec.push(value);
|
||||||
}
|
}
|
||||||
debug!(
|
buff.push(msg_vec.clone());
|
||||||
|
info!(
|
||||||
"Message {:?} has been sent to Buffer({})",
|
"Message {:?} has been sent to Buffer({})",
|
||||||
msg_vec, buffer_id
|
msg_vec, buffer_id
|
||||||
);
|
);
|
||||||
buff.push(msg_vec);
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::error!("Access of non-existent buffer {}", buffer_id)
|
log::error!("Access of non-existent buffer {}", buffer_id)
|
||||||
|
@ -169,37 +116,11 @@ pub fn handler(vm: &mut Vm) {
|
||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
let buffer_id = vm.registers[3].cast::<u64>();
|
let buffer_id = vm.registers[3].cast::<u64>();
|
||||||
let mut map_ptr = vm.registers[4].cast::<u64>();
|
|
||||||
let max_length = vm.registers[5].cast::<u64>();
|
|
||||||
|
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
let mut buffs = IPC_BUFFERS.lock();
|
||||||
let buff: &mut IpcBuffer;
|
let mut buff = buffs.get_mut(&buffer_id).unwrap();
|
||||||
|
let msg = buff.pop();
|
||||||
if buffs.get_mut(&buffer_id).is_some() {
|
info!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||||
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() {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
5 => {
|
5 => {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
@ -211,24 +132,50 @@ pub fn handler(vm: &mut Vm) {
|
||||||
unsafe fn x86_out(address: u16, value: u32) {
|
unsafe fn x86_out(address: u16, value: u32) {
|
||||||
x86_64::instructions::port::Port::new(address).write(value);
|
x86_64::instructions::port::Port::new(address).write(value);
|
||||||
}
|
}
|
||||||
let x = hbvm::value::Value(unsafe { x86_in(r2 as u16) } as u64);
|
vm.registers[3] = hbvm::value::Value(unsafe { x86_in(r2 as u16) } as u64);
|
||||||
// info!("Read {:?} from Port {:?}", x, r2);
|
|
||||||
vm.registers[3] = x
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 5
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
|
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn log_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
pub enum LogError {
|
// let message_length = 8 + 8 + 8;
|
||||||
NoMessages,
|
// log::info!("Mem Addr 0x{:x?} length {}", mem_addr, length);
|
||||||
InvalidLogFormat,
|
let mut msg_vec = block_read(mem_addr, length);
|
||||||
|
|
||||||
|
let log_level = msg_vec.pop().unwrap();
|
||||||
|
match String::from_utf8(msg_vec) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use {alloc::vec, log::Record};
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum LogError {
|
||||||
|
InvalidLogFormat,
|
||||||
|
}
|
||||||
|
use {alloc::vec, log::Record};
|
||||||
|
|
||||||
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
// let mut val = alloc::vec::Vec::new();
|
// let mut val = alloc::vec::Vec::new();
|
||||||
// for _ in 0..4096 {
|
// for _ in 0..4096 {
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
use {
|
|
||||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
|
||||||
alloc::{
|
|
||||||
string::{String, ToString},
|
|
||||||
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 mut bytes: Vec<u8> = Vec::new();
|
|
||||||
for byte in msg_vec {
|
|
||||||
if *byte == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bytes.push(*byte)
|
|
||||||
}
|
|
||||||
let query_string = String::from_utf8(bytes).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: String) -> u64 {
|
|
||||||
let qt_parse_step_one = query_string.split("/");
|
|
||||||
let mut qt_parse_step_two: Vec<String> = Vec::new();
|
|
||||||
for a in qt_parse_step_one {
|
|
||||||
qt_parse_step_two.push(a.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
let first_fragment: &str = &qt_parse_step_two[0];
|
|
||||||
let ret = match first_fragment {
|
|
||||||
"framebuffer" => framebuffer_parse(qt_parse_step_two),
|
|
||||||
"cpu" => cpu_parse(qt_parse_step_two),
|
|
||||||
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cpu_parse(qt_parse_step_two: Vec<String>) -> 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<String>) -> u64 {
|
|
||||||
use crate::kmain::FB_REQ;
|
|
||||||
let fbs = &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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
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);
|
|
||||||
|
|
||||||
let log_level = msg_vec.last().unwrap();
|
|
||||||
|
|
||||||
let file_name = "None";
|
|
||||||
let line_number = 0;
|
|
||||||
|
|
||||||
match core::str::from_utf8(&msg_vec[..msg_vec.len()]) {
|
|
||||||
Ok(strr) => {
|
|
||||||
use log::Level::*;
|
|
||||||
let log_level = match log_level {
|
|
||||||
0 | 48 => Error,
|
|
||||||
1 | 49 => Warn,
|
|
||||||
2 | 50 => Info,
|
|
||||||
3 | 51 => Debug,
|
|
||||||
4 | 52 => Trace,
|
|
||||||
_ => {
|
|
||||||
return Err(LogError::InvalidLogFormat);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
log::logger().log(
|
|
||||||
&Record::builder()
|
|
||||||
.args(format_args!("{}", strr))
|
|
||||||
.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,7 +1,10 @@
|
||||||
use {
|
use {
|
||||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
crate::holeybytes::{
|
||||||
alloc::alloc::{alloc, dealloc},
|
ecah::LogError,
|
||||||
core::alloc::Layout,
|
kernel_services::{block_read, mem_serve},
|
||||||
|
Vm,
|
||||||
|
},
|
||||||
|
alloc::alloc::alloc_zeroed,
|
||||||
log::{debug, info},
|
log::{debug, info},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,10 +19,13 @@ pub enum MemoryQuotaType {
|
||||||
KillQuota = 3,
|
KillQuota = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
fn alloc_page(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), MemoryServiceError> {
|
||||||
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 4096)) };
|
let mut val = alloc::vec::Vec::new();
|
||||||
info!("Block address: {:?}", ptr);
|
for _ in 0..4096 {
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
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);
|
vm.registers[2] = hbvm::value::Value(4096);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -29,39 +35,28 @@ pub fn memory_msg_handler(
|
||||||
mem_addr: u64,
|
mem_addr: u64,
|
||||||
length: usize,
|
length: usize,
|
||||||
) -> Result<(), MemoryServiceError> {
|
) -> Result<(), MemoryServiceError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let mut msg_vec = block_read(mem_addr, length);
|
||||||
let msg_type = msg_vec[0];
|
let msg_type = msg_vec[0];
|
||||||
|
msg_vec.remove(0);
|
||||||
match msg_type {
|
match msg_type {
|
||||||
0 => {
|
0 => {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[0];
|
||||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
msg_vec.remove(0);
|
||||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
|
||||||
|
|
||||||
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
|
// let mptr_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||||
|
// let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||||
|
|
||||||
let ptr = unsafe {
|
// log::debug!("Allocating {} pages @ {}", page_count, mptr);
|
||||||
alloc(Layout::from_size_align_unchecked(
|
|
||||||
page_count as usize * 4096,
|
|
||||||
4096,
|
|
||||||
))
|
|
||||||
};
|
|
||||||
|
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
let mut val = alloc::vec::Vec::new();
|
||||||
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
for _ in 0..(page_count as isize * 4096) {
|
||||||
|
val.push(0);
|
||||||
|
}
|
||||||
|
vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
1 => {
|
1 => {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[0];
|
||||||
|
msg_vec.remove(0);
|
||||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
|
||||||
let mptr: 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, 4096),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
use MemoryQuotaType::*;
|
use MemoryQuotaType::*;
|
||||||
|
@ -72,23 +67,25 @@ pub fn memory_msg_handler(
|
||||||
3 => KillQuota,
|
3 => KillQuota,
|
||||||
_ => NoQuota,
|
_ => NoQuota,
|
||||||
};
|
};
|
||||||
let hid_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
msg_vec.remove(0);
|
||||||
|
let hid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||||
let hid: u64 = u64::from_le_bytes(hid_raw);
|
let hid: u64 = u64::from_le_bytes(hid_raw);
|
||||||
let pid_raw: [u8; 8] = msg_vec[10..18].try_into().unwrap();
|
for _ in 0..8 {
|
||||||
let pid: u64 = u64::from_le_bytes(pid_raw);
|
msg_vec.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let pid_raw: [u8; 8] = msg_vec[0..8].try_into().unwrap();
|
||||||
|
let pid: u64 = u64::from_le_bytes(hid_raw);
|
||||||
|
for _ in 0..8 {
|
||||||
|
msg_vec.remove(0);
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Setting HID-{:x}:PID-{:x}'s quota type to {:?}",
|
"Setting HID-{:x}:PID-{:x}'s quota type to {:?}",
|
||||||
hid, pid, quota_type
|
hid, pid, quota_type
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
3 => {
|
_ => {}
|
||||||
let page_count = msg_vec[0];
|
|
||||||
log::debug!(" {} pages", page_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
log::debug!("Unknown memory service message type: {}", msg_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
use core::slice;
|
use alloc::{vec, vec::Vec};
|
||||||
|
|
||||||
pub mod dt_msg_handler;
|
|
||||||
pub mod logging_service;
|
|
||||||
pub mod mem_serve;
|
pub mod mem_serve;
|
||||||
pub mod service_definition_service;
|
pub mod service_definition_service;
|
||||||
|
|
||||||
#[inline(always)]
|
pub fn block_read(mem_addr: u64, length: usize) -> Vec<u8> {
|
||||||
pub fn block_read<'a>(mem_addr: u64, length: usize) -> &'a mut [u8] {
|
let mut msg_vec = vec![];
|
||||||
unsafe { slice::from_raw_parts_mut(mem_addr as *mut _, 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);
|
||||||
|
}
|
||||||
|
msg_vec
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,35 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
alloc::string::ToString,
|
||||||
arch::hardware_random_u64,
|
arch::hardware_random_u64,
|
||||||
holeybytes::{kernel_services::block_read, Vm},
|
holeybytes::{ecah::LogError, kernel_services::block_read, Vm},
|
||||||
ipc::{buffer::IpcBuffer, protocol::Protocol},
|
ipc::{protocol, protocol::Protocol},
|
||||||
kmain::IPC_BUFFERS,
|
|
||||||
},
|
},
|
||||||
|
alloc::string::String,
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
log::{info, trace},
|
log::info,
|
||||||
spin::{lazy::Lazy, Mutex},
|
spin::{lazy::Lazy, Mutex},
|
||||||
};
|
};
|
||||||
pub struct Services<'a>(HashMap<u64, Protocol<'a>>);
|
pub struct Services(HashMap<u64, Protocol>);
|
||||||
pub static SERVICES: Lazy<Mutex<Services>> = Lazy::new(|| {
|
pub static SERVICES: Lazy<Mutex<Services>> = Lazy::new(|| {
|
||||||
let mut dt = Services(HashMap::new());
|
let mut dt = Services(HashMap::new());
|
||||||
dt.0.insert(0, Protocol::void());
|
dt.0.insert(0, Protocol::void());
|
||||||
Mutex::new(dt)
|
Mutex::new(dt)
|
||||||
});
|
});
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ServiceError {
|
|
||||||
InvalidFormat,
|
|
||||||
}
|
|
||||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
|
||||||
let msg_vec = block_read(mem_addr, length);
|
|
||||||
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
|
||||||
|
|
||||||
// info!("Length {}", msg_vec.len());
|
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
|
let mut msg_vec = block_read(mem_addr, length);
|
||||||
|
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
||||||
|
msg_vec.remove(0);
|
||||||
|
|
||||||
use ServiceEventType::*;
|
use ServiceEventType::*;
|
||||||
match sds_event_type {
|
match sds_event_type {
|
||||||
CreateService => {
|
CreateService => {
|
||||||
let string =
|
let string = String::from_utf8(msg_vec).expect("Our bytes should be valid utf8");
|
||||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
sds_create_service(string);
|
||||||
let ret = sds_create_service(string);
|
|
||||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
|
||||||
}
|
}
|
||||||
DeleteService => todo!(),
|
DeleteService => todo!(),
|
||||||
SearchServices => {
|
SearchServices => todo!(),
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// let buffer_id_raw = &msg_vec[0..8];
|
// let buffer_id_raw = &msg_vec[0..8];
|
||||||
// let mut arr = [0u8; 8];
|
// let mut arr = [0u8; 8];
|
||||||
|
@ -69,41 +59,16 @@ impl From<u8> for ServiceEventType {
|
||||||
// 1 =>
|
// 1 =>
|
||||||
2 => Self::DeleteService,
|
2 => Self::DeleteService,
|
||||||
3 => Self::SearchServices,
|
3 => Self::SearchServices,
|
||||||
10 => {
|
|
||||||
info!("TEST");
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
1_u8 | 4_u8..=u8::MAX => todo!(),
|
1_u8 | 4_u8..=u8::MAX => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sds_create_service(protocol: &'static str) -> u64 {
|
fn sds_create_service(protocol: String) -> u64 {
|
||||||
let buff_id = hardware_random_u64();
|
let buff_id = hardware_random_u64();
|
||||||
let mut services = SERVICES.lock();
|
let mut services = SERVICES.lock();
|
||||||
let mut buffers = IPC_BUFFERS.lock();
|
services.0.insert(buff_id, protocol.clone().into());
|
||||||
|
info!("BufferID({}) => {}", buff_id, protocol);
|
||||||
let protocol_ = Protocol::from(protocol);
|
let a: protocol::Protocol = protocol.into();
|
||||||
let mut buff = IpcBuffer::new(false, 0);
|
|
||||||
|
|
||||||
services.0.insert(buff_id, protocol_.clone());
|
|
||||||
buff.protocol = protocol_;
|
|
||||||
buffers.insert(buff_id, buff);
|
|
||||||
|
|
||||||
trace!("BufferID({}) => {}", buff_id, protocol);
|
|
||||||
// let a: protocol::Protocol = protocol.into();
|
|
||||||
buff_id
|
buff_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sds_search_service(protocol: &str) -> u64 {
|
|
||||||
let services = SERVICES.lock();
|
|
||||||
let compare = Protocol::from(protocol);
|
|
||||||
for (bid, protocol_canidate) in &services.0 {
|
|
||||||
trace!("BID-{bid} protocol_canidate {:?}", protocol_canidate);
|
|
||||||
if protocol_canidate == &compare {
|
|
||||||
trace!("BufferID({}) => {}", bid, protocol);
|
|
||||||
return *bid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use hbvm::mem::Address;
|
use hbvm::mem::Address;
|
||||||
|
|
||||||
fn calc_start_of_page(ptr: u64) -> u64 {
|
fn calc_start_of_page(ptr: u64) -> u64 {
|
||||||
let _page_aligned = false;
|
let mut page_aligned = false;
|
||||||
if ptr % 4096 == 0 {
|
if ptr % 4096 == 0 {
|
||||||
// page_aligned = true;
|
// page_aligned = true;
|
||||||
return ptr / 4096;
|
return ptr / 4096;
|
||||||
|
@ -21,11 +21,11 @@ pub struct Memory {
|
||||||
|
|
||||||
impl Memory {
|
impl Memory {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn read_device(_addr: Address) {
|
fn read_device(addr: Address) {
|
||||||
//unsafe {
|
unsafe {
|
||||||
//
|
//
|
||||||
// x86_64::instructions::port::Port::new(addr.get()).read()
|
// x86_64::instructions::port::Port::new(addr.get()).read()
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ impl hbvm::mem::Memory for Memory {
|
||||||
target: *mut u8,
|
target: *mut u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
) -> Result<(), hbvm::mem::LoadError> {
|
||||||
|
use log::{error, info};
|
||||||
if addr.get() % 4096 == 0 {}
|
if addr.get() % 4096 == 0 {}
|
||||||
core::ptr::copy(addr.get() as *const u8, target, count);
|
core::ptr::copy(addr.get() as *const u8, target, count);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -55,6 +56,6 @@ impl hbvm::mem::Memory for Memory {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
||||||
(addr.get() as *const T).read()
|
(addr.get() as *const T).read_unaligned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,62 +3,68 @@ mod kernel_services;
|
||||||
mod mem;
|
mod mem;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
alloc::alloc::{alloc, dealloc},
|
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||||
core::{
|
alloc::boxed::Box,
|
||||||
alloc::Layout,
|
core::{default, future::Future, marker::PhantomData, ptr::NonNull, task::Poll},
|
||||||
future::Future,
|
|
||||||
pin::Pin,
|
|
||||||
task::{Context, Poll},
|
|
||||||
},
|
|
||||||
hbvm::{
|
hbvm::{
|
||||||
mem::{softpaging::HandlePageFault, Address},
|
mem::{
|
||||||
|
softpaging::{icache::ICache, HandlePageFault, SoftPagedMem},
|
||||||
|
Address, Memory,
|
||||||
|
},
|
||||||
VmRunError, VmRunOk,
|
VmRunError, VmRunOk,
|
||||||
},
|
},
|
||||||
log::error,
|
log::{debug, error, info, trace, warn},
|
||||||
};
|
};
|
||||||
|
|
||||||
const STACK_SIZE: usize = 1024 * 1024;
|
const STACK_SIZE: usize = 1024 * 1024;
|
||||||
const TIMER_QUOTIENT: usize = 1000;
|
const TIMER_QUOTIENT: usize = 100;
|
||||||
type Vm = hbvm::Vm<mem::Memory, TIMER_QUOTIENT>;
|
type Vm = hbvm::Vm<mem::Memory, TIMER_QUOTIENT>;
|
||||||
|
|
||||||
pub struct ExecThread {
|
pub struct ExecThread<'p> {
|
||||||
vm: Vm,
|
vm: Vm,
|
||||||
stack_bottom: *mut u8,
|
stack_bottom: *mut u8,
|
||||||
|
_phantom: PhantomData<&'p [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ExecThread {}
|
unsafe impl<'p> Send for ExecThread<'p> {}
|
||||||
|
impl<'p> ExecThread<'p> {
|
||||||
impl ExecThread {
|
|
||||||
pub fn set_arguments(&mut self, ptr: u64, length: u64) {
|
pub fn set_arguments(&mut self, ptr: u64, length: u64) {
|
||||||
self.vm.registers[1] = hbvm::value::Value(ptr);
|
self.vm.registers[1] = hbvm::value::Value(ptr);
|
||||||
self.vm.registers[2] = hbvm::value::Value(length);
|
self.vm.registers[2] = hbvm::value::Value(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self {
|
pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self {
|
||||||
let mut vm = Vm::new(
|
let mut vm = unsafe {
|
||||||
|
Vm::new(
|
||||||
mem::Memory {},
|
mem::Memory {},
|
||||||
Address::new(program.as_ptr() as u64 + entrypoint.get()),
|
Address::new(program.as_ptr() as u64 + entrypoint.get()),
|
||||||
);
|
)
|
||||||
|
};
|
||||||
let stack_bottom = allocate_stack();
|
|
||||||
|
|
||||||
|
let stack_bottom = unsafe { allocate_stack().as_ptr() };
|
||||||
vm.write_reg(254, (stack_bottom as usize + STACK_SIZE - 1) as u64);
|
vm.write_reg(254, (stack_bottom as usize + STACK_SIZE - 1) as u64);
|
||||||
|
|
||||||
ExecThread { vm, stack_bottom }
|
ExecThread {
|
||||||
|
vm,
|
||||||
|
stack_bottom,
|
||||||
|
_phantom: Default::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Drop for ExecThread {
|
impl<'p> Drop for ExecThread<'p> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { dealloc(self.stack_bottom, stack_layout()) };
|
unsafe { alloc::alloc::dealloc(self.stack_bottom, stack_layout()) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> Future for ExecThread {
|
impl<'p> Future for ExecThread<'p> {
|
||||||
type Output = Result<(), VmRunError>;
|
type Output = Result<(), VmRunError>;
|
||||||
|
|
||||||
#[inline(always)]
|
fn poll(
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
mut self: core::pin::Pin<&mut Self>,
|
||||||
|
cx: &mut core::task::Context<'_>,
|
||||||
|
) -> Poll<Self::Output> {
|
||||||
match self.vm.run() {
|
match self.vm.run() {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers,);
|
log::error!("HBVM Error\r\nRegister dump: {:?}", self.vm.registers,);
|
||||||
|
@ -85,22 +91,33 @@ impl HandlePageFault for PageFaultHandler {
|
||||||
fn page_fault(
|
fn page_fault(
|
||||||
&mut self,
|
&mut self,
|
||||||
reason: hbvm::mem::MemoryAccessReason,
|
reason: hbvm::mem::MemoryAccessReason,
|
||||||
_pagetable: &mut hbvm::mem::softpaging::paging::PageTable,
|
pagetable: &mut hbvm::mem::softpaging::paging::PageTable,
|
||||||
vaddr: hbvm::mem::Address,
|
vaddr: hbvm::mem::Address,
|
||||||
size: hbvm::mem::softpaging::PageSize,
|
size: hbvm::mem::softpaging::PageSize,
|
||||||
dataptr: *mut u8,
|
dataptr: *mut u8,
|
||||||
) -> bool {
|
) -> bool
|
||||||
error!("REASON: {reason} vaddr: {vaddr} size: {size:?} Dataptr {dataptr:p}");
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
log::error!(
|
||||||
|
"REASON: {reason} \
|
||||||
|
vaddr: {vaddr} \
|
||||||
|
size: {size:?} \
|
||||||
|
Dataptr {dataptr:p}",
|
||||||
|
);
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
const fn stack_layout() -> core::alloc::Layout {
|
||||||
const fn stack_layout() -> Layout {
|
unsafe { alloc::alloc::Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
||||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
fn allocate_stack() -> NonNull<u8> {
|
||||||
fn allocate_stack() -> *mut u8 {
|
let layout = stack_layout();
|
||||||
unsafe { alloc(stack_layout()) }
|
match NonNull::new(unsafe { alloc::alloc::alloc_zeroed(layout) }) {
|
||||||
|
Some(ptr) => ptr,
|
||||||
|
None => alloc::alloc::handle_alloc_error(layout),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ pub enum BufferTypes {
|
||||||
Bound(ArrayQueue<Message>),
|
Bound(ArrayQueue<Message>),
|
||||||
}
|
}
|
||||||
/// Interproccess buffer
|
/// Interproccess buffer
|
||||||
pub struct IpcBuffer<'a> {
|
pub struct IpcBuffer {
|
||||||
pub protocol: Protocol<'a>,
|
pub protocol: Protocol,
|
||||||
pub buffer: BufferTypes,
|
pub buffer: BufferTypes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IpcBuffer<'a> {
|
impl IpcBuffer {
|
||||||
pub fn new(bounded: bool, length: u64) -> Self {
|
pub fn new(bounded: bool, length: u64) -> Self {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"New IPCBuffer\r
|
"New IPCBuffer\r
|
||||||
|
@ -23,8 +23,9 @@ impl<'a> IpcBuffer<'a> {
|
||||||
bounded,
|
bounded,
|
||||||
length
|
length
|
||||||
);
|
);
|
||||||
|
|
||||||
match (bounded, length) {
|
match (bounded, length) {
|
||||||
(false, ..) => {
|
(false, a) => {
|
||||||
let buftype = BufferTypes::Unbound(SegQueue::new());
|
let buftype = BufferTypes::Unbound(SegQueue::new());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -48,27 +49,25 @@ impl<'a> IpcBuffer<'a> {
|
||||||
}
|
}
|
||||||
pub fn push(&mut self, msg: Message) {
|
pub fn push(&mut self, msg: Message) {
|
||||||
match &self.buffer {
|
match &self.buffer {
|
||||||
BufferTypes::Unbound(buff) => buff.push(msg),
|
BufferTypes::Unbound(buff) => buff.push(msg.clone()),
|
||||||
BufferTypes::Bound(buff) => {
|
BufferTypes::Bound(buff) => {
|
||||||
let _ = buff.push(msg);
|
let _ = buff.push(msg.clone());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn pop(&mut self) -> Result<Message, IpcError> {
|
pub fn pop(&mut self) -> Message {
|
||||||
let msg = match &self.buffer {
|
let msg = match &self.buffer {
|
||||||
BufferTypes::Unbound(buff) => buff.pop(),
|
BufferTypes::Unbound(buff) => buff.pop(),
|
||||||
BufferTypes::Bound(buff) => buff.pop(),
|
BufferTypes::Bound(buff) => buff.pop(),
|
||||||
};
|
};
|
||||||
match msg {
|
match msg {
|
||||||
Some(msg) => return Ok(msg),
|
Some(msg) => return msg,
|
||||||
None => return Err(IpcError::NoMessagesInBuffer),
|
None => panic!("Recieving msg error. No messages!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Interprocess Communication Errors
|
/// Interprocess Communication Errors
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum IpcError {
|
pub enum IpcError {
|
||||||
/// An invalid message error returned to the sender
|
/// An invalid message error returned to the sender
|
||||||
InvalidMessage,
|
InvalidMessage,
|
||||||
NoMessagesInBuffer,
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
use {
|
use {
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
|
log::info,
|
||||||
};
|
};
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct Type {}
|
pub struct Type {}
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct Funct {
|
pub struct Funct {
|
||||||
takes: Vec<String>,
|
takes: Vec<String>,
|
||||||
gives: Vec<String>,
|
gives: Vec<String>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct Protocol<'a> {
|
pub struct Protocol {
|
||||||
types: HashMap<&'a str, Type>,
|
types: HashMap<String, Type>,
|
||||||
fns: HashMap<&'a str, Funct>,
|
fns: HashMap<String, Funct>,
|
||||||
}
|
}
|
||||||
impl<'a> Protocol<'a> {
|
impl Protocol {
|
||||||
pub fn void() -> Self {
|
pub fn void() -> Self {
|
||||||
Self {
|
Self {
|
||||||
types: HashMap::new(),
|
types: HashMap::new(),
|
||||||
|
@ -27,12 +27,13 @@ impl<'a> Protocol<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Protocol<'a> {
|
impl From<String> for Protocol {
|
||||||
fn from(value: &'a str) -> Self {
|
fn from(value: alloc::string::String) -> Self {
|
||||||
let mut hm_t = HashMap::new();
|
if value.starts_with("protocol") {
|
||||||
hm_t.insert(value, Type {});
|
info!("ABC");
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
types: hm_t,
|
types: HashMap::new(),
|
||||||
fns: HashMap::new(),
|
fns: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,25 +2,27 @@
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
arch::hardware_random_u64,
|
arch::{hardware_random_u64, logging::SERIAL_CONSOLE},
|
||||||
bootmodules::BootModules,
|
bootmodules::{build_cmd, BootModules},
|
||||||
//bootmodules::build_cmd,
|
capabilities,
|
||||||
device_tree::DeviceTree,
|
device_tree::DeviceTree,
|
||||||
holeybytes::ExecThread,
|
holeybytes::ExecThread,
|
||||||
ipc::buffer::IpcBuffer,
|
ipc::buffer::{self, IpcBuffer},
|
||||||
},
|
},
|
||||||
|
alloc::format,
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
hbvm::mem::Address,
|
hbvm::mem::Address,
|
||||||
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
||||||
log::{debug, error, trace},
|
log::{debug, info, trace},
|
||||||
spin::{Lazy, Mutex},
|
spin::{Lazy, Mutex},
|
||||||
|
xml::XMLElement,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
debug!("Entered kmain");
|
debug!("Entered kmain");
|
||||||
|
|
||||||
// let kcmd = build_cmd("Kernel Command Line", cmdline);
|
let kcmd = build_cmd("Kernel Command Line", cmdline);
|
||||||
// trace!("Cmdline: {kcmd:?}");
|
trace!("Cmdline: {kcmd:?}");
|
||||||
|
|
||||||
// for (i, bm) in boot_modules.iter().enumerate() {
|
// for (i, bm) in boot_modules.iter().enumerate() {
|
||||||
// let name = format!("module-{}", i);
|
// let name = format!("module-{}", i);
|
||||||
|
@ -36,9 +38,9 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
let dt = DEVICE_TREE.lock();
|
let dt = DEVICE_TREE.lock();
|
||||||
|
|
||||||
// TODO(Able): This line causes a deadlock
|
// TODO(Able): This line causes a deadlock
|
||||||
debug!("Device Tree: {}", dt);
|
info!("Device Tree: {}", dt);
|
||||||
|
|
||||||
trace!("Boot complete. Moving to init_system");
|
info!("Boot complete. Moving to init_system");
|
||||||
|
|
||||||
// TODO: schedule the disk driver from the initramfs
|
// TODO: schedule the disk driver from the initramfs
|
||||||
// TODO: schedule the filesystem driver from the initramfs
|
// TODO: schedule the filesystem driver from the initramfs
|
||||||
|
@ -56,57 +58,43 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
|
|
||||||
disp.set_attribute("width", fb1.width);
|
disp.set_attribute("width", fb1.width);
|
||||||
disp.set_attribute("height", fb1.height);
|
disp.set_attribute("height", fb1.height);
|
||||||
disp.set_attribute("bpp", fb1.bpp);
|
disp.set_attribute("bits per pixel", fb1.bpp);
|
||||||
disp.set_attribute("pitch", fb1.pitch);
|
disp.set_attribute("pitch", fb1.pitch);
|
||||||
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||||
}
|
}
|
||||||
debug!("Graphics initialised");
|
log::info!("Graphics initialised");
|
||||||
debug!(
|
log::info!(
|
||||||
"Graphics front ptr {:?}",
|
"Graphics front ptr {:?}",
|
||||||
fb1.address.as_ptr().unwrap() as *const u8
|
fb1.address.as_ptr().unwrap() as *const u8
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut executor = crate::task::Executor::new(256);
|
let mut executor = crate::task::Executor::default();
|
||||||
|
let bm_take = boot_modules.len();
|
||||||
unsafe {
|
unsafe {
|
||||||
for module in boot_modules.iter() {
|
for module in boot_modules.into_iter().take(bm_take) {
|
||||||
let cmd = module.cmd.trim_matches('"');
|
let mut cmd = module.cmd;
|
||||||
let cmd_len = cmd.len() as u64;
|
if cmd.len() > 2 {
|
||||||
|
// Remove the quotes
|
||||||
|
cmd.remove(0);
|
||||||
|
cmd.pop();
|
||||||
|
}
|
||||||
|
let cmd_len = cmd.as_bytes().len() as u64;
|
||||||
|
|
||||||
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||||
|
|
||||||
// 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::info!("{code_length} + {data_length} = {end}");
|
|
||||||
|
|
||||||
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
|
|
||||||
if cmd_len > 0 {
|
|
||||||
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
|
|
||||||
}
|
|
||||||
executor.spawn(async move {
|
executor.spawn(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);
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = thr.await {
|
if let Err(e) = thr.await {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Random number: {}", hardware_random_u64());
|
info!("Random number: {}", hardware_random_u64());
|
||||||
|
|
||||||
executor.run();
|
executor.run();
|
||||||
};
|
};
|
||||||
|
@ -120,7 +108,8 @@ pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
||||||
});
|
});
|
||||||
pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||||
|
|
||||||
pub type IpcBuffers<'a> = HashMap<u64, IpcBuffer<'a>>;
|
use alloc::vec::Vec;
|
||||||
|
pub type IpcBuffers = HashMap<u64, IpcBuffer>;
|
||||||
pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
|
pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
|
||||||
let mut bufs = HashMap::new();
|
let mut bufs = HashMap::new();
|
||||||
let log_buffer = IpcBuffer::new(false, 0);
|
let log_buffer = IpcBuffer::new(false, 0);
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
//! The ableOS kernel.
|
//! The ableOS kernel.
|
||||||
//! Named akern.
|
//! Named akern.
|
||||||
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
|
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(
|
#![feature(
|
||||||
exclusive_wrapper,
|
|
||||||
new_uninit,
|
|
||||||
abi_x86_interrupt,
|
abi_x86_interrupt,
|
||||||
alloc_error_handler,
|
alloc_error_handler,
|
||||||
|
inline_const,
|
||||||
|
panic_info_message,
|
||||||
|
pointer_is_aligned,
|
||||||
ptr_sub_ptr,
|
ptr_sub_ptr,
|
||||||
custom_test_frameworks,
|
custom_test_frameworks,
|
||||||
naked_functions,
|
naked_functions,
|
||||||
pointer_is_aligned_to
|
pointer_is_aligned_to
|
||||||
)]
|
)]
|
||||||
#![test_runner(crate::test_runner)]
|
|
||||||
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
#![test_runner(crate::test_runner)]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
|
@ -22,7 +23,6 @@ mod arch;
|
||||||
mod bootmodules;
|
mod bootmodules;
|
||||||
mod capabilities;
|
mod capabilities;
|
||||||
mod device_tree;
|
mod device_tree;
|
||||||
mod exe_format;
|
|
||||||
mod handle;
|
mod handle;
|
||||||
mod holeybytes;
|
mod holeybytes;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
|
@ -42,7 +42,6 @@ pub const VERSION: Version = Version {
|
||||||
};
|
};
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
#[cfg(target_os = "none")]
|
|
||||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
arch::register_dump();
|
arch::register_dump();
|
||||||
|
|
||||||
|
@ -55,8 +54,10 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg = info.message();
|
if let Some(msg) = info.message() {
|
||||||
let _ = crate::arch::log(format_args!("{msg}\r\n"));
|
let _ = crate::arch::log(format_args!("{msg}\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![allow(deprecated)]
|
|
||||||
// TODO: Add a logger api with logger levels and various outputs
|
// TODO: Add a logger api with logger levels and various outputs
|
||||||
pub static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
pub static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||||
|
|
||||||
|
@ -10,11 +9,7 @@ use {
|
||||||
|
|
||||||
pub fn init() -> Result<(), SetLoggerError> {
|
pub fn init() -> Result<(), SetLoggerError> {
|
||||||
log::set_logger(&crate::logger::Logger)?;
|
log::set_logger(&crate::logger::Logger)?;
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
log::set_max_level(log::LevelFilter::Debug);
|
log::set_max_level(log::LevelFilter::Debug);
|
||||||
} else {
|
|
||||||
log::set_max_level(log::LevelFilter::Info);
|
|
||||||
}
|
|
||||||
|
|
||||||
Lazy::force(&TERMINAL_LOGGER);
|
Lazy::force(&TERMINAL_LOGGER);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! The Memory Manager
|
//! The Memory Manager
|
||||||
|
|
||||||
use {alloc::collections::VecDeque, derive_more::*};
|
use alloc::collections::VecDeque;
|
||||||
|
use derive_more::*;
|
||||||
|
|
||||||
pub use crate::arch::PAGE_SIZE;
|
pub use crate::arch::PAGE_SIZE;
|
||||||
pub const MAX_ORDER: usize = 10;
|
pub const MAX_ORDER: usize = 10;
|
||||||
|
@ -43,7 +44,7 @@ pub const MAX_ORDER: usize = 10;
|
||||||
Sum,
|
Sum,
|
||||||
UpperHex,
|
UpperHex,
|
||||||
)]
|
)]
|
||||||
#[display("0x{:x}", _0)]
|
#[display(fmt = "0x{:x}", _0)]
|
||||||
#[from(forward)]
|
#[from(forward)]
|
||||||
pub struct VirtualAddress(usize);
|
pub struct VirtualAddress(usize);
|
||||||
|
|
||||||
|
@ -54,11 +55,11 @@ impl VirtualAddress {
|
||||||
pub fn vpns(&self) -> [usize; 3] {
|
pub fn vpns(&self) -> [usize; 3] {
|
||||||
[
|
[
|
||||||
// [20:12]
|
// [20:12]
|
||||||
(self.0 >> 12) & 0x1FF,
|
(self.0 >> 12) & 0x1ff,
|
||||||
// [29:21]
|
// [29:21]
|
||||||
(self.0 >> 21) & 0x1FF,
|
(self.0 >> 21) & 0x1ff,
|
||||||
// [38:30]
|
// [38:30]
|
||||||
(self.0 >> 30) & 0x1FF,
|
(self.0 >> 30) & 0x1ff,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ impl VirtualAddress {
|
||||||
Sum,
|
Sum,
|
||||||
UpperHex,
|
UpperHex,
|
||||||
)]
|
)]
|
||||||
#[display("0x{:x}", _0)]
|
#[display(fmt = "0x{:x}", _0)]
|
||||||
#[from(forward)]
|
#[from(forward)]
|
||||||
pub struct PhysicalAddress(usize);
|
pub struct PhysicalAddress(usize);
|
||||||
|
|
||||||
|
@ -124,11 +125,11 @@ impl PhysicalAddress {
|
||||||
pub fn ppns(&self) -> [usize; 3] {
|
pub fn ppns(&self) -> [usize; 3] {
|
||||||
[
|
[
|
||||||
// [20:12]
|
// [20:12]
|
||||||
(self.0 >> 12) & 0x1FF,
|
(self.0 >> 12) & 0x1ff,
|
||||||
// [29:21]
|
// [29:21]
|
||||||
(self.0 >> 21) & 0x1FF,
|
(self.0 >> 21) & 0x1ff,
|
||||||
// [55:30]
|
// [55:30]
|
||||||
(self.0 >> 30) & 0x3FFFFFF,
|
(self.0 >> 30) & 0x3ffffff,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,31 @@
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
use {
|
use {
|
||||||
alloc::{boxed::Box, sync::Arc},
|
alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake},
|
||||||
core::{
|
core::{
|
||||||
future::Future,
|
future::Future,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
|
task::{Context, Poll, Waker},
|
||||||
},
|
},
|
||||||
crossbeam_queue::SegQueue,
|
crossbeam_queue::SegQueue,
|
||||||
|
kiam::when,
|
||||||
slab::Slab,
|
slab::Slab,
|
||||||
|
spin::RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static SPAWN_QUEUE: RwLock<Option<SpawnQueue>> = RwLock::new(None);
|
||||||
|
pub fn spawn(future: impl Future<Output = ()> + Send + 'static) {
|
||||||
|
match &*SPAWN_QUEUE.read() {
|
||||||
|
Some(s) => s.push(Task::new(future)),
|
||||||
|
None => panic!("no task executor is running"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn yield_now() -> impl Future<Output = ()> {
|
pub fn yield_now() -> impl Future<Output = ()> {
|
||||||
struct YieldNow(bool);
|
struct YieldNow(bool);
|
||||||
impl Future for YieldNow {
|
impl Future for YieldNow {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
if self.0 {
|
if self.0 {
|
||||||
Poll::Ready(())
|
Poll::Ready(())
|
||||||
|
@ -29,150 +40,101 @@ pub fn yield_now() -> impl Future<Output = ()> {
|
||||||
YieldNow(false)
|
YieldNow(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Executor<F: Future<Output = ()> + Send> {
|
#[derive(Default)]
|
||||||
tasks: Slab<Task<F>>,
|
pub struct Executor {
|
||||||
task_queue: Arc<TaskQueue>,
|
tasks: Slab<Task>,
|
||||||
|
queue: TaskQueue,
|
||||||
|
to_spawn: SpawnQueue,
|
||||||
|
wakers: BTreeMap<TaskId, Waker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Future<Output = ()> + Send> Executor<F> {
|
impl Executor {
|
||||||
pub fn new(size: usize) -> Self {
|
pub fn spawn(&mut self, future: impl Future<Output = ()> + Send + 'static) {
|
||||||
Self {
|
self.queue
|
||||||
tasks: Slab::with_capacity(size),
|
.push(TaskId(self.tasks.insert(Task::new(future))));
|
||||||
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 run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let mut task_batch = [0; 32];
|
{
|
||||||
let mut batch_len = 0;
|
let mut global_spawner = SPAWN_QUEUE.write();
|
||||||
|
if global_spawner.is_some() {
|
||||||
|
panic!("Task executor is already running");
|
||||||
|
}
|
||||||
|
|
||||||
|
*global_spawner = Some(Arc::clone(&self.to_spawn));
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
self.task_queue.batch_pop(&mut task_batch, &mut batch_len);
|
when! {
|
||||||
|
let Some(id) = self
|
||||||
|
.to_spawn
|
||||||
|
.pop()
|
||||||
|
.map(|t| TaskId(self.tasks.insert(t)))
|
||||||
|
.or_else(|| self.queue.pop())
|
||||||
|
=> {
|
||||||
|
let Some(task) = self.tasks.get_mut(id.0) else {
|
||||||
|
panic!("Attempted to get task from empty slot: {}", id.0);
|
||||||
|
};
|
||||||
|
|
||||||
if batch_len == 0 {
|
let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| {
|
||||||
if self.task_queue.is_empty() {
|
Waker::from(Arc::new(TaskWaker {
|
||||||
break;
|
id,
|
||||||
} else {
|
queue: Arc::clone(&self.queue),
|
||||||
continue;
|
}))
|
||||||
|
}));
|
||||||
|
|
||||||
|
match task.poll(&mut cx) {
|
||||||
|
Poll::Ready(()) => {
|
||||||
|
self.tasks.remove(id.0);
|
||||||
|
self.wakers.remove(&id);
|
||||||
|
}
|
||||||
|
Poll::Pending => (),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
self.tasks.is_empty() => break,
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for &id in &task_batch[..batch_len] {
|
*SPAWN_QUEUE.write() = None;
|
||||||
if let Some(task) = self.tasks.get_mut(id) {
|
|
||||||
let waker = task
|
|
||||||
.waker
|
|
||||||
.get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue)));
|
|
||||||
|
|
||||||
let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) };
|
|
||||||
let mut cx = Context::from_waker(&waker);
|
|
||||||
|
|
||||||
if let Poll::Ready(()) = task.poll(&mut cx) {
|
|
||||||
self.tasks.remove(id);
|
|
||||||
self.task_queue.free_tasks.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Task<F: Future<Output = ()> + Send> {
|
struct Task {
|
||||||
future: Pin<Box<F>>,
|
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: impl Future<Output = ()> + Send + 'static) -> Self {
|
||||||
pub fn new(future: F) -> Self {
|
log::trace!("New task scheduled");
|
||||||
Self {
|
Self {
|
||||||
future: Box::pin(future),
|
future: Box::pin(future),
|
||||||
waker: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
|
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
|
||||||
self.future.as_mut().poll(cx)
|
self.future.as_mut().poll(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct TaskId(usize);
|
||||||
|
|
||||||
|
type TaskQueue = Arc<SegQueue<TaskId>>;
|
||||||
|
type SpawnQueue = Arc<SegQueue<Task>>;
|
||||||
|
|
||||||
struct TaskWaker {
|
struct TaskWaker {
|
||||||
id: usize,
|
id: TaskId,
|
||||||
task_queue: Arc<TaskQueue>,
|
queue: TaskQueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskWaker {
|
impl Wake for TaskWaker {
|
||||||
#[inline(always)]
|
fn wake(self: Arc<Self>) {
|
||||||
fn new(id: usize, task_queue: Arc<TaskQueue>) -> Self {
|
log::trace!("Woke Task-{:?}", self.id);
|
||||||
Self { id, task_queue }
|
self.wake_by_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
fn wake_by_ref(self: &Arc<Self>) {
|
||||||
fn wake(&self) {
|
self.queue.push(self.id);
|
||||||
self.task_queue.queue.push(self.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_raw_waker(waker: &TaskWaker) -> RawWaker {
|
|
||||||
let ptr = waker as *const TaskWaker;
|
|
||||||
RawWaker::new(ptr.cast(), &VTABLE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw);
|
|
||||||
|
|
||||||
unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
|
|
||||||
let waker = &*(ptr as *const TaskWaker);
|
|
||||||
TaskWaker::into_raw_waker(waker)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn wake_raw(ptr: *const ()) {
|
|
||||||
let waker = &*(ptr as *const TaskWaker);
|
|
||||||
waker.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn wake_by_ref_raw(ptr: *const ()) {
|
|
||||||
let waker = &*(ptr as *const TaskWaker);
|
|
||||||
waker.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn drop_raw(_: *const ()) {}
|
|
||||||
|
|
||||||
struct TaskQueue {
|
|
||||||
queue: SegQueue<usize>,
|
|
||||||
next_task: usize,
|
|
||||||
free_tasks: SegQueue<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TaskQueue {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
queue: SegQueue::new(),
|
|
||||||
next_task: 0,
|
|
||||||
free_tasks: SegQueue::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn batch_pop(&self, output: &mut [usize], len: &mut usize) {
|
|
||||||
*len = 0;
|
|
||||||
while let Some(id) = self.queue.pop() {
|
|
||||||
output[*len] = id;
|
|
||||||
*len += 1;
|
|
||||||
if *len == output.len() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.queue.is_empty()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,15 @@ version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
str-reader = "0.1"
|
str-reader = "0.1.2"
|
||||||
derive_more = { version = "1", default-features = false, features = [
|
derive_more = "0.99"
|
||||||
"add",
|
error-stack = "0.4"
|
||||||
"add_assign",
|
|
||||||
"constructor",
|
|
||||||
"display",
|
|
||||||
"from",
|
|
||||||
"into",
|
|
||||||
"mul",
|
|
||||||
"mul_assign",
|
|
||||||
"not",
|
|
||||||
"sum",
|
|
||||||
] }
|
|
||||||
error-stack = "0.5"
|
|
||||||
fatfs = "0.3"
|
fatfs = "0.3"
|
||||||
toml = "0.8"
|
toml = "0.5.2"
|
||||||
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.12"
|
version = "0.11"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["rustls-tls", "blocking"]
|
features = ["rustls-tls", "blocking"]
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
#![allow(unused)]
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::format,
|
|
||||||
fs::{read_to_string, File},
|
fs::{read_to_string, File},
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
process::exit,
|
process::exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
use {error_stack::Report, hblang::Options};
|
use error_stack::Report;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
|
@ -65,38 +63,38 @@ impl Package {
|
||||||
}
|
}
|
||||||
pub fn build(&self) {
|
pub fn build(&self) {
|
||||||
if self.binaries.contains(&"hblang".to_string()) {
|
if self.binaries.contains(&"hblang".to_string()) {
|
||||||
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
|
let file_order = self.build_cmd.split_ascii_whitespace();
|
||||||
|
let mut files = vec![];
|
||||||
let path = format!("sysdata/programs/{}/{}", self.name, file);
|
for (count, file) in file_order.enumerate() {
|
||||||
let mut bytes = Vec::new();
|
if count != 0 {
|
||||||
// compile here
|
println!("{}", file);
|
||||||
|
files.push(file);
|
||||||
let _ = hblang::run_compiler(
|
}
|
||||||
&path,
|
}
|
||||||
Options {
|
let mut bundle = vec![];
|
||||||
fmt: true,
|
for file in files {
|
||||||
..Default::default()
|
let contents = read_to_string(file).unwrap();
|
||||||
},
|
bundle.push((file, contents));
|
||||||
&mut bytes,
|
}
|
||||||
);
|
|
||||||
let _ = hblang::run_compiler(&path, Default::default(), &mut bytes);
|
|
||||||
|
|
||||||
|
use hblang::{codegen, parser};
|
||||||
|
let mut codegen = codegen::Codegen::default();
|
||||||
|
for (path, content) in bundle.iter() {
|
||||||
|
println!("A");
|
||||||
|
codegen.files = vec![parser::Ast::new(&path, &content, &parser::no_loader)];
|
||||||
|
codegen.generate();
|
||||||
|
}
|
||||||
|
let mut buf = BufWriter::new(Vec::new());
|
||||||
|
codegen.dump(&mut buf);
|
||||||
|
let bytes = buf.into_inner().unwrap();
|
||||||
match std::fs::create_dir("target/programs") {
|
match std::fs::create_dir("target/programs") {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!(),
|
||||||
}
|
}
|
||||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
|
let path = format!("target/test-programs/{}.hbf", self.name);
|
||||||
bytes.clear();
|
let mut file = File::create(path).unwrap();
|
||||||
let _ = hblang::run_compiler(
|
file.write_all(&bytes).unwrap();
|
||||||
&path,
|
|
||||||
Options {
|
|
||||||
dump_asm: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
&mut bytes,
|
|
||||||
);
|
|
||||||
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// #![allow(unused)]
|
|
||||||
|
|
||||||
mod dev;
|
mod dev;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
@ -8,7 +6,7 @@ use {
|
||||||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||||
std::{
|
std::{
|
||||||
// fmt::Display,
|
fmt::Display,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
@ -21,16 +19,21 @@ fn main() -> Result<(), Error> {
|
||||||
let mut args = std::env::args();
|
let mut args = std::env::args();
|
||||||
args.next();
|
args.next();
|
||||||
|
|
||||||
|
// let disk_meta = fs::metadata("target/disk.img").unwrap();
|
||||||
|
// let config_meta = fs::metadata("system.toml").unwrap();
|
||||||
|
|
||||||
|
// if disk_meta.modified().unwrap() < config_meta.modified().unwrap() {
|
||||||
|
// // TODO: work on adding in system.toml support
|
||||||
|
// // TODO: rebuild the disk
|
||||||
|
// }
|
||||||
|
|
||||||
match args.next().as_deref() {
|
match args.next().as_deref() {
|
||||||
Some("build" | "b") => {
|
Some("build" | "b") => {
|
||||||
let mut release = false;
|
let mut release = false;
|
||||||
let mut debuginfo = false;
|
|
||||||
let mut target = Target::X86_64;
|
let mut target = Target::X86_64;
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if arg == "-r" || arg == "--release" {
|
if arg == "-r" || arg == "--release" {
|
||||||
release = true;
|
release = true;
|
||||||
} else if arg == "-d" || arg == "--debuginfo" {
|
|
||||||
debuginfo = true;
|
|
||||||
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||||
target = Target::Riscv64Virt;
|
target = Target::Riscv64Virt;
|
||||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||||
|
@ -40,17 +43,15 @@ fn main() -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build(release, target, debuginfo).change_context(Error::Build)
|
assemble()?;
|
||||||
|
build(release, target).change_context(Error::Build)
|
||||||
}
|
}
|
||||||
Some("run" | "r") => {
|
Some("run" | "r") => {
|
||||||
let mut release = false;
|
let mut release = false;
|
||||||
let mut debuginfo = false;
|
|
||||||
let mut target = Target::X86_64;
|
let mut target = Target::X86_64;
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if arg == "-r" || arg == "--release" {
|
if arg == "-r" || arg == "--release" {
|
||||||
release = true;
|
release = true;
|
||||||
} else if arg == "-d" || arg == "--debuginfo" {
|
|
||||||
debuginfo = true;
|
|
||||||
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
} else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||||
target = Target::Riscv64Virt;
|
target = Target::Riscv64Virt;
|
||||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||||
|
@ -60,7 +61,8 @@ fn main() -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build(release, target, debuginfo)?;
|
assemble()?;
|
||||||
|
build(release, target)?;
|
||||||
run(release, target)
|
run(release, target)
|
||||||
}
|
}
|
||||||
Some("help" | "h") => {
|
Some("help" | "h") => {
|
||||||
|
@ -80,6 +82,49 @@ fn main() -> Result<(), Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assemble() -> Result<(), Error> {
|
||||||
|
match std::fs::create_dir("target/test-programs") {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||||
|
Err(e) => return Err(Report::new(e).change_context(Error::Io)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in std::fs::read_dir("sysdata/test-programs")
|
||||||
|
.map_err(Report::from)
|
||||||
|
.change_context(Error::Io)?
|
||||||
|
{
|
||||||
|
let entry = entry.map_err(Report::from).change_context(Error::Io)?;
|
||||||
|
if !entry
|
||||||
|
.file_type()
|
||||||
|
.map_err(Report::from)
|
||||||
|
.change_context(Error::Io)?
|
||||||
|
.is_file()
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = entry.file_name();
|
||||||
|
let name = name.to_string_lossy();
|
||||||
|
let name = name.trim_end_matches(".rhai");
|
||||||
|
|
||||||
|
let mut out = File::options()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(Path::new("target/test-programs").join(format!("{name}.hbf")))
|
||||||
|
.map_err(Report::from)
|
||||||
|
.change_context(Error::Io)?;
|
||||||
|
|
||||||
|
out.set_len(0)
|
||||||
|
.map_err(Report::from)
|
||||||
|
.change_context(Error::Io)?;
|
||||||
|
|
||||||
|
// hbasm::assembler(&mut out, |engine| engine.run_file(entry.path()))
|
||||||
|
// .map_err(|e| report!(Error::Assembler).attach_printable(e.to_string()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_path_without_boot_prefix(val: &Value) -> Option<&str> {
|
fn get_path_without_boot_prefix(val: &Value) -> Option<&str> {
|
||||||
val.as_str()?.split("boot:///").last()
|
val.as_str()?.split("boot:///").last()
|
||||||
}
|
}
|
||||||
|
@ -195,8 +240,8 @@ TERM_BACKDROP={}
|
||||||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||||
// let mut real_modules = modules.clone();
|
// let mut real_modules = modules.clone();
|
||||||
|
|
||||||
modules.into_iter().for_each(|(_, value)| {
|
modules.into_iter().for_each(|(key, value)| {
|
||||||
if value.is_table() {
|
if value.is_table() && key == "tests" {
|
||||||
let path = get_path_without_boot_prefix(
|
let path = get_path_without_boot_prefix(
|
||||||
value.get("path").expect("You must have `path` as a value"),
|
value.get("path").expect("You must have `path` as a value"),
|
||||||
)
|
)
|
||||||
|
@ -235,7 +280,7 @@ TERM_BACKDROP={}
|
||||||
.expect("You must have a `path` as a value"),
|
.expect("You must have a `path` as a value"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let fpath = format!("target/programs/{}", path);
|
let fpath = format!("target/test-programs/{}", path);
|
||||||
copy_file_to_img(&fpath, &fs);
|
copy_file_to_img(&fpath, &fs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -244,7 +289,7 @@ TERM_BACKDROP={}
|
||||||
let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?;
|
let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?;
|
||||||
|
|
||||||
let mut f = fs.root_dir().create_file("limine.cfg")?;
|
let mut f = fs.root_dir().create_file("limine.cfg")?;
|
||||||
let _ = f.write(limine_str.as_bytes())?;
|
let a = f.write(limine_str.as_bytes())?;
|
||||||
drop(f);
|
drop(f);
|
||||||
|
|
||||||
io::copy(
|
io::copy(
|
||||||
|
@ -267,7 +312,6 @@ TERM_BACKDROP={}
|
||||||
|
|
||||||
fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
|
fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
|
||||||
let path = Path::new(fpath);
|
let path = Path::new(fpath);
|
||||||
// println!("{path:?}");
|
|
||||||
io::copy(
|
io::copy(
|
||||||
&mut File::open(path).expect(&format!("Could not open file {fpath}")),
|
&mut File::open(path).expect(&format!("Could not open file {fpath}")),
|
||||||
&mut fs
|
&mut fs
|
||||||
|
@ -278,7 +322,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
|
||||||
.expect("Copy failed");
|
.expect("Copy failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
fn build(release: bool, target: Target) -> Result<(), Error> {
|
||||||
let fs = get_fs().change_context(Error::Io)?;
|
let fs = get_fs().change_context(Error::Io)?;
|
||||||
let mut com = Command::new("cargo");
|
let mut com = Command::new("cargo");
|
||||||
com.current_dir("kernel");
|
com.current_dir("kernel");
|
||||||
|
@ -286,9 +330,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
if release {
|
if release {
|
||||||
com.arg("-r");
|
com.arg("-r");
|
||||||
}
|
}
|
||||||
if debuginfo {
|
|
||||||
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
|
|
||||||
}
|
|
||||||
|
|
||||||
if target == Target::Riscv64Virt {
|
if target == Target::Riscv64Virt {
|
||||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||||
|
@ -345,12 +386,10 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||||
com.args([
|
com.args([
|
||||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||||
"-drive", "file=target/disk.img,format=raw",
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
"-device", "vmware-svga",
|
"-m", "4G",
|
||||||
"-m", "2G",
|
"-smp", "cores=4",
|
||||||
"-smp", "1",
|
// "-enable-kvm",
|
||||||
"-machine", "accel=kvm",
|
"-cpu", "Broadwell-v4"
|
||||||
"-cpu", "host",
|
|
||||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
Target::Riscv64Virt => {
|
Target::Riscv64Virt => {
|
||||||
|
@ -371,7 +410,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
com.args([
|
com.args([
|
||||||
"-M", "virt",
|
"-M", "virt",
|
||||||
"-cpu", "neoverse-n2",
|
"-cpu", "cortex-a72",
|
||||||
"-device", "ramfb",
|
"-device", "ramfb",
|
||||||
"-device", "qemu-xhci",
|
"-device", "qemu-xhci",
|
||||||
"-device", "usb-kbd",
|
"-device", "usb-kbd",
|
||||||
|
@ -430,11 +469,11 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||||
|
|
||||||
#[derive(Debug, Display)]
|
#[derive(Debug, Display)]
|
||||||
enum OvmfFetchError {
|
enum OvmfFetchError {
|
||||||
#[display("Failed to fetch OVMF package")]
|
#[display(fmt = "Failed to fetch OVMF package")]
|
||||||
Fetch,
|
Fetch,
|
||||||
#[display("No OVMF package available")]
|
#[display(fmt = "No OVMF package available")]
|
||||||
Empty,
|
Empty,
|
||||||
#[display("IO Error")]
|
#[display(fmt = "IO Error")]
|
||||||
Io,
|
Io,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,28 +486,26 @@ enum Target {
|
||||||
Aarch64,
|
Aarch64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
#[derive(Debug, Display)]
|
#[derive(Debug, Display)]
|
||||||
enum Error {
|
enum Error {
|
||||||
#[display("Failed to build the kernel")]
|
#[display(fmt = "Failed to build the kernel")]
|
||||||
Build,
|
Build,
|
||||||
#[display("Missing or invalid subcommand (available: build, run)")]
|
#[display(fmt = "Missing or invalid subcommand (available: build, run)")]
|
||||||
InvalidSubCom,
|
InvalidSubCom,
|
||||||
#[display("IO Error")]
|
#[display(fmt = "IO Error")]
|
||||||
Io,
|
Io,
|
||||||
#[display("Failed to spawn a process")]
|
#[display(fmt = "Failed to spawn a process")]
|
||||||
ProcessSpawn,
|
ProcessSpawn,
|
||||||
#[display("Failed to fetch UEFI firmware")]
|
#[display(fmt = "Failed to fetch UEFI firmware")]
|
||||||
OvmfFetch,
|
OvmfFetch,
|
||||||
#[display("Failed to assemble Holey Bytes code")]
|
#[display(fmt = "Failed to assemble Holey Bytes code")]
|
||||||
Assembler,
|
Assembler,
|
||||||
#[display("QEMU Error: {}", "fmt_qemu_err(*_0)")]
|
#[display(fmt = "QEMU Error: {}", "fmt_qemu_err(*_0)")]
|
||||||
Qemu(Option<i32>),
|
Qemu(Option<i32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context for Error {}
|
impl Context for Error {}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
fn fmt_qemu_err(e: Option<i32>) -> impl Display {
|
fn fmt_qemu_err(e: Option<i32>) -> impl Display {
|
||||||
struct W(Option<i32>);
|
struct W(Option<i32>);
|
||||||
impl Display for W {
|
impl Display for W {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2024-07-27"
|
channel = "nightly-2024-05-17"
|
||||||
components = ["rust-src", "llvm-tools", "rust-analyzer"]
|
components = ["rust-src", "llvm-tools"]
|
||||||
|
|
41
shell.nix
Normal file
41
shell.nix
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{ pkgs ? import <nixpkgs> { } }:
|
||||||
|
pkgs.mkShell rec {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
clang
|
||||||
|
llvmPackages.bintools
|
||||||
|
rustup
|
||||||
|
qemu_full
|
||||||
|
# OMVFFull
|
||||||
|
# OMVF
|
||||||
|
];
|
||||||
|
extraCmds = '''';
|
||||||
|
RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain.toml;
|
||||||
|
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
||||||
|
LIBCLANG_PATH =
|
||||||
|
pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
|
||||||
|
shellHook = ''
|
||||||
|
export REPBUILD_QEMU_FIRMWARE_PATH=${pkgs.OVMF.fd}/FV/OVMF.fd
|
||||||
|
|
||||||
|
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
|
||||||
|
export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
|
||||||
|
'';
|
||||||
|
# Add precompiled library to rustc search path
|
||||||
|
RUSTFLAGS = (builtins.map (a: "-L ${a}/lib") [
|
||||||
|
# add libraries here (e.g. pkgs.libvmi)
|
||||||
|
]);
|
||||||
|
# Add glibc, clang, glib and other headers to bindgen search path
|
||||||
|
BINDGEN_EXTRA_CLANG_ARGS =
|
||||||
|
# Includes with normal include path
|
||||||
|
(builtins.map (a: ''-I"${a}/include"'') [
|
||||||
|
# add dev libraries here (e.g. pkgs.libvmi.dev)
|
||||||
|
pkgs.glibc.dev
|
||||||
|
])
|
||||||
|
# Includes with special directory paths
|
||||||
|
++ [
|
||||||
|
''
|
||||||
|
-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
|
||||||
|
''-I"${pkgs.glib.dev}/include/glib-2.0"''
|
||||||
|
"-I${pkgs.glib.out}/lib/glib-2.0/include/"
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
# abc
|
|
|
@ -1,24 +0,0 @@
|
||||||
@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;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
# dt_api
|
|
|
@ -1,8 +0,0 @@
|
||||||
stn := @use("../../stn/src/lib.hb");
|
|
||||||
.{string, memory, buffer} := stn
|
|
||||||
|
|
||||||
dt_get := fn(query: ^u8): int {
|
|
||||||
message_length := string.length(query)
|
|
||||||
|
|
||||||
return @eca(3, 5, query, message_length)
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Horizon
|
|
||||||
Horizon is the windowing system for ableOS.
|
|
||||||
This is the API library to handle it nicely.
|
|
|
@ -1,25 +0,0 @@
|
||||||
stn := @use("../../stn/src/lib.hb");
|
|
||||||
.{string, memory, buffer} := stn
|
|
||||||
|
|
||||||
input := @use("../../intouch/src/lib.hb")
|
|
||||||
|
|
||||||
WindowID := struct {
|
|
||||||
host_id: int,
|
|
||||||
window_id: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
create_window := fn(channel: int): void {
|
|
||||||
// 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")
|
|
||||||
|
|
||||||
if windowing_system_buffer == 0 {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
msg := "\{01}\0"
|
|
||||||
msg_length := 2
|
|
||||||
return @eca(3, windowing_system_buffer, msg, msg_length)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
# Ignim
|
|
||||||
Ignim is the ableOS vulkan interface library.
|
|
|
@ -1,21 +0,0 @@
|
||||||
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: int,
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
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
|
|
|
@ -1,10 +0,0 @@
|
||||||
Extent3D := struct {
|
|
||||||
width: int,
|
|
||||||
height: int,
|
|
||||||
depth: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
Extent2D := struct {
|
|
||||||
width: int,
|
|
||||||
height: int,
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
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,17 +0,0 @@
|
||||||
application := @use("application.hb")
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
Offset3D := struct {
|
|
||||||
x: int,
|
|
||||||
y: int,
|
|
||||||
z: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
Offset2D := struct {
|
|
||||||
x: int,
|
|
||||||
y: int,
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
offsets := @use("offset.hb")
|
|
||||||
extends := @use("extends.hb")
|
|
||||||
|
|
||||||
Rect2D := struct {
|
|
||||||
offset: offsets.Offset2D,
|
|
||||||
extent: extends.Extent2D,
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
// NonErrors
|
|
||||||
Success := 0
|
|
||||||
NotReady := 1
|
|
||||||
Timeout := 2
|
|
||||||
EventSet := 3
|
|
||||||
EventReset := 4
|
|
||||||
Incomplete := 5
|
|
|
@ -1,61 +0,0 @@
|
||||||
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
|
|
|
@ -1,9 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
# 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
|
|
|
@ -1,2 +0,0 @@
|
||||||
0x0D -> press Tab
|
|
||||||
0xF0 0x0D -> release Tab
|
|
|
@ -1,67 +0,0 @@
|
||||||
KeyCode := u32
|
|
||||||
|
|
||||||
// https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
|
||||||
Backspace := KeyCode.(8)
|
|
||||||
Tab := KeyCode.(9)
|
|
||||||
Clear := KeyCode.(12)
|
|
||||||
Return := KeyCode.(13)
|
|
||||||
Pause := KeyCode.(19)
|
|
||||||
Escape := KeyCode.(27)
|
|
||||||
Space := KeyCode.(32)
|
|
||||||
|
|
||||||
A := KeyCode.(97)
|
|
||||||
/*
|
|
||||||
ETC
|
|
||||||
*/
|
|
||||||
Z := KeyCode.(122)
|
|
||||||
|
|
||||||
Delete := KeyCode.(127)
|
|
||||||
|
|
||||||
/*
|
|
||||||
ETC
|
|
||||||
*/
|
|
||||||
|
|
||||||
KeypadNumber0 := KeyCode.(256)
|
|
||||||
KeypadNumber1 := KeyCode.(257)
|
|
||||||
KeypadNumber2 := KeyCode.(258)
|
|
||||||
KeypadNumber3 := KeyCode.(259)
|
|
||||||
KeypadNumber4 := KeyCode.(260)
|
|
||||||
KeypadNumber5 := KeyCode.(261)
|
|
||||||
KeypadNumber6 := KeyCode.(262)
|
|
||||||
KeypadNumber7 := KeyCode.(263)
|
|
||||||
KeypadNumber8 := KeyCode.(264)
|
|
||||||
KeypadNumber9 := KeyCode.(265)
|
|
||||||
|
|
||||||
KeypadPeriod := KeyCode.(266)
|
|
||||||
KeypadDivide := KeyCode.(267)
|
|
||||||
KeypadMultiply := KeyCode.(268)
|
|
||||||
KeypadMinus := KeyCode.(269)
|
|
||||||
KeypadPlus := KeyCode.(270)
|
|
||||||
KeypadEnter := KeyCode.(271)
|
|
||||||
KeypadEquals := KeyCode.(272)
|
|
||||||
|
|
||||||
NumLock := KeyCode.(300)
|
|
||||||
CapsLock := KeyCode.(301)
|
|
||||||
ScrollLock := KeyCode.(302)
|
|
||||||
|
|
||||||
RightShift := KeyCode.(303)
|
|
||||||
LeftShift := KeyCode.(304)
|
|
||||||
|
|
||||||
RightControl := KeyCode.(305)
|
|
||||||
LeftControl := KeyCode.(306)
|
|
||||||
RightAlt := KeyCode.(307)
|
|
||||||
LeftAlt := KeyCode.(308)
|
|
||||||
RightMeta := KeyCode.(309)
|
|
||||||
LeftMeta := KeyCode.(310)
|
|
||||||
|
|
||||||
/* Left "Windows" key */
|
|
||||||
LeftSuper := KeyCode.(311)
|
|
||||||
|
|
||||||
/* Right "Windows" key */
|
|
||||||
RightSuper := KeyCode.(312)
|
|
||||||
|
|
||||||
/* "Alt Gr" key */
|
|
||||||
Mode := KeyCode.(313)
|
|
||||||
|
|
||||||
/* Multi-key compose key */
|
|
||||||
Compose := KeyCode.(314)
|
|
|
@ -1,22 +0,0 @@
|
||||||
keycodes := @use("keycodes.hb");
|
|
||||||
.{KeyCode} := keycodes
|
|
||||||
|
|
||||||
MouseEvent := struct {
|
|
||||||
x_change: u8,
|
|
||||||
y_change: u8,
|
|
||||||
left: u8,
|
|
||||||
middle: u8,
|
|
||||||
right: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyEvent := struct {
|
|
||||||
// 0 if down
|
|
||||||
// 1 if up
|
|
||||||
up: u8,
|
|
||||||
// 0 if not just triggered
|
|
||||||
// 1 if just triggered
|
|
||||||
just_triggered: u8,
|
|
||||||
key: KeyCode,
|
|
||||||
}
|
|
||||||
|
|
||||||
GamepadEvent := struct {}
|
|
|
@ -1 +0,0 @@
|
||||||
# pci
|
|
|
@ -1,93 +0,0 @@
|
||||||
.{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)
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
Rendering interface for SVGA and Software renderers
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
|
|
||||||
- SVGA Driver
|
|
||||||
- needs pci driver
|
|
||||||
- needs init (requiring program)
|
|
||||||
- Double Buffer mode for Software renderer
|
|
||||||
- needs init (requiring program)
|
|
|
@ -1,47 +0,0 @@
|
||||||
svga := @use("svga.hb")
|
|
||||||
software := @use("software.hb")
|
|
||||||
|
|
||||||
// default mode
|
|
||||||
mode := software
|
|
||||||
|
|
||||||
init := mode.init
|
|
||||||
doublebuffer := mode.doublebuffer
|
|
||||||
|
|
||||||
// Colours
|
|
||||||
Color := mode.Color
|
|
||||||
white := mode.white
|
|
||||||
black := mode.black
|
|
||||||
gray := mode.gray
|
|
||||||
red := mode.red
|
|
||||||
green := mode.green
|
|
||||||
yellow := mode.yellow
|
|
||||||
blue := mode.blue
|
|
||||||
magenta := mode.magenta
|
|
||||||
cyan := mode.cyan
|
|
||||||
light_gray := mode.light_gray
|
|
||||||
light_red := mode.light_red
|
|
||||||
light_green := mode.light_green
|
|
||||||
light_yellow := mode.light_yellow
|
|
||||||
light_blue := mode.light_blue
|
|
||||||
light_magenta := mode.light_magenta
|
|
||||||
light_cyan := mode.light_cyan
|
|
||||||
|
|
||||||
// Drawing
|
|
||||||
put_pixel := mode.put_pixel
|
|
||||||
put_rect := mode.put_rect
|
|
||||||
put_filled_rect := mode.put_filled_rect
|
|
||||||
put_line := mode.put_line
|
|
||||||
clear := mode.clear
|
|
||||||
|
|
||||||
// Display
|
|
||||||
width := mode.width
|
|
||||||
height := mode.height
|
|
||||||
dimensions := mode.dimensions
|
|
||||||
set_height := mode.set_height
|
|
||||||
set_width := mode.set_width
|
|
||||||
set_dimensions := mode.set_dimensions
|
|
||||||
sync := mode.sync
|
|
||||||
|
|
||||||
// Math
|
|
||||||
UVec2 := struct {x: uint, y: uint}
|
|
||||||
IVec2 := struct {x: int, y: int}
|
|
|
@ -1,261 +0,0 @@
|
||||||
.{math, memory} := @use("../../stn/src/lib.hb");
|
|
||||||
.{dt_get} := @use("../../dt_api/src/lib.hb");
|
|
||||||
.{IVec2} := @use("lib.hb")
|
|
||||||
|
|
||||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
|
||||||
white := Color.(255, 255, 255, 255)
|
|
||||||
black := Color.(0, 0, 0, 255)
|
|
||||||
gray := Color.(127, 127, 127, 255)
|
|
||||||
red := Color.(0, 0, 205, 255)
|
|
||||||
green := Color.(0, 205, 0, 255)
|
|
||||||
yellow := Color.(0, 205, 205, 255)
|
|
||||||
blue := Color.(205, 0, 0, 255)
|
|
||||||
magenta := Color.(205, 0, 205, 255)
|
|
||||||
cyan := Color.(205, 205, 0, 255)
|
|
||||||
light_gray := Color.(229, 229, 229, 255)
|
|
||||||
light_red := Color.(0, 0, 255, 255)
|
|
||||||
light_green := Color.(0, 255, 0, 255)
|
|
||||||
light_yellow := Color.(0, 255, 255, 255)
|
|
||||||
light_blue := Color.(255, 0, 0, 255)
|
|
||||||
light_magenta := Color.(255, 0, 255, 255)
|
|
||||||
light_cyan := Color.(255, 255, 0, 255)
|
|
||||||
|
|
||||||
// might not work for some resolutions, but needs to be comptime because...
|
|
||||||
copy_pixels := 0xC000 >> 2
|
|
||||||
|
|
||||||
ctx := @as(Context, idk)
|
|
||||||
|
|
||||||
// some of these are redudant holdovers from fb_driver
|
|
||||||
// will keep them for future work if necessary
|
|
||||||
Context := struct {
|
|
||||||
fb: ^Color,
|
|
||||||
bb: ^Color,
|
|
||||||
buf: ^Color,
|
|
||||||
width: int,
|
|
||||||
height: int,
|
|
||||||
partitions: int,
|
|
||||||
pixels: int,
|
|
||||||
bb_pages: int,
|
|
||||||
double_buffer: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
init := fn(): void {
|
|
||||||
width := dt_get("framebuffer/fb0/width\0")
|
|
||||||
height := dt_get("framebuffer/fb0/height\0")
|
|
||||||
// width := 1024
|
|
||||||
// height := 768
|
|
||||||
pixels := width * height
|
|
||||||
bytes := pixels << 2
|
|
||||||
partitions := pixels / copy_pixels
|
|
||||||
pages := 1 + bytes >> 12
|
|
||||||
back_buffer := create_back_buffer(pages)
|
|
||||||
ctx = Context.{
|
|
||||||
fb: dt_get("framebuffer/fb0/ptr\0"),
|
|
||||||
bb: back_buffer,
|
|
||||||
buf: back_buffer,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
partitions,
|
|
||||||
pixels,
|
|
||||||
bb_pages: pages,
|
|
||||||
double_buffer: true,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
doublebuffer := fn(enable: bool): void {
|
|
||||||
if enable {
|
|
||||||
ctx.buf = ctx.bb
|
|
||||||
} else {
|
|
||||||
ctx.buf = ctx.fb
|
|
||||||
}
|
|
||||||
ctx.double_buffer = enable
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
create_back_buffer := fn(pages: int): ^Color {
|
|
||||||
if pages <= 0xFF {
|
|
||||||
return @bitcast(@inline(memory.request_page, pages))
|
|
||||||
}
|
|
||||||
ptr := @inline(memory.request_page, 255)
|
|
||||||
remaining := pages - 0xFF
|
|
||||||
loop if remaining <= 0 break else {
|
|
||||||
if remaining < 0xFF {
|
|
||||||
memory.request_page(remaining)
|
|
||||||
} else {
|
|
||||||
memory.request_page(0xFF)
|
|
||||||
}
|
|
||||||
remaining -= 0xFF
|
|
||||||
}
|
|
||||||
return @bitcast(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
clear := fn(color: Color): void {
|
|
||||||
cursor := ctx.buf
|
|
||||||
boundary := cursor + 512
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*cursor = color
|
|
||||||
cursor += 1
|
|
||||||
}
|
|
||||||
boundary += 512 * 7
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(ctx.buf))
|
|
||||||
cursor += 512
|
|
||||||
}
|
|
||||||
boundary += copy_pixels - 4096
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(ctx.buf))
|
|
||||||
cursor += 4096
|
|
||||||
}
|
|
||||||
boundary += (ctx.partitions - 1) * copy_pixels
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(ctx.buf))
|
|
||||||
cursor += @sizeof([u8; copy_pixels])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sync := fn(): void {
|
|
||||||
if ctx.double_buffer {
|
|
||||||
bb := ctx.buf
|
|
||||||
fb := ctx.fb
|
|
||||||
boundary := bb + ctx.pixels
|
|
||||||
loop if bb == boundary break else {
|
|
||||||
*@as(^[Color; copy_pixels], @bitcast(fb)) = *@as(^[Color; copy_pixels], @bitcast(bb))
|
|
||||||
bb += copy_pixels
|
|
||||||
fb += copy_pixels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
width := fn(): int {
|
|
||||||
return ctx.width
|
|
||||||
}
|
|
||||||
|
|
||||||
height := fn(): int {
|
|
||||||
return ctx.height
|
|
||||||
}
|
|
||||||
|
|
||||||
screenidx := fn(x: int, y: int): int {
|
|
||||||
return x + ctx.width * y
|
|
||||||
}
|
|
||||||
|
|
||||||
put_pixel := fn(pos: IVec2, color: Color): void {
|
|
||||||
*(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
|
||||||
x := pos.x
|
|
||||||
y := pos.y
|
|
||||||
end := pos + tr
|
|
||||||
loop if x == end.x break else {
|
|
||||||
loop if y == end.y break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
x += 1
|
|
||||||
y = pos.y
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
|
||||||
x := pos.x
|
|
||||||
y := pos.y
|
|
||||||
end := pos + tr
|
|
||||||
loop if y == end.y break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
|
||||||
*(ctx.buf + @inline(screenidx, x + tr.x, y)) = color
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
y = pos.y
|
|
||||||
loop if x == end.x break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y + tr.y)) = color
|
|
||||||
x += 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
dx := p1.x - p0.x
|
|
||||||
dy := p1.y - p0.y
|
|
||||||
yi := 1
|
|
||||||
if dy < 0 {
|
|
||||||
yi = -1
|
|
||||||
dy = -dy
|
|
||||||
}
|
|
||||||
D := 2 * dy - dx
|
|
||||||
y := p0.y
|
|
||||||
x := p0.x
|
|
||||||
loop if x == p1.x break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
||||||
if D > 0 {
|
|
||||||
y += yi
|
|
||||||
D += 2 * (dy - dx)
|
|
||||||
} else {
|
|
||||||
D += 2 * dy
|
|
||||||
}
|
|
||||||
x += 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
dx := p1.x - p0.x
|
|
||||||
dy := p1.y - p0.y
|
|
||||||
xi := 1
|
|
||||||
if dy < 0 {
|
|
||||||
xi = -1
|
|
||||||
dx = -dx
|
|
||||||
}
|
|
||||||
D := 2 * dx - dy
|
|
||||||
x := p0.x
|
|
||||||
y := p0.y
|
|
||||||
loop if y == p1.y break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
||||||
if D > 0 {
|
|
||||||
x += xi
|
|
||||||
D += 2 * (dx - dy)
|
|
||||||
} else {
|
|
||||||
D += 2 * dx
|
|
||||||
}
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) {
|
|
||||||
if p0.x > p1.x {
|
|
||||||
@inline(put_line_low, p1, p0, color)
|
|
||||||
} else {
|
|
||||||
@inline(put_line_low, p0, p1, color)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if p0.y > p1.y {
|
|
||||||
@inline(put_line_high, p1, p0, color)
|
|
||||||
} else {
|
|
||||||
@inline(put_line_high, p0, p1, color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_height := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_width := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dimensions := fn(): IVec2 {
|
|
||||||
return .(ctx.width, ctx.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dimensions := fn(new: IVec2): void {
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
.{IVec2} := @use("lib.hb")
|
|
||||||
// .{pci, memory, string, log} := @use("../../stn/src/lib.hb");
|
|
||||||
|
|
||||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
|
||||||
white := Color.(255, 255, 255, 255)
|
|
||||||
black := Color.(0, 0, 0, 255)
|
|
||||||
gray := Color.(127, 127, 127, 255)
|
|
||||||
red := Color.(0, 0, 205, 255)
|
|
||||||
green := Color.(0, 205, 0, 255)
|
|
||||||
yellow := Color.(0, 205, 205, 255)
|
|
||||||
blue := Color.(205, 0, 0, 255)
|
|
||||||
magenta := Color.(205, 0, 205, 255)
|
|
||||||
cyan := Color.(205, 205, 0, 255)
|
|
||||||
light_gray := Color.(229, 229, 229, 255)
|
|
||||||
light_red := Color.(0, 0, 255, 255)
|
|
||||||
light_green := Color.(0, 255, 0, 255)
|
|
||||||
light_yellow := Color.(0, 255, 255, 255)
|
|
||||||
light_blue := Color.(255, 0, 0, 255)
|
|
||||||
light_magenta := Color.(255, 0, 255, 255)
|
|
||||||
light_cyan := Color.(255, 255, 0, 255)
|
|
||||||
|
|
||||||
clear := fn(color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
width := fn(): int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
height := fn(): int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
dimensions := fn(): IVec2 {
|
|
||||||
return .(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
put_pixel := fn(position: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// do not use, use line() instead
|
|
||||||
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_height := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_width := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dimensions := fn(new: IVec2): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sync := fn(): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
init := fn(): void {
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
//! This is a reserved file for use with the AbleOS Clustering System
|
|
||||||
|
|
||||||
HostID := int
|
|
||||||
ID := int
|
|
||||||
|
|
||||||
FileID := struct {
|
|
||||||
host_id: HostID,
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
// A DeviceID points to a specific device in the ACS.
|
|
||||||
DeviceID := struct {
|
|
||||||
host_id: HostID,
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
DiskID := DeviceID
|
|
||||||
|
|
||||||
BufferID := struct {
|
|
||||||
host_id: HostID,
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessID := struct {
|
|
||||||
host_id: HostID,
|
|
||||||
id: ID,
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowID := struct {
|
|
||||||
host_id: HostID,
|
|
||||||
id: ID,
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
string := @use("string.hb")
|
|
||||||
|
|
||||||
receive_message := fn(buffer_id: int, memory_map_location: ^u8, length: int): ^u8 {
|
|
||||||
return @eca(4, buffer_id, memory_map_location, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
send_message := fn(msg: ^u8, buffer_id: int, length: int): void {
|
|
||||||
return @eca(3, buffer_id, msg, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
create := fn(msg: ^u8): int {
|
|
||||||
msg_length := @inline(string.length, msg);
|
|
||||||
*msg = 0
|
|
||||||
return @eca(3, 0, msg, msg_length)
|
|
||||||
}
|
|
||||||
|
|
||||||
search := fn(msg: ^u8): int {
|
|
||||||
msg_length := @inline(string.length, msg);
|
|
||||||
*msg = 3
|
|
||||||
|
|
||||||
return @eca(3, 0, msg, msg_length)
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
acs := @use("acs.hb");
|
|
||||||
.{DiskID, FileID} := acs
|
|
||||||
|
|
||||||
// Paths without a node-disk component are to be treated as local files.
|
|
||||||
// file_path := "DID:/test\0";
|
|
||||||
Path := struct {
|
|
||||||
// DiskID holds the host id
|
|
||||||
disk_id: DiskID,
|
|
||||||
length: u8,
|
|
||||||
data: ^u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
open := fn(file_path: Path): FileID {
|
|
||||||
}
|
|
||||||
close := fn(file_id: FileID): int {
|
|
||||||
}
|
|
||||||
// This reads in page_count of pages out of the file. If file_size is less than an exact multiple of pages do something.
|
|
||||||
// TODO: Figureout how to encode errors.
|
|
||||||
read_pages := fn(file_id: FileID, offset: int, page_count: int): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
// This writes out page_count of pages out of the file.
|
|
||||||
write_pages := fn(file_id: FileID, offset: int, page_count: int): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
// This reads out byte_count of bytes from the file.
|
|
||||||
read_bytes := fn(file_id: FileID, offset: int, byte_count: int): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
write_bytes := fn(file_id: FileID, offset: int, byte_count: int): void {
|
|
||||||
}
|
|
|
@ -1,9 +1,31 @@
|
||||||
acs := @use("acs.hb")
|
char := struct {}
|
||||||
|
|
||||||
string := @use("string.hb")
|
|
||||||
log := @use("log.hb")
|
log := fn(log_level: int, message: ^char, message_length: int): int {
|
||||||
memory := @use("memory.hb")
|
|
||||||
buffer := @use("buffer.hb")
|
return 0;
|
||||||
math := @use("math.hb")
|
}
|
||||||
random := @use("random.hb")
|
|
||||||
file := @use("file_io.hb")
|
error := fn(message: ^char, message_length: int): int {
|
||||||
|
log(0, message, message_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
warn := fn(message: ^char, message_length: int): int {
|
||||||
|
log(1, message, message_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
info := fn(message: ^char, message_length: int): int {
|
||||||
|
log(2, message, message_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
debug := fn(message: ^char, message_length: int): int {
|
||||||
|
log(3, message, message_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
trace := fn(message: ^char, message_length: int): int {
|
||||||
|
log(4, message, message_length)
|
||||||
|
}
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
string := @use("string.hb")
|
|
||||||
buffer := @use("buffer.hb")
|
|
||||||
|
|
||||||
log := fn(message: ^u8, level: u8): void {
|
|
||||||
message_length := @inline(string.length, message);
|
|
||||||
*(message + message_length) = level
|
|
||||||
|
|
||||||
return @eca(3, 1, message, message_length + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
error := fn(message: ^u8): void return log(message, 0)
|
|
||||||
warn := fn(message: ^u8): void return log(message, 1)
|
|
||||||
info := fn(message: ^u8): void return log(message, 2)
|
|
||||||
debug := fn(message: ^u8): void return log(message, 3)
|
|
||||||
trace := fn(message: ^u8): void return log(message, 4)
|
|
|
@ -1,15 +0,0 @@
|
||||||
shift := 31
|
|
||||||
|
|
||||||
// following only work for: int
|
|
||||||
abs := fn(x: int): int {
|
|
||||||
mask := x >> shift
|
|
||||||
return (x ^ mask) - mask
|
|
||||||
}
|
|
||||||
min := fn(a: int, b: int): int {
|
|
||||||
c := a - b
|
|
||||||
return b + (c & c >> shift)
|
|
||||||
}
|
|
||||||
max := fn(a: int, b: uint): int {
|
|
||||||
c := a - b
|
|
||||||
return a - (c & c >> shift)
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
request_page := fn(page_count: u8): ^u8 {
|
|
||||||
msg := "\{00}\{01}xxxxxxxx\0"
|
|
||||||
msg_page_count := msg + 1;
|
|
||||||
*msg_page_count = page_count
|
|
||||||
return @eca(3, 2, msg, 12)
|
|
||||||
}
|
|
||||||
|
|
||||||
release_page := fn(ptr: ^u8, page_count: u8): void {
|
|
||||||
msg := "\{01}\{00}xxxxxxxx\0"
|
|
||||||
|
|
||||||
msg_page_count := msg + 1;
|
|
||||||
*msg_page_count = page_count
|
|
||||||
|
|
||||||
msg_ptr := @as(^^u8, @bitcast(msg + 2));
|
|
||||||
*msg_ptr = ptr
|
|
||||||
|
|
||||||
return @eca(3, 2, msg, 12)
|
|
||||||
}
|
|
||||||
|
|
||||||
OutbMsg := struct {a: u8, b: u8, addr: u16, value: u8}
|
|
||||||
InbMsg := struct {a: u8, b: u8, addr: u16}
|
|
||||||
OutlMsg := struct {a: u8, b: u8, addr: u16, value: u32}
|
|
||||||
InlMsg := struct {a: u8, b: u8, addr: u16}
|
|
||||||
|
|
||||||
outb := fn(addr: u16, value: u8): void {
|
|
||||||
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
inb := fn(addr: u16): u8 {
|
|
||||||
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
outl := fn(addr: u16, value: u32): void {
|
|
||||||
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
inl := fn(addr: u16): u32 {
|
|
||||||
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
integer := fn(): int {
|
|
||||||
return @eca(3, 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
integer_range := fn(min: int, max: int): int {
|
|
||||||
return @eca(3, 4) % (max - min + 1) + min
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
length := fn(ptr: ^u8): int {
|
|
||||||
len := 0
|
|
||||||
loop if *(ptr + len) == 0 break else len += 1
|
|
||||||
return len
|
|
||||||
}
|
|
||||||
|
|
||||||
// WTFFF is wrong with display_int
|
|
||||||
display_int := fn(num: int, p: ^u8): ^u8 {
|
|
||||||
ptr := p
|
|
||||||
negative := num < 0
|
|
||||||
if negative {
|
|
||||||
num = -num
|
|
||||||
}
|
|
||||||
if num == 0 {
|
|
||||||
*ptr = 48
|
|
||||||
ptr += 1
|
|
||||||
} else {
|
|
||||||
loop if num == 0 break else {
|
|
||||||
*ptr = num % 10 + 48
|
|
||||||
ptr += 1
|
|
||||||
num /= 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if negative {
|
|
||||||
*ptr = 45
|
|
||||||
ptr += 1
|
|
||||||
};
|
|
||||||
*ptr = 0
|
|
||||||
@inline(reverse, p)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
reverse := fn(s: ^u8): void {
|
|
||||||
//reverse a string, don't remove digits
|
|
||||||
len := 0
|
|
||||||
loop if *(s + len) == 0 break else len += 1
|
|
||||||
i := 0
|
|
||||||
j := len - 1
|
|
||||||
temp := 0
|
|
||||||
loop if i >= j break else {
|
|
||||||
temp = *(s + i);
|
|
||||||
*(s + i) = *(s + j);
|
|
||||||
*(s + j) = temp
|
|
||||||
i += 1
|
|
||||||
j -= 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
40
sysdata/limine.cfg
Normal file
40
sysdata/limine.cfg
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
${ABLEOS_KERNEL}=boot:///kernel
|
||||||
|
# TODO: Make a boot background image for ableOS
|
||||||
|
|
||||||
|
DEFAULT_ENTRY=1
|
||||||
|
TIMEOUT=0
|
||||||
|
VERBOSE=yes
|
||||||
|
INTERFACE_RESOLUTION=1024x768
|
||||||
|
# Terminal related settings
|
||||||
|
TERM_WALLPAPER=boot:///background.bmp
|
||||||
|
TERM_BACKDROP=008080
|
||||||
|
|
||||||
|
:AbleOS
|
||||||
|
COMMENT=Default AbleOS boot entry.
|
||||||
|
PROTOCOL=limine
|
||||||
|
KERNEL_PATH=boot:///kernel_${ARCH}
|
||||||
|
# execute is an array of boot modules to execute
|
||||||
|
KERNEL_CMDLINE=""
|
||||||
|
# Setting a default resolution for the framebuffer
|
||||||
|
RESOLUTION=1024x768x24
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///failure.hbf
|
||||||
|
MODULE_CMDLINE=""
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///ecall.hbf
|
||||||
|
MODULE_CMDLINE=""
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///main.hbf
|
||||||
|
MODULE_CMDLINE=""
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///keyboard_driver.hbf
|
||||||
|
MODULE_CMDLINE="arch=${ARCH}"
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///vfs_test.hbf
|
||||||
|
MODULE_CMDLINE=""
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///limine_framebuffer_driver.hbf
|
||||||
|
MODULE_CMDLINE="height=10 width=10 arch=${ARCH}"
|
||||||
|
|
||||||
|
MODULE_PATH=boot:///serial_driver.hbf
|
||||||
|
MODULE_CMDLINE="arch=${ARCH}"
|
|
@ -1,11 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "diskio_driver"
|
|
||||||
authors = ["able"]
|
|
||||||
|
|
||||||
[dependants.libraries]
|
|
||||||
|
|
||||||
[dependants.binaries]
|
|
||||||
hblang.version = "1.0.0"
|
|
||||||
|
|
||||||
[build]
|
|
||||||
command = "hblang src/main.hb"
|
|
|
@ -1,13 +1,4 @@
|
||||||
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
// shuts down ableOS
|
|
||||||
// memory.outb(0xF400, 0)
|
|
||||||
|
|
||||||
a := memory.inb(0x4600)
|
return 0;
|
||||||
b := memory.inb(0x4700)
|
|
||||||
|
|
||||||
c := buffer.search("XNumber\0")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
|
@ -1 +0,0 @@
|
||||||
# dt_buffer_test
|
|
|
@ -1,14 +0,0 @@
|
||||||
dt_api := @use("../../../libraries/dt_api/src/lib.hb");
|
|
||||||
.{dt_get} := dt_api
|
|
||||||
|
|
||||||
main := fn(): int {
|
|
||||||
dt_api.dt_get("framebuffer/fb0/width\0")
|
|
||||||
dt_api.dt_get("cpu/cpu0/architecture\0")
|
|
||||||
|
|
||||||
// Checking if the first detected serial port is memory mapped or port mapped
|
|
||||||
// 0 -> memory mapped
|
|
||||||
// 1 -> port mapped
|
|
||||||
dt_get("serial_ports/sp0/mapping\0")
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "dt_buffer_test"
|
name = "dev"
|
||||||
authors = ["able"]
|
authors = ["able"]
|
||||||
|
|
||||||
[dependants.libraries]
|
[dependants.libraries]
|
||||||
|
@ -7,5 +7,5 @@ authors = ["able"]
|
||||||
[dependants.binaries]
|
[dependants.binaries]
|
||||||
hblang.version = "1.0.0"
|
hblang.version = "1.0.0"
|
||||||
|
|
||||||
[build]
|
[build.debug]
|
||||||
command = "hblang src/main.hb"
|
command = "hblang libraries/stn/src/lib.hb src/main.hbl"
|
7
sysdata/programs/fb_driver/src/main.hb
Normal file
7
sysdata/programs/fb_driver/src/main.hb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
loop {
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
# filesystem_fat32
|
|
|
@ -1,11 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "filesystem_fat32"
|
|
||||||
authors = [""]
|
|
||||||
|
|
||||||
[dependants.libraries]
|
|
||||||
|
|
||||||
[dependants.binaries]
|
|
||||||
hblang.version = "1.0.0"
|
|
||||||
|
|
||||||
[build]
|
|
||||||
command = "hblang src/main.hb"
|
|
|
@ -1,7 +0,0 @@
|
||||||
READ_ONLY := 0x1
|
|
||||||
HIDDEN := 0x2
|
|
||||||
SYSTEM := 0x4
|
|
||||||
VOLUME_ID := 0x8
|
|
||||||
DIRECTORY := 0x10
|
|
||||||
ARCHIVE := 0x20
|
|
||||||
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID
|
|
|
@ -1,181 +0,0 @@
|
||||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
|
||||||
.{string, memory, buffer, log} := stn
|
|
||||||
|
|
||||||
VALID_JUMP_BYTES := [u8].(0xEB, 0x3C, 0x90)
|
|
||||||
|
|
||||||
OemIdent := struct {
|
|
||||||
dos_version: [u8; 8],
|
|
||||||
dos_version_name: [u8; 8],
|
|
||||||
}
|
|
||||||
|
|
||||||
new_oem_ident := fn(major: int, minor: int): OemIdent {
|
|
||||||
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
|
|
||||||
return OemIdent.(ver, ver)
|
|
||||||
}
|
|
||||||
|
|
||||||
BiosParameterBlock := struct {
|
|
||||||
jump_bytes: [u8; 3],
|
|
||||||
oem_ident: OemIdent,
|
|
||||||
bytes_per_sector: u16,
|
|
||||||
sectors_per_cluster: u8,
|
|
||||||
reserved_sectors: u16,
|
|
||||||
// The amount of FileAllocationTables on the disk. Often 2.
|
|
||||||
fat_count: u8,
|
|
||||||
root_directory_count: u16,
|
|
||||||
// if 0 then refer to large_sector_count
|
|
||||||
total_sectors: u16,
|
|
||||||
media_type: u8,
|
|
||||||
// if 0 refer to sectors_per_fat in the ExtendedBootRecord
|
|
||||||
sectors_per_fat: u16,
|
|
||||||
sectors_per_track: u16,
|
|
||||||
head_count: u16,
|
|
||||||
hidden_sectors: u32,
|
|
||||||
large_sector_count: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
bpb_sanity_check := fn(bpb: BiosParameterBlock): int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
new_bpb := fn(): BiosParameterBlock {
|
|
||||||
oem := new_oem_ident(0, 0)
|
|
||||||
|
|
||||||
return BiosParameterBlock.(VALID_JUMP_BYTES, oem, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
|
||||||
if bpb.total_sectors == 0 {
|
|
||||||
return bpb.large_sector_count
|
|
||||||
} else {
|
|
||||||
return bpb.total_sectors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FatVersionNumber := struct {
|
|
||||||
major_version: u8,
|
|
||||||
minor_version: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
FormatReservation := [u8; 12]
|
|
||||||
|
|
||||||
// Padded with spaces.
|
|
||||||
VolumeName := [u8; 11]
|
|
||||||
|
|
||||||
SystemIdentifierString := [u8; 8]
|
|
||||||
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
|
||||||
BOOTABLE_PARTITION_SIGNATURE := 0xAA55
|
|
||||||
|
|
||||||
BootCode := [u8; 420]
|
|
||||||
|
|
||||||
ExtendedBootRecord := struct {
|
|
||||||
sectors_per_fat: u32,
|
|
||||||
flags: u16,
|
|
||||||
fat_version_number: FatVersionNumber,
|
|
||||||
// Typically set to 2.
|
|
||||||
root_directory_cluster_number: u32,
|
|
||||||
fsinfo_structure: u16,
|
|
||||||
backup_boot_sector: u16,
|
|
||||||
// When a volume is formated these bytes should be zero. As a sanity check I guess?
|
|
||||||
format_reserved: FormatReservation,
|
|
||||||
// 0x00 floppy or 0x80 hard disk
|
|
||||||
drive_number: u8,
|
|
||||||
nt_reserved: u8,
|
|
||||||
// must be 0x28 or 0x29
|
|
||||||
signature: u8,
|
|
||||||
volume_id_serial: u32,
|
|
||||||
volume_id_name: VolumeName,
|
|
||||||
// The spec says this is always FAT32. Untrustworthy and another sanity check I guess.
|
|
||||||
system_identifier_string: SystemIdentifierString,
|
|
||||||
boot_code: BootCode,
|
|
||||||
partition_signature: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
|
|
||||||
ret := 0
|
|
||||||
if ebr.drive_number != 0x0 | ebr.drive_number != 0x80 {
|
|
||||||
log.warn("EBR-Drive-Number sanity check failed\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebr.signature != 0x28 | ebr.signature != 0x29 {
|
|
||||||
log.warn("EBR-Signature sanity check failed\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
|
|
||||||
log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
new_ebr := fn(): ExtendedBootRecord {
|
|
||||||
version := FatVersionNumber.(0, 0)
|
|
||||||
fmt_res := FormatReservation.(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
||||||
vol_name := @as([u8; 11], idk)
|
|
||||||
boot_code := @as([u8; 420], idk)
|
|
||||||
|
|
||||||
return ExtendedBootRecord.(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
version,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
fmt_res,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
vol_name,
|
|
||||||
VALID_SYSTEM_IDENTIFIER_STRING,
|
|
||||||
boot_code,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
VALID_LEAD_FS_INFO := 0x41615252
|
|
||||||
VALID_TRAIL_FS_INFO := 0xAA550000
|
|
||||||
|
|
||||||
FSInfo := struct {
|
|
||||||
// Must be 0x41615252 to indicate a valid FSInfo structure
|
|
||||||
lead_signature: u32,
|
|
||||||
lead_reserved: [u8; 480],
|
|
||||||
// If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. However, this value might be incorrect and should at least be range checked (<= volume cluster count)
|
|
||||||
last_known_free_cluster_count: u32,
|
|
||||||
last_known_avalible_cluster: u32,
|
|
||||||
trail_reserved: [u8; 12],
|
|
||||||
trail_signature: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
fs_info_sanity_check := fn(fs_info: FSInfo): int {
|
|
||||||
ret := 0
|
|
||||||
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
|
|
||||||
ret &= 1
|
|
||||||
log.warn("Invalid leading signature in FSInfo.\0")
|
|
||||||
}
|
|
||||||
if fs_info.last_known_free_cluster_count == 0xFFFFFFFF {
|
|
||||||
ret &= 2
|
|
||||||
log.warn("Last known free cluster count unknown.\0")
|
|
||||||
}
|
|
||||||
if fs_info.last_known_avalible_cluster == 0xFFFFFFFF {
|
|
||||||
ret &= 4
|
|
||||||
log.warn("Last known avalible cluster count unknown.\0")
|
|
||||||
}
|
|
||||||
if fs_info.trail_signature != VALID_TRAIL_FS_INFO {
|
|
||||||
ret &= 8
|
|
||||||
log.warn("Invalid trailing signature in FSInfo.\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
new_fs_info := fn(): FSInfo {
|
|
||||||
lead_reserved := @as([u8; 480], idk)
|
|
||||||
trail_reserved := @as([u8; 12], idk)
|
|
||||||
return FSInfo.(
|
|
||||||
VALID_LEAD_FS_INFO,
|
|
||||||
lead_reserved,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
trail_reserved,
|
|
||||||
VALID_TRAIL_FS_INFO,
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
Date := struct {
|
|
||||||
year: u16,
|
|
||||||
month: u16,
|
|
||||||
day: u16,
|
|
||||||
}
|
|
||||||
Time := struct {
|
|
||||||
hour: u16,
|
|
||||||
minutes: u16,
|
|
||||||
seconds: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
compress_date := fn(year: u16, month: u16, day: u16): u16 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
decompress_date := fn(date: u16): Date {
|
|
||||||
return Date.(0, 0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
compress_time := fn(hour: u16, minutes: u16, seconds: u16): u16 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
decompress_time := fn(time: u16): Time {
|
|
||||||
return Time.(0, 0, 0)
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
attributes := @use("attributes.hb")
|
|
||||||
datetime := @use("datetime.hb")
|
|
||||||
|
|
||||||
FileName := [u8; 11]
|
|
||||||
|
|
||||||
// This is the File Allocation Table entry that tells us where on disk the File is.
|
|
||||||
FileEntry := struct {
|
|
||||||
file_name: FileName,
|
|
||||||
attributes: u8,
|
|
||||||
// We could use this byte for something but we likely will not
|
|
||||||
nt_reserved: u8,
|
|
||||||
hundredths_seconds_creation: u8,
|
|
||||||
creation_time: datetime.time,
|
|
||||||
creation_date: datetime.date,
|
|
||||||
last_accessed_date: datetime.date,
|
|
||||||
high_cluster_number: u16,
|
|
||||||
last_modification_time: datetime.time,
|
|
||||||
last_modification_date: datetime.date,
|
|
||||||
low_cluster_number: u16,
|
|
||||||
file_size: u32,
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
|
||||||
.{string, memory, buffer, log} := stn
|
|
||||||
|
|
||||||
attributes := @use("attributes.hb")
|
|
||||||
datetime := @use("datetime.hb")
|
|
||||||
directory := @use("file.hb")
|
|
||||||
bios_parameter_block := @use("bios_parameter_block.hb");
|
|
||||||
.{bpb_sanity_check, ebr_sanity_check, fs_info_sanity_check} := bios_parameter_block;
|
|
||||||
.{new_bpb, new_ebr, new_fs_info} := bios_parameter_block
|
|
||||||
|
|
||||||
FAT12_THRESHOLD := 4085
|
|
||||||
FAT16_THRESHOLD := 65525
|
|
||||||
|
|
||||||
ExFAT := 0
|
|
||||||
FAT12 := 1
|
|
||||||
FAT16 := 2
|
|
||||||
FAT32 := 3
|
|
||||||
|
|
||||||
calculate_fat_type := fn(sector_size: int, total_clusters: int): int {
|
|
||||||
if sector_size == 0 {
|
|
||||||
return ExFAT
|
|
||||||
} else if total_clusters < 4085 {
|
|
||||||
return FAT12
|
|
||||||
} else if total_clusters < 65525 {
|
|
||||||
return FAT16
|
|
||||||
} else {
|
|
||||||
return FAT32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main := fn(): int {
|
|
||||||
bpb := new_bpb()
|
|
||||||
ebr := new_ebr()
|
|
||||||
fsi := new_fs_info()
|
|
||||||
|
|
||||||
fat_type := calculate_fat_type(1, 100)
|
|
||||||
|
|
||||||
if fat_type != FAT32 {
|
|
||||||
log.warn("filesystem_fat32 driver only supports Fat32.\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
bsc := bpb_sanity_check(bpb)
|
|
||||||
esc := ebr_sanity_check(ebr)
|
|
||||||
fssc := fs_info_sanity_check(fsi)
|
|
||||||
|
|
||||||
msg_type := 0
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Open file
|
|
||||||
if msg_type == 0 {
|
|
||||||
// Paths without a node-disk component are to be treated as local files.
|
|
||||||
file_path := "node-disk:/test\0"
|
|
||||||
} else {
|
|
||||||
// error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Horizon
|
|
||||||
The Horizon Windowing system server. This is the component that spawns/layouts and renders windows.
|
|
||||||
For the api look in libraries/horizon_api.
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue