From 2f8efad24a2dd3d68dee5e82c36fb375eb8a70a6 Mon Sep 17 00:00:00 2001 From: clizia Date: Mon, 25 Aug 2025 01:47:42 +0200 Subject: [PATCH 01/10] it now boots and prints hello world --- .cargo/config.toml | 9 +++++++++ Cargo.toml | 1 + src/main.rs | 13 ++++++++++++- x86_64-totos.json | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .cargo/config.toml create mode 100644 x86_64-totos.json diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..f95e6aa --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,9 @@ +[unstable] +build-std-features = ["compiler-builtins-mem"] +build-std = ["core", "compiler_builtins"] + +[build] +target = "x86_64-totos.json" + +[target.'cfg(target_os = "none")'] +runner = "bootimage runner" diff --git a/Cargo.toml b/Cargo.toml index 60e9fc5..4f6eaa3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ panic = "abort" # disable stack unwinding on panic panic = "abort" # disable stack unwinding on panic [dependencies] +bootloader = "0.9" diff --git a/src/main.rs b/src/main.rs index 132c4cc..8d80305 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,22 @@ use core::panic::PanicInfo; +static HELLO: &[u8] = b"Hello toto :3"; + // this function is the entry point since the linker // looks for a function named `_start` by default #[unsafe(no_mangle)] pub extern "C" fn _start() -> ! { - loop{} + let vga_buffer = 0xb8000 as *mut u8; + + for (i, &byte) in HELLO.iter().enumerate() { + unsafe { + *vga_buffer.offset(i as isize * 2) = byte; + *vga_buffer.offset(i as isize * 2 + 1) = 0xb; + } + } + + loop {} } // called on panic diff --git a/x86_64-totos.json b/x86_64-totos.json new file mode 100644 index 0000000..669ca9d --- /dev/null +++ b/x86_64-totos.json @@ -0,0 +1,16 @@ +{ + "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", + "rustc-abi": "x86-softfloat" +} From daa95130d8cae2cbe82424186e469764ad2b6b6c Mon Sep 17 00:00:00 2001 From: clizia Date: Mon, 25 Aug 2025 01:49:41 +0200 Subject: [PATCH 02/10] updated readme --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 16eedd4..fb00697 100644 --- a/README.md +++ b/README.md @@ -1 +1,14 @@ +### ABOUT + trying to make a toy OS in rust following [this](https://os.phil-opp.com) + +### HOWTO + +to run this just do: + +``` +cargo run +``` + +(ensure qemu is installed) + From 1fbe7a483b0d0e85f61bf44c6d27ff8bacd048d9 Mon Sep 17 00:00:00 2001 From: clizia Date: Mon, 25 Aug 2025 15:21:24 +0200 Subject: [PATCH 03/10] it prints what i say yo --- src/main.rs | 13 ++---- src/vga_buffer.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 src/vga_buffer.rs diff --git a/src/main.rs b/src/main.rs index 8d80305..22929da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,21 +3,16 @@ use core::panic::PanicInfo; +mod vga_buffer; + static HELLO: &[u8] = b"Hello toto :3"; // this function is the entry point since the linker // looks for a function named `_start` by default #[unsafe(no_mangle)] pub extern "C" fn _start() -> ! { - let vga_buffer = 0xb8000 as *mut u8; - - for (i, &byte) in HELLO.iter().enumerate() { - unsafe { - *vga_buffer.offset(i as isize * 2) = byte; - *vga_buffer.offset(i as isize * 2 + 1) = 0xb; - } - } - + vga_buffer::print_something(); + loop {} } diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs new file mode 100644 index 0000000..db9f6e6 --- /dev/null +++ b/src/vga_buffer.rs @@ -0,0 +1,102 @@ +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(transparent)] +struct ColorCode(u8); + +impl ColorCode { + fn new(foreground: Color, background: Color) -> ColorCode { + ColorCode((background as u8) << 4 | (foreground as u8)) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(C)] +struct ScreenChar { + ascii_carachter: u8, + color_code: ColorCode, +} + +const BUFFER_HEIGHT: usize = 25; +const BUFFER_WIDTH: usize = 80; + +#[repr(transparent)] +struct Buffer { + chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], +} + +pub struct Writer { + column_position: usize, + color_code: ColorCode, + buffer: &'static mut Buffer, +} + +impl Writer { + pub fn write_byte(&mut self, byte: u8) { + match byte { + b'\n' => self.new_line(), + byte => { + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } + + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + + let color_code = self.color_code; + self.buffer.chars[row][col] = ScreenChar { + ascii_carachter: byte, + color_code, + }; + self.column_position += 1; + } + } + } + + pub fn write_string(&mut self, s: &str) { + for byte in s.bytes() { + match byte { + // printable ascii byte or newline + 0x20..=0x7E | b'\n' => self.write_byte(byte), + // not part of printable ascii range + _ => self.write_byte(0xFE), + } + } + } + + fn new_line(&mut self) { + todo!() + } +} + +pub fn print_something() { + let mut writer = Writer { + column_position: 0, + color_code: ColorCode::new(Color::Yellow, Color::Black), + buffer: unsafe { &mut *(0xB8000 as *mut Buffer) }, + }; + + writer.write_byte(b'H'); + writer.write_string("ello "); + writer.write_string("Wörld!"); +} From 237b99941fb6f34efbb39d4e4370b34d526c7799 Mon Sep 17 00:00:00 2001 From: clizia Date: Tue, 26 Aug 2025 14:31:37 +0200 Subject: [PATCH 04/10] added volatile type to prevent the compiler from optimizing writings to the buffer away --- Cargo.toml | 1 + src/vga_buffer.rs | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f6eaa3..5ebddac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,4 @@ panic = "abort" # disable stack unwinding on panic [dependencies] bootloader = "0.9" +volatile = "0.2.6" diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index db9f6e6..64d246a 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -1,3 +1,5 @@ +use volatile::Volatile; + #[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -42,7 +44,15 @@ const BUFFER_WIDTH: usize = 80; #[repr(transparent)] struct Buffer { - chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], + // wrapping the `ScreenChar` in a generic `Volatile` + // type prevents the compiler from optimizing writes + // away since the program only writes to it but never + // reads from it. + // by making it volatile we signal to the compiler + // that our write call have side-effects + // to interact with this type the `write()` and `read()` + // methods must be used now + chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], } pub struct Writer { @@ -64,10 +74,10 @@ impl Writer { let col = self.column_position; let color_code = self.color_code; - self.buffer.chars[row][col] = ScreenChar { + self.buffer.chars[row][col].write(ScreenChar { ascii_carachter: byte, color_code, - }; + }); self.column_position += 1; } } @@ -89,10 +99,11 @@ impl Writer { } } +// function to test things: to be removed pub fn print_something() { let mut writer = Writer { column_position: 0, - color_code: ColorCode::new(Color::Yellow, Color::Black), + color_code: ColorCode::new(Color::Pink, Color::Black), buffer: unsafe { &mut *(0xB8000 as *mut Buffer) }, }; From 2bd6ba35fc1433117a86e52a82632b16b78b718b Mon Sep 17 00:00:00 2001 From: clizia Date: Tue, 26 Aug 2025 14:36:22 +0200 Subject: [PATCH 05/10] implemented fmt::Write for Writer --- src/vga_buffer.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index 64d246a..21ac5af 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -1,3 +1,4 @@ +use core::fmt; use volatile::Volatile; #[allow(dead_code)] @@ -61,6 +62,13 @@ pub struct Writer { buffer: &'static mut Buffer, } +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.write_string(s); + Ok(()) + } +} + impl Writer { pub fn write_byte(&mut self, byte: u8) { match byte { @@ -101,6 +109,7 @@ impl Writer { // function to test things: to be removed pub fn print_something() { + use core::fmt::Write; let mut writer = Writer { column_position: 0, color_code: ColorCode::new(Color::Pink, Color::Black), @@ -109,5 +118,5 @@ pub fn print_something() { writer.write_byte(b'H'); writer.write_string("ello "); - writer.write_string("Wörld!"); + write!(writer, "The numbers are {} and {}", 42, 1.0/3.0).unwrap(); } From daec1c75bf4e9dc58104aa76b183d8ac728c3367 Mon Sep 17 00:00:00 2001 From: clizia Date: Tue, 26 Aug 2025 23:44:17 +0200 Subject: [PATCH 06/10] added a static Writer to reuse in the program --- Cargo.toml | 5 +++++ src/main.rs | 6 ++++-- src/vga_buffer.rs | 46 +++++++++++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5ebddac..6cf02d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,8 @@ panic = "abort" # disable stack unwinding on panic [dependencies] bootloader = "0.9" volatile = "0.2.6" +spin = "0.5.2" + +[dependencies.lazy_static] +version = "1.0" +features = ["spin_no_std"] diff --git a/src/main.rs b/src/main.rs index 22929da..83bce51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,10 @@ static HELLO: &[u8] = b"Hello toto :3"; // looks for a function named `_start` by default #[unsafe(no_mangle)] pub extern "C" fn _start() -> ! { - vga_buffer::print_something(); - + use core::fmt::Write; + vga_buffer::WRITER.lock().write_str("TOTOTO !!!! :3").unwrap(); + write!(vga_buffer::WRITER.lock(), ", smoking cigarette in the shower when they get wet i just light another :{}", 3).unwrap(); + loop {} } diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index 21ac5af..8f71171 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -1,5 +1,15 @@ use core::fmt; use volatile::Volatile; +use lazy_static::lazy_static; +use spin::Mutex; + +lazy_static! { + pub static ref WRITER: Mutex = Mutex::new(Writer { + column_position: 0, + color_code: ColorCode::new(Color::Pink, Color::Black), + buffer: unsafe { &mut *(0xB8000 as *mut Buffer) }, + }); +} #[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -103,20 +113,26 @@ impl Writer { } fn new_line(&mut self) { - todo!() + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + let character = self.buffer.chars[row][col].read(); + self.buffer.chars[row - 1][col].write(character); + } + } + self.clear_row(BUFFER_HEIGHT - 1); + self.column_position = 0; + } + + // this method clears a row by overwriting all of its + // characters with a space character. + fn clear_row(&mut self, row: usize) { + let blank = ScreenChar { + ascii_carachter: b' ', + color_code: self.color_code, + }; + + for col in 0..BUFFER_WIDTH { + self.buffer.chars[row][col].write(blank); + } } } - -// function to test things: to be removed -pub fn print_something() { - use core::fmt::Write; - let mut writer = Writer { - column_position: 0, - color_code: ColorCode::new(Color::Pink, Color::Black), - buffer: unsafe { &mut *(0xB8000 as *mut Buffer) }, - }; - - writer.write_byte(b'H'); - writer.write_string("ello "); - write!(writer, "The numbers are {} and {}", 42, 1.0/3.0).unwrap(); -} From 177420c0865ac31507cd718b804aa93651cc576c Mon Sep 17 00:00:00 2001 From: clizia Date: Tue, 26 Aug 2025 23:49:05 +0200 Subject: [PATCH 07/10] updated README --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb00697..489428f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ trying to make a toy OS in rust following [this](https://os.phil-opp.com) +### DEPENDENCIES + +- qemu +- [cargo bootimage](https://github.com/rust-osdev/bootimage) + ### HOWTO to run this just do: @@ -10,5 +15,3 @@ to run this just do: cargo run ``` -(ensure qemu is installed) - From 82173a4b9ab691c6d94b2524e701adb106eea594 Mon Sep 17 00:00:00 2001 From: clizia Date: Wed, 27 Aug 2025 00:38:35 +0200 Subject: [PATCH 08/10] updated readme --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 489428f..ad3dd7c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,4 @@ trying to make a toy OS in rust following [this](https://os.phil-opp.com) to run this just do: -``` -cargo run -``` - +```cargo run``` From 75e90f0ed2fc9759214aaa0e54aafe4b31ebcb4e Mon Sep 17 00:00:00 2001 From: clizia Date: Wed, 27 Aug 2025 00:39:18 +0200 Subject: [PATCH 09/10] updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad3dd7c..9ede113 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,4 @@ trying to make a toy OS in rust following [this](https://os.phil-opp.com) to run this just do: -```cargo run``` +`cargo run` From f94b8537cf99f2867d1adec867e40e6f361185c9 Mon Sep 17 00:00:00 2001 From: clizia Date: Wed, 27 Aug 2025 00:41:30 +0200 Subject: [PATCH 10/10] updated README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ede113..45cb86e 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ trying to make a toy OS in rust following [this](https://os.phil-opp.com) ### HOWTO -to run this just do: +to run this just install the [dependencies](#dependencies) and do: -`cargo run` +```shell +cargo run +```