1
0
Fork 0
forked from koniifer/ableos

adding system info (X86_64 only)

This commit is contained in:
Able 2022-01-01 18:06:46 -06:00
parent 07f8df04d1
commit f2dfad3162
11 changed files with 1044 additions and 11 deletions

View file

@ -8,7 +8,7 @@ version = "0.1.0"
panic = "abort"
[package.metadata.bootimage]
run-args = ["-serial", "stdio"]
run-args = ["-serial", "stdio", "-smp", "cores=2"]
test-args = [
"-device",
"isa-debug-exit,iobase=0xf4,iosize=0x04",

View file

@ -0,0 +1,946 @@
#![feature(asm)]
#![cfg_attr(
not(any(target_arch = "x86_64", target_arch = "x86")),
allow(dead_code)
)]
//! ```
//! extern crate cupid;
//!
//! fn main() {
//! let information = cupid::master();
//! println!("{:#?}", information);
//! if let Some(information) = information {
//! if information.sse4_2() {
//! println!("SSE 4.2 Available");
//! }
//! }
//! }
//! ```
use core::ops::Deref;
use core::{fmt, slice, str};
#[repr(u32)]
pub enum RequestType {
BasicInformation = 0x00000000,
VersionInformation = 0x00000001,
ThermalPowerManagementInformation = 0x00000006,
StructuredExtendedInformation = 0x00000007,
ExtendedFunctionInformation = 0x80000000,
ExtendedProcessorSignature = 0x80000001,
BrandString1 = 0x80000002,
BrandString2 = 0x80000003,
BrandString3 = 0x80000004,
// reserved = 0x80000005,
CacheLine = 0x80000006,
TimeStampCounter = 0x80000007,
PhysicalAddressSize = 0x80000008,
}
pub fn cpuid(code: RequestType) -> (u32, u32, u32, u32) {
let res1;
let res2;
let res3;
let res4;
unsafe {
llvm_asm!("cpuid"
: // output operands
"={eax}"(res1),
"={ebx}"(res2),
"={ecx}"(res3),
"={edx}"(res4)
: // input operands
"{eax}"(code as u32),
"{ecx}"(0 as u32)
: // clobbers
: // options
);
}
(res1, res2, res3, res4)
}
/// The main entrypoint to the CPU information
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
pub fn master() -> Option<Master> {
Some(Master::new())
}
// This matches the Intel Architecture guide, with bits 31 -> 0.
// The bit positions are inclusive.
fn bits_of(val: u32, start_bit: u8, end_bit: u8) -> u32 {
let mut silly = 0;
for _ in start_bit..end_bit + 1 {
silly <<= 1;
silly |= 1;
}
(val >> start_bit) & silly
}
pub fn as_bytes(v: &u32) -> &[u8] {
let start = v as *const u32 as *const u8;
// TODO: use u32::BYTES
unsafe { slice::from_raw_parts(start, 4) }
}
macro_rules! bit {
($reg:ident, {$($idx:expr => $name:ident),+}) => {
$(pub fn $name(self) -> bool {
((self.$reg >> $idx) & 1) != 0
})+
}
}
macro_rules! dump {
($me:expr, $f: expr, $sname:expr, {$($name:ident),+}) => {
$f.debug_struct($sname)
$(.field(stringify!($name), &$me.$name()))+
.finish()
}
}
macro_rules! delegate_flag {
($item:ident, {$($name:ident),+}) => {
$(pub fn $name(&self) -> bool {
self.$item.map(|i| i.$name()).unwrap_or(false)
})+
}
}
macro_rules! master_attr_reader {
($name:ident, $kind:ty) => {
pub fn $name(&self) -> Option<&$kind> {
self.$name.as_ref()
}
};
}
#[derive(Copy, Clone)]
pub struct VersionInformation {
eax: u32,
ebx: u32,
ecx: u32,
edx: u32,
}
impl VersionInformation {
pub fn new() -> VersionInformation {
let (a, b, c, d) = cpuid(RequestType::VersionInformation);
VersionInformation {
eax: a,
ebx: b,
ecx: c,
edx: d,
}
}
pub fn family_id(self) -> u32 {
let family_id = bits_of(self.eax, 8, 11);
let extended_family_id = bits_of(self.eax, 20, 27);
if family_id != 0x0F {
family_id
} else {
extended_family_id + family_id
}
}
pub fn model_id(self) -> u32 {
let family_id = self.family_id();
let model_id = bits_of(self.eax, 4, 7);
let extended_model_id = bits_of(self.eax, 16, 19);
if family_id == 0x06 || family_id == 0x0F {
(extended_model_id << 4) + model_id
} else {
model_id
}
}
pub fn stepping(self) -> u32 {
bits_of(self.eax, 0, 3)
}
fn processor_signature(self) -> u32 {
self.eax
}
pub fn brand_string(self) -> Option<&'static str> {
let brand_index = bits_of(self.ebx, 0, 7);
let processor_signature = self.processor_signature();
match brand_index {
0x00 => None,
0x01 => Some("Intel(R) Celeron(R)"),
0x02 => Some("Intel(R) Pentium(R) III"),
0x03 => {
if processor_signature == 0x06B1 {
Some("Intel(R) Celeron(R)")
} else {
Some("Intel(R) Pentium(R) III Xeon(R)")
}
}
0x04 => Some("Intel(R) Pentium(R) III"),
0x06 => Some("Mobile Intel(R) Pentium(R) III-M"),
0x07 => Some("Mobile Intel(R) Celeron(R)"),
0x08 => Some("Intel(R) Pentium(R) 4"),
0x09 => Some("Intel(R) Pentium(R) 4"),
0x0A => Some("Intel(R) Celeron(R)"),
0x0B => {
if processor_signature == 0x0F13 {
Some("Intel(R) Xeon(R) MP")
} else {
Some("Intel(R) Xeon(R)")
}
}
0x0C => Some("Intel(R) Xeon(R) MP"),
0x0E => {
if processor_signature == 0x0F13 {
Some("Intel(R) Xeon(R)")
} else {
Some("Mobile Intel(R) Pentium(R) 4-M")
}
}
0x0F => Some("Mobile Intel(R) Celeron(R)"),
0x11 => Some("Mobile Genuine Intel(R)"),
0x12 => Some("Intel(R) Celeron(R) M"),
0x13 => Some("Mobile Intel(R) Celeron(R)"),
0x14 => Some("Intel(R) Celeron(R)"),
0x15 => Some("Mobile Genuine Intel(R)"),
0x16 => Some("Intel(R) Pentium(R) M"),
0x17 => Some("Mobile Intel(R) Celeron(R)"),
_ => None,
}
}
bit!(ecx, {
0 => sse3,
1 => pclmulqdq,
2 => dtes64,
3 => monitor,
4 => ds_cpl,
5 => vmx,
6 => smx,
7 => eist,
8 => tm2,
9 => ssse3,
10 => cnxt_id,
11 => sdbg,
12 => fma,
13 => cmpxchg16b,
14 => xtpr_update_control,
15 => pdcm,
// 16 - reserved
17 => pcid,
18 => dca,
19 => sse4_1,
20 => sse4_2,
21 => x2apic,
22 => movbe,
23 => popcnt,
24 => tsc_deadline,
25 => aesni,
26 => xsave,
27 => osxsave,
28 => avx,
29 => f16c,
30 => rdrand
// 31 - unused
});
bit!(edx, {
0 => fpu,
1 => vme,
2 => de,
3 => pse,
4 => tsc,
5 => msr,
6 => pae,
7 => mce,
8 => cx8,
9 => apic,
// 10 - reserved
11 => sep,
12 => mtrr,
13 => pge,
14 => mca,
15 => cmov,
16 => pat,
17 => pse_36,
18 => psn,
19 => clfsh,
// 20 - reserved
21 => ds,
22 => acpi,
23 => mmx,
24 => fxsr,
25 => sse,
26 => sse2,
27 => ss,
28 => htt,
29 => tm,
// 30 -reserved
31 => pbe
});
}
impl fmt::Debug for VersionInformation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "VersionInformation", {
family_id,
model_id,
stepping,
brand_string,
sse3,
pclmulqdq,
dtes64,
monitor,
ds_cpl,
vmx,
smx,
eist,
tm2,
ssse3,
cnxt_id,
sdbg,
fma,
cmpxchg16b,
xtpr_update_control,
pdcm,
pcid,
dca,
sse4_1,
sse4_2,
x2apic,
movbe,
popcnt,
tsc_deadline,
aesni,
xsave,
osxsave,
avx,
f16c,
rdrand,
fpu,
vme,
de,
pse,
tsc,
msr,
pae,
mce,
cx8,
apic,
sep,
mtrr,
pge,
mca,
cmov,
pat,
pse_36,
psn,
clfsh,
ds,
acpi,
mmx,
fxsr,
sse,
sse2,
ss,
htt,
tm,
pbe
})
}
}
#[derive(Copy, Clone)]
pub struct ExtendedProcessorSignature {
ecx: u32,
edx: u32,
}
impl ExtendedProcessorSignature {
fn new() -> ExtendedProcessorSignature {
let (_, _, c, d) = cpuid(RequestType::ExtendedProcessorSignature);
ExtendedProcessorSignature { ecx: c, edx: d }
}
bit!(ecx, {
0 => lahf_sahf_in_64_bit,
// 1-4 reserved
5 => lzcnt,
// 6-7 reserved
8 => prefetchw
// 9-31 reserved
});
bit!(edx, {
// 0-10 reserved
11 => syscall_sysret_in_64_bit,
// 12-19 reserved
20 => execute_disable,
// 21-25 reserved
26 => gigabyte_pages,
27 => rdtscp_and_ia32_tsc_aux,
// 28 reserved
29 => intel_64_bit_architecture
// 30-31 reserved
});
}
impl fmt::Debug for ExtendedProcessorSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "ThermalPowerManagementInformation", {
lahf_sahf_in_64_bit,
lzcnt,
prefetchw,
syscall_sysret_in_64_bit,
execute_disable,
gigabyte_pages,
rdtscp_and_ia32_tsc_aux,
intel_64_bit_architecture
})
}
}
// 3 calls of 4 registers of 4 bytes
const BRAND_STRING_LENGTH: usize = 3 * 4 * 4;
pub struct BrandString {
bytes: [u8; BRAND_STRING_LENGTH],
}
impl BrandString {
fn new() -> BrandString {
fn append_bytes(a: RequestType, bytes: &mut [u8]) {
let (a, b, c, d) = cpuid(a);
let result_bytes = as_bytes(&a)
.iter()
.chain(as_bytes(&b).iter())
.chain(as_bytes(&c).iter())
.chain(as_bytes(&d).iter());
for (output, input) in bytes.iter_mut().zip(result_bytes) {
*output = *input
}
}
let mut brand_string = BrandString {
bytes: [0; BRAND_STRING_LENGTH],
};
append_bytes(RequestType::BrandString1, &mut brand_string.bytes[0..]);
append_bytes(RequestType::BrandString2, &mut brand_string.bytes[16..]);
append_bytes(RequestType::BrandString3, &mut brand_string.bytes[32..]);
brand_string
}
}
impl Clone for BrandString {
fn clone(&self) -> Self {
let mut bytes = [0; BRAND_STRING_LENGTH];
for (d, s) in bytes.iter_mut().zip(self.bytes.iter()) {
*d = *s;
}
BrandString { bytes: bytes }
}
}
impl Deref for BrandString {
type Target = str;
fn deref(&self) -> &str {
let nul_terminator = self.bytes.iter().position(|&b| b == 0).unwrap_or(0);
let usable_bytes = &self.bytes[..nul_terminator];
unsafe { str::from_utf8_unchecked(usable_bytes) }.trim()
}
}
impl fmt::Display for BrandString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self as &str).fmt(f)
}
}
impl fmt::Debug for BrandString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self as &str).fmt(f)
}
}
#[derive(Copy, Clone)]
pub struct ThermalPowerManagementInformation {
eax: u32,
ebx: u32,
ecx: u32,
}
impl ThermalPowerManagementInformation {
fn new() -> ThermalPowerManagementInformation {
let (a, b, c, _) = cpuid(RequestType::ThermalPowerManagementInformation);
ThermalPowerManagementInformation {
eax: a,
ebx: b,
ecx: c,
}
}
bit!(eax, {
0 => digital_temperature_sensor,
1 => intel_turbo_boost,
2 => arat,
// 3 - reserved
4 => pln,
5 => ecmd,
6 => ptm,
7 => hwp,
8 => hwp_notification,
9 => hwp_activity_window,
10 => hwp_energy_performance_preference,
// 12 - reserved
13 => hdc
});
pub fn number_of_interrupt_thresholds(self) -> u32 {
bits_of(self.ebx, 0, 3)
}
bit!(ecx, {
0 => hardware_coordination_feedback,
// 1-2 - reserved
3 => performance_energy_bias
});
}
impl fmt::Debug for ThermalPowerManagementInformation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "ThermalPowerManagementInformation", {
digital_temperature_sensor,
intel_turbo_boost,
arat,
pln,
ecmd,
ptm,
hwp,
hwp_notification,
hwp_activity_window,
hwp_energy_performance_preference,
hdc,
number_of_interrupt_thresholds,
hardware_coordination_feedback,
performance_energy_bias
})
}
}
#[derive(Copy, Clone)]
pub struct StructuredExtendedInformation {
ebx: u32,
ecx: u32,
}
impl StructuredExtendedInformation {
fn new() -> StructuredExtendedInformation {
let (_, b, c, _) = cpuid(RequestType::StructuredExtendedInformation);
StructuredExtendedInformation { ebx: b, ecx: c }
}
bit!(ebx, {
0 => fsgsbase,
1 => ia32_tsc_adjust_msr,
// 2 - reserved
3 => bmi1,
4 => hle,
5 => avx2,
// 6 - reserved
7 => smep,
8 => bmi2,
9 => enhanced_rep_movsb_stosb,
10 => invpcid,
11 => rtm,
12 => pqm,
13 => deprecates_fpu_cs_ds,
// 14 - reserved
15 => pqe,
// 16-17 - reserved
18 => rdseed,
19 => adx,
20 => smap,
// 21-24 - reserved
25 => intel_processor_trace
// 26-31 - reserved
});
bit!(ecx, {
0 => prefetchwt1
});
}
impl fmt::Debug for StructuredExtendedInformation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "StructuredExtendedInformation", {
fsgsbase,
ia32_tsc_adjust_msr,
bmi1,
hle,
avx2,
smep,
bmi2,
enhanced_rep_movsb_stosb,
invpcid,
rtm,
pqm,
deprecates_fpu_cs_ds,
pqe,
rdseed,
adx,
smap,
intel_processor_trace,
prefetchwt1
})
}
}
#[derive(Debug, Copy, Clone)]
pub enum CacheLineAssociativity {
Disabled,
DirectMapped,
TwoWay,
FourWay,
EightWay,
SixteenWay,
Full,
}
#[derive(Copy, Clone)]
pub struct CacheLine(u32);
impl CacheLine {
fn new() -> CacheLine {
let (_, _, c, _) = cpuid(RequestType::CacheLine);
CacheLine(c)
}
pub fn cache_line_size(self) -> u32 {
bits_of(self.0, 0, 7)
}
pub fn l2_associativity(self) -> Option<CacheLineAssociativity> {
match bits_of(self.0, 12, 15) {
0x00 => Some(CacheLineAssociativity::Disabled),
0x01 => Some(CacheLineAssociativity::DirectMapped),
0x02 => Some(CacheLineAssociativity::TwoWay),
0x04 => Some(CacheLineAssociativity::FourWay),
0x06 => Some(CacheLineAssociativity::EightWay),
0x08 => Some(CacheLineAssociativity::SixteenWay),
0x0F => Some(CacheLineAssociativity::Full),
_ => None,
}
}
pub fn cache_size(self) -> u32 {
bits_of(self.0, 16, 31)
}
}
impl fmt::Debug for CacheLine {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "CacheLine", {
cache_line_size,
l2_associativity,
cache_size
})
}
}
#[derive(Copy, Clone)]
pub struct TimeStampCounter {
edx: u32,
}
impl TimeStampCounter {
fn new() -> TimeStampCounter {
let (_, _, _, d) = cpuid(RequestType::TimeStampCounter);
TimeStampCounter { edx: d }
}
bit!(edx, {
// 0-7 - reserved
8 => invariant_tsc
// 9-31 - reserved
});
}
impl fmt::Debug for TimeStampCounter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "TimeStampCounter", { invariant_tsc })
}
}
#[derive(Copy, Clone)]
pub struct PhysicalAddressSize(u32);
impl PhysicalAddressSize {
fn new() -> PhysicalAddressSize {
let (a, _, _, _) = cpuid(RequestType::PhysicalAddressSize);
PhysicalAddressSize(a)
}
pub fn physical_address_bits(self) -> u32 {
bits_of(self.0, 0, 7)
}
pub fn linear_address_bits(self) -> u32 {
bits_of(self.0, 8, 15)
}
}
impl fmt::Debug for PhysicalAddressSize {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
dump!(self, f, "PhysicalAddressSize", {
physical_address_bits,
linear_address_bits
})
}
}
/// Information about the currently running processor
///
/// Feature flags match the feature mnemonic listed in the Intel
/// Instruction Set Reference. This struct provides a facade for flags
/// so the consumer doesn't need to worry about which particular CPUID
/// leaf provides the information.
///
/// For data beyond simple feature flags, you will need to retrieve
/// the nested struct and call the appropriate methods on it.
#[derive(Debug, Clone)]
pub struct Master {
// TODO: Rename struct
version_information: Option<VersionInformation>,
thermal_power_management_information: Option<ThermalPowerManagementInformation>,
structured_extended_information: Option<StructuredExtendedInformation>,
extended_processor_signature: Option<ExtendedProcessorSignature>,
brand_string: Option<BrandString>,
cache_line: Option<CacheLine>,
time_stamp_counter: Option<TimeStampCounter>,
physical_address_size: Option<PhysicalAddressSize>,
}
impl Master {
pub fn new() -> Master {
fn when_supported<F, T>(max: u32, kind: RequestType, then: F) -> Option<T>
where
F: FnOnce() -> T,
{
if max >= kind as u32 {
Some(then())
} else {
None
}
}
let (max_value, _, _, _) = cpuid(RequestType::BasicInformation);
let vi = when_supported(max_value, RequestType::VersionInformation, || {
VersionInformation::new()
});
let tpm = when_supported(
max_value,
RequestType::ThermalPowerManagementInformation,
|| ThermalPowerManagementInformation::new(),
);
let sei = when_supported(
max_value,
RequestType::StructuredExtendedInformation,
|| StructuredExtendedInformation::new(),
);
// Extended information
let (max_value, _, _, _) = cpuid(RequestType::ExtendedFunctionInformation);
let eps = when_supported(max_value, RequestType::ExtendedProcessorSignature, || {
ExtendedProcessorSignature::new()
});
let brand_string =
when_supported(max_value, RequestType::BrandString3, || BrandString::new());
let cache_line = when_supported(max_value, RequestType::CacheLine, || CacheLine::new());
let tsc = when_supported(max_value, RequestType::TimeStampCounter, || {
TimeStampCounter::new()
});
let pas = when_supported(max_value, RequestType::PhysicalAddressSize, || {
PhysicalAddressSize::new()
});
Master {
version_information: vi,
thermal_power_management_information: tpm,
structured_extended_information: sei,
extended_processor_signature: eps,
brand_string: brand_string,
cache_line: cache_line,
time_stamp_counter: tsc,
physical_address_size: pas,
}
}
master_attr_reader!(version_information, VersionInformation);
master_attr_reader!(
thermal_power_management_information,
ThermalPowerManagementInformation
);
master_attr_reader!(
structured_extended_information,
StructuredExtendedInformation
);
master_attr_reader!(extended_processor_signature, ExtendedProcessorSignature);
master_attr_reader!(cache_line, CacheLine);
master_attr_reader!(time_stamp_counter, TimeStampCounter);
master_attr_reader!(physical_address_size, PhysicalAddressSize);
pub fn brand_string(&self) -> Option<&str> {
self.brand_string
.as_ref()
.map(|bs| bs as &str)
.or(self.version_information.and_then(|vi| vi.brand_string()))
}
delegate_flag!(version_information, {
sse3,
pclmulqdq,
dtes64,
monitor,
ds_cpl,
vmx,
smx,
eist,
tm2,
ssse3,
cnxt_id,
sdbg,
fma,
cmpxchg16b,
xtpr_update_control,
pdcm,
pcid,
dca,
sse4_1,
sse4_2,
x2apic,
movbe,
popcnt,
tsc_deadline,
aesni,
xsave,
osxsave,
avx,
f16c,
rdrand,
fpu,
vme,
de,
pse,
tsc,
msr,
pae,
mce,
cx8,
apic,
sep,
mtrr,
pge,
mca,
cmov,
pat,
pse_36,
psn,
clfsh,
ds,
acpi,
mmx,
fxsr,
sse,
sse2,
ss,
htt,
tm,
pbe
});
delegate_flag!(thermal_power_management_information, {
digital_temperature_sensor,
intel_turbo_boost,
arat,
pln,
ecmd,
ptm,
hwp,
hwp_notification,
hwp_activity_window,
hwp_energy_performance_preference,
hdc,
hardware_coordination_feedback,
performance_energy_bias
});
delegate_flag!(structured_extended_information, {
fsgsbase,
ia32_tsc_adjust_msr,
bmi1,
hle,
avx2,
smep,
bmi2,
enhanced_rep_movsb_stosb,
invpcid,
rtm,
pqm,
deprecates_fpu_cs_ds,
pqe,
rdseed,
adx,
smap,
intel_processor_trace,
prefetchwt1
});
delegate_flag!(extended_processor_signature, {
lahf_sahf_in_64_bit,
lzcnt,
prefetchw,
syscall_sysret_in_64_bit,
execute_disable,
gigabyte_pages,
rdtscp_and_ia32_tsc_aux,
intel_64_bit_architecture
});
delegate_flag!(time_stamp_counter, { invariant_tsc });
}
/*
cfg_if! {
if #[cfg(any(target_arch = "x86_64", target_arch = "x86"))] {
#[test]
fn basic_genuine_intel() {
let (_, b, c, d) = cpuid(RequestType::BasicInformation);
assert_eq!(b"Genu", as_bytes(&b));
assert_eq!(b"ntel", as_bytes(&c));
assert_eq!(b"ineI", as_bytes(&d));
}
#[test]
fn brand_string_contains_intel() {
assert!(master().unwrap().brand_string().unwrap().contains("Intel(R)"))
}
} else {}
}
*/

