Compare commits

...

13 Commits

Author SHA1 Message Date
Able efb1a98bc6
add a pci device view on boot 2022-11-30 01:47:15 -06:00
Able 556b3656f3
solid 2022-11-23 06:23:36 -06:00
Able 7aee7ab371
changing color parsing from \0 to \1a 2022-11-23 02:32:12 -06:00
Able 25c2a72fd1
fix echo command and add traces to vfs 2022-11-23 01:55:09 -06:00
ondra05 41ee39e1b9 Skeleton for architecture-specific things 2022-11-07 21:21:16 +01:00
ondra05 ed0c0ad43f Threw stuff from the microkernel. Start of moving core parts there. 2022-11-07 20:29:42 +01:00
ondra05 67510d7ae9 clippy 2022-11-05 01:43:41 +01:00
ondra05 444bbb7bd1 removed module that I forgot to remove + 1.65 stuff 2022-11-05 01:40:38 +01:00
ondra05 b6fdfaefa0 removed sus messaging module 2022-11-05 00:39:37 +01:00
ondra05 5818182028 update 2022-10-29 19:53:08 +02:00
ondra05 27bda3a403 fixed sound 2022-10-29 19:20:23 +02:00
ondra05 8d0b756b42 merge 2022-08-28 22:04:55 +02:00
ondra05 7e0c645003 fixed qr code 2022-08-21 11:45:28 +02:00
41 changed files with 219 additions and 578 deletions

2
.gitignore vendored
View File

@ -1,5 +1,7 @@
userland/root_fs/mnt/
target/
limine/
.disk.img
.gdb_history
!*/.gitkeep
__pycache__/

View File

