diff --git a/Makefile b/Makefile index 2c1cd65..5bdea49 100644 --- a/Makefile +++ b/Makefile @@ -8,24 +8,91 @@ default: all .PHONY: clean clean: rm -drf $(BUILD) - cd bootloader; make clean + cd tetros; cargo clean # Make everything +# (but don't run qemu) .PHONY: all all: img -# Make bios bootloader -# dd if=./bootloader/build/stage2.bin of=$@ conv=notrunc bs=512 seek=40 +# +# MARK: boot +# +# Compile tetros as library +LIB_SRC = ./tetros/Cargo.toml ./tetros/Cargo.lock $(shell find ./tetros/src -type f) +$(BUILD)/tetros.lib: $(LIB_SRC) + @mkdir -p $(BUILD) + cd tetros && \ + env RUSTFLAGS="-C soft-float" \ + cargo rustc \ + --manifest-path="./Cargo.toml" \ + -Z build-std=core \ + -Z build-std-features=compiler-builtins-mem \ + --target "./targets/x86-unknown-none.json" \ + --lib \ + --release \ + -- \ + --emit link="$(CURDIR)/$@" + +# Link tetros +BIOS_LD = ./tetros/linkers/x86-unknown-none.ld +$(BUILD)/tetros.elf: $(BUILD)/tetros.lib $(BIOS_LD) + ld \ + -m elf_i386 \ + --gc-sections \ + -z max-page-size=0x1000 \ + -T "$(BIOS_LD)" \ + -o "$@" \ + "$<" + + objcopy --only-keep-debug "$@" "$@.sym" + objcopy --strip-debug "$@" + +# Wrap tetros in three-stage BIOS loader +# Parameters: +# - BIOS_SRC: source directory of bios assembly +# - STAGE2_SECTOR: the index of the first sector of the stage 2 binary on the disk +BIOS_SRC = ./bios +STAGE2_SECTOR = 1 +$(BUILD)/bios.bin: $(wildcard $(BIOS_SRC)/*.asm) $(BUILD)/tetros.elf + @mkdir -p "$(BUILD)" + nasm \ + -f bin \ + -D STAGE3=$(BUILD)/tetros.elf \ + -D STAGE2_SECTOR=$(STAGE2_SECTOR) \ + -o "$@" \ + -l "$@.lst" \ + -i "$(BIOS_SRC)" \ + "$(BIOS_SRC)/main.asm" + +# Extract full mbr (first 512 bytes) +$(BUILD)/mbr.bin: $(BUILD)/bios.bin + @mkdir -p "$(BUILD)" + @echo "" + dd if="$<" bs=512 count=1 of="$@" + +# Extract stage 2 (rest of file) +$(BUILD)/stage2.bin: $(BUILD)/bios.bin + @mkdir -p "$(BUILD)" + @echo "" + dd if="$<" bs=512 skip=1 of="$@" + +# +# MARK: bundle +# + +# Make full disk image .PHONY: img img: $(BUILD)/disk.img -$(BUILD)/disk.img: - mkdir -p $(BUILD) - cd bootloader; make +$(BUILD)/disk.img: $(BUILD)/mbr.bin $(BUILD)/stage2.bin + @mkdir -p $(BUILD) + @echo "" dd if=/dev/zero of=$@ bs=512 count=32 - dd if=./bootloader/build/512.bin of=$@ conv=notrunc bs=512 - dd if=./bootloader/build/stage2.bin of=$@ conv=notrunc seek=5 bs=512 + dd if="$(BUILD)/mbr.bin" of=$@ conv=notrunc bs=512 + dd if="$(BUILD)/stage2.bin" of=$@ conv=notrunc seek=$(STAGE2_SECTOR) bs=512 +.PHONY: qemu qemu: $(BUILD)/disk.img qemu-system-i386 \ -d cpu_reset \ @@ -35,6 +102,20 @@ qemu: $(BUILD)/disk.img -net none \ -serial stdio \ -fda "$<" + +# Same as qemu, but with no dependency. +# Used for remote dev, where build box != run box. +.PHONY: qemu-remote +qemu-remote: + qemu-system-i386 \ + -d cpu_reset \ + -no-reboot \ + -smp 1 -m 2048 \ + -machine q35 \ + -net none \ + -serial stdio \ + -fda "$(BUILD)/disk.img" + # -gdb tcp::26000 \ # -S # -enable-kvm \ diff --git a/README.md b/README.md new file mode 100644 index 0000000..06ab1c0 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +- fix asm loader +- clock +- input +- music +- document everything diff --git a/bootloader/bios/cpuid.asm b/bios/cpuid.asm similarity index 100% rename from bootloader/bios/cpuid.asm rename to bios/cpuid.asm diff --git a/bootloader/bios/gdt.asm b/bios/gdt.asm similarity index 81% rename from bootloader/bios/gdt.asm rename to bios/gdt.asm index 896b04f..0322a53 100644 --- a/bootloader/bios/gdt.asm +++ b/bios/gdt.asm @@ -64,27 +64,6 @@ gdt: .null equ $ - gdt dq 0 -.lm64_code equ $ - gdt -istruc GDTEntry - at GDTEntry.limitl, dw 0 - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 - at GDTEntry.attribute, db gdt_attr.present | gdt_attr.user | gdt_attr.code - at GDTEntry.flags__limith, db gdt_flag.long_mode - at GDTEntry.baseh, db 0 -iend - -.lm64_data equ $ - gdt -istruc GDTEntry - at GDTEntry.limitl, dw 0 - at GDTEntry.basel, dw 0 - at GDTEntry.basem, db 0 -; AMD System Programming Manual states that the writeable bit is ignored in long mode, but ss can not be set to this descriptor without it - at GDTEntry.attribute, db gdt_attr.present | gdt_attr.user | gdt_attr.writable - at GDTEntry.flags__limith, db 0 - at GDTEntry.baseh, db 0 -iend - ; All GTD addresses are multiples of 8, ; and thus end in three zero bits. ; diff --git a/bootloader/bios/main.asm b/bios/main.asm similarity index 100% rename from bootloader/bios/main.asm rename to bios/main.asm diff --git a/bootloader/bios/print.asm b/bios/print.asm similarity index 100% rename from bootloader/bios/print.asm rename to bios/print.asm diff --git a/bootloader/bios/protected_mode.asm b/bios/protected_mode.asm similarity index 100% rename from bootloader/bios/protected_mode.asm rename to bios/protected_mode.asm diff --git a/bootloader/bios/stage1.asm b/bios/stage1.asm similarity index 100% rename from bootloader/bios/stage1.asm rename to bios/stage1.asm diff --git a/bootloader/bios/stage2.asm b/bios/stage2.asm similarity index 100% rename from bootloader/bios/stage2.asm rename to bios/stage2.asm diff --git a/bootloader/bios/thunk.asm b/bios/thunk.asm similarity index 100% rename from bootloader/bios/thunk.asm rename to bios/thunk.asm diff --git a/bootloader/.gitignore b/bootloader/.gitignore deleted file mode 100644 index 378eac2..0000000 --- a/bootloader/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build diff --git a/bootloader/Makefile b/bootloader/Makefile deleted file mode 100644 index 2f04455..0000000 --- a/bootloader/Makefile +++ /dev/null @@ -1,83 +0,0 @@ -# This compiles our bootloader as a static library, -# and wraps it in a multistage loader. - - -BUILD = ./build - - -.PHONY: all -all: $(BUILD)/mbr.bin $(BUILD)/512.bin $(BUILD)/stage2.bin - -.PHONY: clean -clean: - rm -drf $(BUILD) - cd bootloader; cargo clean - -# Compile bootloader as library -LIB_SRC = ./bootloader/Cargo.toml ./bootloader/Cargo.lock $(shell find ./bootloader/src -type f) -$(BUILD)/bootloader.lib: $(LIB_SRC) - @mkdir -p $(BUILD) - cd bootloader && \ - env RUSTFLAGS="-C soft-float" \ - cargo rustc \ - --manifest-path="./Cargo.toml" \ - -Z build-std=core,alloc \ - -Z build-std-features=compiler-builtins-mem \ - --target "./targets/x86-unknown-none.json" \ - --lib \ - --release \ - -- \ - --emit link="$(CURDIR)/$@" - -# Link bootloader -BIOS_LD = ./bootloader/linkers/x86-unknown-none.ld -$(BUILD)/bootloader.elf: $(BUILD)/bootloader.lib $(BIOS_LD) - ld \ - -m elf_i386 \ - --gc-sections \ - -z max-page-size=0x1000 \ - -T "$(BIOS_LD)" \ - -o "$@" \ - "$<" - - objcopy --only-keep-debug "$@" "$@.sym" - objcopy --strip-debug "$@" - -# Wrap bootloader in three-stage BIOS loader -# Parameters: -# - BIOS_SRC: source directory of bios assembly -# - STAGE3: path to linked stage 3 binary -# - STAGE2_SECTOR: the index of the first sector of the stage 2 binary on the disk -BIOS_SRC = ./bios -STAGE2_SECTOR = 5 -STAGE3 = $(BUILD)/bootloader.elf -$(BUILD)/bios.bin: $(wildcard $(BIOS_SRC)/*.asm) $(STAGE3) - @mkdir -p "$(BUILD)" - nasm \ - -f bin \ - -D STAGE3=$(STAGE3) \ - -D STAGE2_SECTOR=$(STAGE2_SECTOR) \ - -o "$@" \ - -l "$@.lst" \ - -i "$(BIOS_SRC)" \ - "$(BIOS_SRC)/main.asm" - -# Extract MBR code (first 440 bytes) -# This can be used to embed this mbr in gpt-partitioned disks -$(BUILD)/mbr.bin: $(BUILD)/bios.bin - @mkdir -p "$(BUILD)" - @echo "" - dd if="$<" bs=440 count=1 of="$@" - -# Extract full mbr (first 512 bytes) -# This can be used to make raw boot disks -$(BUILD)/512.bin: $(BUILD)/bios.bin - @mkdir -p "$(BUILD)" - @echo "" - dd if="$<" bs=512 count=1 of="$@" - -# Extract stage 2 (rest of file) -$(BUILD)/stage2.bin: $(BUILD)/bios.bin - @mkdir -p "$(BUILD)" - @echo "" - dd if="$<" bs=512 skip=1 of="$@" \ No newline at end of file diff --git a/bootloader/bootloader/src/main.rs b/bootloader/bootloader/src/main.rs deleted file mode 100644 index a6c4b65..0000000 --- a/bootloader/bootloader/src/main.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![no_std] -#![feature(alloc_error_handler)] -#![feature(int_roundings)] -#![feature(lang_items)] -#![allow(internal_features)] - -extern crate alloc; - -use self::os::{OsMemoryEntry, OsMemoryKind}; - -#[macro_use] -mod os; - -#[macro_use] -mod serial; - -//TODO: allocate this in a more reasonable manner -static mut AREAS: [OsMemoryEntry; 1024] = [OsMemoryEntry { - base: 0, - size: 0, - kind: OsMemoryKind::Null, -}; 1024]; -static mut AREAS_LEN: usize = 0; - -pub fn area_add(area: OsMemoryEntry) { - unsafe { - for existing_area in &mut AREAS[0..AREAS_LEN] { - if existing_area.kind == area.kind { - if existing_area.base.unchecked_add(existing_area.size) == area.base { - existing_area.size += area.size; - return; - } - if area.base.unchecked_add(area.size) == existing_area.base { - existing_area.base = area.base; - return; - } - } - } - *AREAS.get_mut(AREAS_LEN).expect("AREAS overflowed!") = area; - AREAS_LEN += 1; - } -} - -pub static mut LIVE_OPT: Option<(u64, &'static [u8])> = None; - -#[allow(dead_code)] -#[derive(Debug)] -#[repr(C, packed(8))] -pub struct KernelArgs { - kernel_base: u64, - kernel_size: u64, - stack_base: u64, - stack_size: u64, - env_base: u64, - env_size: u64, - - /// The base pointer to the saved RSDP. - /// - /// This field can be NULL, and if so, the system has not booted with UEFI or in some other way - /// retrieved the RSDPs. The kernel or a userspace driver will thus try searching the BIOS - /// memory instead. On UEFI systems, searching is not guaranteed to actually work though. - acpi_rsdp_base: u64, - /// The size of the RSDP region. - acpi_rsdp_size: u64, - - areas_base: u64, - areas_size: u64, - - bootstrap_base: u64, - bootstrap_size: u64, -} - -fn main() {} diff --git a/bootloader/bootloader/src/os/bios/memory_map.rs b/bootloader/bootloader/src/os/bios/memory_map.rs deleted file mode 100644 index bdb42c6..0000000 --- a/bootloader/bootloader/src/os/bios/memory_map.rs +++ /dev/null @@ -1,84 +0,0 @@ -use core::{cmp, mem, ptr}; - -use crate::area_add; -use crate::os::{OsMemoryEntry, OsMemoryKind}; - -use super::{thunk::ThunkData, MEMORY_MAP_ADDR}; - -#[repr(C, packed)] -struct MemoryMapEntry { - pub base: u64, - pub size: u64, - pub kind: u32, -} - -pub struct MemoryMapIter { - thunk15: extern "C" fn(), - data: ThunkData, - first: bool, -} - -impl MemoryMapIter { - pub fn new(thunk15: extern "C" fn()) -> Self { - Self { - thunk15, - data: ThunkData::new(), - first: true, - } - } -} - -impl Iterator for MemoryMapIter { - type Item = OsMemoryEntry; - fn next(&mut self) -> Option { - if self.first { - self.first = false; - } else if self.data.ebx == 0 { - return None; - } - - self.data.eax = 0xE820; - self.data.ecx = mem::size_of::() as u32; - self.data.edx = 0x534D4150; - self.data.edi = MEMORY_MAP_ADDR as u32; - - unsafe { - self.data.with(self.thunk15); - } - - //TODO: return error? - assert_eq!({ self.data.eax }, 0x534D4150); - assert_eq!({ self.data.ecx }, mem::size_of::() as u32); - - let entry = unsafe { ptr::read(MEMORY_MAP_ADDR as *const MemoryMapEntry) }; - Some(Self::Item { - base: entry.base, - size: entry.size, - kind: match entry.kind { - 0 => OsMemoryKind::Null, - 1 => OsMemoryKind::Free, - 3 => OsMemoryKind::Reclaim, - _ => OsMemoryKind::Reserved, - }, - }) - } -} - -pub unsafe fn memory_map(thunk15: extern "C" fn()) -> Option<(usize, usize)> { - let mut heap_limits = None; - for entry in MemoryMapIter::new(thunk15) { - let heap_start = 1 * 1024 * 1024; - if { entry.kind } == OsMemoryKind::Free - && entry.base <= heap_start as u64 - && (entry.base + entry.size) >= heap_start as u64 - { - let heap_end = cmp::min(entry.base + entry.size, usize::MAX as u64) as usize; - if heap_end >= heap_start { - heap_limits = Some((heap_start, heap_end - heap_start)); - } - } - - area_add(entry); - } - heap_limits -} diff --git a/bootloader/bootloader/src/os/bios/vga-copy.rs b/bootloader/bootloader/src/os/bios/vga-copy.rs deleted file mode 100644 index bb19823..0000000 --- a/bootloader/bootloader/src/os/bios/vga-copy.rs +++ /dev/null @@ -1,119 +0,0 @@ -use core::{fmt, slice}; - -#[derive(Clone, Copy)] -#[repr(C, packed)] -pub struct VgaTextBlock { - pub char: u8, - pub color: u8, -} - -#[allow(dead_code)] -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum VgaTextColor { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Purple = 5, - Brown = 6, - Gray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - LightPurple = 13, - Yellow = 14, - White = 15, -} - -pub struct Vga { - pub base: usize, - pub width: usize, - pub height: usize, - pub x: usize, - pub y: usize, - pub bg: VgaTextColor, - pub fg: VgaTextColor, -} - -impl Vga { - pub const unsafe fn new(base: usize, width: usize, height: usize) -> Self { - Self { - base, - width, - height, - x: 0, - y: 0, - bg: VgaTextColor::Black, - fg: VgaTextColor::Gray, - } - } - - pub unsafe fn blocks(&mut self) -> &'static mut [VgaTextBlock] { - slice::from_raw_parts_mut(self.base as *mut VgaTextBlock, self.width * self.height) - } - - pub fn clear(&mut self) { - self.x = 0; - self.y = 0; - let blocks = unsafe { self.blocks() }; - for i in 0..blocks.len() { - blocks[i] = VgaTextBlock { - char: 0, - color: ((self.bg as u8) << 4) | (self.fg as u8), - }; - } - } -} - -impl fmt::Write for Vga { - fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { - let blocks = unsafe { self.blocks() }; - for c in s.chars() { - if self.x >= self.width { - self.x = 0; - self.y += 1; - } - while self.y >= self.height { - for y in 1..self.height { - for x in 0..self.width { - let i = y * self.width + x; - let j = i - self.width; - blocks[j] = blocks[i]; - if y + 1 == self.height { - blocks[i].char = 0; - } - } - } - self.y -= 1; - } - match c { - '\x08' => { - if self.x > 0 { - self.x -= 1; - } - } - '\r' => { - self.x = 0; - } - '\n' => { - self.x = 0; - self.y += 1; - } - _ => { - let i = self.y * self.width + self.x; - if let Some(block) = blocks.get_mut(i) { - block.char = c as u8; - block.color = ((self.bg as u8) << 4) | (self.fg as u8); - } - self.x += 1; - } - } - } - - Ok(()) - } -} diff --git a/bootloader/bootloader/src/os/mod.rs b/bootloader/bootloader/src/os/mod.rs deleted file mode 100644 index d37243c..0000000 --- a/bootloader/bootloader/src/os/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub use self::bios::*; -#[macro_use] -mod bios; - -// Keep synced with BootloaderMemoryKind in kernel -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u64)] -pub enum OsMemoryKind { - Null = 0, - Free = 1, - Reclaim = 2, - Reserved = 3, -} - -// Keep synced with BootloaderMemoryEntry in kernel -#[derive(Clone, Copy, Debug)] -#[repr(C, packed(8))] -pub struct OsMemoryEntry { - pub base: u64, - pub size: u64, - pub kind: OsMemoryKind, -} diff --git a/bootloader/bootloader/Cargo.lock b/tetros/Cargo.lock similarity index 84% rename from bootloader/bootloader/Cargo.lock rename to tetros/Cargo.lock index 9657937..cda49db 100644 --- a/bootloader/bootloader/Cargo.lock +++ b/tetros/Cargo.lock @@ -35,15 +35,6 @@ 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" @@ -84,21 +75,11 @@ 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 = "tetros" version = "1.0.0" dependencies = [ "lazy_static", - "linked_list_allocator", "spin", "uart_16550", ] diff --git a/bootloader/bootloader/Cargo.toml b/tetros/Cargo.toml similarity index 91% rename from bootloader/bootloader/Cargo.toml rename to tetros/Cargo.toml index cff0838..7589804 100644 --- a/bootloader/bootloader/Cargo.toml +++ b/tetros/Cargo.toml @@ -6,7 +6,7 @@ publish = false [lib] name = "tetros" -path = "src/main.rs" +path = "src/lib.rs" crate-type = ["staticlib"] @@ -32,7 +32,6 @@ missing_docs = "allow" needless_return = "allow" new_without_default = "allow" tabs_in_doc_comments = "allow" -expect_used = "deny" dbg_macro = "deny" allow_attributes = "deny" create_dir = "deny" @@ -55,8 +54,9 @@ match_on_vec_items = "deny" wildcard_dependencies = "deny" negative_feature_names = "deny" redundant_feature_names = "deny" -multiple_crate_versions = "deny" - +multiple_crate_versions = "allow" +missing_safety_doc = "allow" +identity_op = "allow" # # MARK: dependencies @@ -64,8 +64,7 @@ multiple_crate_versions = "deny" [dependencies] -linked_list_allocator = "0.10.5" -spin = "0.9.5" +spin = "0.9.8" uart_16550 = "0.3.2" [dependencies.lazy_static] diff --git a/bootloader/bootloader/linkers/x86-unknown-none.ld b/tetros/linkers/x86-unknown-none.ld similarity index 100% rename from bootloader/bootloader/linkers/x86-unknown-none.ld rename to tetros/linkers/x86-unknown-none.ld diff --git a/bootloader/bootloader/rust-toolchain.toml b/tetros/rust-toolchain.toml similarity index 100% rename from bootloader/bootloader/rust-toolchain.toml rename to tetros/rust-toolchain.toml diff --git a/tetros/src/drivers/mod.rs b/tetros/src/drivers/mod.rs new file mode 100644 index 0000000..9088681 --- /dev/null +++ b/tetros/src/drivers/mod.rs @@ -0,0 +1,4 @@ +#[macro_use] +pub mod serial; + +pub mod vga; diff --git a/bootloader/bootloader/src/serial.rs b/tetros/src/drivers/serial.rs similarity index 95% rename from bootloader/bootloader/src/serial.rs rename to tetros/src/drivers/serial.rs index 5553985..4018a3c 100644 --- a/bootloader/bootloader/src/serial.rs +++ b/tetros/src/drivers/serial.rs @@ -42,7 +42,7 @@ pub fn _print(args: core::fmt::Arguments<'_>) { #[macro_export] macro_rules! print { ($($arg:tt)*) => { - $crate::serial::_print(format_args!($($arg)*)); + $crate::drivers::serial::_print(format_args!($($arg)*)); }; } diff --git a/bootloader/bootloader/src/os/bios/vga.rs b/tetros/src/drivers/vga.rs similarity index 100% rename from bootloader/bootloader/src/os/bios/vga.rs rename to tetros/src/drivers/vga.rs diff --git a/bootloader/bootloader/src/os/bios/mod.rs b/tetros/src/lib.rs similarity index 56% rename from bootloader/bootloader/src/os/bios/mod.rs rename to tetros/src/lib.rs index 8bde669..a26dba0 100644 --- a/bootloader/bootloader/src/os/bios/mod.rs +++ b/tetros/src/lib.rs @@ -1,26 +1,18 @@ -use linked_list_allocator::LockedHeap; +#![no_std] +#![feature(int_roundings)] +#![feature(lang_items)] +#![allow(internal_features)] + +use drivers::vga::Vga13h; +use os::thunk::ThunkData; use spin::Mutex; -use tetris::TetrisBoard; -use vga::Vga13h; +use tetrisboard::TetrisBoard; -use self::memory_map::memory_map; -use self::thunk::ThunkData; +mod os; +mod tetrisboard; -use crate::println; - -mod memory_map; -mod panic; -mod tetris; -mod thunk; -mod vga; - -// Real mode memory allocation, for use with thunk -// 0x500 to 0x7BFF is free -const MEMORY_MAP_ADDR: usize = 0x1380; // 24 bytes, ends at 0x1397 -const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards - -#[global_allocator] -static ALLOCATOR: LockedHeap = LockedHeap::empty(); +#[macro_use] +mod drivers; pub(crate) static VGA: Mutex = Mutex::new(unsafe { Vga13h::new() }); @@ -67,9 +59,5 @@ pub unsafe extern "C" fn start( let t = TetrisBoard::new(); t.draw(&mut v); - let (heap_start, heap_size) = memory_map(thunk15).expect("No memory for heap"); - - ALLOCATOR.lock().init(heap_start as *mut u8, heap_size); - panic!("kernel"); } diff --git a/tetros/src/os/mod.rs b/tetros/src/os/mod.rs new file mode 100644 index 0000000..99795d2 --- /dev/null +++ b/tetros/src/os/mod.rs @@ -0,0 +1,6 @@ +pub mod thunk; + +#[macro_use] +pub mod panic; + +const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards diff --git a/bootloader/bootloader/src/os/bios/panic.rs b/tetros/src/os/panic.rs similarity index 71% rename from bootloader/bootloader/src/os/bios/panic.rs rename to tetros/src/os/panic.rs index 688398d..fea6607 100644 --- a/bootloader/bootloader/src/os/bios/panic.rs +++ b/tetros/src/os/panic.rs @@ -1,6 +1,5 @@ //! Intrinsics for panic handling -use core::alloc::Layout; use core::arch::asm; use core::panic::PanicInfo; @@ -22,13 +21,6 @@ pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! { } } -#[alloc_error_handler] -#[no_mangle] -#[allow(improper_ctypes_definitions)] // Layout is not repr(C) -pub extern "C" fn rust_oom(_layout: Layout) -> ! { - panic!("memory allocation failed"); -} - #[allow(non_snake_case)] #[no_mangle] /// Required to handle panics diff --git a/bootloader/bootloader/src/os/bios/thunk.rs b/tetros/src/os/thunk.rs similarity index 100% rename from bootloader/bootloader/src/os/bios/thunk.rs rename to tetros/src/os/thunk.rs diff --git a/tetros/src/tetrisboard/cell.rs b/tetros/src/tetrisboard/cell.rs new file mode 100644 index 0000000..1662adf --- /dev/null +++ b/tetros/src/tetrisboard/cell.rs @@ -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) + } +} diff --git a/bootloader/bootloader/src/os/bios/tetris.rs b/tetros/src/tetrisboard/draw.rs similarity index 52% rename from bootloader/bootloader/src/os/bios/tetris.rs rename to tetros/src/tetrisboard/draw.rs index 763b47f..579c2fd 100644 --- a/bootloader/bootloader/src/os/bios/tetris.rs +++ b/tetros/src/tetrisboard/draw.rs @@ -1,70 +1,10 @@ -use super::vga::Vga13h; +use crate::drivers::vga::Vga13h; -#[repr(u8)] -#[derive(Debug, Clone, Copy)] -pub enum TetrisCell { - Empty, - Blue, - Cyan, - Orange, - Red, - Green, - Purple, - Yellow, -} - -impl TetrisCell { - pub fn to_vga_color(&self) -> u8 { - match self { - Self::Empty => 0b000_00000, - Self::Blue => 0b000_00001, - Self::Cyan => 0b000_00011, - Self::Orange => 0b000_00110, - Self::Red => 0b000_00100, - Self::Green => 0b000_00010, - Self::Purple => 0b000_00101, - Self::Yellow => 0b110_000_00, - } - } - - pub fn is_empty(&self) -> bool { - matches!(self, Self::Empty) - } -} - -pub struct TetrisBoard { - board: [TetrisCell; TetrisBoard::BOARD_WIDTH * TetrisBoard::BOARD_HEIGHT], -} +use super::{TetrisBoard, TetrisCell}; 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 - } - fn draw_cell(&self, fb: &mut [u8], state: TetrisCell, x: usize, y: usize) { - let color = state.to_vga_color(); + 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); @@ -73,7 +13,7 @@ impl TetrisBoard { } fn draw_frame(&self, fb: &mut [u8], x: usize, y: usize) { - let color = 0b111_000_00; + 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); diff --git a/tetros/src/tetrisboard/mod.rs b/tetros/src/tetrisboard/mod.rs new file mode 100644 index 0000000..596c0c7 --- /dev/null +++ b/tetros/src/tetrisboard/mod.rs @@ -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 + } +} diff --git a/bootloader/bootloader/targets/x86-unknown-none.json b/tetros/targets/x86-unknown-none.json similarity index 100% rename from bootloader/bootloader/targets/x86-unknown-none.json rename to tetros/targets/x86-unknown-none.json