From f2dfad3162e07449b331973eafe7a784d0d14f6c Mon Sep 17 00:00:00 2001 From: Able Date: Sat, 1 Jan 2022 18:06:46 -0600 Subject: [PATCH] adding system info (X86_64 only) --- ableos/Cargo.toml | 2 +- ableos/src/experiments/info.rs | 946 ++++++++++++++++++++++++++++ ableos/src/experiments/mod.rs | 2 + ableos/src/kmain.rs | 9 +- ableos/src/log.rs | 4 +- ableos/src/relib/clparse/mod.rs | 71 +++ ableos/src/relib/mod.rs | 2 + ableos/src/scheduler.rs | 4 +- ableos/src/wasm/{ => bin}/rust.wasm | Bin ableos/src/wasm/{ => bin}/zig.wasm | Bin ableos/src/wasm/mod.rs | 15 +- 11 files changed, 1044 insertions(+), 11 deletions(-) create mode 100644 ableos/src/experiments/info.rs create mode 100644 ableos/src/relib/clparse/mod.rs rename ableos/src/wasm/{ => bin}/rust.wasm (100%) rename ableos/src/wasm/{ => bin}/zig.wasm (100%) diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 9c6bda86..9b0bbb69 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -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", diff --git a/ableos/src/experiments/info.rs b/ableos/src/experiments/info.rs new file mode 100644 index 00000000..fc6aec08 --- /dev/null +++ b/ableos/src/experiments/info.rs @@ -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 { + 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 { + 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, + thermal_power_management_information: Option, + structured_extended_information: Option, + extended_processor_signature: Option, + brand_string: Option, + cache_line: Option, + time_stamp_counter: Option, + physical_address_size: Option, +} + +impl Master { + pub fn new() -> Master { + fn when_supported(max: u32, kind: RequestType, then: F) -> Option + 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 {} +} +*/ diff --git a/ableos/src/experiments/mod.rs b/ableos/src/experiments/mod.rs index 2e5f4f15..6149dba8 100644 --- a/ableos/src/experiments/mod.rs +++ b/ableos/src/experiments/mod.rs @@ -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"); diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index 6e07e974..3b3dab9e 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -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$"); diff --git a/ableos/src/log.rs b/ableos/src/log.rs index 93c74548..e32af3af 100644 --- a/ableos/src/log.rs +++ b/ableos/src/log.rs @@ -100,9 +100,9 @@ impl Log for ANSISerialLogger { macro_rules! debug { ($($arg:tt)*) => ({ if $crate::log::LOG_STATE.lock().debug{ - use crate::log::Log; + use crate::log::Log; - let _ = &log::ANSISerialLogger::debug(&alloc::format!($($arg)*)); + let _ = crate::log::ANSISerialLogger::debug(&alloc::format!($($arg)*)); } }) } diff --git a/ableos/src/relib/clparse/mod.rs b/ableos/src/relib/clparse/mod.rs new file mode 100644 index 00000000..c953fc22 --- /dev/null +++ b/ableos/src/relib/clparse/mod.rs @@ -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, + arguments: Vec, +} + +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 = 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); +} diff --git a/ableos/src/relib/mod.rs b/ableos/src/relib/mod.rs index 3104cf57..02edbf59 100644 --- a/ableos/src/relib/mod.rs +++ b/ableos/src/relib/mod.rs @@ -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, diff --git a/ableos/src/scheduler.rs b/ableos/src/scheduler.rs index 66e951c7..a395ac38 100644 --- a/ableos/src/scheduler.rs +++ b/ableos/src/scheduler.rs @@ -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![], diff --git a/ableos/src/wasm/rust.wasm b/ableos/src/wasm/bin/rust.wasm similarity index 100% rename from ableos/src/wasm/rust.wasm rename to ableos/src/wasm/bin/rust.wasm diff --git a/ableos/src/wasm/zig.wasm b/ableos/src/wasm/bin/zig.wasm similarity index 100% rename from ableos/src/wasm/zig.wasm rename to ableos/src/wasm/bin/zig.wasm diff --git a/ableos/src/wasm/mod.rs b/ableos/src/wasm/mod.rs index a4113723..5f9105ee 100644 --- a/ableos/src/wasm/mod.rs +++ b/ableos/src/wasm/mod.rs @@ -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()