@ -22,18 +22,14 @@ run-command = [
]
run-args = [
# "--nodefaults",
"-cpu",
"Broadwell-v3",
"-m",
"4G",
"-serial",
"stdio",
"-smp",
"cores=2",
"-cpu", "Broadwell-v3",
"-m", "4G",
"-serial", "stdio",
"-smp", "cores=2",
"-soundhw",
"pcspk",
"-audiodev", "id=pa,driver=pa",
"-machine", "pcspk-audiodev=pa",
# "-device",
@ -41,11 +37,8 @@ run-args = [
# "-device",
# "virtio-gpu-pci",
"-device",
"vmware-svga",
"-device",
"sb16",
"-device", "vmware-svga",
"-device", "sb16",
# "-machine", "pcspk-audiodev=0",

View File

@ -7,9 +7,10 @@ enabled = true
level = "Trace"
log_to_serial = true
log_to_vterm = false
filter = ["ableos::ps2_mouse", "ableos::vterm"]
filter = ["ableos::ps2_mouse", "ableos::vterm", "ableos::filesystem::vfs"]
# Exact paths required
[tests]
run_tests = false
run_demos = false

View File

@ -1 +1 @@
nightly-2022-01-04
nightly

View File

@ -256,7 +256,7 @@ pub fn bsod(src: BSODSource) -> ! {
let image = code
.render::<char>()
.quiet_zone(false)
.module_dimensions(2, 1)
.module_dimensions(1, 1)
.build();
println!("{}", image);

View File

@ -1,4 +1,4 @@
use kernel::device_interface::CharacterDevice;
use crate::device_interface::CharacterDevice;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DevNull;

View File

@ -1,4 +1,4 @@
use kernel::device_interface::CharacterDevice;
use crate::device_interface::CharacterDevice;
#[derive(Debug)]
pub struct DevUnicode {

View File

@ -1,4 +1,4 @@
use kernel::device_interface::CharacterDevice;
use crate::device_interface::CharacterDevice;
#[derive(Debug)]
pub struct DevZero;

View File

@ -2,4 +2,4 @@ pub mod dev_null;
pub mod dev_unicode;
pub mod dev_zero;
pub use kernel::device_interface::CharacterDevice;
pub use crate::device_interface::CharacterDevice;

View File

@ -1,9 +1,9 @@
// ! A virtual terminal device.
use crate::device_interface::CharacterDevice;
use core::ops::Not;
use core::sync::atomic::AtomicU32;
use core::sync::atomic::Ordering;
use kernel::device_interface::CharacterDevice;
use crate::pixel_format::Rgba64;

View File

@ -6,10 +6,10 @@ pub mod pci;
pub use self::Device::*;
use crate::device_interface::{BlockDevice, CharacterDevice};
use crate::devices::dev_vterm::VTerm;
use character_devs::{dev_null::DevNull, dev_unicode::DevUnicode, dev_zero::DevZero};
use hashbrown::HashMap;
use kernel::device_interface::{BlockDevice, CharacterDevice};
use spin::Lazy;
pub static DEVICE_TABLE: Lazy<spin::Mutex<DeviceTable>> =

View File

@ -184,56 +184,61 @@ impl Display for PciFullClass {
write!(f, " Class: ")?;
match self {
PciFullClass::Unclassified_NonVgaCompatible => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Unclassified_VgaCompatible => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::MassStorage_ScsiBus => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_IDE => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_Floppy => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_IpiBus => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_RAID => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_ATA => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_SATA => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_SerialSCSI => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_NVM => write!(f, "\0CYAN\0")?,
PciFullClass::MassStorage_Other => write!(f, "\0CYAN\0")?,
PciFullClass::Network_Ethernet => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_TokenRing => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_FDDI => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_ATM => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_ISDN => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_WorldFlip => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_PICMG => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_Infiniband => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_Fabric => write!(f, "\0MAGENTA\0")?,
PciFullClass::Network_Other => write!(f, "\0MAGENTA\0")?,
PciFullClass::Display_VGA => write!(f, "\0YELLOW\0")?,
PciFullClass::Display_XGA => write!(f, "\0YELLOW\0")?,
PciFullClass::Display_3D => write!(f, "\0YELLOW\0")?,
PciFullClass::Display_Other => write!(f, "\0YELLOW\0")?,
PciFullClass::Multimedia_Video => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Multimedia_AudioController => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Multimedia_Telephony => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Multimedia_AudioDevice => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Multimedia_Other => write!(f, "\0LIGHTBLUE\0")?,
PciFullClass::Memory_RAM => write!(f, "\0BLUE\0")?,
PciFullClass::Memory_Flash => write!(f, "\0WHITE\0")?,
PciFullClass::Memory_Other => write!(f, "\0LIGHTGREY\0")?,
PciFullClass::Bridge_Host => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_ISA => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_EISA => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_MCA => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_PciToPci => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_PCMCIA => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_NuBus => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_CardBus => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_RACEway => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_PciToPciSemiTransparent => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_InfinibandToPci => write!(f, "\0GREEN\0")?,
PciFullClass::Bridge_Other => write!(f, "\0GREEN\0")?,
PciFullClass::Unknown => write!(f, "\0RED\0")?,
PciFullClass::Unclassified_NonVgaCompatible => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Unclassified_VgaCompatible => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::MassStorage_ScsiBus => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_IDE => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_Floppy => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_IpiBus => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_RAID => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_ATA => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_SATA => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_SerialSCSI => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_NVM => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::MassStorage_Other => write!(f, "\u{001A}CYAN\u{001A}")?,
PciFullClass::Network_Ethernet => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_TokenRing => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_FDDI => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_ATM => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_ISDN => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_WorldFlip => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_PICMG => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_Infiniband => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_Fabric => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Network_Other => write!(f, "\u{001A}MAGENTA\u{001A}")?,
PciFullClass::Display_VGA => write!(f, "\u{001A}YELLOW\u{001A}")?,
PciFullClass::Display_XGA => write!(f, "\u{001A}YELLOW\u{001A}")?,
PciFullClass::Display_3D => write!(f, "\u{001A}YELLOW\u{001A}")?,
PciFullClass::Display_Other => write!(f, "\u{001A}YELLOW\u{001A}")?,
PciFullClass::Multimedia_Video => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Multimedia_AudioController => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Multimedia_Telephony => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Multimedia_AudioDevice => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Multimedia_Other => write!(f, "\u{001A}LIGHTBLUE\u{001A}")?,
PciFullClass::Memory_RAM => write!(f, "\u{001A}BLUE\u{001A}")?,
PciFullClass::Memory_Flash => write!(f, "\u{001A}WHITE\u{001A}")?,
PciFullClass::Memory_Other => write!(f, "\u{001A}LIGHTGREY\u{001A}")?,
PciFullClass::Bridge_Host => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_ISA => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_EISA => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_MCA => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_PciToPci => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_PCMCIA => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_NuBus => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_CardBus => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_RACEway => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_PciToPciSemiTransparent => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_InfinibandToPci => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Bridge_Other => write!(f, "\u{001A}GREEN\u{001A}")?,
PciFullClass::Unknown => write!(f, "\u{001A}RED\u{001A}")?,
}
write!(f, "{:?} ({:#06X})\0RESET\0", self, self.as_u16())?;
write!(
f,
"{:?} ({:#06X})\u{001A}RESET\u{001A}",
self,
self.as_u16()
)?;
Ok(())
}

View File

@ -84,7 +84,7 @@ const CMD_READ_DMA_EXT: u8 = 0x25;
/// ATA write using LBA48 DMA command
const CMD_WRITE_DMA_EXT: u8 = 0x35;
#[derive(Debug)]
pub struct PciIde {
device_info: PciDeviceInfo,
ide_devices: Vec<IdeDevice>,
@ -629,6 +629,7 @@ unsafe fn read_dword_buffer(port: u16, buffer: *mut u32, mut count: u32) {
});
}
#[derive(Debug)]
struct IdeDevice {
pub channel: Channel,
pub drive: Drive,

View File

@ -28,6 +28,7 @@ lazy_static! {
}
#[non_exhaustive]
#[derive(Debug)]
pub enum PciDevice {
Ide(PciIde),
// Variant so that we aren't about irrefutable if-let patterns
@ -41,6 +42,7 @@ pub fn init(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut BootInfoFr
for device in 0..32 {
if let Some(device_info) = device::check_device(bus, device) {
trace!("{device_info}");
println!("{device_info}");
match device_info.device_id {
// FIXME: Unknown class
S3_TRIO64V2 => {}

View File

@ -164,17 +164,17 @@ impl Display for Vendor {
use Vendor::*;
match self {
Qemu => write!(f, "{}", "\0PINK\0QEMU (0x1234)"),
VirtIO => write!(f, "{}", "\0PINK\0VirtIO (0x1AF4)"),
VMWareInc => write!(f, "{}", "\0PINK\0VMWARE (0x15AD)"),
S3Inc => write!(f, "{}", "\0YELLOW\0S3 Incorporated (0x5333)"),
IntelCorp => write!(f, "{}", "\0BLUE\0Intel Corp. (0x8086)"),
ATITechnologiesInc => write!(f, "{}", "\0RED\0ATI (0x1002)"),
Unknown(id) => write!(f, "\0RED\0Unknown ({:#6})", id),
Qemu => write!(f, "{}", "\u{001A}PINK\u{001A}QEMU (0x1234)"),
VirtIO => write!(f, "{}", "\u{001A}PINK\u{001A}VirtIO (0x1AF4)"),
VMWareInc => write!(f, "{}", "\u{001A}PINK\u{001A}VMWARE (0x15AD)"),
S3Inc => write!(f, "{}", "\u{001A}YELLOW\u{001A}S3 Incorporated (0x5333)"),
IntelCorp => write!(f, "{}", "\u{001A}BLUE\u{001A}Intel Corp. (0x8086)"),
ATITechnologiesInc => write!(f, "{}", "\u{001A}RED\u{001A}ATI (0x1002)"),
Unknown(id) => write!(f, "\u{001A}RED\u{001A}Unknown ({:#6})", id),
other => write!(f, "{other:?}"),
}?;
write!(f, "\0RESET\0")?;
write!(f, "\u{001A}RESET\u{001A}")?;
Ok(())
}
}

View File

@ -1,4 +1,4 @@
use kernel::device_interface::CharacterDevice;
use crate::device_interface::CharacterDevice;
pub struct Serial {
pub base: usize,

View File

@ -4,6 +4,8 @@
* SPDX-License-Identifier: MPL-2.0
*/
use core::fmt::Display;
#[derive(Copy, Clone, Debug)]
pub enum FsError {
EndOfFile,
@ -17,6 +19,11 @@ pub enum FsError {
Recursion,
UnsupportedOperation,
}
impl Display for FsError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}", self)
}
}
impl Into<FsError> for ext2::error::Error {
fn into(self) -> FsError {

View File

@ -51,23 +51,26 @@ impl VirtualFileSystem {
if !path.starts_with('/') {
// FIXME: use current process working directory for relative paths?
error!("Nonabsolute path {}", path);
Err(FsError::NotAbsolute)?;
}
trace!("Splitting path up");
let mut components = path.split_terminator('/');
components.next(); // throw the empty string caused by the root /
// will be initialised beforehand so okay to unwrap
let mut resolved_node = self.root_handle.unwrap();
// let mut symlink_recursion_level = 0;
for component in components {
trace!("iterating through split up path");
// if symlink_recursion_level >= SYMLINK_RECURSION_LIMIT {
// Err(FsError::Recursion)?;
// }
if component == "" {
error!("Invalid Path {}", path);
Err(FsError::InvalidPath)?;
}
trace!("Getting parent of file");
// checked by previous iteration so okay to unwrap
let parent = self.fs_node(resolved_node).unwrap();
@ -77,16 +80,18 @@ impl VirtualFileSystem {
// that's just more boilerplate in StorageDevice impls
// we should probably check that here instead to reduce
// required boilerplate
// if !parent.is_dir() {
// Err(FsError::NotADirectory)?;
// }
if !parent.is_dir() {
error!("file parent {:?} is not a directory", parent);
Err(FsError::NotADirectory)?;
}
// FIXME: handle mount points
// FIXME: handle symlinks
trace!("resolving node");
resolved_node = parent.find_dir(self, component)?;
}
trace!("returning resolved node");
Ok(resolved_node)
}
@ -107,6 +112,7 @@ impl VirtualFileSystem {
}
pub fn fs_node(&self, handle: Handle) -> Option<Arc<FsNode>> {
trace!("Cloning file node and returning");
self.fs_nodes.get(&handle).cloned()
}
@ -212,12 +218,16 @@ impl FsNode {
}
pub fn find_dir(&self, vfs: &mut VirtualFileSystem, name: &str) -> Result<Handle> {
trace!("Locking the kernel state");
let state = KERNEL_STATE.lock();
trace!("Grabbing storage device");
let device = state
.storage_device(self.device_handle)
.ok_or_else(|| FsError::InvalidDevice)?;
device.find_dir(vfs, self, name)
trace!("locating directory");
let ret = device.find_dir(vfs, self, name);
trace!("returning directory");
ret
}
pub fn directory(self: Arc<Self>) -> Option<Directory> {

View File

@ -14,12 +14,12 @@
#![feature(
abi_x86_interrupt,
alloc_error_handler,
arbitrary_enum_discriminant,
asm_sym, // Needed for RISC-V
custom_test_frameworks,
naked_functions,
prelude_import,
)]
#![feature(arbitrary_enum_discriminant)]
#![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"]
#![test_runner(crate::test_runner)]
@ -57,6 +57,7 @@ pub mod print;
pub mod serial_print;
pub mod boot_conf;
pub mod device_interface;
pub mod devices;
pub mod driver_traits;
pub mod experiments;
@ -97,7 +98,6 @@ pub use driver_traits::*;
pub use experiments::*;
pub use graphics::*;
pub use kernel;
pub use kernel::messaging;
// pub use kernel::panic;
pub use kernel_state::*;
pub use keyboard::*;

View File

@ -87,10 +87,10 @@ pub fn scratchpad() {
println!(
"{}
,-------. OS: \0BLUE\0AbleOS\0RESET\0
,'\\ _ _`. Host: \0PINK\0{}\0RESET\0
/ \\)_)-)_)-\\ Kernel: \0RED\0AKern-{}-v{}\0RESET\0
: : Uptime: \0GREEN\0{}\0RESET\0
,-------. OS: \u{001A}BLUE\u{001A}AbleOS\u{001A}RESET\u{001A}
,'\\ _ _`. Host: \u{001A}PINK\u{001A}{}\u{001A}RESET\u{001A}
/ \\)_)-)_)-\\ Kernel: \u{001A}RED\u{001A}AKern-{}-v{}\u{001A}RESET\u{001A}
: : Uptime: \u{001A}GREEN\u{001A}{}\u{001A}RESET\u{001A}
\\ / Packages: None
\\ / Shell: BuiltinShell
`. ,' Resolution: 640x480
@ -120,7 +120,8 @@ pub fn scratchpad() {
.iter()
.find_map(|device_ref| {
let device = device_ref.lock();
if let PciDevice::Ide(_) = &*device {
if let PciDevice::Ide(dev) = &*device {
println!("IDE Device found: {}", dev.device_info());
Some(device_ref.clone())
} else {
None
@ -133,8 +134,10 @@ pub fn scratchpad() {
let mut pci_ide_device = pci_ide_device.lock();
if let PciDevice::Ide(device) = &mut *pci_ide_device {
let mut first_sector = Vec::with_capacity(512);
device.read(Channel::Primary, Drive::Master, 0, 1, &mut first_sector).unwrap();
trace!("IDE Primary/Master sector 0: {first_sector:?}");
device
.read(Channel::Primary, Drive::Master, 0, 1, &mut first_sector)
.unwrap();
// trace!("IDE Primary/Master sector 0: {first_sector:?}");
}
}
@ -323,18 +326,53 @@ pub fn sound_off() {
}
pub fn echo_file(path: String) {
let mut current_path = String::from("/");
println!("{}", path);
let mut current_path = String::from("");
current_path.push_str(&path);
debug!("Aquiring lock");
let mut vfs = VFS.lock();
let handle = vfs.resolve(&current_path).unwrap();
let file = vfs.fs_node(handle).unwrap();
debug!("Resolving path");
let maybe_handle = vfs.resolve(&current_path);
match maybe_handle {
Ok(handle) => {
debug!("Loading file");
let maybe_file = vfs.fs_node(handle);
if file.is_dir() {
// println!("{} is a directory", path);
} else {
let mut file_contents = Vec::new();
file.read(0, file.size(), &mut file_contents).unwrap();
let file_contents_str = String::from_utf8_lossy(&file_contents);
println!("{}", file_contents_str);
match maybe_file {
Some(file) => {
trace!("checking is directory");
if file.is_dir() {
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A} {} is a directory",
path
);
error!("{} is a directory", path);
} else {
trace!("allocating buffer for file contents");
let mut file_contents = Vec::new();
trace!("Reading file {} into buffer", path);
file.read(0, file.size(), &mut file_contents).unwrap();
trace!("Converting file bytes into string");
let file_contents_str = String::from_utf8_lossy(&file_contents);
println!("{}", file_contents_str);
}
}
None => {
error!("File {} doesn't exist", path);
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: File {} doesn't exist",
path
);
}
}
}
Err(err) => {
println!(
"\u{001A}RED\u{001A}ERROR\u{001A}RESET\u{001A}: path {} Error {}",
path, err
);
error!("path {} Error {}", path, err);
}
}
}

View File

@ -1,7 +1,7 @@
use {
crate::device_interface::CharacterDevice,
crate::devices::Device::{Block, Character, Vterm},
core::fmt::{Arguments, Error, Write},
kernel::device_interface::CharacterDevice,
};
#[derive(Debug, Clone)]

View File

@ -66,5 +66,3 @@ pub fn test_kernel_main(boot_info: &'static BootInfo) -> ! {
loop {}
}
use bootloader::{entry_point, BootInfo};
use crate::test_main;

View File

@ -36,7 +36,7 @@ impl VTerm {
dirty: false,
x: 0,
back_buffer: [0; 640 * 480],
term: [('\0', Color16::DarkGrey); 80 * 60],
term: [('\u{001A}', Color16::DarkGrey); 80 * 60],
color: Color16::White,
}
}
@ -88,7 +88,7 @@ impl VTerm {
}
// trace!("C");
match c {
'\0' => {
'\u{001A}' => {
self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] =
(c, self.color);
self.x += 1;
@ -101,7 +101,7 @@ impl VTerm {
}
self.x -= 1;
self.term[TERM_MINUS_ONE_LINE + (self.x as usize)] =
('\0', Color16::LightGrey);
('\u{001A}', Color16::LightGrey);
}
'\n' => {
self.move_up();
@ -124,7 +124,7 @@ impl VTerm {
pub fn move_up(&mut self) {
self.term.rotate_left(80);
for x in 0..80 {
self.term[TERM_MINUS_ONE_LINE + x] = ('\0', Color16::DarkGrey);
self.term[TERM_MINUS_ONE_LINE + x] = ('\u{001A}', Color16::DarkGrey);
}
self.x = 0;
}
@ -211,40 +211,40 @@ enum Token {
#[error]
Error,
#[token("\0RESET\0", priority = 10)]
#[token("\u{001A}RESET\u{001A}", priority = 10)]
Reset,
#[token("\0BLACK\0", priority = 10)]
#[token("\u{001A}BLACK\u{001A}", priority = 10)]
TBlack,
#[regex("\0BLUE\0", priority = 10)]
#[regex("\u{001A}BLUE\u{001A}", priority = 10)]
TBlue,
#[token("\0GREEN\0", priority = 10)]
#[token("\u{001A}GREEN\u{001A}", priority = 10)]
TGreen,
#[token("\0CYAN\0", priority = 10)]
#[token("\u{001A}CYAN\u{001A}", priority = 10)]
TCyan,
#[token("\0RED\0", priority = 10)]
#[token("\u{001A}RED\u{001A}", priority = 10)]
TRed,
#[token("\0MAGENTA\0", priority = 10)]
#[token("\u{001A}MAGENTA\u{001A}", priority = 10)]
TMagenta,
#[token("\0BROWN\0", priority = 10)]
#[token("\u{001A}BROWN\u{001A}", priority = 10)]
TBrown,
#[token("\0LIGHTGREY\0", priority = 10)]
#[token("\u{001A}LIGHTGREY\u{001A}", priority = 10)]
TLightGrey,
#[token("\0DARKGREY\0", priority = 10)]
#[token("\u{001A}DARKGREY\u{001A}", priority = 10)]
TDarkGrey,
#[token("\0LIGHTBLUE\0", priority = 10)]
#[token("\u{001A}LIGHTBLUE\u{001A}", priority = 10)]
TLightBlue,
#[token("\0LIGHTGREEN\0", priority = 10)]
#[token("\u{001A}LIGHTGREEN\u{001A}", priority = 10)]
TLightGreen,
#[token("\0LIGHTCYAN\0", priority = 10)]
#[token("\u{001A}LIGHTCYAN\u{001A}", priority = 10)]
TLightCyan,
#[token("\0LIGHTRED\0", priority = 10)]
#[token("\u{001A}LIGHTRED\u{001A}", priority = 10)]
TLightRed,
#[token("\0PINK\0", priority = 10)]
#[token("\u{001A}PINK\u{001A}", priority = 10)]
TPink,
#[token("\0YELLOW\0", priority = 10)]
#[token("\u{001A}YELLOW\u{001A}", priority = 10)]
TYellow,
#[token("\0WHITE\0", priority = 10)]
#[token("\u{001A}WHITE\u{001A}", priority = 10)]
TWhite,
// #[token(" ")]

BIN
disk.img Normal file

Binary file not shown.

View File

@ -1,122 +0,0 @@
//! The allocator to be implemented by ableOS
//!
//! NOTE: All memory regions are taken from https://wiki.osdev.org/Memory_Map_(x86)
#![allow(missing_docs)]
use alloc::alloc::{GlobalAlloc, Layout};
use core::{fmt::Display, ptr::null_mut};
use log::{debug, info};
// const HEAP_START: usize = 600_000_000;
const HEAP_START: usize = 0x00100000;
const BLOCK_SIZE: usize = 1024;
const BLOCK_COUNT: usize = 512;
#[derive(Debug, Clone, Copy)]
pub struct MemoryRegion {
start: usize,
end: usize,
}
impl Display for MemoryRegion {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
writeln!(
f,
"MemoryRegion {{ start: {}, end: {}, size: {} bytes}}",
self.start,
self.end,
self.end - self.start
)
}
}
impl MemoryRegion {
pub fn new(start: usize, end: usize) -> MemoryRegion {
MemoryRegion { start, end }
}
pub fn test_region(&self) -> bool {
unsafe {
let mutptr = self.start as *mut u8;
core::ptr::write(mutptr, 0xFF);
// trace!("{}", core::ptr::read(mutptr));
}
true
}
}
#[derive(Debug, Clone, Copy)]
pub struct AAlloc {
current_region: usize,
memory_regions: [Option<MemoryRegion>; 512],
}
impl AAlloc {
fn test_regions(&self) {
for x in 0..self.current_region {
if let Some(region) = self.memory_regions[x] {
debug!("Region {}: {:?}", x, region);
}
}
}
pub fn add_region(&mut self, mem: MemoryRegion) {
self.memory_regions[self.current_region] = Some(mem);
self.current_region += 1;
}
pub fn intialize() {
info!("Heap Start: {}", HEAP_START);
info!("Heap Size: {}", BLOCK_SIZE * BLOCK_COUNT);
info!("Heap End: {}", HEAP_START + BLOCK_SIZE * BLOCK_COUNT);
let mut aalloc = AAlloc {
current_region: 0,
memory_regions: [None; 512],
};
// BS MEMORY REGION
aalloc.add_region(MemoryRegion::new(HEAP_START, HEAP_START + 10));
aalloc.add_region(MemoryRegion::new(0x00007E00, 0x0007FFFF));
aalloc.add_region(MemoryRegion::new(0x00100000, 0x00EFFFFF));
// ISA Memory Hole
aalloc.add_region(MemoryRegion::new(0x00F00000, 0x00FFFFFF));
aalloc.add_region(MemoryRegion::new(0x0000000100000000, 0x0000000100000000));
aalloc.memory_regions[0].unwrap().test_region();
debug!("{}", aalloc);
}
}
impl Display for AAlloc {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "AAlloc {{\n\tcurrent_region: {},\n", self.current_region)?;
for x in 0..self.current_region {
if let Some(region) = self.memory_regions[x] {
write!(f, "\tRegion {}: {}", x, region)?;
}
}
write!(f, "}}")?;
Ok(())
}
}
unsafe impl GlobalAlloc for AAlloc {
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
info!("Allocating memory");
info!("{}", _layout.size());
info!("{}", _layout.align());
null_mut()
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
panic!("dealloc should be never called")
}
}

View File

@ -1,12 +0,0 @@
#![allow(missing_docs)]
pub mod aalloc;
pub use aalloc::*;
/*
#[alloc_error_handler]
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
panic!("allocation error: {:?}", layout)
}
*/

View File

@ -0,0 +1 @@
//!

View File

@ -1,6 +1,16 @@
//! Architecture-specific code.
//! Architecture specific code
/// X86 specific code
#[cfg(target_arch = "x86_64")]
#[path = "x86_64/mod.rs"]
pub mod arch;
macro_rules! arch_cond {
($($arch:ident: $str:literal),* $(,)?) => {$(
#[cfg(target_arch = $str)]
pub mod $arch;
#[cfg(target_arch = $str)]
pub use $arch::*;
)*};
}
arch_cond!(
aarch64: "aarch64",
riscv64: "riscv64",
x86_64: "x86_64",
);

View File

@ -0,0 +1 @@
//!

View File

@ -1,9 +1 @@
///
pub fn sloop() {
loop {
unsafe {
core::arch::asm!("hlt");
}
}
}
//!

View File

@ -1,47 +1,20 @@
//! The ableOS kernel.
#![feature(alloc_error_handler)]
#![feature(arbitrary_enum_discriminant)]
#![feature(prelude_import)]
#![feature(alloc_error_handler, prelude_import)]
#![no_std]
#![deny(missing_docs)]
extern crate alloc;
pub mod aalloc;
pub mod allocator;
pub mod arch;
pub mod device_interface;
pub mod messaging;
// pub mod panic;
pub mod proccess;
pub mod syscalls;
pub mod task;
pub mod time;
use core::arch::asm;
use versioning::Version;
/// The number of ticks since the first CPU was started
// pub static TICK: AtomicU64 = AtomicU64::new(0);
/// Kernel's version
pub const KERNEL_VERSION: Version = Version {
major: 0,
minor: 1,
patch: 2,
};
/*
/// called by arch specific timers to tick up all kernel related functions
pub fn tick() {
let mut data = TICK.load(Relaxed);
data = data.wrapping_add(1);
TICK.store(data, Relaxed)
}
*/
/// Cause a software interrupt
pub fn software_int() {
unsafe { asm!("int 54") }
}

View File

@ -1,193 +0,0 @@
//! Interprocess communication.
use alloc::vec::Vec;
use crate::{proccess::PID, time::Time};
extern crate alloc;
/// 131070 * 128
pub const TINY_MESSAGE_COUNT: usize = 131070;
/// 16384 * 1024
pub const SMALL_MESSAGE_COUNT: usize = 16384;
/// 65536 * 256
pub const MEDIUM_MESSAGE_COUNT: usize = 256;
/// 262144 * 16
pub const LARGE_MESSAGE_COUNT: usize = 16;
/// 16777216 * 4
pub const HUGE_MESSAGE_COUNT: usize = 4;
/// 128 Bytes
pub type Tiny = [u8; 128];
/// 1 KiB
pub type Small = [u8; 1024];
/// 65.536 KiB
pub type Medium = [u8; 65536];
/// 1MiB
pub type Large = [u8; 1048576];
/// 16MiB
pub type Huge = [u8; 16777216];
/// An internal message to be held in a process message
pub enum Message {
/// A Tiny message
///
/// The message is 128 bytes long
Tiny(Tiny),
/// A Small message
///
/// The message is 1 KiB long
Small(Small),
/// A Medium message
///
/// The message is 65.536 KiB long
Medium(Medium),
/// A Large message
///
/// The message is 1 MiB long
Large(Large),
/// A Huge message
///
/// The message is 16 MiB long
Huge(Huge),
}
/// A message that can be sent between processes
pub struct ProcessMessage {
/// The sender of the message
pub to_pid: PID,
/// The receiver of the message
pub from_pid: PID,
/// The message
pub message: Message,
/// The time the message was sent
pub sender_time: Time,
/// The time the message was received
pub receiver_time: Time,
}
impl ProcessMessage {
/// Return the size of the message
pub fn size(&self) -> usize {
match &self.message {
Message::Tiny(_) => 128,
Message::Small(_) => 1024,
Message::Medium(_) => 65536,
Message::Large(_) => 1048576,
Message::Huge(_) => 16777216,
}
}
}
#[derive(Debug)]
/// An enum of all possible errors that can occur when sending a message
pub enum MessagingError {
/// The message is too large to be sent
MessageTooLarge,
/// The reciever of the message is not valid
ProcessNonExistant,
/// The message Queue is full
TooManyMessages,
}
/// A mailbox that holds messages and PipeState
pub struct Mailbox {
/// The messages in the mailbox
pub messages: Vec<ProcessMessage>,
/// The count of messages in the mailbox
pub message_count: MessageCount,
}
impl Mailbox {
/// append a message to the mailbox
pub fn append(&mut self, message: ProcessMessage) -> Result<(), MessagingError> {
let msg_size = message.size();
if self.message_count.total() > 147730 {
return Err(MessagingError::TooManyMessages);
}
match msg_size {
TINY_MESSAGE_COUNT => {
if self.message_count.tiny < TINY_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.tiny += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
SMALL_MESSAGE_COUNT => {
if self.message_count.small < SMALL_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.small += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
MEDIUM_MESSAGE_COUNT => {
if self.message_count.medium < MEDIUM_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.medium += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
LARGE_MESSAGE_COUNT => {
if self.message_count.large < LARGE_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.large += 1;
Ok(())
} else {
Err(MessagingError::TooManyMessages)
}
}
HUGE_MESSAGE_COUNT => {
if self.message_count.huge < HUGE_MESSAGE_COUNT {
self.messages.push(message);
self.message_count.huge += 1;
Ok(())
} else {
return Err(MessagingError::TooManyMessages);
}
}
_ => Err(MessagingError::MessageTooLarge),
}
}
}
/// A proper struct to list the number of messages in the mailbox
pub struct MessageCount {
/// The number of tiny messages in the mailbox
pub tiny: usize,
/// The number of small messages in the mailbox
pub small: usize,
/// The number of medium messages in the mailbox
pub medium: usize,
/// The number of large messages in the mailbox
pub large: usize,
/// The number of huge messages in the mailbox
pub huge: usize,
}
impl MessageCount {
/// Return the total number of messages in the mailbox
pub fn total(&self) -> usize {
self.tiny + self.small + self.medium + self.large + self.huge
}
}
impl Default for MessageCount {
fn default() -> Self {
MessageCount {
tiny: 0,
small: 0,
medium: 0,
large: 0,
huge: 0,
}
}
}

View File

@ -1,11 +0,0 @@
//! Panic-related stuff
use core::panic::PanicInfo;
use log::error;
#[panic_handler]
fn panic_handler(info: &PanicInfo) -> ! {
error!("{}", info);
loop {}
}

View File

@ -1,14 +0,0 @@
//! Platform agnostic process
/// A process ID
pub type PID = u64;
/// Signals that can be sent to a process
#[repr(C)]
pub enum Signals {
/// Terminate the process
Terminate,
/// Shutdown the process and allow it to shutdown cleanly
Quit,
}

View File

@ -1,26 +0,0 @@
//!
use crate::proccess::{Signals, PID};
/// All possible system calls
pub enum Syscall {
/// Create a new process and return its PID
CreateProcess,
/// Send a signal to a process
SendSignal(PID, Signals),
/// Get the current process ID
GetPID,
/// Get the current time
GetTime,
/// Set the time
SetTime,
// ListInodes,
// CreateInode,
// RemoveInode,
// OpenInode,
// CloseInode,
}

View File

@ -87,16 +87,16 @@ impl Executor {
.map(|t| TaskId(self.tasks.insert(t)))
.or_else(|| self.queue.pop())
{
let task = match self.tasks.get_mut(id.0) {
Some(t) => t,
None => panic!("attempted to get non-extant task with id {}", id.0),
let Some(task) = self.tasks.get_mut(id.0) else {
panic!("attempted to get non-extant task with id {}", id.0)
};
let mut cx = Context::from_waker(
self.wakers
.entry(id)
.or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.queue))),
);
let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| {
Waker::from(Arc::new(TaskWaker {
id,
queue: Arc::clone(&self.queue),
}))
}));
match task.poll(&mut cx) {
Poll::Ready(()) => {
@ -138,12 +138,6 @@ struct TaskWaker {
queue: TaskQueue,
}
impl TaskWaker {
fn new(id: TaskId, queue: TaskQueue) -> Waker {
Waker::from(Arc::new(Self { id, queue }))
}
}
impl Wake for TaskWaker {
fn wake(self: Arc<Self>) {
self.wake_by_ref();

View File

@ -1,10 +0,0 @@
//! Time
/// An internal structure that is used to keep track of the time
pub struct Time {
/// The number of seconds since the kernel was started
pub seconds: u64,
/// The number of nanoseconds since the kernel was started
pub nanoseconds: u32,
}

1
limine Submodule

@ -0,0 +1 @@
Subproject commit 2b12406a79d9bd0a4bc0c06f6261ecb72f51c9c2