From bb6dd4881b9c5d14c3c5caf97b88b7e02c6a6682 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Mon, 21 Oct 2024 14:39:21 +0200 Subject: [PATCH] base --- .cargo/config.toml | 10 ++++ .gitignore | 1 + .vscode/settings.json | 4 ++ Cargo.lock | 124 ++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 21 +++++++ README.md | 4 ++ rust-toolchain | 1 + rustfmt.toml | 2 + setup.sh | 6 ++ src/dev/alloc.rs | 6 ++ src/dev/console.rs | 118 ++++++++++++++++++++++++++++++++++++++++ src/dev/input.rs | 23 ++++++++ src/dev/mod.rs | 3 + src/hard/int.rs | 49 +++++++++++++++++ src/hard/keyboard.rs | 7 +++ src/hard/mod.rs | 5 ++ src/hard/vga.rs | 16 ++++++ src/main.rs | 26 +++++++++ x86_64-nulfos.json | 15 +++++ 19 files changed, 441 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 rust-toolchain create mode 100644 rustfmt.toml create mode 100644 setup.sh create mode 100644 src/dev/alloc.rs create mode 100644 src/dev/console.rs create mode 100644 src/dev/input.rs create mode 100644 src/dev/mod.rs create mode 100644 src/hard/int.rs create mode 100644 src/hard/keyboard.rs create mode 100644 src/hard/mod.rs create mode 100644 src/hard/vga.rs create mode 100644 src/main.rs create mode 100644 x86_64-nulfos.json diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..357ec76 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,10 @@ + +[build] +target = ["x86_64-nulfos.json"] + +[unstable] +build-std = ["core", "compiler_builtins"] +build-std-features = ["compiler-builtins-mem"] + +[target.'cfg(target_os = "none")'] +runner = "bootimage runner" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c56a76b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "rust-analyzer.cargo.target": "x86_64-unknown-none", + "rust-analyzer.checkOnSave.allTargets": false +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..dfaf80c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,124 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bootloader" +version = "0.9.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365861702868e2a37b4247aaecc7bd8f4389baec8d025497ad8ba7ff37ee9440" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" +dependencies = [ + "spinning_top", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "nulfos" +version = "0.1.0" +dependencies = [ + "bootloader", + "lazy_static", + "linked_list_allocator", + "pic8259", + "spin", + "x86_64", +] + +[[package]] +name = "pic8259" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d9a86c292b165f757e47e7fd66855def189b2564609bc4203727b27c33db22" +dependencies = [ + "x86_64", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" +dependencies = [ + "lock_api", +] + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "x86_64" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df" +dependencies = [ + "bit_field", + "bitflags", + "rustversion", + "volatile", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6c3d150 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "nulfos" +version = "0.1.0" +edition = "2021" + +[dependencies] +bootloader = { version = "0.9", features = ["map_physical_memory"] } +lazy_static = { version = "1.5.0", features = ["spin_no_std"] } +linked_list_allocator = "0.10.5" +pic8259 = "0.11.0" +spin = "0.9.8" +x86_64 = "0.15.1" + + +# artefact configuration + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" diff --git a/README.md b/README.md new file mode 100644 index 0000000..946ec23 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# Nulf OS + +Toy kernel in rust. + diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..bf867e0 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..768ff5c --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +hard_tabs = true +max_width = 120 diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..ecf7d2c --- /dev/null +++ b/setup.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +rustup target add x86_64-unknown-none +rustup component add rust-src +rustup component add llvm-tools-preview diff --git a/src/dev/alloc.rs b/src/dev/alloc.rs new file mode 100644 index 0000000..705348d --- /dev/null +++ b/src/dev/alloc.rs @@ -0,0 +1,6 @@ +use crate::println; + +pub fn init() { + println!("Initializing Allocator."); + // TODO +} diff --git a/src/dev/console.rs b/src/dev/console.rs new file mode 100644 index 0000000..2d04943 --- /dev/null +++ b/src/dev/console.rs @@ -0,0 +1,118 @@ +use core::fmt; + +use lazy_static::lazy_static; +use spin::Mutex; + +use crate::hard::vga::{self, Vga}; + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::dev::console::print_args(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); +} + +lazy_static! { + static ref Out: Mutex = Mutex::new(Console::init()); +} + +pub struct Console { + cursor: Cursor, + vga: Vga, +} + +impl Console { + pub fn init() -> Self { + let cursor = Cursor::new(vga::WIDTH, vga::HEIGHT); + let vga = Vga; + Self { cursor, vga } + } + + pub fn print_(&mut self, text: &str) { + for c in text.chars() { + match c { + '\n' => self.cursor.ret(), + '\t' => self.print_(" "), + _ => { + self.vga.write_at(self.cursor.pos(), c); + self.cursor.progress(); + } + } + } + } +} + +struct Cursor { + line: usize, + column: usize, + width: usize, + height: usize, +} + +impl Cursor { + pub fn new(width: usize, height: usize) -> Self { + Self { + line: 0, + column: 0, + width, + height, + } + } + + pub fn pos(&self) -> (usize, usize) { + (self.column, self.line) + } + + pub fn set_line(&mut self, line: usize) { + self.line = line; + } + + pub fn set_col(&mut self, col: usize) { + self.column = col; + } + + pub fn line(&self) -> usize { + self.line + } + + pub fn col(&self) -> usize { + self.column + } + + pub fn progress(&mut self) { + self.column += 1; + if self.column < self.width { + return; + } + self.column = 0; + self.line += 1; + if self.line < self.height { + return; + } + self.line = 0; + } + + pub fn ret(&mut self) { + self.column = self.width; + self.progress(); + } +} + +impl fmt::Write for Console { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.print_(s); + Ok(()) + } +} + +pub fn print_args(args: fmt::Arguments) { + use core::fmt::Write; + use x86_64::instructions::interrupts; + interrupts::without_interrupts(|| { + Out.lock().write_fmt(args).unwrap(); + }); +} diff --git a/src/dev/input.rs b/src/dev/input.rs new file mode 100644 index 0000000..74829d7 --- /dev/null +++ b/src/dev/input.rs @@ -0,0 +1,23 @@ +use lazy_static::lazy_static; +use spin::Mutex; + +use crate::hard::keyboard::Keyboard; + +lazy_static! { + static ref In: Mutex = Mutex::new(Input::init()); +} + +pub struct Input { + keyboard: Keyboard, +} + +impl Input { + pub fn init() -> Self { + let keyboard = Keyboard; + Self { keyboard } + } + + pub fn read(out: &mut [char]) -> usize { + 0 + } +} diff --git a/src/dev/mod.rs b/src/dev/mod.rs new file mode 100644 index 0000000..c2b67ed --- /dev/null +++ b/src/dev/mod.rs @@ -0,0 +1,3 @@ +pub mod alloc; +pub mod console; +pub mod input; diff --git a/src/hard/int.rs b/src/hard/int.rs new file mode 100644 index 0000000..c5a4557 --- /dev/null +++ b/src/hard/int.rs @@ -0,0 +1,49 @@ +use lazy_static::lazy_static; +use pic8259::ChainedPics; +use spin::Mutex; +use x86_64::{ + instructions::{interrupts, port::Port}, + structures::idt::{InterruptDescriptorTable, InterruptStackFrame}, +}; + +use crate::{print, println}; + +pub fn init() { + println!("Initializing interrupt handler."); + IDT.load(); + unsafe { PICS.lock().initialize() }; + interrupts::enable(); +} + +const INT_OFFSET: u8 = 32; +const INT_IDX_TIMER: u8 = 32; +const INT_IDX_KEYBOARD: u8 = 33; + +lazy_static! { + static ref IDT: InterruptDescriptorTable = { + let mut idt = InterruptDescriptorTable::new(); + let entries = idt.slice_mut(INT_OFFSET..); + entries[(INT_IDX_TIMER - INT_OFFSET) as usize].set_handler_fn(timer_handler); + entries[(INT_IDX_KEYBOARD - INT_OFFSET) as usize].set_handler_fn(keyboard_handler); + idt + }; +} + +static PICS: Mutex = Mutex::new(unsafe { ChainedPics::new(0x20, 0x28) }); + +extern "x86-interrupt" fn keyboard_handler(_stack_frame: InterruptStackFrame) { + let mut port = Port::new(0x60); + let _scancode: u8 = unsafe { port.read() }; + // crate::task::keyboard::add_scancode(scancode); + println!("keyboard got scancode"); + unsafe { + PICS.lock().notify_end_of_interrupt(INT_IDX_KEYBOARD); + } +} + +extern "x86-interrupt" fn timer_handler(_stack_frame: InterruptStackFrame) { + print!("."); + unsafe { + PICS.lock().notify_end_of_interrupt(INT_IDX_TIMER); + } +} diff --git a/src/hard/keyboard.rs b/src/hard/keyboard.rs new file mode 100644 index 0000000..352121d --- /dev/null +++ b/src/hard/keyboard.rs @@ -0,0 +1,7 @@ +pub struct Keyboard; + +impl Keyboard { + pub fn record(key_code: u8) { + // todo!() + } +} diff --git a/src/hard/mod.rs b/src/hard/mod.rs new file mode 100644 index 0000000..da93ec9 --- /dev/null +++ b/src/hard/mod.rs @@ -0,0 +1,5 @@ +pub mod vga; + +pub mod keyboard; + +pub mod int; diff --git a/src/hard/vga.rs b/src/hard/vga.rs new file mode 100644 index 0000000..e4c3cc7 --- /dev/null +++ b/src/hard/vga.rs @@ -0,0 +1,16 @@ +pub const WIDTH: usize = 80; +pub const HEIGHT: usize = 25; + +pub struct Vga; + +impl Vga { + const BUFF: *mut u8 = 0xb8000 as _; + pub fn write_at(&self, pos: (usize, usize), text: char) { + let index = (pos.0 + pos.1 * WIDTH) as isize; + let byte = text as u8; + unsafe { + *Vga::BUFF.offset(index * 2) = byte; + *Vga::BUFF.offset(index * 2 + 1) = 0xb; + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d6ffdc5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] +#![feature(abi_x86_interrupt)] + +mod dev; +mod hard; + +use core::panic::PanicInfo; + +use dev::alloc; +use hard::int; + +#[no_mangle] +pub extern "C" fn _start() -> ! { + println!("Starting."); + int::init(); + alloc::init(); + println!("Finished initializations."); + loop {} +} + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + println!("Paniced."); + loop {} +} diff --git a/x86_64-nulfos.json b/x86_64-nulfos.json new file mode 100644 index 0000000..ceedc5d --- /dev/null +++ b/x86_64-nulfos.json @@ -0,0 +1,15 @@ +{ + "llvm-target": "x86_64-unknown-none", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "executables": true, + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "panic-strategy": "abort", + "disable-redzone": true, + "features": "-mmx,-sse,+soft-float" +}