forked from AbleOS/ableos
Compare commits
24 Commits
f97e203b7f
...
b60389ea21
Author | SHA1 | Date |
---|---|---|
able | b60389ea21 | |
able | 6d8fe6fb7b | |
able | 7806be2e4d | |
able | 18e7fbb2bb | |
able | fe84ee85bf | |
able | 7eec674766 | |
able | bf75c0e3c8 | |
IntoTheNight | 17937705e0 | |
IntoTheNight | c791192bbd | |
able | 2384658d0d | |
able | 9db3384728 | |
ondra05 | d0c0c7f616 | |
able | 2b5883d5cf | |
able | 5a1d918d7a | |
able | 1d28e60977 | |
able | 6eed872e47 | |
able | f1c029412a | |
MunirG05 | a23d5770a9 | |
able | 0c7edead3d | |
able | ef544011ae | |
MunirG05 | 88e324a8a9 | |
MunirG05 | e3f6295997 | |
MunirG05 | 1d5bb220ec | |
MunirG05 | f98fde1247 |
File diff suppressed because it is too large
Load Diff
68
MANIFESTO.md
68
MANIFESTO.md
|
@ -1,68 +0,0 @@
|
|||
# The Design of AbleOS
|
||||
## The unix philosophy and why it shouldn't exist
|
||||
small is only beautiful if its complete.
|
||||
grep for example supports the `-r` flag which should instead be `grep`+`find`
|
||||
Everything is not a stream of bytes.
|
||||
|
||||
programs can do multiple things well
|
||||
`cat`, `head` and `tail` could all be one program with a flag
|
||||
`which head` `which tail` `which cat` should all return the same binary with different flags
|
||||
```
|
||||
which head == /bin/cat range=0-10
|
||||
|
||||
which tail == /bin/cat reverse_index=true range=0-10
|
||||
|
||||
which cat == /bin/cat
|
||||
```
|
||||
|
||||
build a prototype quickly only applies if you are being pressured. do thing quickly then refine
|
||||
'choose portability over effeciency' this is a flawed idealogy choose modularity over pure portability
|
||||
'store data in flat text files' this leads to a psuedostandardization on KVPair configuration languages that all sit in a flat text file. Instead pick a configuration format that gets loaded into a tree structure
|
||||
|
||||
## File Systems
|
||||
### The amount of files inside of a folder
|
||||
32765. Why you might ask?
|
||||
### Dot files
|
||||
`dotfiles` were a mistake given to us by bad programmers mocking better programmers. [link](https://web.archive.org/web/20230413171520/http://xahlee.info/UnixResource_dir/writ/unix_origin_of_dot_filename.html)
|
||||
|
||||
### File name case sensitivity
|
||||
Case sensitivity seems like a great idea! But in practice leads to the following filetree
|
||||
```
|
||||
/kernel
|
||||
/Kernel
|
||||
/kErnEl
|
||||
/KeRnEl
|
||||
```
|
||||
which is a nightmare and you should be erradicated if you think this is a positive
|
||||
provide a display name for files that allows case and save the file as caseless
|
||||
|
||||
### File name character limits
|
||||
unix is a plauge upon this earth. name a file `:(){ :|:& };:` and try listing it. You have lost access to your terminal.
|
||||
if you defined a sane method of listing files and allowing programs to provide the OS a standard method of providing argument suggestions and being aware you would never run into this issue
|
||||
|
||||
## CLI vs GUI
|
||||
Graphics are not your enemy unix lovers. You mustn't be stuck in 1981. Times have changed! You can have a graphical shell enviroment. SGI Irix was aware of this in 1988, not perfect of course but 7 years after dos is an impressive leap.
|
||||
FFMPEG??? Why no gui? Give me a good git ui
|
||||
|
||||
|
||||
### Emails plain text
|
||||
Unix believes in plain text emails. Quotes are `>`
|
||||
|
||||
### Unix Wizards and Instability
|
||||
[Do not meddle in the affairs of Unix, for it is subtle and quick to anger.]
|
||||
|
||||
### Unix why are your mouse a file?
|
||||
This list is incomplete
|
||||
`/dev/input/event1` The PS2 Mouse
|
||||
`/dev/input/event3` The USB Mouse
|
||||
`/dev/input/psaux` The PS2 Mouse
|
||||
`/dev/input/psmouse` The PS2 Mouse
|
||||
`/dev/input/mice` The Not(?) PS2 Mouse I think?
|
||||
`/dev/input/mouse0` The not Not(?) ps2 mouse? First usb mouse I think?
|
||||
`/dev/input/usbhid` USB mice (should be autodetected)
|
||||
`/dev/input/sermouse` Most serial mice
|
||||
`/dev/input/logibm` Bus mouse connected to Logitech adapter card
|
||||
`/dev/input/inport` Bus mouse connected to ATI or Microsoft InPort card
|
||||
`/dev/input/by-id/usb-<usbid here>` A usb mouse via its id
|
||||
|
||||
I propose a unified system for input via a Device Tree of sorts
|
10
README.md
10
README.md
|
@ -1,3 +1,4 @@
|
|||
```
|
||||
TODO
|
||||
- Integrate HBVM
|
||||
HBVM also needs full spec compliance
|
||||
|
@ -23,10 +24,17 @@ TODO
|
|||
- VFS
|
||||
- Disk driver
|
||||
- A ton more
|
||||
```
|
||||
|
||||
# Community
|
||||
[Discord](https://discord.gg/5TnJ8sa7)
|
||||
[Discord](https://discord.gg/JrKVukDtgs)
|
||||
|
||||
|
||||
|
||||
# Compiling
|
||||
Firstly, I would like to apologize. I am not capable of supporting building on any random machine with any random operating system.
|
||||
|
||||
AbleOS very likely builds with `nix-shell` on your operating system.
|
||||
|
||||
1. `git submodule update --init`
|
||||
1. `cargo repbuild`
|
||||
|
|
|
@ -4,6 +4,7 @@ build-std-features = ["compiler-builtins-mem"]
|
|||
|
||||
[build]
|
||||
target = "./targets/x86_64-ableos.json"
|
||||
# target = "./targets/aarch64-virt-ableos.json"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
rustflags = ["-C", "target-feature=+rdrand"]
|
||||
|
|
|
@ -5,9 +5,10 @@ version = "0.2.0"
|
|||
|
||||
|
||||
[dependencies]
|
||||
limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" }
|
||||
|
||||
hbvm = { git = "https://git.ablecorp.us/ableos/holey-bytes" }
|
||||
hbasm = { git = "https://git.ablecorp.us/ableos/holey-bytes" }
|
||||
# hbasm = { git = "https://git.ablecorp.us/ableos/holey-bytes" }
|
||||
|
||||
embedded-graphics = "0.7.1"
|
||||
|
||||
|
@ -47,7 +48,6 @@ features = [
|
|||
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||
limine = { version = "0.1", git = "https://github.com/limine-bootloader/limine-rs" }
|
||||
x86_64 = "0.14"
|
||||
x2apic = "0.4"
|
||||
virtio-drivers = "0.4.0"
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
|
||||
.//// *(####
|
||||
(####((/, (########,
|
||||
(##%##(###(( ,(#########%#
|
||||
#%%%%###(###((. *((####%%&%%%%#
|
||||
.#####%%%%%####((. *(####%&&&&&%%%%#
|
||||
#(((((((##%%&&%#((/ /#(##%&&%##########
|
||||
/######%%%%%%%(..........(#%%%%%%#####%%#
|
||||
,#%%%%%%#/...... ..............,&&&%%###.
|
||||
,%%#(#(...........................(#&&%%#
|
||||
.###%...............................%%#(#.
|
||||
#%&.................................%#
|
||||
,%&&*.................................&&%(
|
||||
%%#//........./............*/..,......&&&%#
|
||||
.......,..............*,*.,,,,,,.
|
||||
......./....,.........*,,,,.,,,,,,
|
||||
,...../..(###%,.....&*&%###/..,.,,.
|
||||
,,..../%(((#(,.....,%%%%###,..,..,.
|
||||
.,,*.../..,#,.........,(&(,,**.,,,,,
|
||||
,/((..,*..........,,.,,,,,**.,##((
|
||||
/(((%%%,,,,,.,,,,,,,,,,,#/##(,(/
|
||||
.***..(,.#%%%&&#/%,,(%*,,**#
|
||||
**,...,(#%%%%&#%%%#%%%%,,.,,***.
|
||||
.....,*,*#%%%%%###%##%%%&,,*,,....
|
||||
......,*/. (############%%%&&&&#*,,....
|
||||
...,*,..,(((((((((((#((((((((((((&&&#*,
|
||||
,##///////(((((((((((((#///#///(##/.
|
||||
/*/**//... ...**(((((((,. .,*......
|
||||
....... ......,,/*,. ...........
|
||||
,..,,,,...... .. .... ,,....... ..,,,
|
||||
........,.,.,*//////*,......,.
|
||||
...,,,, ,,,,,,
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40080000;
|
||||
.text.boot : { *(.text.boot) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.rodata : { *(.rodata) }
|
||||
.bss : { *(.bss) }
|
||||
|
||||
. = ALIGN(8);
|
||||
. = . + 0x4000;
|
||||
LD_STACK_PTR = .;
|
||||
}
|
|
@ -48,7 +48,7 @@ SECTIONS
|
|||
. = ALIGN(4K);
|
||||
PROVIDE(_initial_kernel_heap_start = .);
|
||||
/* PROVIDE(_initial_kernel_heap_size = 1024 * 1024); */
|
||||
PROVIDE(_initial_kernel_heap_size = 1024 * 4096);
|
||||
PROVIDE(_initial_kernel_heap_size = 1024 * 4096 * 100);
|
||||
. += _initial_kernel_heap_size;
|
||||
} :data
|
||||
}
|
||||
|
|
|
@ -1 +1,21 @@
|
|||
//!
|
||||
//!
|
||||
// #[allow(deprecated)]
|
||||
// use limine::{TerminalRequest, TerminalResponse};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn _kernel_start() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
pub fn log(_args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
panic!()
|
||||
}
|
||||
|
||||
pub fn sloop() -> ! {
|
||||
loop {}
|
||||
}
|
||||
pub fn hardware_random_u64() -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
pub const PAGE_SIZE: usize = 10;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::cpu_features;
|
||||
|
||||
use {
|
||||
alloc::vec::Vec,
|
||||
core::{arch::asm, fmt, ops::Deref, slice, str},
|
||||
|
@ -772,23 +774,8 @@ impl Master {
|
|||
// TODO: Macroify this and also include all of the cpu features from self
|
||||
pub fn features(&self) -> Vec<(&str, bool)> {
|
||||
let mut fv = Vec::new();
|
||||
let apic = self.apic();
|
||||
let avx = self.avx();
|
||||
let avx2 = self.avx2();
|
||||
let x2 = self.x2apic();
|
||||
|
||||
let gb_pages = self.gigabyte_pages();
|
||||
let rdseed = self.rdseed();
|
||||
let rdrand = self.rdrand();
|
||||
|
||||
fv.push(("apic", apic));
|
||||
fv.push(("avx", avx));
|
||||
fv.push(("avx2", avx2));
|
||||
fv.push(("gigabyte pages", gb_pages));
|
||||
fv.push(("rdrand", rdrand));
|
||||
fv.push(("rdseed", rdseed));
|
||||
fv.push(("x2apic", x2));
|
||||
fv
|
||||
cpu_features!(self, fv);
|
||||
return fv;
|
||||
}
|
||||
|
||||
master_attr_reader!(version_information, VersionInformation);
|
||||
|
|
|
@ -63,49 +63,26 @@ pub enum HostError {
|
|||
// // pub fn rpc_register(_engine: &mut Engine) {}
|
||||
// // pub fn rpc_call(_engine: &mut Engine) {}
|
||||
|
||||
use log::error;
|
||||
|
||||
use hbvm::vm::{
|
||||
mem::{Memory, MemoryAccessReason, PageSize},
|
||||
trap::HandleTrap,
|
||||
value::Value,
|
||||
};
|
||||
|
||||
use {hbvm::vm::mem::HandlePageFault, log::error};
|
||||
/// AbleOS HBVM traphandler
|
||||
pub struct TrapHandler;
|
||||
impl HandleTrap for TrapHandler {
|
||||
impl HandlePageFault for TrapHandler {
|
||||
fn page_fault(
|
||||
&mut self,
|
||||
mar: MemoryAccessReason,
|
||||
memory: &mut Memory,
|
||||
reason: hbvm::vm::mem::MemoryAccessReason,
|
||||
memory: &mut hbvm::vm::mem::Memory,
|
||||
vaddr: u64,
|
||||
size: PageSize,
|
||||
size: hbvm::vm::mem::PageSize,
|
||||
dataptr: *mut u8,
|
||||
) -> bool {
|
||||
error!(
|
||||
"MemoryAccessReason: {}
|
||||
Memory: {:?}
|
||||
VAddr: {}
|
||||
Size: {:?}
|
||||
DataPTR: {:?}",
|
||||
mar, memory, vaddr, size, dataptr
|
||||
"REASON: {}
|
||||
memory: {:?}
|
||||
vaddr: {}
|
||||
size: {:?}
|
||||
Dataptr {:?}",
|
||||
reason, memory, vaddr, size, dataptr
|
||||
);
|
||||
false
|
||||
}
|
||||
|
||||
fn invalid_op(&mut self, _: &mut [Value; 256], _: &mut usize, _: &mut Memory, _: u8) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
log::trace!("Invalid opcode");
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn ecall(&mut self, _: &mut [Value; 256], _: &mut usize, _: &mut Memory)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
log::trace!("ableOS system call made");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
//! AbleOS Kernel Entrypoint
|
||||
|
||||
use crate::capabilities;
|
||||
|
||||
// use crate::arch::sloop;
|
||||
use {
|
||||
crate::{
|
||||
arch::logging::SERIAL_CONSOLE,
|
||||
bootmodules::{build_cmd, BootModules},
|
||||
capabilities,
|
||||
device_tree::DeviceTree,
|
||||
scheduler::Scheduler,
|
||||
},
|
||||
alloc::format,
|
||||
log::{debug, info, trace},
|
||||
|
@ -32,7 +31,7 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
|
||||
let dt = DEVICE_TREE.lock();
|
||||
|
||||
info!("Device Tree{}", dt);
|
||||
info!("Device Tree: {}", dt);
|
||||
info!("Boot complete. Moving to init_system");
|
||||
|
||||
// TODO: schedule the disk driver from the initramfs
|
||||
|
@ -41,65 +40,12 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
|
||||
capabilities::example();
|
||||
|
||||
// TODO: change this to a driver
|
||||
{
|
||||
let mut prog = alloc::vec![];
|
||||
let mut code = alloc::string::String::new();
|
||||
|
||||
let mut sc = SERIAL_CONSOLE.lock();
|
||||
loop {
|
||||
match sc.receive() {
|
||||
b'\r' => {
|
||||
code.push('\n');
|
||||
|
||||
sc.send(b'\r');
|
||||
sc.send(b'\n');
|
||||
|
||||
match hbasm::assembly(&code, &mut prog) {
|
||||
Ok(_) => {
|
||||
use hbvm::validate::validate;
|
||||
match validate(&prog) {
|
||||
Err(_e) => {
|
||||
// log::error!("Program validation error: {e:?}");
|
||||
}
|
||||
Ok(_) => {
|
||||
// log::info!("valid program");
|
||||
use {crate::host::TrapHandler, hbvm::vm::Vm};
|
||||
let mut vm;
|
||||
unsafe {
|
||||
vm = Vm::new_unchecked(&prog, TrapHandler);
|
||||
vm.memory.insert_test_page();
|
||||
}
|
||||
// log::info!("Program interrupt: {:?}", vm.run());
|
||||
// log::debug!("{:?}", vm.registers);
|
||||
}
|
||||
}
|
||||
|
||||
sc.send(b'>');
|
||||
}
|
||||
Err(_e) => {
|
||||
// log::error!(
|
||||
// "Error {:?} at {:?} (`{}`)",
|
||||
// e.kind,
|
||||
// e.span.clone(),
|
||||
// &code[e.span],
|
||||
// );
|
||||
for x in "err".as_bytes() {
|
||||
sc.send(*x);
|
||||
}
|
||||
}
|
||||
}
|
||||
code = alloc::string::String::new();
|
||||
}
|
||||
byte => {
|
||||
code.push(byte as char);
|
||||
|
||||
sc.send(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut sched = Scheduler::new();
|
||||
// AHEM that isn't a valid HBVM program
|
||||
sched.new_process(boot_modules[0].bytes.clone());
|
||||
sched.new_process(boot_modules[1].bytes.clone());
|
||||
|
||||
sched.run();
|
||||
// sloop();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,16 +16,17 @@ impl log::Log for Logger {
|
|||
|
||||
fn log(&self, record: &log::Record) {
|
||||
let lvl = record.level();
|
||||
let lvl_color = match lvl {
|
||||
Level::Error => "160",
|
||||
Level::Warn => "172",
|
||||
Level::Info => "47",
|
||||
Level::Debug => "25",
|
||||
Level::Trace => "103",
|
||||
};
|
||||
let module = record.module_path().unwrap_or_default();
|
||||
let line = record.line().unwrap_or_default();
|
||||
crate::arch::log(format_args!(
|
||||
"\x1b[38;5;{}m{lvl}\x1b[0m [{}]: {}\r\n",
|
||||
match lvl {
|
||||
Level::Error => "160",
|
||||
Level::Warn => "172",
|
||||
Level::Info => "47",
|
||||
Level::Debug => "25",
|
||||
Level::Trace => "103",
|
||||
},
|
||||
record.module_path().unwrap_or_default(),
|
||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
||||
record.args(),
|
||||
))
|
||||
.expect("write to serial console");
|
||||
|
|
|
@ -1,22 +1,58 @@
|
|||
use {crate::host::TrapHandler, alloc::vec::Vec, hbvm::vm::Vm};
|
||||
use {
|
||||
alloc::{collections::VecDeque, rc::Rc, slice, vec::Vec},
|
||||
hbvm::validate::validate,
|
||||
};
|
||||
|
||||
use {crate::host::TrapHandler, hbvm::vm::Vm};
|
||||
const TIMER_QUOTIENT: usize = 100;
|
||||
|
||||
pub struct Scheduler<'a> {
|
||||
data: Vec<Vm<'a, TrapHandler>>,
|
||||
data: VecDeque<Vm<'a, TrapHandler, TIMER_QUOTIENT>>,
|
||||
}
|
||||
|
||||
// NOTE: This is a very simple schduler and it sucks and should be replaced with a better one
|
||||
// Written By Yours Truly: Munir
|
||||
|
||||
impl Scheduler<'_> {
|
||||
// fn new_process(&mut self, program: Vec<u8>) {
|
||||
// let prog = program.clone();
|
||||
// #[allow(clippy::redundant_else)]
|
||||
// if let Err(e) = validate(&prog) {
|
||||
// log::error!("Program validation error: {e:?}");
|
||||
// } else {
|
||||
// log::info!("valid program");
|
||||
// unsafe {
|
||||
// let mut vm = Vm::new_unchecked(&prog, TrapHandler);
|
||||
// vm.memory.insert_test_page();
|
||||
// self.data.push(vm);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
data: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
pub fn new_process(&mut self, program: Vec<u8>) {
|
||||
let prog = program.clone();
|
||||
let prog_arc = Rc::new(prog);
|
||||
|
||||
let binding = Rc::try_unwrap(prog_arc).ok().unwrap();
|
||||
|
||||
#[allow(clippy::redundant_else)]
|
||||
if let Err(e) = validate(&program.as_slice()) {
|
||||
log::error!("Program validation error: {e:?}");
|
||||
} else {
|
||||
log::info!("valid program");
|
||||
unsafe {
|
||||
let slice = slice::from_raw_parts(binding.as_ptr(), binding.len());
|
||||
let mut vm = Vm::new_unchecked(&*slice, TrapHandler);
|
||||
vm.memory.insert_test_page();
|
||||
self.data.push_front(vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> ! {
|
||||
loop {
|
||||
// If there are no programs to run then sleep.
|
||||
if self.data.is_empty() {
|
||||
use crate::arch::sloop;
|
||||
sloop();
|
||||
}
|
||||
|
||||
let mut prog = self.data.pop_front().unwrap();
|
||||
prog.run().unwrap();
|
||||
|
||||
// log::info!("VM registers {:?}", prog.registers);
|
||||
log::info!("Scheduled program");
|
||||
self.data.push_back(prog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,29 @@ macro_rules! device_tree {
|
|||
$devtree.devices.insert(each_device_type.to_string(), Vec::new());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: this only reduces the code duplication in source code not in generated code!
|
||||
// Written by Yours Truly: Munir
|
||||
/// A simple macro to reduce code duplication when we insert cpu features into the array/vector
|
||||
#[macro_export]
|
||||
macro_rules! cpu_features {
|
||||
($cpu_master_object:expr, $result_vec:expr) => {
|
||||
// checks for cpu features and returns bool for each feature
|
||||
let apic = $cpu_master_object.apic();
|
||||
let avx = $cpu_master_object.avx();
|
||||
let avx2 = $cpu_master_object.avx2();
|
||||
let x2 = $cpu_master_object.x2apic();
|
||||
let gb_pages = $cpu_master_object.gigabyte_pages();
|
||||
let rdseed = $cpu_master_object.rdseed();
|
||||
let rdrand = $cpu_master_object.rdrand();
|
||||
|
||||
$result_vec.push(("apic", apic));
|
||||
$result_vec.push(("avx", avx));
|
||||
$result_vec.push(("avx2", avx2));
|
||||
$result_vec.push(("gigabyte pages", gb_pages));
|
||||
$result_vec.push(("rdrand", rdrand));
|
||||
$result_vec.push(("rdseed", rdseed));
|
||||
$result_vec.push(("x2apic", x2));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"arch": "aarch64",
|
||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||
"disable-redzone": true,
|
||||
"env": "",
|
||||
"executables": true,
|
||||
"features": "+strict-align,+neon,+fp-armv8",
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker-is-gnu": true,
|
||||
"pre-link-args": {
|
||||
"ld.lld": [
|
||||
"-Tkernel/lds/aarch64-qemu.ld"
|
||||
]
|
||||
},
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"max-atomic-width": 128,
|
||||
"os": "none",
|
||||
"panic-strategy": "abort",
|
||||
"relocation-model": "static",
|
||||
"target-c-int-width": "32",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"vendor": ""
|
||||
}
|
51
meta.md
51
meta.md
|
@ -1,51 +0,0 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ARI AbleOS Remote Install
|
||||
|
||||
Server
|
||||
/boot/server_kernel_x86_64.bin
|
||||
/boot/kernel_x86_64.bin
|
||||
/boot/kernel_aarch64.bin
|
||||
|
||||
/home/projects/askl.askl - aksldfhlkasjdhflkajshdflkj
|
||||
|
||||
|
||||
ARI_SERVER.wasm
|
||||
NAS 10.1.10.10
|
||||
|
||||
ARI 10.1.10.10
|
||||
/boot/limine.cfg
|
||||
/boot/kernel_x86_64.bin
|
||||
/boot/kernel.toml
|
||||
/home/projects/askl.askl
|
||||
aksldfhlkasjdhflkajshdflkj
|
||||
|
||||
|
||||
ARI 10.1.10.10
|
||||
/boot/limine.cfg
|
||||
/boot/kernel_aarch64.bin
|
||||
/boot/kernel.toml
|
||||
|
||||
|
||||
|
||||
/system/
|
||||
/shared/
|
||||
/home/programs/
|
||||
project_name/
|
||||
project_name.wasm
|
||||
project_name.toml
|
||||
|
||||
|
||||
|
||||
|
||||
/system/pkgman.toml
|
||||
|
||||
//////
|
||||
[repositories]
|
||||
PUR = "https://git.ablecorp.us/ableos/pur"
|
||||
|
|
@ -4,7 +4,16 @@ version = "0.2.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
env_logger = "0.10"
|
||||
cpio_reader = "0.1"
|
||||
derive_more = "0.99"
|
||||
env_logger = "0.10"
|
||||
error-stack = "0.2"
|
||||
fatfs = "0.3"
|
||||
log = "0.4"
|
||||
fatfs = "0.3"
|
||||
log = "0.4"
|
||||
rpm = "0.11"
|
||||
zstd = "0.12"
|
||||
|
||||
[dependencies.reqwest]
|
||||
version = "0.11"
|
||||
default-features = false
|
||||
features = ["rustls-tls", "blocking"]
|
||||
|
|
Binary file not shown.
|
@ -18,8 +18,8 @@ TERM_BACKDROP=008080
|
|||
# Setting a default resolution for the framebuffer
|
||||
RESOLUTION=1024x768x24
|
||||
|
||||
MODULE_PATH=boot:///background.bmp
|
||||
MODULE_PATH=boot:///inf_loop.hb
|
||||
MODULE_CMDLINE="diskid=123456789"
|
||||
|
||||
MODULE_PATH=boot:///background.bmp
|
||||
MODULE_PATH=boot:///inf_loop.hb
|
||||
MODULE_CMDLINE=""
|
|
@ -1,9 +1,14 @@
|
|||
use std::fs;
|
||||
|
||||
use {
|
||||
error_stack::{bail, report, Context, IntoReport, Result, ResultExt},
|
||||
derive_more::{Deref, DerefMut, Display},
|
||||
error_stack::{bail, ensure, report, Context, IntoReport, Result, ResultExt},
|
||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||
std::{fmt::Display, fs::File, io, path::Path, process::Command},
|
||||
std::{
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{self, Write},
|
||||
path::Path,
|
||||
process::Command,
|
||||
},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
|
@ -30,6 +35,9 @@ fn main() -> Result<(), Error> {
|
|||
if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||
target = Target::Riscv64Virt;
|
||||
}
|
||||
if arg == "aarch" || arg == "arm64" {
|
||||
target = Target::Aarch64;
|
||||
}
|
||||
}
|
||||
|
||||
build(release, target).change_context(Error::Build)
|
||||
|
@ -44,6 +52,9 @@ fn main() -> Result<(), Error> {
|
|||
if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
|
||||
target = Target::Riscv64Virt;
|
||||
}
|
||||
if arg == "arm64" || arg == "aarch64" {
|
||||
target = Target::Aarch64;
|
||||
}
|
||||
}
|
||||
|
||||
build(release, target)?;
|
||||
|
@ -110,12 +121,18 @@ fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
|
|||
&mut File::open("repbuild/background.bmp")?,
|
||||
&mut fs.root_dir().create_file("background.bmp")?,
|
||||
)?;
|
||||
io::copy(
|
||||
&mut File::open("repbuild/inf_loop.hb")?,
|
||||
&mut fs.root_dir().create_file("inf_loop.hb")?,
|
||||
)?;
|
||||
|
||||
drop(bootdir);
|
||||
Ok(fs)
|
||||
}
|
||||
|
||||
fn build(release: bool, target: Target) -> Result<(), Error> {
|
||||
fetch_ovmf().change_context(Error::OvmfFetch)?;
|
||||
|
||||
let fs = get_fs().change_context(Error::Io)?;
|
||||
let mut com = Command::new("cargo");
|
||||
com.current_dir("kernel");
|
||||
|
@ -124,11 +141,11 @@ fn build(release: bool, target: Target) -> Result<(), Error> {
|
|||
com.arg("-r");
|
||||
}
|
||||
|
||||
match target {
|
||||
Target::Riscv64Virt => {
|
||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||
}
|
||||
_ => {}
|
||||
if target == Target::Riscv64Virt {
|
||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||
}
|
||||
if target == Target::Aarch64 {
|
||||
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
||||
}
|
||||
|
||||
match com.status() {
|
||||
|
@ -160,15 +177,13 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
let mut com = match target {
|
||||
Target::X86_64 => Command::new("qemu-system-x86_64"),
|
||||
Target::Riscv64Virt => Command::new("qemu-system-riscv64"),
|
||||
Target::Aarch64 => Command::new("qemu-system-aarch64"),
|
||||
};
|
||||
|
||||
if target == Target::X86_64 {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-bios",
|
||||
std::env::var("REPBUILD_QEMU_FIRMWARE_PATH")
|
||||
.as_deref()
|
||||
.unwrap_or("/usr/share/ovmf/x64/OVMF_CODE.fd"),
|
||||
"-bios", "target/OVMF_CODE.fd",
|
||||
"-drive", "file=target/disk.img,format=raw",
|
||||
"-m", "4G",
|
||||
// "-serial", "stdio",
|
||||
|
@ -188,7 +203,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
|
||||
// com.args(["-enable-kvm", "-cpu", "host"]);
|
||||
//com.args(["-enable-kvm", "-cpu", "host"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,6 +222,14 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
]);
|
||||
}
|
||||
|
||||
if target == Target::Aarch64 {
|
||||
com.args([
|
||||
"-M", "virt", "-m", //
|
||||
"128M",
|
||||
// "-serial", "stdio",
|
||||
]);
|
||||
}
|
||||
|
||||
match com
|
||||
.status()
|
||||
.into_report()
|
||||
|
@ -217,33 +240,122 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fetch_ovmf() -> Result<(), OvmfFetchError> {
|
||||
const OVMF_RPM_URL: &str = "https://kojipkgs.fedoraproject.org/packages/edk2/20230524/3.fc38/noarch/edk2-ovmf-20230524-3.fc38.noarch.rpm";
|
||||
|
||||
let mut file = match std::fs::metadata("target/OVMF_CODE.fd") {
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open("target/OVMF_CODE.fd")
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::Io)?,
|
||||
Ok(_) => return Ok(()),
|
||||
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
||||
};
|
||||
|
||||
log::info!("No OVMF found, downloading…");
|
||||
let rpm = rpm::RPMPackage::parse(
|
||||
&mut std::convert::identity::<reqwest::Result<_>>((|| {
|
||||
reqwest::blocking::get(OVMF_RPM_URL)?.bytes()
|
||||
})())
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::Fetch)?
|
||||
.as_ref(),
|
||||
)
|
||||
.map_err(RpmError)
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::RpmParse)?;
|
||||
|
||||
ensure!(
|
||||
rpm.metadata
|
||||
.get_payload_compressor()
|
||||
.map_err(RpmError)
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::RpmParse)?
|
||||
== rpm::CompressionType::Zstd,
|
||||
OvmfFetchError::UnsupportedCompression,
|
||||
);
|
||||
|
||||
file.write_all(
|
||||
cpio_reader::iter_files(
|
||||
&zstd::decode_all(std::io::Cursor::new(rpm.content))
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::Zstd)?,
|
||||
)
|
||||
.find(|file| file.name() == "./usr/share/edk2/ovmf/OVMF_CODE.fd")
|
||||
.ok_or_else(|| report!(OvmfFetchError::NoFileFound))?
|
||||
.file(),
|
||||
)
|
||||
.into_report()
|
||||
.change_context(OvmfFetchError::Io)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Display, Deref, DerefMut)]
|
||||
struct RpmError(rpm::RPMError);
|
||||
impl Context for RpmError {}
|
||||
|
||||
// Ehhh?? I am pretty sure they just forgot :ferrisClueless:
|
||||
unsafe impl Sync for RpmError {}
|
||||
unsafe impl Send for RpmError {}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
enum OvmfFetchError {
|
||||
#[display(fmt = "Failed to fetch OVMF package")]
|
||||
Fetch,
|
||||
#[display(fmt = "RPM parse error")]
|
||||
RpmParse,
|
||||
#[display(fmt = "Unsupported compression (ZSTD is the only supported one)")]
|
||||
UnsupportedCompression,
|
||||
#[display(fmt = "Decompression error")]
|
||||
Zstd,
|
||||
#[display(fmt = "Requested file not found in package")]
|
||||
NoFileFound,
|
||||
#[display(fmt = "IO Error")]
|
||||
Io,
|
||||
}
|
||||
|
||||
impl Context for OvmfFetchError {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Target {
|
||||
X86_64,
|
||||
Riscv64Virt,
|
||||
Aarch64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Display)]
|
||||
enum Error {
|
||||
#[display(fmt = "Failed to build the kernel")]
|
||||
Build,
|
||||
#[display(fmt = "Missing or invalid subcommand (available: build, run)")]
|
||||
InvalidSubCom,
|
||||
#[display(fmt = "IO Error")]
|
||||
Io,
|
||||
#[display(fmt = "Failed to spawn a process")]
|
||||
ProcessSpawn,
|
||||
#[display(fmt = "Failed to fetch UEFI firmware")]
|
||||
OvmfFetch,
|
||||
#[display(fmt = "QEMU Error: {}", "fmt_qemu_err(*_0)")]
|
||||
Qemu(Option<i32>),
|
||||
}
|
||||
|
||||
impl Context for Error {}
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Build => f.write_str("failed to build the kernel"),
|
||||
Self::InvalidSubCom => {
|
||||
f.write_str("missing or invalid subcommand (available: build, run)")
|
||||
|
||||
fn fmt_qemu_err(e: Option<i32>) -> impl Display {
|
||||
struct W(Option<i32>);
|
||||
impl Display for W {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(c) = self.0 {
|
||||
c.fmt(f)
|
||||
} else {
|
||||
f.write_str("Interrupted by signal")
|
||||
}
|
||||
Self::Io => f.write_str("IO error"),
|
||||
Self::ProcessSpawn => f.write_str("failed to spawn a process"),
|
||||
Self::Qemu(Some(c)) => write!(f, "QEMU Error: {c}"),
|
||||
Self::Qemu(None) => write!(f, "QEMU Error: interrupted by signal"),
|
||||
}
|
||||
}
|
||||
|
||||
W(e)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue