Commit so I can work on my school chromebook

This commit is contained in:
Arthur Beck 2025-01-31 07:23:37 -06:00
parent 402586b860
commit 9901560753
19 changed files with 273 additions and 125 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "kernel"
version = "0.1.0"
version = "0.2.0-devel-0000"
edition = "2024"
[dependencies]
@ -14,7 +14,7 @@ codegen-units = 1
panic = "abort"
[[bin]]
name = "entrypoint"
name = "entrypoint_x86"
path = "src/internal/arch/x86_asmp/entry.rs"
[[bin]]

View file

@ -8,8 +8,15 @@
. "$DIR/functions"
rm config.aphro.tmp
cp config.aphro config.aphro.tmp
# -f makes it so it won't error out if the file doesn't exist
rm -f config.aphro.tmp
envsubst < "config.aphro" > "config.aphro.tmp"
# see above about -f
rm -f targets.tmp
envsubst < "targets" > "targets.tmp"
export $(grep -Ev '^#' targets.tmp | xargs)
export $(grep -Ev '^#' config.aphro.tmp | xargs)
@ -26,7 +33,9 @@
cd ../kernel
cargo build --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint
for target in $TARGETS; do
cargo build --target "$target" --release -Zbuild-std --bin entrypoint
done
# build the kernel's entrypoint
cp target/i686-unknown-none/release/entrypoint kernel.flat

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,10 @@
set timeout=15
set timeout=5
set default=0
set gfxpayload=keep
insmod all_video
insmod gfxterm
insmod efi_uga
insmod efi_gop
menuentry "Aphrodite" --class aphrodite --class kernel --class os $menuentry_id_option 'aphrodite-basic-%{VERSION}' {
echo 'Loading Aphrodite aphrodite-%{VERSION} ...'

View file

@ -7,6 +7,6 @@ use crate::output::*;
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this.
#[allow(non_snake_case)]
pub fn _entry(display: Option<&dyn crate::TextDisplay>, BI: &crate::boot::BootInfo) -> ! {
pub fn _entry(display: Option<&dyn crate::display::TextDisplay>, BI: &crate::boot::BootInfo) -> ! {
loop {}
}

View file

@ -1,4 +1,4 @@
//! Arch-specific code.
//! Arch-specific code. This module re-exports all code from the architecture being used.
mod x86_asmp;

View file

@ -1,7 +1,7 @@
//! Stuff for writing and reading to the EGA text buffer.
#![cfg(any(target_arch = "x86"))]
use crate::Color;
use crate::display::Color;
/// Information about the framebuffer.
#[derive(Clone, Copy)]
@ -25,7 +25,7 @@ pub const ERR_INVALID_X: i16 = -1;
/// Returned when the provided position is invalid in the Y direction.
pub const ERR_INVALID_Y: i16 = -2;
impl crate::TextDisplay for FramebufferInfo {
impl crate::display::TextDisplay for FramebufferInfo {
/// Writes a character to the screen.
fn write_char(&self, mut pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>> {
let mut clr = color.0;

View file

@ -49,7 +49,7 @@ pub trait MemoryMap: _MemoryMap + core::any::Any {}
#[derive(Clone)]
pub struct BootInfo<'a> {
/// The commandline of the kernel.
/// See https://github.com/AverseABFun/aphrodite/wiki/Plan#bootloader (remember to update link later!) for the format.
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
pub cmdline: Option<&'static str>,
/// The memory map provided by the bootloader. If None, the kernel will attempt to generate it.
@ -59,5 +59,5 @@ pub struct BootInfo<'a> {
pub bootloader_name: Option<&'static str>,
/// Provides a way to display text.
pub output: Option<&'a dyn crate::TextDisplay>,
pub output: Option<&'a dyn crate::display::TextDisplay>,
}

View file

@ -0,0 +1,70 @@
//! Types, constants and traits for displaying text. Mostly implemented in arch/.
/// A type used for color in the functions of [TextDisplay].
///
/// Type alias for (u8, bool). Boolean argument is whether to
/// change the value(i.e. for [COLOR_BLACK] and [COLOR_DEFAULT]).
pub type Color = (u8, bool);
/// Black-on-black.
pub const COLOR_BLACK: Color = (0, true);
/// Should be whatever color commonly used for status messages.
/// Generally should be white-on-black. Value is one.
pub const COLOR_DEFAULT: Color = (1, true);
/// Some form of display that can be written to with text.
pub trait TextDisplay {
/// Writes a single character to the specified position.
fn write_char(&self, pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>>;
/// Gets the size of the screen.
fn get_size(&self) -> (u32, u32);
}
impl dyn TextDisplay + '_ {
/// Clears the screen.
pub fn clear_screen(&self, color: Color) {
let (width, height) = self.get_size();
for x in 0..width {
for y in 0..height {
self.write_char((x, y), b' ', color).unwrap();
}
}
}
/// Writes a &str to the screen.
pub fn write_str(&self, pos: (u32, u32), str: &str, color: Color) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size();
let (mut x, mut y) = pos;
for char in str.as_bytes() {
self.write_char((x, y), *char, color)?;
if *char == 0 {
continue
}
x += 1;
while x>width {
x -= width;
y += 1;
}
}
Ok((x, y))
}
/// Writes a &\[u8] to the screen.
pub fn write_bytes(&self, pos: (u32, u32), str: &[u8], color: Color) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size();
let (mut x, mut y) = pos;
for char in str {
self.write_char((x, y), *char, color)?;
if *char == 0 {
continue
}
x += 1;
while x>width {
x -= width;
y += 1;
}
}
Ok((x, y))
}
}

Binary file not shown.

View file

@ -1,4 +1,4 @@
//! This provides syscalls(for userspace programs) and types(for userspace and kernelspace programs) for the Aphrodite kernel.
//! This provides raw methods for internal kernel usage for the Aphrodite kernel. See aphrodite_user for userspace.
#![no_std]
#![warn(missing_docs)]
#![feature(ptr_metadata)]
@ -13,10 +13,14 @@ pub mod _entry;
mod traits;
pub mod output;
pub mod boot;
pub mod psfont;
pub mod display;
#[allow(unused_imports)] // if there are no constants, then it gives a warning
pub use constants::*;
pub use errors::*;
pub use util::*;
#[allow(unused_imports)] // if there are no traits, then it gives a warning
pub use traits::*;

View file

@ -1,6 +1,6 @@
//! Definitions of structs for multiboot2 information. Mostly used during pre-userspace.
/// Used for Multiboot2 tags. This shouldn't be used after a [BootInfo] struct has been initalized, but it still can be used.
/// Used for Multiboot2 tags. This shouldn't be used after a [crate::boot::BootInfo] struct has been initalized, but it still can be used.
#[repr(C)]
#[derive(Clone)]
pub struct Tag {
@ -21,7 +21,7 @@ pub struct RootTag {
reserved: u32,
}
/// A Multiboot2 module. See https://github.com/AverseABFun/aphrodite/wiki/Plan/#Bootloader-modules (remember to update link later!).
/// A Multiboot2 module. See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
#[derive(Clone)]
pub struct Module {
/// A pointer to the start of the module
@ -29,7 +29,7 @@ pub struct Module {
/// A pointer to the end of the module
pub mod_end: *const u8,
/// A string that should be in the format `module_name (command line arguments)`.
/// See https://github.com/AverseABFun/aphrodite/wiki/Plan/#Bootloader-modules (remember to update link later!).
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
pub mod_str: &'static core::ffi::CStr
}
@ -193,7 +193,7 @@ pub struct FramebufferInfo {
/// Boot info collected from provided [Tag]s.
#[derive(Clone)]
pub struct Multiboot2BootInfo {
/// See https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-memory-information.
/// See <https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-memory-information>.
/// Tl;dr: mem_lower indicates the amount of "lower memory"
/// and mem_upper the amount of "upper memory".
pub mem_lower: Option<u32>,
@ -206,7 +206,7 @@ pub struct Multiboot2BootInfo {
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This should contain the original pointer provided by
/// the bootloader.
/// See https://github.com/AverseABFun/aphrodite/wiki/Plan#bootloader (remember to update link later!) for the format.
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
pub cmdline: Option<&'static core::ffi::CStr>,
// Due to the way modules work, it's not easily possible to make a struct that contains all the modules.

View file

@ -1,15 +1,15 @@
//! Architecture-independent output functions.
use paste::paste;
use crate::COLOR_DEFAULT;
use crate::display::COLOR_DEFAULT;
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);
macro_rules! message_funcs {
($func_name:ident, $prefix:literal, $level:ident) => {
paste! {
/// Outputs a $func_name message &str to the terminal.
pub fn [< t $func_name s >](s: &str, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &str to the terminal.
pub fn [< t $func_name s >](s: &str, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -19,8 +19,8 @@ macro_rules! message_funcs {
}
Ok(())
}
/// Outputs a $func_name message &str and a newline to the terminal.
pub fn [< t $func_name sln >](s: &str, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &str and a newline to the terminal.
pub fn [< t $func_name sln >](s: &str, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -33,8 +33,8 @@ macro_rules! message_funcs {
Ok(())
}
/// Outputs a $func_name message &\[u8] to the terminal.
pub fn [< t $func_name b >](s: &[u8], info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &\[u8] to the terminal.
pub fn [< t $func_name b >](s: &[u8], info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -44,8 +44,8 @@ macro_rules! message_funcs {
}
Ok(())
}
/// Outputs a $func_name message &\[u8] and a newline to the terminal.
pub fn [< t $func_name bln >](s: &[u8], info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &\[u8] and a newline to the terminal.
pub fn [< t $func_name bln >](s: &[u8], info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -58,8 +58,8 @@ macro_rules! message_funcs {
Ok(())
}
/// Outputs a(n) $func_name message u8 to the terminal.
pub fn [< t $func_name u >](s: u8, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message u8 to the terminal.
pub fn [< t $func_name u >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
let (width, _) = info.get_size();
unsafe {
if cfg!($level = "false") {
@ -78,8 +78,8 @@ macro_rules! message_funcs {
///////////////////////////////////////////////////////////////
/// Outputs a $func_name message &str to the terminal without a prefix.
pub fn [< t $func_name snp >](s: &str, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &str to the terminal without a prefix.
pub fn [< t $func_name snp >](s: &str, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -88,8 +88,8 @@ macro_rules! message_funcs {
}
Ok(())
}
/// Outputs a $func_name message &str and a newline to the terminal without a prefix.
pub fn [< t $func_name snpln >](s: &str, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &str and a newline to the terminal without a prefix.
pub fn [< t $func_name snpln >](s: &str, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -101,8 +101,8 @@ macro_rules! message_funcs {
Ok(())
}
/// Outputs a $func_name message &\[u8] to the terminal without a prefix.
pub fn [< t $func_name bnp >](s: &[u8], info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &\[u8] to the terminal without a prefix.
pub fn [< t $func_name bnp >](s: &[u8], info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -111,8 +111,8 @@ macro_rules! message_funcs {
}
Ok(())
}
/// Outputs a $func_name message &\[u8] and a newline to the terminal without a prefix.
pub fn [< t $func_name bnpln >](s: &[u8], info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message &\[u8] and a newline to the terminal without a prefix.
pub fn [< t $func_name bnpln >](s: &[u8], info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
unsafe {
if cfg!($level = "false") {
return Ok(());
@ -124,8 +124,8 @@ macro_rules! message_funcs {
Ok(())
}
/// Outputs a(n) $func_name message u8 to the terminal without a prefix.
pub fn [< t $func_name unp >](s: u8, info: &dyn crate::TextDisplay) -> Result<(), crate::Error<'static>> {
/// Outputs a message u8 to the terminal without a prefix.
pub fn [< t $func_name unp >](s: u8, info: &dyn crate::display::TextDisplay) -> Result<(), crate::Error<'static>> {
let (width, _) = info.get_size();
unsafe {
if cfg!($level = "false") {

View file

@ -0,0 +1,118 @@
//! PC Screen Font stuff
/// The font selected to be the "main" font. I selected Linux's
/// ISO01-12x22 font.
pub const FONT1: &[u8; 12107] = include_bytes!("iso01-12x22.psfu");
/// One glyph for [RawPCScreenFont].
pub type RawGlyph = [u8];
/// PC Screen Font magic number.
pub const PSF_MAGIC: u32 = 0x864ab572;
/// A PC Screen font.
pub struct RawPCScreenFont {
/// The magic number. Should be 0x864ab572.
pub magic: u32,
/// The version. Should be 0.
pub version: u32,
/// The size of the header/offset of bitmaps.
pub header_size: u32,
/// Flags. 0 if there's no unicode table.
pub flags: u32,
/// The number of glyphs.
pub num_glyphs: u32,
/// The number of bytes per glyph.
pub bytes_per_glyph: u32,
/// The height of each glyph.
pub height: u32,
/// The width of each glyph.
pub width: u32,
/// The glyphs.
pub glyphs: *const RawGlyph,
}
/// The glyph type for [PCScreenFont].
pub struct Glyph {
/// The size of this glyph.
pub len: u32,
/// The height of this glyph.
pub height: u32,
/// The width of this glyph.
pub width: u32,
/// The raw glyph data.
pub data: &'static [u8],
}
/// A more useful form of [RawPCScreenFont].
pub struct PCScreenFont {
/// The version. Should be 0.
pub version: u32,
/// Flags. 0 if there's no unicode table.
pub flags: u32,
/// The height of each glyph.
pub height: u32,
/// The width of each glyph.
pub width: u32,
/// The glyphs.
pub glyphs: &'static [Glyph],
/// The unicode translation table.
pub unitable: &'static [&'static [u8]]
}
/// Error code returned when the PSF has an invalid magic number.
pub const ERR_INVALID_MAGIC: i16 = -1;
/// Parses a PC Screen Font into a [RawPCScreenFont].
pub fn parse_raw_pc_screen_font(data: &[u8]) -> Result<RawPCScreenFont, crate::Error> {
let out = RawPCScreenFont {
magic: u32::from_le_bytes(data[0..3].try_into().unwrap()),
version: u32::from_le_bytes(data[4..7].try_into().unwrap()),
header_size: u32::from_le_bytes(data[8..11].try_into().unwrap()),
flags: u32::from_le_bytes(data[12..15].try_into().unwrap()),
num_glyphs: u32::from_le_bytes(data[16..20].try_into().unwrap()),
bytes_per_glyph: u32::from_le_bytes(data[20..23].try_into().unwrap()),
height: u32::from_le_bytes(data[24..27].try_into().unwrap()),
width: u32::from_le_bytes(data[28..31].try_into().unwrap()),
glyphs: &data[32..] as *const [u8]
};
if out.magic != PSF_MAGIC {
return Err(crate::Error::new("Invalid magic", ERR_INVALID_MAGIC));
}
Ok(out)
}
/// Parses a PC Screen Font into a [PCScreenFont].
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
unsafe {
let unitable: &[&[u8]] = &[];
let unistr = data.glyphs.byte_add(data.bytes_per_glyph as usize*data.num_glyphs as usize);
let mut i = 0usize;
let mut f = 0usize;
loop {
let g = i+f;
if i>=data.num_glyphs as usize {
break;
}
let char = (*unistr)[g];
if char == 0xFF {
i += 1;
f = 0;
continue;
}
unitable[g];
f += 1;
}
let out = PCScreenFont {
version: data.version,
flags: data.flags,
height: data.height,
width: data.width,
glyphs: &*(core::ptr::from_raw_parts(data.glyphs as *const Glyph, data.num_glyphs as usize) as *const [Glyph]),
unitable
};
Ok(out)
}
}

View file

@ -1,70 +1 @@
//! General traits. Mostly implemented in arch/*.
/// A type used for color in the functions of [TextDisplay].
///
/// Type alias for (u8, bool). Boolean argument is whether to
/// change the value(i.e. for [COLOR_BLACK] and [COLOR_DEFAULT]).
pub type Color = (u8, bool);
/// Black-on-black.
pub const COLOR_BLACK: Color = (0, true);
/// Should be whatever color commonly used for status messages.
/// Generally should be white-on-black. Value is one.
pub const COLOR_DEFAULT: Color = (1, true);
/// Some form of display that can be written too with text.
pub trait TextDisplay {
/// Writes a single character to the specified position.
fn write_char(&self, pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>>;
/// Gets the size of the screen.
fn get_size(&self) -> (u32, u32);
}
impl dyn TextDisplay + '_ {
/// Clears the screen.
pub fn clear_screen(&self, color: Color) {
let (width, height) = self.get_size();
for x in 0..width {
for y in 0..height {
self.write_char((x, y), b' ', color).unwrap();
}
}
}
/// Writes a &str to the screen.
pub fn write_str(&self, pos: (u32, u32), str: &str, color: Color) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size();
let (mut x, mut y) = pos;
for char in str.as_bytes() {
self.write_char((x, y), *char, color)?;
if *char == 0 {
continue
}
x += 1;
while x>width {
x -= width;
y += 1;
}
}
Ok((x, y))
}
/// Writes a &\[u8] to the screen.
pub fn write_bytes(&self, pos: (u32, u32), str: &[u8], color: Color) -> Result<(u32, u32), crate::Error<'static>> {
let (width, _) = self.get_size();
let (mut x, mut y) = pos;
for char in str {
self.write_char((x, y), *char, color)?;
if *char == 0 {
continue
}
x += 1;
while x>width {
x -= width;
y += 1;
}
}
Ok((x, y))
}
}

View file

@ -17,11 +17,15 @@ use aphrodite::output::*;
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
#[unsafe(link_section = ".multiboot2")]
#[unsafe(no_mangle)]
static MULTIBOOT2_HEADER: [u8; 29] = [
0xd6, 0x50, 0x52, 0xe8, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x12, 0xaf, 0xad, 0x17,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
0xe9, 0x55, 0x00, 0x00, 0x00
static MULTIBOOT2_HEADER: [u8; 24] = [
0xd6, 0x50, 0x52, 0xe8, // Magic number
0x00, 0x00, 0x00, 0x00, // Architecture
0x18, 0x00, 0x00, 0x00, // Size
0x12, 0xaf, 0xad, 0x17, // Checksum
0x00, 0x00, // End tag
0x00, 0x00, // Flags
0x08, 0x00, 0x00, 0x00, // Size
];
// The root tag, provided directly from the multiboot2 bootloader.
@ -52,15 +56,7 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
#[unsafe(link_section = ".start")]
#[unsafe(no_mangle)]
extern "C" fn _start() -> ! {
#[allow(non_snake_case)]
let mut BI: BootInfo<'static> = BootInfo {
cmdline: None,
memory_map: None,
bootloader_name: None,
output: None,
};
unsafe { // Copy values provided by the bootloader out
// Aphrodite bootloaders pass values in eax and ebx, however rust doesn't know that it can't overwrite those.
// we force using ebx and eax as the output of an empty assembly block to let it know.
asm!(
@ -69,6 +65,13 @@ extern "C" fn _start() -> ! {
options(nomem, nostack, preserves_flags, pure)
);
}
#[allow(non_snake_case)]
let mut BI: BootInfo<'static> = BootInfo {
cmdline: None,
memory_map: None,
bootloader_name: None,
output: None,
};
unsafe {
match MAGIC {
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
@ -227,7 +230,7 @@ extern "C" fn _start() -> ! {
}
}
sdebugsln("Bootloader information has been successfully loaded");
soutputu(b'\n');
sdebugunp(b'\n');
unsafe {
if BI.output.clone().is_some() {
let framebuffer_info = FBI;
@ -248,9 +251,9 @@ extern "C" fn _start() -> ! {
let ega: &dyn aphrodite::TextDisplay = &framebuffer_info;
framebuffer_info.disable_cursor();
ega.clear_screen(aphrodite::COLOR_DEFAULT);
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
tdebugsln("Testing EGA Text framebuffer...", ega).unwrap();
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
aphrodite::_entry::_entry(Some(ega), &BI);
}

4
kernel/targets Normal file
View file

@ -0,0 +1,4 @@
# Targets used for documentation.
x86=$KERNEL_DIR/i686-unknown-none.json
TARGETS=$x86

4
kernel/targets.tmp Normal file
View file

@ -0,0 +1,4 @@
# Targets used for documentation.
x86=/i686-unknown-none.json
TARGETS=