Compare commits
3 Commits
28efc562d5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 386d64ddd5 | |||
| e6b231488d | |||
| a2dfc5c775 |
@@ -1,5 +1,5 @@
|
|||||||
[build]
|
[build]
|
||||||
target = ".cargo/target-i386.json"
|
target = ".cargo/target-protected-i386.json"
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["core", "compiler_builtins"]
|
build-std = ["core", "compiler_builtins"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
ENTRY(start)
|
ENTRY(start_stub)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 1M;
|
. = 1M;
|
||||||
|
|||||||
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -2,6 +2,12 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ascii"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bios"
|
name = "bios"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -10,5 +16,6 @@ version = "0.1.0"
|
|||||||
name = "oxide"
|
name = "oxide"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ascii",
|
||||||
"bios",
|
"bios",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,18 +6,9 @@ members = ["deps/bios", "members/oxide"]
|
|||||||
bios = { path = "deps/bios" }
|
bios = { path = "deps/bios" }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "z"
|
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[profile.release.package.microloader-mbr]
|
|
||||||
codegen-units = 1
|
|
||||||
opt-level = "z"
|
|
||||||
|
|
||||||
[profile.release.package.microloader-vba]
|
|
||||||
codegen-units = 1
|
|
||||||
opt-level = "z"
|
|
||||||
|
|||||||
8
Makefile
8
Makefile
@@ -7,9 +7,11 @@ RUST_DEP := Cargo.toml Cargo.lock $(shell find .cargo -type f) $(shell find deps
|
|||||||
|
|
||||||
KERNELFILE = $(OXIDE_MULTIBOOT)
|
KERNELFILE = $(OXIDE_MULTIBOOT)
|
||||||
$(KERNELFILE): $(shell find members/oxide -type f) $(RUST_DEP)
|
$(KERNELFILE): $(shell find members/oxide -type f) $(RUST_DEP)
|
||||||
cargo b -r --target=.cargo/target-protected-i386.json --package oxide
|
cargo b -r --package oxide
|
||||||
|
|
||||||
BOOTLOADER ?= grub
|
BOOTLOADER ?= grub
|
||||||
|
# Must not contain '/' with current limitations
|
||||||
|
CMDLINE ?=
|
||||||
include mk/make_bootloader/$(BOOTLOADER).mk
|
include mk/make_bootloader/$(BOOTLOADER).mk
|
||||||
|
|
||||||
.PHONY: clean \
|
.PHONY: clean \
|
||||||
@@ -24,6 +26,6 @@ run-bootloader-qemu-nographic: $(OUTIMG)
|
|||||||
qemu-system-x86_64 -nographic -drive format=raw,file=$(OUTIMG)
|
qemu-system-x86_64 -nographic -drive format=raw,file=$(OUTIMG)
|
||||||
# one day qemu will support multiboot2
|
# one day qemu will support multiboot2
|
||||||
run-qemu: $(KERNELFILE)
|
run-qemu: $(KERNELFILE)
|
||||||
qemu-system-x86_64 -kernel $(KERNELFILE)
|
qemu-system-x86_64 -kernel $(KERNELFILE) -append $(CMDLINE)
|
||||||
run-qemu-nographic: $(KERNELFILE)
|
run-qemu-nographic: $(KERNELFILE)
|
||||||
qemu-system-x86_64 -nographic -kernel $(KERNELFILE)
|
qemu-system-x86_64 -nographic -kernel $(KERNELFILE) -append $(CMDLINE)
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ set timeout=2
|
|||||||
set default=0
|
set default=0
|
||||||
|
|
||||||
menuentry "OxideOS" {
|
menuentry "OxideOS" {
|
||||||
multiboot2 /boot/kernel.bin
|
multiboot2 /boot/kernel.bin $args
|
||||||
boot
|
boot
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ test = false
|
|||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ascii = { version = "1.1.0", default-features = false }
|
||||||
bios = { workspace = true }
|
bios = { workspace = true }
|
||||||
|
|||||||
@@ -2,36 +2,48 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
#![deny(clippy::float_arithmetic)]
|
#![deny(clippy::float_arithmetic)]
|
||||||
#![feature(
|
#![feature(
|
||||||
|
arbitrary_self_types,
|
||||||
|
arbitrary_self_types_pointers,
|
||||||
|
associated_type_defaults,
|
||||||
|
const_convert,
|
||||||
const_range,
|
const_range,
|
||||||
const_trait_impl,
|
const_trait_impl,
|
||||||
const_convert,
|
decl_macro,
|
||||||
generic_const_exprs,
|
generic_const_exprs,
|
||||||
associated_type_defaults
|
ptr_metadata
|
||||||
)]
|
)]
|
||||||
|
|
||||||
/// Triggers a linker failure if this reaches that phase
|
/// Triggers a linker failure if this reaches that phase
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
unsafe extern "C" {
|
// 2026-02-21: Officially the end of panicless OxideOS, did you know `Debug for str` has panic
|
||||||
static __PANIC_HANDLER_WAS_LINKED__DO_NOT_DEFINE: extern "C" fn() -> !;
|
// code paths :pensive:. At least compile ones, maybe runtime impossible but still not compiled
|
||||||
|
// away.
|
||||||
|
unsafe { asm!("ud2", "hlt", options(noreturn)) };
|
||||||
|
|
||||||
|
// unsafe extern "C" {
|
||||||
|
// static __PANIC_HANDLER_WAS_LINKED__DO_NOT_DEFINE: extern "C" fn() -> !;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// unsafe { __PANIC_HANDLER_WAS_LINKED__DO_NOT_DEFINE() };
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { __PANIC_HANDLER_WAS_LINKED__DO_NOT_DEFINE() };
|
use core::{arch::asm, fmt::Write as _, hint::black_box, panic::PanicInfo};
|
||||||
}
|
|
||||||
|
|
||||||
use core::{arch::asm, hint::black_box, panic::PanicInfo};
|
use crate::{
|
||||||
|
multiboot2::bif,
|
||||||
use crate::vga::{ColorNibble, VgaBuffer, VgaColor};
|
vga::{ColorNibble, VgaBuffer, VgaColor},
|
||||||
|
};
|
||||||
|
|
||||||
pub mod multiboot2;
|
pub mod multiboot2;
|
||||||
|
pub mod start_stub;
|
||||||
pub mod vga;
|
pub mod vga;
|
||||||
|
|
||||||
#[used]
|
#[used]
|
||||||
#[unsafe(link_section = ".multiboot2_header")]
|
#[unsafe(link_section = ".multiboot2_header")]
|
||||||
static HEADER: multiboot2::Header = multiboot2::Header::new();
|
static HEADER: multiboot2::Header = multiboot2::Header::new();
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
extern "C" fn start(boot_info: &bif::FixedPart) -> ! {
|
||||||
fn start() -> ! {
|
|
||||||
let mut vga = unsafe { VgaBuffer::<vga::text_modes::VGAText2>::new_uninitialized() };
|
let mut vga = unsafe { VgaBuffer::<vga::text_modes::VGAText2>::new_uninitialized() };
|
||||||
|
|
||||||
vga.write_at(0, 1, b'H');
|
vga.write_at(0, 1, b'H');
|
||||||
@@ -42,12 +54,51 @@ fn start() -> ! {
|
|||||||
vt.set_color(VgaColor::new(ColorNibble::BLUE, ColorNibble::GREEN));
|
vt.set_color(VgaColor::new(ColorNibble::BLUE, ColorNibble::GREEN));
|
||||||
vt.put_at(10, 5);
|
vt.put_at(10, 5);
|
||||||
vt.slide();
|
vt.slide();
|
||||||
vt.write(b"testinggg");
|
vt.write(b"testinggg\ntags:\n");
|
||||||
// loop {
|
|
||||||
// for x in b'a'..b'z' {
|
let tags = bif::TagsIter::new(boot_info);
|
||||||
// vt.write(&[x]);
|
for tag in tags {
|
||||||
// }
|
sleep_short();
|
||||||
|
|
||||||
|
let _ = write!(&mut vt, "{}: ", tag.typ());
|
||||||
|
let Some(tag) = tag.tag() else {
|
||||||
|
vt.write(b"unknown tag\n");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// this single line pulls like half of the fmt module which means ~ 7.5KiB of BS
|
||||||
|
let _ = writeln!(&mut vt, "{tag:?}");
|
||||||
|
|
||||||
|
// tbh I prefer these, I need to like, write u8 chars, on the TTY level like I really care
|
||||||
|
// about writting binary, still need to differenciate a slice of u8's and a asciistr,
|
||||||
|
// AsciiChar looks innteresting in std and could make astr = [AsciiChar], the thing I don't
|
||||||
|
// like is that disply is straight up against non-utf8 output, so I'd have to make my own
|
||||||
|
// raw-display?? but then Im going all against rust, no Display or Derive std macros
|
||||||
|
// either...
|
||||||
|
//
|
||||||
|
// match tag {
|
||||||
|
// bif::TagTagged::BootCommandLine(_) => vt.write(b"BootCommandLine\n"),
|
||||||
|
// bif::TagTagged::BasicMemoryInformation(_) => vt.write(b"BasicMemoryInformation\n"),
|
||||||
|
// bif::TagTagged::BIOSBootDevice(_) => vt.write(b"BIOSBootDevice\n"),
|
||||||
|
// bif::TagTagged::Terminate(_) => vt.write(b"Terminate\n"),
|
||||||
|
// bif::TagTagged::BootLoaderName(_) => vt.write(b"BootLoaderName\n"),
|
||||||
|
// bif::TagTagged::ImageLoadBasePhyAddr(_) => vt.write(b"ImageLoadBasePhyAddr\n"),
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Somebody else, body else, body elseeee, e- e- e- elsee
|
||||||
|
//
|
||||||
|
// I don't know what to do, 'cause when you are around then I'm aaaaaalll over youuuu
|
||||||
|
//
|
||||||
|
// I always think about it, I can't play it coooool
|
||||||
|
//
|
||||||
|
// Blazing in your heeeeell, he- he- he- heeeellllll~
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..=30 {
|
||||||
|
sleep_short();
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0..=5 {
|
for _ in 0..=5 {
|
||||||
sleep_short();
|
sleep_short();
|
||||||
@@ -63,6 +114,7 @@ fn start() -> ! {
|
|||||||
fn sleep_short() {
|
fn sleep_short() {
|
||||||
let mut n = 0_u64;
|
let mut n = 0_u64;
|
||||||
while n < 100_000_000 {
|
while n < 100_000_000 {
|
||||||
|
#[allow(clippy::unit_arg)]
|
||||||
black_box(n += 1);
|
black_box(n += 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,4 +39,218 @@ impl Default for Header {
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum HeaderArchitecture {
|
pub enum HeaderArchitecture {
|
||||||
ProtectedI386 = 0,
|
ProtectedI386 = 0,
|
||||||
|
MIPS32 = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod bif {
|
||||||
|
//! # Boot Information Format
|
||||||
|
//!
|
||||||
|
//! <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html>
|
||||||
|
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
pub trait TagType {
|
||||||
|
const ID: u32 = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod types {
|
||||||
|
use ascii::AsciiStr;
|
||||||
|
|
||||||
|
macro tagset($taggedvis:vis $taggedname:ident { $( $typname:ident ($typn:expr) { $($typprop:ident : $typpropty:ty),* $(,)? } ),* $(,)? }) {
|
||||||
|
$(
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct $typname { $(pub $typprop: $typpropty),* }
|
||||||
|
|
||||||
|
impl super::TagType for $typname {
|
||||||
|
const ID: u32 = $typn;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
$taggedvis enum $taggedname<'a> {
|
||||||
|
$( $typname(&'a $typname) ),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All these AsciiStr are actually CStr's
|
||||||
|
tagset! { pub TagTagged {
|
||||||
|
Terminate(0) {},
|
||||||
|
BootCommandLine(1) {
|
||||||
|
string: AsciiStr,
|
||||||
|
},
|
||||||
|
BootLoaderName(2) {
|
||||||
|
string: AsciiStr,
|
||||||
|
},
|
||||||
|
BasicMemoryInformation(4) {
|
||||||
|
mem_lower: u32,
|
||||||
|
mem_upper: u32,
|
||||||
|
},
|
||||||
|
BIOSBootDevice(5) {
|
||||||
|
biosdev: u32,
|
||||||
|
partition: u32,
|
||||||
|
sub_partition: u32,
|
||||||
|
},
|
||||||
|
MemoryMap(6) {
|
||||||
|
entry_size: u32,
|
||||||
|
entry_version: u32,
|
||||||
|
entries: [u8], // "varies"?
|
||||||
|
},
|
||||||
|
FramebufferInfo(8) {
|
||||||
|
addr: u64,
|
||||||
|
pitch: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
bpp: u8,
|
||||||
|
typ: u8,
|
||||||
|
_reserved: u8,
|
||||||
|
color_info: [u8],
|
||||||
|
},
|
||||||
|
ELFSymbols(9) {
|
||||||
|
num: u16,
|
||||||
|
entsize: u16,
|
||||||
|
shndx: u16,
|
||||||
|
_reserved: u16,
|
||||||
|
section_headers: [u8], // "varies"?
|
||||||
|
},
|
||||||
|
APMTable(10) {
|
||||||
|
version: u16,
|
||||||
|
cseg: u16,
|
||||||
|
offset: u32,
|
||||||
|
cseg_16: u16,
|
||||||
|
dseg: u16,
|
||||||
|
flags: u16,
|
||||||
|
cseg_len: u16,
|
||||||
|
cseg_16_len: u16,
|
||||||
|
dseg_len: u16,
|
||||||
|
},
|
||||||
|
ACPIoldRSDP(14) {
|
||||||
|
rsdpv1_old: [u8],
|
||||||
|
},
|
||||||
|
ImageLoadBasePhyAddr(21) {
|
||||||
|
load_base_addr: u32,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use types::TagTagged;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TagHead {
|
||||||
|
typ: u32,
|
||||||
|
size: u32,
|
||||||
|
__end: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TagHead {
|
||||||
|
pub fn typ(&self) -> u32 {
|
||||||
|
self.typ
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> u32 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn aligned8_size(&self) -> u32 {
|
||||||
|
(self.size + 7) & !7
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the reference of the next laying in memory tag, considering this one's size.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Assumes there's a contiguous one in memory.
|
||||||
|
pub unsafe fn next(&self) -> &Self {
|
||||||
|
unsafe { &*ptr::from_ref(self).byte_add(self.aligned8_size() as usize) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tag<'a>(&self) -> Option<TagTagged<'a>> {
|
||||||
|
let typ = self.typ;
|
||||||
|
let size = self.size;
|
||||||
|
|
||||||
|
let contents_addr = ptr::addr_of!(self.__end).cast::<()>();
|
||||||
|
|
||||||
|
macro typ_match(match $var:ident { $($name:ident)* } fat { $($fatname:ident)* }) {
|
||||||
|
match $var {
|
||||||
|
$(
|
||||||
|
types::$name::ID => Some(TagTagged::$name(unsafe {
|
||||||
|
&*core::ptr::from_raw_parts::<types::$name>(
|
||||||
|
contents_addr,
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
),*,
|
||||||
|
$(
|
||||||
|
types::$fatname::ID => Some(TagTagged::$fatname(unsafe {
|
||||||
|
&*core::ptr::from_raw_parts::<types::$fatname>(
|
||||||
|
contents_addr,
|
||||||
|
size as usize - core::mem::size_of::<Self>(),
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
),*,
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typ_match!(match typ {
|
||||||
|
Terminate
|
||||||
|
BasicMemoryInformation
|
||||||
|
BIOSBootDevice
|
||||||
|
APMTable
|
||||||
|
ImageLoadBasePhyAddr
|
||||||
|
} fat {
|
||||||
|
BootCommandLine
|
||||||
|
BootLoaderName
|
||||||
|
MemoryMap
|
||||||
|
FramebufferInfo
|
||||||
|
ELFSymbols
|
||||||
|
ACPIoldRSDP
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
/// Represents the fixed part of the BIF
|
||||||
|
#[repr(C, align(8))]
|
||||||
|
pub struct FixedPart {
|
||||||
|
pub total_size: u32,
|
||||||
|
_reserved: u32,
|
||||||
|
__end: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator for the tags of a [`FixedPart`]
|
||||||
|
pub struct TagsIter<'a> {
|
||||||
|
rem_size: u32,
|
||||||
|
next_ref: &'a TagHead,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TagsIter<'a> {
|
||||||
|
pub fn new(fixed: &FixedPart) -> Self {
|
||||||
|
let rem_size = fixed.total_size - core::mem::size_of::<FixedPart>() as u32;
|
||||||
|
let next_ptr = unsafe { &*core::ptr::addr_of!(fixed.__end).cast() };
|
||||||
|
|
||||||
|
Self {
|
||||||
|
rem_size,
|
||||||
|
next_ref: next_ptr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for TagsIter<'a> {
|
||||||
|
type Item = &'a TagHead;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<&'a TagHead> {
|
||||||
|
if self.rem_size > 0 {
|
||||||
|
let this_ref = self.next_ref;
|
||||||
|
self.rem_size -= this_ref.aligned8_size();
|
||||||
|
// SAFETY: if there were no tags left we'd reach rem_size and not use this referece
|
||||||
|
// any further
|
||||||
|
self.next_ref = unsafe { this_ref.next() };
|
||||||
|
Some(this_ref)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
members/oxide/src/start_stub.rs
Normal file
16
members/oxide/src/start_stub.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//! <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html>
|
||||||
|
|
||||||
|
use core::arch::naked_asm;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
#[unsafe(naked)]
|
||||||
|
unsafe extern "C" fn start_stub() -> ! {
|
||||||
|
// In cdecl, protected i386, the first argument is passed in the stack
|
||||||
|
|
||||||
|
// Sadly need to call bcs stack expectations, I wanna make a extern natural compiled thing for
|
||||||
|
// this.
|
||||||
|
|
||||||
|
const _: extern "C" fn(&crate::multiboot2::bif::FixedPart) -> ! = crate::start;
|
||||||
|
naked_asm!("push ebx", "call {}", sym crate::start);
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ impl<M: TextMode> VgaBuffer<M> {
|
|||||||
where
|
where
|
||||||
[[(u8, u8); M::WIDTH as usize]; M::HEIGHT as usize]:,
|
[[(u8, u8); M::WIDTH as usize]; M::HEIGHT as usize]:,
|
||||||
{
|
{
|
||||||
unsafe { core::mem::transmute(Self::VGA_ADDR) }
|
unsafe { &mut *Self::VGA_ADDR.cast() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
use crate::vga::{ColorNibble, TextMode, VgaBuffer, VgaColor};
|
use crate::vga::{ColorNibble, TextMode, VgaBuffer, VgaColor};
|
||||||
|
|
||||||
pub struct Writer<M: TextMode> {
|
pub struct Writer<M: TextMode> {
|
||||||
@@ -20,7 +22,7 @@ where
|
|||||||
|
|
||||||
pub fn carry(&mut self) {
|
pub fn carry(&mut self) {
|
||||||
self.pos.0 = 0;
|
self.pos.0 = 0;
|
||||||
if self.pos.1 >= M::HEIGHT {
|
if self.pos.1 + 1 >= M::HEIGHT {
|
||||||
self.slide();
|
self.slide();
|
||||||
} else {
|
} else {
|
||||||
self.pos.1 += 1;
|
self.pos.1 += 1;
|
||||||
@@ -28,7 +30,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_cell(&mut self) {
|
pub fn next_cell(&mut self) {
|
||||||
if self.pos.0 >= M::WIDTH {
|
if self.pos.0 + 1 >= M::WIDTH {
|
||||||
self.carry();
|
self.carry();
|
||||||
} else {
|
} else {
|
||||||
self.pos.0 += 1;
|
self.pos.0 += 1;
|
||||||
@@ -94,3 +96,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<M: TextMode> Write for Writer<M>
|
||||||
|
where
|
||||||
|
[[(u8, u8); M::WIDTH as usize]; M::HEIGHT as usize]:,
|
||||||
|
{
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
self.write(s.as_bytes());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ $(OUTIMG): $(KERNELFILE) $(GRUB_CFG)
|
|||||||
mkdir -p $(GRUB_DIR)/boot/grub
|
mkdir -p $(GRUB_DIR)/boot/grub
|
||||||
cp $(KERNELFILE) $(GRUB_DIR)/boot/kernel.bin
|
cp $(KERNELFILE) $(GRUB_DIR)/boot/kernel.bin
|
||||||
cp $(GRUB_CFG) $(GRUB_DIR)/boot/grub/grub.cfg
|
cp $(GRUB_CFG) $(GRUB_DIR)/boot/grub/grub.cfg
|
||||||
|
sed -i 's/$$args/$(CMDLINE)/' $(GRUB_DIR)/boot/grub/grub.cfg
|
||||||
grub-mkrescue -o $@ $(GRUB_DIR)
|
grub-mkrescue -o $@ $(GRUB_DIR)
|
||||||
|
|||||||
Reference in New Issue
Block a user