View file

@ -9,4 +9,6 @@ pub mod virtual_memory;
// added for experimental use
pub mod kinfo;
pub mod mail;
pub mod info;
pub const BANNER: &str = include_str!("banner.txt");

View file

@ -1,6 +1,6 @@
#![allow(clippy::empty_loop)]
use crate::log::LOG_STATE;
use crate::experiments::info::master;
use {
crate::{
@ -32,7 +32,7 @@ lazy_static! {
#[no_mangle]
pub fn kernel_main() -> ! {
init::init();
LOG_STATE.lock().log_to_screen = false;
// LOG_STATE.lock().log_to_screen = false;
let mut a_thread = Thread::new();
@ -46,6 +46,11 @@ pub fn kernel_main() -> ! {
info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION);
info!(
"Brand String: {:?}",
master().unwrap().brand_string().unwrap()
);
println!("$PINK$Hi$RED$ from$GREEN$ able!$RESET$");
println!("$RED$hi$RESET$");

View file

@ -102,7 +102,7 @@ macro_rules! debug {
if $crate::log::LOG_STATE.lock().debug{
use crate::log::Log;
let _ = &log::ANSISerialLogger::debug(&alloc::format!($($arg)*));
let _ = crate::log::ANSISerialLogger::debug(&alloc::format!($($arg)*));
}
})
}

View file

@ -0,0 +1,71 @@
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
/*
clparse
* A simple command line parser for ableOS
*/
// use std::collections::HashMap;
#[derive(Debug)]
pub struct Argument {
key: String,
value: String,
}
#[derive(Debug)]
struct Command {
root_command: String,
// arguments: HashMap<String, String>,
arguments: Vec<Argument>,
}
impl Command {
pub fn parse(command: String) -> Command {
let split_command = command.split("?");
let mut root = "".to_string();
let mut root_count = 0;
let mut args: Vec<Argument> = vec![];
for subcommand in split_command {
match root_count {
0 => root = subcommand.to_string(),
1 => {
for subarg in subcommand.split("&") {
let mut arg1 = "";
let mut arg2 = "";
let mut arg_count = 0;
for arg in subarg.split("=") {
if arg_count == 0 {
arg1 = arg;
} else {
arg2 = arg;
}
arg_count += 1;
}
let arg_struct = Argument {
key: arg1.to_string(),
value: arg2.to_string(),
};
args.push(arg_struct);
}
}
_ => {}
}
root_count += 1;
}
Command {
root_command: root,
arguments: args,
}
}
}
fn test() {
let x = Command::parse("hi?there=uwu&hi=abc".to_string());
let y = &x.arguments[0];
println!("{:?}", y);
}

View file

@ -1,6 +1,8 @@
pub mod clparse;
pub mod image;
pub mod math;
pub mod time;
pub struct VectorTwo {
pub x: i32,
pub y: i32,

View file

@ -1,5 +1,5 @@
use {
crate::{kmain::THREAD_LIST, log},
crate::kmain::THREAD_LIST,
alloc::{vec, vec::Vec},
core::cmp::Ordering,
};
@ -60,7 +60,7 @@ impl Thread {
Some(last_thread) => final_threadid = last_thread.id + 1,
None => {}
}
debug!("New thread with $BLUE$ThreadID$RESET$: {}", final_threadid);
debug!("New thread with ThreadID: {}", final_threadid);
Self {
id: final_threadid,
tasks: vec![],

View file

@ -29,14 +29,22 @@ impl Externals for HostFunctions {
// Take in one arg discard the rest
SysCall::KILL => {
info!("Program run at runtime called a system call");
debug!("Runtime arguments: {:?}", _args);
Ok(None)
}
// Do nothing
SysCall::EMPTY => Ok(None),
SysCall::EXIT => Ok(None),
SysCall::CONSOLE_RESET => Ok(None),
SysCall::CONSOLE_IN => Ok(None),
SysCall::CONSOLE_OUT => Ok(None),
SysCall::CONSOLE_IN => {
info!("In");
Ok(None)
}
SysCall::CONSOLE_OUT => {
info!("Out");
Ok(None)
}
SysCall::CONSOLE_GET_TITLE => Ok(None),
SysCall::CONSOLE_SET_TITLE => Ok(None),
_ => panic!("Unimplemented function at {}", index),
@ -72,7 +80,7 @@ impl ModuleImportResolver for HostFunctions {
}
pub fn evaluate() {
let wasm_binary = include_bytes!("rust.wasm");
let wasm_binary = include_bytes!("bin/rust.wasm");
// Load wasm binary and prepare it for instantiation.
let module = wasmi::Module::from_buffer(&wasm_binary).expect("failed to load wasm");
@ -89,7 +97,6 @@ pub fn evaluate() {
// and empty external function executor.
let result: i32 = instance
.invoke_export("_start", &[], &mut HostFunctions)
// .with_resolver(&mut HostFunctions)
.expect("failed to execute export")
.unwrap()
.try_into()