Reorganize

This commit is contained in:
--global
2025-02-18 20:39:57 +00:00
committed by Mark
parent 622f6d1791
commit b8cd346b0a
31 changed files with 192 additions and 533 deletions
+107
View File
@@ -0,0 +1,107 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[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 = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
"spin",
]
[[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 = "raw-cpuid"
version = "10.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "rustversion"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[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 = "tetros"
version = "1.0.0"
dependencies = [
"lazy_static",
"spin",
"uart_16550",
]
[[package]]
name = "uart_16550"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
dependencies = [
"bitflags 2.8.0",
"rustversion",
"x86",
]
[[package]]
name = "x86"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385"
dependencies = [
"bit_field",
"bitflags 1.3.2",
"raw-cpuid",
]
+72
View File
@@ -0,0 +1,72 @@
[package]
name = "tetros"
version = "1.0.0"
edition = "2021"
publish = false
[lib]
name = "tetros"
path = "src/lib.rs"
crate-type = ["staticlib"]
#
# MARK: lints
#
[lints.rust]
unused_import_braces = "deny"
unit_bindings = "deny"
single_use_lifetimes = "deny"
non_ascii_idents = "deny"
macro_use_extern_crate = "deny"
elided_lifetimes_in_paths = "deny"
absolute_paths_not_starting_with_crate = "deny"
explicit_outlives_requirements = "warn"
unused_crate_dependencies = "warn"
redundant_lifetimes = "warn"
missing_docs = "allow"
[lints.clippy]
needless_return = "allow"
new_without_default = "allow"
tabs_in_doc_comments = "allow"
dbg_macro = "deny"
allow_attributes = "deny"
create_dir = "deny"
filetype_is_file = "deny"
integer_division = "deny"
lossy_float_literal = "deny"
map_err_ignore = "deny"
mutex_atomic = "deny"
needless_raw_strings = "deny"
print_stderr = "deny"
print_stdout = "deny"
str_to_string = "deny"
string_add = "deny"
string_to_string = "deny"
unimplemented = "deny"
use_debug = "deny"
verbose_file_reads = "deny"
large_types_passed_by_value = "deny"
match_on_vec_items = "deny"
wildcard_dependencies = "deny"
negative_feature_names = "deny"
redundant_feature_names = "deny"
multiple_crate_versions = "allow"
missing_safety_doc = "allow"
identity_op = "allow"
#
# MARK: dependencies
#
[dependencies]
spin = "0.9.8"
uart_16550 = "0.3.2"
[dependencies.lazy_static]
version = "1.0"
features = ["spin_no_std"]
+57
View File
@@ -0,0 +1,57 @@
ENTRY(start)
OUTPUT_FORMAT(elf32-i386)
SECTIONS {
/* The start address must match bootloader.asm */
. = 0x9000;
. += SIZEOF_HEADERS;
. = ALIGN(4096);
.text : {
__text_start = .;
*(.text*)
. = ALIGN(4096);
__text_end = .;
}
.rodata : {
__rodata_start = .;
*(.rodata*)
. = ALIGN(4096);
__rodata_end = .;
}
.data : {
__data_start = .;
*(.data*)
. = ALIGN(4096);
__data_end = .;
__bss_start = .;
*(.bss*)
. = ALIGN(4096);
__bss_end = .;
}
.tdata : {
__tdata_start = .;
*(.tdata*)
. = ALIGN(4096);
__tdata_end = .;
__tbss_start = .;
*(.tbss*)
. += 8;
. = ALIGN(4096);
__tbss_end = .;
}
__end = .;
/DISCARD/ : {
*(.comment*)
*(.eh_frame*)
*(.gcc_except_table*)
*(.note*)
*(.rel.eh_frame*)
}
}
+3
View File
@@ -0,0 +1,3 @@
[toolchain]
channel = "nightly-2024-05-11"
components = ["rust-src"]
+4
View File
@@ -0,0 +1,4 @@
#[macro_use]
pub mod serial;
pub mod vga;
+56
View File
@@ -0,0 +1,56 @@
use core::arch::asm;
use lazy_static::lazy_static;
use spin::Mutex;
use uart_16550::SerialPort;
lazy_static! {
pub static ref SERIAL1: Mutex<SerialPort> = {
let mut serial_port = unsafe { SerialPort::new(0x3F8) };
serial_port.init();
Mutex::new(serial_port)
};
}
#[doc(hidden)]
pub fn _print(args: core::fmt::Arguments<'_>) {
use core::fmt::Write;
// TODO: preserve previous interrupt state
// Disable interrupts to prevent deadlocks
// (we might get an interrupt while printing)
unsafe {
asm!("cli", options(preserves_flags, nostack));
}
SERIAL1
.lock()
.write_fmt(args)
.expect("Printing to serial failed");
// TODO:
// This is broken, triple-faults right away.
// Uncomment after enabling interrupts in the bootloader & fixing idt
//
// unsafe {
// asm!("sti", options(preserves_flags, nostack));
// }
}
/// Prints to the host through the serial interface.
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {
$crate::drivers::serial::_print(format_args!($($arg)*));
};
}
/// Prints to the host through the serial interface, appending a newline.
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($fmt:expr) => ($crate::print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => ($crate::print!(
concat!($fmt, "\n"), $($arg)*));
}
+67
View File
@@ -0,0 +1,67 @@
use core::slice;
/// VGA driver for mode 0x13:
///
/// - mode: graphics
/// - text res: 40x25
/// - pixel box: 8x8
/// - pixel res: 320x200
/// - colors: 256/256k
/// - addr: A000
/// - pixel format: RRRGGGBB
pub struct Vga13h {
// Double frame buffers
fb_a: [u8; Vga13h::WIDTH * Vga13h::HEIGHT],
fb_b: [u8; Vga13h::WIDTH * Vga13h::HEIGHT],
/// If true, show fb_a (and write to fb_b).
/// if false, show fb_b.
show_fb_a: bool,
}
impl Vga13h {
pub const WIDTH: usize = 320;
pub const HEIGHT: usize = 200;
pub const ADDR: usize = 0xA0000;
pub const unsafe fn new() -> Self {
Self {
fb_a: [0; Vga13h::WIDTH * Vga13h::HEIGHT],
fb_b: [0; Vga13h::WIDTH * Vga13h::HEIGHT],
show_fb_a: true,
}
}
unsafe fn segment(&mut self) -> &'static mut [u8] {
slice::from_raw_parts_mut(Vga13h::ADDR as *mut u8, Vga13h::WIDTH * Vga13h::HEIGHT)
}
pub fn swap(&mut self) {
let seg = unsafe { self.segment() };
if self.show_fb_a {
seg.copy_from_slice(&self.fb_b);
self.show_fb_a = false
} else {
seg.copy_from_slice(&self.fb_a);
self.show_fb_a = true
}
}
pub fn get_fb(&mut self) -> &mut [u8; Vga13h::WIDTH * Vga13h::HEIGHT] {
unsafe { self.segment().try_into().unwrap() }
/*
if self.show_fb_a {
&mut self.fb_b
} else {
&mut self.fb_a
}
*/
}
pub fn pix_idx(x: usize, y: usize) -> usize {
debug_assert!(x < Vga13h::WIDTH);
debug_assert!(y < Vga13h::HEIGHT);
return y * Vga13h::WIDTH + x;
}
}
+63
View File
@@ -0,0 +1,63 @@
#![no_std]
#![feature(int_roundings)]
#![feature(lang_items)]
#![allow(internal_features)]
use drivers::vga::Vga13h;
use os::thunk::ThunkData;
use spin::Mutex;
use tetrisboard::TetrisBoard;
mod os;
mod tetrisboard;
#[macro_use]
mod drivers;
pub(crate) static VGA: Mutex<Vga13h> = Mutex::new(unsafe { Vga13h::new() });
#[no_mangle]
pub unsafe extern "C" fn start(
_boot_disk: usize,
thunk10: extern "C" fn(),
_thunk13: extern "C" fn(),
thunk15: extern "C" fn(),
_thunk16: extern "C" fn(),
) -> ! {
println!("Entered Rust, serial ready.");
{
// Set vga mode
let mut data = ThunkData::new();
data.eax = 0x13;
data.with(thunk10);
}
{
// Disable cursor
let mut data = ThunkData::new();
data.eax = 0x0100;
data.ecx = 0x3F00;
data.with(thunk10);
}
// Clear screen
let mut v = VGA.lock();
/*
let fb = v.get_fb();
let mut c: u8 = 0;
for x in 0..128 {
for y in 0..128 {
let idx = Vga13h::pix_idx(x, y);
fb[idx] = c;
c = c.wrapping_add(1);
}
}
*/
let t = TetrisBoard::new();
t.draw(&mut v);
panic!("kernel");
}
+6
View File
@@ -0,0 +1,6 @@
pub mod thunk;
#[macro_use]
pub mod panic;
const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards
+33
View File
@@ -0,0 +1,33 @@
//! Intrinsics for panic handling
use core::arch::asm;
use core::panic::PanicInfo;
use crate::println;
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}
/// Required to handle panics
#[panic_handler]
#[no_mangle]
pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! {
unsafe {
println!("TETRIS PANIC:\n{}", info);
loop {
asm!("hlt");
}
}
}
#[allow(non_snake_case)]
#[no_mangle]
/// Required to handle panics
pub extern "C" fn _Unwind_Resume() -> ! {
loop {
unsafe {
asm!("hlt");
}
}
}
+46
View File
@@ -0,0 +1,46 @@
use core::ptr;
use super::THUNK_STACK_ADDR;
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct ThunkData {
pub es: u16,
pub edi: u32,
pub esi: u32,
pub ebp: u32,
pub ebx: u32,
pub edx: u32,
pub ecx: u32,
pub eax: u32,
}
impl ThunkData {
pub fn new() -> Self {
Self {
es: 0,
edi: 0,
esi: 0,
ebp: 0,
ebx: 0,
edx: 0,
ecx: 0,
eax: 0,
}
}
pub unsafe fn save(&self) {
ptr::write((THUNK_STACK_ADDR - 64) as *mut ThunkData, *self);
}
pub unsafe fn load(&mut self) {
*self = ptr::read((THUNK_STACK_ADDR - 64) as *const ThunkData);
}
pub unsafe fn with(&mut self, f: extern "C" fn()) {
self.save();
f();
self.load();
}
}
+31
View File
@@ -0,0 +1,31 @@
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum TetrisCell {
Empty,
Blue,
Cyan,
Orange,
Red,
Green,
Purple,
Yellow,
}
impl TetrisCell {
pub fn vga_color(&self) -> u8 {
match self {
Self::Empty => 0b0000_0000,
Self::Blue => 0b0000_0001,
Self::Cyan => 0b0000_0011,
Self::Orange => 0b0000_0110,
Self::Red => 0b0000_0100,
Self::Green => 0b0000_0010,
Self::Purple => 0b0000_0101,
Self::Yellow => 0b1100_0000,
}
}
pub fn is_empty(&self) -> bool {
matches!(self, Self::Empty)
}
}
+56
View File
@@ -0,0 +1,56 @@
use crate::drivers::vga::Vga13h;
use super::{TetrisBoard, TetrisCell};
impl TetrisBoard {
fn draw_cell(&self, fb: &mut [u8], state: TetrisCell, x: usize, y: usize) {
let color = state.vga_color();
for yo in 0..TetrisBoard::CELL_SIZE {
let left = Vga13h::pix_idx(x, y + yo);
let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo);
fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]);
}
}
fn draw_frame(&self, fb: &mut [u8], x: usize, y: usize) {
let color = 0b1110_0000;
for yo in 0..TetrisBoard::CELL_SIZE {
let left = Vga13h::pix_idx(x, y + yo);
let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo);
fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]);
}
}
pub fn draw(&self, vga: &mut Vga13h) {
let fb = vga.get_fb();
// Draw cells
for bx in 0..TetrisBoard::BOARD_WIDTH {
for by in 0..TetrisBoard::BOARD_HEIGHT {
let cell = self.board[by * TetrisBoard::BOARD_WIDTH + bx];
let dx = (bx + 1) * TetrisBoard::CELL_SIZE;
let dy = (by + 1) * TetrisBoard::CELL_SIZE;
self.draw_cell(fb, cell, dx, dy);
}
}
// Draw frame
for bx in 0..TetrisBoard::BOARD_WIDTH + 2 {
self.draw_frame(fb, bx * TetrisBoard::CELL_SIZE, 0);
self.draw_frame(
fb,
bx * TetrisBoard::CELL_SIZE,
(TetrisBoard::BOARD_HEIGHT + 1) * TetrisBoard::CELL_SIZE,
);
}
for by in 0..TetrisBoard::BOARD_HEIGHT + 2 {
self.draw_frame(fb, 0, by * 9);
self.draw_frame(
fb,
(TetrisBoard::BOARD_WIDTH + 1) * TetrisBoard::CELL_SIZE,
by * TetrisBoard::CELL_SIZE,
);
}
}
}
+35
View File
@@ -0,0 +1,35 @@
mod cell;
mod draw;
pub use cell::*;
pub struct TetrisBoard {
board: [TetrisCell; TetrisBoard::BOARD_WIDTH * TetrisBoard::BOARD_HEIGHT],
}
impl TetrisBoard {
const BOARD_WIDTH: usize = 10;
const BOARD_HEIGHT: usize = 20;
const CELL_SIZE: usize = 9;
pub fn new() -> Self {
let mut x = Self {
board: [TetrisCell::Empty; TetrisBoard::BOARD_WIDTH * TetrisBoard::BOARD_HEIGHT],
};
x.board[0] = TetrisCell::Blue;
x.board[1] = TetrisCell::Cyan;
x.board[2] = TetrisCell::Orange;
x.board[3] = TetrisCell::Red;
x.board[4] = TetrisCell::Green;
x.board[5] = TetrisCell::Purple;
x.board[6] = TetrisCell::Yellow;
x.board[9] = TetrisCell::Blue;
x.board[8] = TetrisCell::Blue;
x.board[10] = TetrisCell::Blue;
x.board[12] = TetrisCell::Blue;
x
}
}
+28
View File
@@ -0,0 +1,28 @@
{
"llvm-target": "i686-unknown-none",
"target-endian": "little",
"target-pointer-width": "32",
"target-c-int-width": "32",
"data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
"arch": "x86",
"os": "none",
"env": "",
"vendor": "unknown",
"linker-flavor": "gcc",
"panic-strategy": "abort",
"pre-link-args": {
"gcc": ["-m32", "-nostdlib", "-static"]
},
"features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float",
"dynamic-linking": false,
"executables": false,
"relocation-model": "static",
"code-model": "large",
"disable-redzone": true,
"frame-pointer": "always",
"exe-suffix": "",
"has-rpath": false,
"no-default-libraries": true,
"position-independent-executables": false,
"tls-model": "global-dynamic"
}