Worked on build script a bunch, added format script and formatted everything
This commit is contained in:
parent
7ae1677a87
commit
884e9aa3cf
33 changed files with 393 additions and 272 deletions
|
@ -21,7 +21,3 @@ path = "src/arch_boot_entry/x86.rs"
|
|||
[lib]
|
||||
name = "aphrodite"
|
||||
path = "src/kernel/mod.rs"
|
||||
|
||||
[[test]]
|
||||
name = "test_aphrodite"
|
||||
path = "src/include/test.rs"
|
||||
|
|
43
kernel/build
43
kernel/build
|
@ -1,29 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
(
|
||||
set -o errexit -o pipefail -o noclobber
|
||||
flags=$-
|
||||
set -o pipefail -o noclobber
|
||||
|
||||
HAVE_GETOPT=true
|
||||
HAVE_GETOPT="${HAVE_GETOPT:-true}"
|
||||
getopt --test > /dev/null && true
|
||||
if [[ $? -ne 4 ]]; then
|
||||
if [[ $? -ne 4 && $HAVE_GETOPT ]]; then
|
||||
if [[ -n "EXIT_WITHOUT_GETOPT" ]]; then
|
||||
echo '`getopt --test` failed. Exiting.'
|
||||
echo '[ERROR] `getopt --test` failed. Exiting.'
|
||||
exit 1
|
||||
else
|
||||
echo '`getopt --test` failed. Continuing and ignoring command line flags. (note that $1 will still be used for the target)'
|
||||
echo '(to exit instead of ignoring, set the environment variable `EXIT_WITHOUT_GETOPT` to a non-null value)'
|
||||
echo '[WARN] `getopt --test` failed. Continuing and ignoring command line flags. (note that $1 will still be used for the target)'
|
||||
echo '[WARN] (to exit instead of ignoring, set the environment variable `EXIT_WITHOUT_GETOPT` to a non-null value)'
|
||||
HAVE_GETOPT=false
|
||||
fi
|
||||
fi
|
||||
|
||||
set -o errexit # put down here as getopt returns error code four if it's working, and it probably would work otherwise, but I'm not taking chances
|
||||
|
||||
check=false
|
||||
format=false
|
||||
|
||||
if [[ "$HAVE_GETOPT" = "true" ]]; then
|
||||
LONGOPTS=check
|
||||
OPTIONS=c
|
||||
LONGOPTS=check,format
|
||||
OPTIONS=cf
|
||||
|
||||
PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || (
|
||||
echo '`getopt` failed to parse command line arguments. Check the arguments passed.'
|
||||
echo '[ERROR] Failed to parse command line arguments. If your getopt is broken, set HAVE_GETOPT=true.'
|
||||
exit 1
|
||||
)
|
||||
eval set -- "$PARSED"
|
||||
|
@ -34,6 +38,10 @@
|
|||
check=true
|
||||
shift
|
||||
;;
|
||||
-f|--format)
|
||||
format=true
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
|
@ -44,6 +52,12 @@
|
|||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $check == "true" && $format == "true" ]]; then
|
||||
echo "[WARN] Both --check and --format were passed."
|
||||
echo "[WARN] Interpretting as only --format, as format will also check that Aphrokern can compile."
|
||||
check=false
|
||||
fi
|
||||
fi
|
||||
|
||||
export KERNEL_DIR=$(readlink -e .)
|
||||
|
@ -79,11 +93,11 @@
|
|||
function compile_one {
|
||||
target=$1
|
||||
real_target=${!target}
|
||||
real_target=$(basename $real_target)
|
||||
echo "Compiling target $target(with rust target of $real_target)"
|
||||
if [[ $check = "true" ]]; then
|
||||
echo "[INFO] Checking target $target(with rust target of $real_target)"
|
||||
cargo check --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
|
||||
else
|
||||
echo "[INFO] Compiling target $target(with rust target of $real_target)"
|
||||
cargo build --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
|
||||
cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target
|
||||
|
||||
|
@ -103,6 +117,12 @@
|
|||
fi
|
||||
}
|
||||
|
||||
if [[ $format = "true" ]]; then
|
||||
echo "[INFO] Formatting"
|
||||
cargo fmt --all
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $# -ge 1 ]]; then
|
||||
echo "[INFO] Compiling only target $1"
|
||||
compile_one $1
|
||||
|
@ -114,4 +134,5 @@
|
|||
done
|
||||
|
||||
reset_version_vars
|
||||
set +$flags
|
||||
)
|
|
@ -1,22 +1,42 @@
|
|||
fn main() {
|
||||
let env = std::env::vars();
|
||||
|
||||
|
||||
// Begin checks
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_DISABLE_MULTIBOOT2_SUPPORT, values("true", "false", none()))"#);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_DISABLE_MULTIBOOT2_SUPPORT, values("true", "false", none()))"#
|
||||
);
|
||||
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_HALT_ON_PANIC, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_SPIN_ON_PANIC, values("true", "false", none()))"#);
|
||||
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH, values("true", "false", none()))"#);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH, values("true", "false", none()))"#
|
||||
);
|
||||
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_INFO, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_WARN, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_ERROR, values("true", "false", none()))"#);
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_FATAL, values("true", "false", none()))"#);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_INFO, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_WARN, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_ERROR, values("true", "false", none()))"#
|
||||
);
|
||||
println!(
|
||||
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_FATAL, values("true", "false", none()))"#
|
||||
);
|
||||
|
||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_BUILD_GRUB, values("true", "false", none()))"#);
|
||||
// End checks
|
||||
|
@ -26,9 +46,9 @@ fn main() {
|
|||
|
||||
for (var, val) in env {
|
||||
if !var.starts_with("CONFIG_") {
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed={}", var);
|
||||
println!("cargo:rustc-cfg={}=\"{}\"", var, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint_x86
|
7
kernel/format
Executable file
7
kernel/format
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
(
|
||||
set -o errexit -o pipefail -o noclobber
|
||||
|
||||
./build --format $!
|
||||
)
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
function get_version() {
|
||||
local TEMP_SUFFIX
|
||||
if git add . && git diff --quiet && git diff --cached --quiet
|
||||
|
|
|
@ -9,26 +9,27 @@
|
|||
#![feature(cfg_match)]
|
||||
#![feature(formatting_options)]
|
||||
|
||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
||||
use core::fmt::Debug;
|
||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
||||
|
||||
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||
use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag};
|
||||
use aphrodite::arch::egatext;
|
||||
use aphrodite::arch::output::*;
|
||||
use aphrodite::arch::egatext as egatext;
|
||||
use aphrodite::output::*;
|
||||
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||
use aphrodite::display::COLOR_DEFAULT;
|
||||
use aphrodite::multiboot2::{
|
||||
FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag,
|
||||
};
|
||||
use aphrodite::output::*;
|
||||
|
||||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
||||
#[unsafe(link_section = ".bootheader")]
|
||||
#[unsafe(no_mangle)]
|
||||
static MULTIBOOT2_HEADER: [u8; 24] = [
|
||||
0xd6, 0x50, 0x52, 0xe8, // Magic number
|
||||
0xd6, 0x50, 0x52, 0xe8, // Magic number
|
||||
0x00, 0x00, 0x00, 0x00, // Architecture
|
||||
0x18, 0x00, 0x00, 0x00, // Size
|
||||
0x18, 0x00, 0x00, 0x00, // Size
|
||||
0x12, 0xaf, 0xad, 0x17, // Checksum
|
||||
|
||||
0x00, 0x00, // End tag
|
||||
0x00, 0x00, // End tag
|
||||
0x00, 0x00, // Flags
|
||||
0x08, 0x00, 0x00, 0x00, // Size
|
||||
];
|
||||
|
@ -45,14 +46,15 @@ static mut MM: MemoryMap = MemoryMap {
|
|||
sections: &[],
|
||||
};
|
||||
|
||||
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo {
|
||||
address: 0,
|
||||
pitch: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
bpp: 0,
|
||||
change_cursor: false,
|
||||
};
|
||||
static mut FBI: aphrodite::arch::egatext::FramebufferInfo =
|
||||
aphrodite::arch::egatext::FramebufferInfo {
|
||||
address: 0,
|
||||
pitch: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
bpp: 0,
|
||||
change_cursor: false,
|
||||
};
|
||||
|
||||
// The magic number in eax. 0x36D76289 for multiboot2.
|
||||
static mut MAGIC: u32 = 0xFFFFFFFF;
|
||||
|
@ -61,7 +63,8 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
|
|||
#[unsafe(no_mangle)]
|
||||
#[aphrodite_proc_macros::kernel_item(ArchBootEntry)]
|
||||
extern "C" fn _start() -> ! {
|
||||
unsafe { // Copy values provided by the bootloader out
|
||||
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.
|
||||
// (if necessary, we'll store all of the registers for other bootloaders and identify which one it is later)
|
||||
// we force using ebx and eax as the output of an empty assembly block to let it know.
|
||||
|
@ -81,7 +84,8 @@ extern "C" fn _start() -> ! {
|
|||
unsafe {
|
||||
match MAGIC {
|
||||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
||||
0x36D76289 => { // Multiboot2
|
||||
0x36D76289 => {
|
||||
// Multiboot2
|
||||
RT = O as *const RootTag; // This is unsafe rust! We can do whatever we want! *manical laughter*
|
||||
|
||||
sdebugs("Total boot info length is ");
|
||||
|
@ -92,11 +96,12 @@ extern "C" fn _start() -> ! {
|
|||
sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
|
||||
sdebugunp(b'\n');
|
||||
|
||||
if (*RT).total_len<16 { // Size of root tag+size of terminating tag. Something's up.
|
||||
if (*RT).total_len < 16 {
|
||||
// Size of root tag+size of terminating tag. Something's up.
|
||||
panic!("total length < 16")
|
||||
}
|
||||
|
||||
let end_addr = O as usize+(*RT).total_len as usize;
|
||||
let end_addr = O as usize + (*RT).total_len as usize;
|
||||
|
||||
sdebugunp(b'\n');
|
||||
|
||||
|
@ -104,7 +109,7 @@ extern "C" fn _start() -> ! {
|
|||
ptr += size_of::<RootTag>();
|
||||
|
||||
let mut current_tag = core::ptr::read_volatile(ptr as *const Tag);
|
||||
|
||||
|
||||
loop {
|
||||
sdebugs("Tag address is ");
|
||||
sdebugbnpln(&aphrodite::usize_as_u8_slice(ptr));
|
||||
|
@ -114,26 +119,34 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
sdebugs("Tag length is ");
|
||||
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
|
||||
|
||||
|
||||
match current_tag.tag_type {
|
||||
0 => { // Ending tag
|
||||
if current_tag.tag_len != 8 { // Unexpected size, something is probably up
|
||||
0 => {
|
||||
// Ending tag
|
||||
if current_tag.tag_len != 8 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of ending tag != 8");
|
||||
}
|
||||
break
|
||||
},
|
||||
4 => { // Basic memory information
|
||||
if current_tag.tag_len != 16 { // Unexpected size, something is probably up
|
||||
break;
|
||||
}
|
||||
4 => {
|
||||
// Basic memory information
|
||||
if current_tag.tag_len != 16 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of basic memory information tag != 16");
|
||||
}
|
||||
},
|
||||
5 => { // BIOS boot device, ignore
|
||||
if current_tag.tag_len != 20 { // Unexpected size, something is probably up
|
||||
}
|
||||
5 => {
|
||||
// BIOS boot device, ignore
|
||||
if current_tag.tag_len != 20 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of bios boot device tag != 20");
|
||||
}
|
||||
},
|
||||
1 => { // Command line
|
||||
if current_tag.tag_len < 8 { // Unexpected size, something is probably up
|
||||
}
|
||||
1 => {
|
||||
// Command line
|
||||
if current_tag.tag_len < 8 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of command line tag < 8");
|
||||
}
|
||||
let cstring = CStr::from_ptr((ptr + 8) as *const i8);
|
||||
|
@ -141,13 +154,16 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
BI.cmdline = Some(cstring.to_str().unwrap());
|
||||
// ...before the BootInfo's commandline is set.
|
||||
},
|
||||
6 => { // Memory map tag
|
||||
if current_tag.tag_len < 16 { // Unexpected size, something is probably up
|
||||
}
|
||||
6 => {
|
||||
// Memory map tag
|
||||
if current_tag.tag_len < 16 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of memory map tag < 16");
|
||||
}
|
||||
let rawmemorymap: *mut RawMemoryMap = core::ptr::from_raw_parts_mut(
|
||||
ptr as *mut u8, (current_tag.tag_len / *((ptr + 8usize) as *const u32)) as usize
|
||||
ptr as *mut u8,
|
||||
(current_tag.tag_len / *((ptr + 8usize) as *const u32)) as usize,
|
||||
);
|
||||
// The end result of the above is creating a *const RawMemoryMap that has the same address as current_tag
|
||||
// and has all of the [aphrodite::multiboot2::MemorySection]s for the memory map
|
||||
|
@ -169,12 +185,14 @@ extern "C" fn _start() -> ! {
|
|||
size_pages: 1,
|
||||
page_size: MM.mem_size(),
|
||||
sections: MM.sections,
|
||||
idx: 0
|
||||
idx: 0,
|
||||
};
|
||||
BI.memory_map = Some(mm2);
|
||||
},
|
||||
2 => { // Bootloader name
|
||||
if current_tag.tag_len < 8 { // Unexpected size, something is probably up
|
||||
}
|
||||
2 => {
|
||||
// Bootloader name
|
||||
if current_tag.tag_len < 8 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of command line tag < 8");
|
||||
}
|
||||
let cstring = CStr::from_ptr((ptr + 8) as *const i8);
|
||||
|
@ -182,21 +200,26 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
BI.bootloader_name = Some(cstring.to_str().unwrap());
|
||||
// ...before the BootInfo's bootloader_name is set.
|
||||
},
|
||||
8 => { // Framebuffer info
|
||||
if current_tag.tag_len < 32 { // Unexpected size, something is probably up
|
||||
}
|
||||
8 => {
|
||||
// Framebuffer info
|
||||
if current_tag.tag_len < 32 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of framebuffer info tag < 32");
|
||||
}
|
||||
let framebufferinfo: *const FramebufferInfo = (ptr as usize + size_of::<Tag>()) as *const FramebufferInfo;
|
||||
let framebufferinfo: *const FramebufferInfo =
|
||||
(ptr as usize + size_of::<Tag>()) as *const FramebufferInfo;
|
||||
match (*framebufferinfo).fb_type {
|
||||
0 => { // Indexed
|
||||
0 => {
|
||||
// Indexed
|
||||
panic!("Indexed color is unimplemented");
|
||||
},
|
||||
1 => { // RGB
|
||||
}
|
||||
1 => {
|
||||
// RGB
|
||||
panic!("RGB color is unimplemented");
|
||||
},
|
||||
}
|
||||
2 => { // EGA Text
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
panic!("unknown color info type")
|
||||
}
|
||||
|
@ -212,15 +235,16 @@ extern "C" fn _start() -> ! {
|
|||
change_cursor: false,
|
||||
};
|
||||
BI.output = Some(&FBI)
|
||||
},
|
||||
_ => { // Unknown/unimplemented tag type, ignore
|
||||
}
|
||||
_ => {
|
||||
// Unknown/unimplemented tag type, ignore
|
||||
swarnings("Unknown tag type ");
|
||||
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
||||
}
|
||||
}
|
||||
sinfounp(b'\n');
|
||||
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
||||
if ptr>end_addr {
|
||||
if ptr > end_addr {
|
||||
cfg_match! {
|
||||
all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
|
||||
serrorsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH is set, continuing");
|
||||
|
@ -242,8 +266,9 @@ extern "C" fn _start() -> ! {
|
|||
}
|
||||
current_tag = core::ptr::read_volatile(ptr as *const Tag);
|
||||
}
|
||||
},
|
||||
_ => { // Unknown bootloader, panic
|
||||
}
|
||||
_ => {
|
||||
// Unknown bootloader, panic
|
||||
panic!("unknown bootloader");
|
||||
}
|
||||
}
|
||||
|
@ -261,10 +286,12 @@ extern "C" fn _start() -> ! {
|
|||
sdebugs("Framebuffer pitch: ");
|
||||
sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.pitch));
|
||||
sdebugs("Framebuffer address: ");
|
||||
sdebugbnpln(&aphrodite::usize_as_u8_slice(framebuffer_info.address as usize));
|
||||
sdebugbnpln(&aphrodite::usize_as_u8_slice(
|
||||
framebuffer_info.address as usize,
|
||||
));
|
||||
sdebugs("Framebuffer bpp: ");
|
||||
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
|
||||
|
||||
|
||||
sdebugsln("Beginning test output to screen...");
|
||||
|
||||
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
|
||||
|
@ -293,12 +320,13 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
|
|||
sfatalsnp(":");
|
||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
||||
sfatalsnp(":");
|
||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
|
||||
sfatalsnp(": ");
|
||||
sfatalbnpln(&aphrodite::u32_as_u8_slice(
|
||||
info.location().unwrap().column(),
|
||||
));
|
||||
} else {
|
||||
sfatals("Panic: ");
|
||||
}
|
||||
let mut formatter = FormattingOptions::new().create_formatter(unsafe { &mut FBI });
|
||||
let mut formatter = FormattingOptions::new().create_formatter(unsafe { &mut FBI });
|
||||
let _ = info.message().fmt(&mut formatter);
|
||||
aphrodite::arch::interrupts::disable_interrupts();
|
||||
unsafe {
|
||||
|
@ -308,7 +336,7 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
|
|||
|
||||
#[unsafe(link_section = ".panic")]
|
||||
#[panic_handler]
|
||||
#[cfg(all(CONFIG_SPIN_ON_PANIC = "true", CONFIG_PREUSER_HALT_ON_PANIC = "false"))]
|
||||
#[cfg(all(CONFIG_SPIN_ON_PANIC = "true", CONFIG_HALT_ON_PANIC = "false"))]
|
||||
fn spin_on_panic(info: &PanicInfo) -> ! {
|
||||
if info.location().is_some() {
|
||||
sfatals("Panic at ");
|
||||
|
@ -316,7 +344,9 @@ fn spin_on_panic(info: &PanicInfo) -> ! {
|
|||
sfatalsnp(":");
|
||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
||||
sfatalsnp(":");
|
||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
|
||||
sfatalbnp(&aphrodite::u32_as_u8_slice(
|
||||
info.location().unwrap().column(),
|
||||
));
|
||||
sfatalsnp(": ");
|
||||
} else {
|
||||
sfatals("Panic: ");
|
||||
|
@ -329,4 +359,4 @@ fn spin_on_panic(info: &PanicInfo) -> ! {
|
|||
}
|
||||
aphrodite::arch::interrupts::disable_interrupts();
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
//! An example implementation of an architecture. DO NOT use this module!
|
||||
//! Everything must be implemented via either kernel items, or for constants
|
||||
//! making them public.
|
||||
//!
|
||||
//!
|
||||
//! This is commented out for obvious reasons, but make sure to have this at
|
||||
//! the top of the all files in your arch(with "arch" replaced with the
|
||||
//! actual architecture, of course):
|
||||
//! #![cfg(any(target_arch = "arch"))]
|
||||
|
||||
/// Returns the most specific architecture available.
|
||||
pub const fn get_arch() -> super::Architecture {
|
||||
super::Architecture::ExampleDummy
|
||||
}
|
||||
|
@ -15,11 +16,11 @@ pub mod interrupts {
|
|||
//! Interrupt-related functions.
|
||||
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
|
||||
/// Must be a u16 or castable to a u16.
|
||||
/// Value used in x86 shown here as an example.
|
||||
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
||||
|
||||
|
||||
/// Returns whether interrupts are enabled or not.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsCheck)]
|
||||
fn interrupts_enabled() -> bool {
|
||||
|
@ -28,15 +29,11 @@ pub mod interrupts {
|
|||
|
||||
/// Enables interrupts.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
|
||||
fn enable_interrupts() {
|
||||
|
||||
}
|
||||
fn enable_interrupts() {}
|
||||
|
||||
/// Disables interrupts.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||
fn disable_interrupts() {
|
||||
|
||||
}
|
||||
fn disable_interrupts() {}
|
||||
|
||||
/// Disables interrupts and a value that can be used to restore them
|
||||
/// with [restore_irq].
|
||||
|
@ -47,21 +44,17 @@ pub mod interrupts {
|
|||
|
||||
/// Restores interrupts after a [pop_irq] call.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsRestore)]
|
||||
fn restore_irq(irq: u64) {
|
||||
irq;
|
||||
}
|
||||
fn restore_irq(_irq: u64) {}
|
||||
|
||||
/// Activates an IDT.
|
||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||
fn activate_idt(idt: Idt) {
|
||||
idt;
|
||||
}
|
||||
fn activate_idt(_idt: Idt) {}
|
||||
|
||||
/// An IDT.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Idt {
|
||||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn ()>; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
|
@ -70,14 +63,14 @@ pub mod interrupts {
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct IdtBuilder {
|
||||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn ()>; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl IdtBuilder {
|
||||
/// Start creating a new IDT.
|
||||
pub fn new() -> Self {
|
||||
IdtBuilder {
|
||||
IdtBuilder {
|
||||
vectors: [0; 256],
|
||||
funcs: [MaybeUninit::uninit(); 256],
|
||||
idx: 0,
|
||||
|
@ -95,7 +88,7 @@ pub mod interrupts {
|
|||
Idt {
|
||||
vectors: self.vectors,
|
||||
funcs: self.funcs,
|
||||
len: self.idx
|
||||
len: self.idx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +99,3 @@ pub mod output {
|
|||
//! LOT of output functions must be implemented. Using macros to
|
||||
//! implement these is HIGHLY recommended.
|
||||
}
|
||||
|
||||
/// Returns whether paging is available for this architecture.
|
||||
#[aphrodite_proc_macros::kernel_item(PagingAvailabe)]
|
||||
pub fn paging_available() -> bool {
|
||||
true
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
//! Arch-specific code. This module re-exports all code from the architecture being used.
|
||||
//!
|
||||
//!
|
||||
//! See [example_impl] for everything that has to be implemented by an architecture module.
|
||||
|
||||
mod x86;
|
||||
pub mod example_impl;
|
||||
mod x86;
|
||||
|
||||
pub use x86::*;
|
||||
|
||||
|
@ -16,4 +16,4 @@ pub enum Architecture {
|
|||
ExampleDummy,
|
||||
/// 32-bit x86.
|
||||
X86,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
#![cfg(any(target_arch = "x86"))]
|
||||
|
||||
/// The assembly port number to output debug messages to.
|
||||
pub(super) const DEBUG_PORT: u16 = 0xE9;
|
||||
pub(super) const DEBUG_PORT: u16 = 0xE9;
|
||||
|
|
|
@ -34,7 +34,12 @@ impl core::fmt::Write 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>> {
|
||||
fn write_char(
|
||||
&self,
|
||||
mut pos: (u32, u32),
|
||||
char: u8,
|
||||
color: Color,
|
||||
) -> Result<(), crate::Error<'static>> {
|
||||
let mut clr = color.0;
|
||||
if color.1 {
|
||||
match clr {
|
||||
|
@ -44,18 +49,18 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
|||
}
|
||||
}
|
||||
let color = clr;
|
||||
if pos.0>self.width {
|
||||
if pos.0 > self.width {
|
||||
return Err(crate::Error::new("Invalid X position", ERR_INVALID_X));
|
||||
}
|
||||
if pos.1>self.height {
|
||||
if pos.1 > self.height {
|
||||
return Err(crate::Error::new("Invalid Y position", ERR_INVALID_Y));
|
||||
}
|
||||
unsafe {
|
||||
let mut addr = self.address as usize;
|
||||
addr += (pos.1*self.pitch) as usize;
|
||||
addr += (pos.0*(self.bpp as u32/8)) as usize;
|
||||
addr += (pos.1 * self.pitch) as usize;
|
||||
addr += (pos.0 * (self.bpp as u32 / 8)) as usize;
|
||||
let base_ptr = addr as *mut u16;
|
||||
(*base_ptr) = ((color as u16)<<8) | (char as u16);
|
||||
(*base_ptr) = ((color as u16) << 8) | (char as u16);
|
||||
}
|
||||
pos.1 += 1;
|
||||
if self.change_cursor {
|
||||
|
@ -69,7 +74,6 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
|||
}
|
||||
|
||||
impl FramebufferInfo {
|
||||
|
||||
/// Disables the cursor.
|
||||
pub fn disable_cursor(self) {
|
||||
super::ports::outb(0x3D4, 0x0A);
|
||||
|
|
|
@ -5,15 +5,18 @@ use core::alloc::Layout;
|
|||
use alloc::vec::Vec;
|
||||
|
||||
/// Writes a series of GDT entries to an allocated section of memory and returns a pointer.
|
||||
pub unsafe fn write_gdt_entries(entries: Vec<GDTEntry>) -> Result<*const [u8], crate::Error<'static>> {
|
||||
let mut mem = unsafe { alloc::alloc::alloc(Layout::from_size_align(8*entries.len(), 1).unwrap()) };
|
||||
pub unsafe fn write_gdt_entries(
|
||||
entries: Vec<GDTEntry>,
|
||||
) -> Result<*const [u8], crate::Error<'static>> {
|
||||
let mut mem =
|
||||
unsafe { alloc::alloc::alloc(Layout::from_size_align(8 * entries.len(), 1).unwrap()) };
|
||||
for ele in &entries {
|
||||
let ele: &GDTEntry = ele;
|
||||
unsafe { ele.write_to_addr(mem as *mut ())? }
|
||||
mem = (mem as usize + 8) as *mut u8;
|
||||
}
|
||||
|
||||
Ok(core::ptr::from_raw_parts(mem, 8*entries.len()))
|
||||
Ok(core::ptr::from_raw_parts(mem, 8 * entries.len()))
|
||||
}
|
||||
|
||||
/// A GDT entry.
|
||||
|
@ -35,7 +38,10 @@ const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
|||
impl GDTEntry {
|
||||
const unsafe fn write_to_addr(self, ptr: *mut ()) -> Result<(), crate::Error<'static>> {
|
||||
if self.limit > 0xFFFFF {
|
||||
return Err(crate::Error::new("Invalid GDT entry limit(more than 0xFFFFF)", GDT_WRITE_ADDR_INVALID_LIMIT));
|
||||
return Err(crate::Error::new(
|
||||
"Invalid GDT entry limit(more than 0xFFFFF)",
|
||||
GDT_WRITE_ADDR_INVALID_LIMIT,
|
||||
));
|
||||
}
|
||||
let mut serialized = (0u64).to_ne_bytes();
|
||||
|
||||
|
@ -55,7 +61,7 @@ impl GDTEntry {
|
|||
unsafe {
|
||||
core::ptr::write(ptr as *mut [u8; 8], serialized);
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
#![cfg(any(target_arch = "x86"))]
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
use core::{alloc::{Allocator, Layout}, arch::asm, mem::MaybeUninit};
|
||||
use core::{
|
||||
alloc::{Allocator, Layout},
|
||||
arch::asm,
|
||||
mem::MaybeUninit,
|
||||
};
|
||||
|
||||
/// The syscall vector.
|
||||
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
||||
|
@ -23,9 +27,7 @@ pub fn interrupts_enabled() -> bool {
|
|||
/// Disables interrupts.
|
||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||
pub fn disable_interrupts() {
|
||||
unsafe {
|
||||
asm!("cli")
|
||||
}
|
||||
unsafe { asm!("cli") }
|
||||
}
|
||||
|
||||
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
|
||||
|
@ -62,9 +64,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
|
|||
asm!(
|
||||
"push {0:e}", in(reg) flags
|
||||
);
|
||||
asm!(
|
||||
"popf"
|
||||
);
|
||||
asm!("popf");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
|
|||
#[repr(C)]
|
||||
struct IDTR {
|
||||
base: *const u8,
|
||||
size: usize
|
||||
size: usize,
|
||||
}
|
||||
|
||||
unsafe impl Send for IDTR {}
|
||||
|
@ -83,53 +83,54 @@ unsafe impl Sync for IDTR {}
|
|||
fn load_idt(base: *const u8, size: usize) {
|
||||
static mut IDTR: MaybeUninit<IDTR> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
IDTR.write(IDTR {
|
||||
base,
|
||||
size
|
||||
});
|
||||
}
|
||||
unsafe {
|
||||
asm!("lidt {}", in(reg) IDTR.as_ptr() as usize)
|
||||
IDTR.write(IDTR { base, size });
|
||||
}
|
||||
unsafe { asm!("lidt {}", in(reg) IDTR.as_ptr() as usize) }
|
||||
}
|
||||
|
||||
/// Activate an IDT.
|
||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||
fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
|
||||
let mem = alloc.allocate(unsafe { Layout::from_size_align_unchecked(8*idt.len, 1) }).unwrap().as_mut_ptr();
|
||||
let _mem = alloc
|
||||
.allocate(unsafe { Layout::from_size_align_unchecked(8 * idt.len, 1) })
|
||||
.unwrap()
|
||||
.as_mut_ptr();
|
||||
for i in 0..idt.len {
|
||||
let vector = idt.vectors[i];
|
||||
let func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
||||
let user_callable = idt.user_callable[i];
|
||||
|
||||
let _vector = idt.vectors[i];
|
||||
let _func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
||||
let _user_callable = idt.user_callable[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// An Interrupt Descriptor Table.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Idt {
|
||||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn ()>; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
user_callable: [bool; 256],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
/// A builder of an [Idt].
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct IdtBuilder {
|
||||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn ()>; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
user_callable: [bool; 256],
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl IdtBuilder {
|
||||
/// Create a new IdtBuilder.
|
||||
pub fn new() -> Self {
|
||||
IdtBuilder {
|
||||
IdtBuilder {
|
||||
vectors: [0; 256],
|
||||
funcs: [MaybeUninit::uninit(); 256],
|
||||
user_callable: [false; 256],
|
||||
idx: 0,
|
||||
}
|
||||
}
|
||||
/// Add a function to this IdtBuilder.
|
||||
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
|
||||
self.vectors[self.idx] = vector;
|
||||
self.funcs[self.idx].write(func);
|
||||
|
@ -137,12 +138,13 @@ impl IdtBuilder {
|
|||
self.idx += 1;
|
||||
self
|
||||
}
|
||||
/// Finish creating this IdtBuilder and return an [Idt].
|
||||
pub fn finish(&self) -> Idt {
|
||||
Idt {
|
||||
vectors: self.vectors,
|
||||
funcs: self.funcs,
|
||||
user_callable: self.user_callable,
|
||||
len: self.idx
|
||||
len: self.idx,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,9 @@ use alloc::{vec, vec::Vec};
|
|||
|
||||
use crate::memsections::*;
|
||||
|
||||
use super::gdt::{write_gdt_entries, GDTEntry};
|
||||
use super::gdt::{GDTEntry, write_gdt_entries};
|
||||
|
||||
/// A list of memory sections. Create one with [MemorySectionBuilder].
|
||||
pub struct MemorySections {
|
||||
sections: Vec<MemorySection>,
|
||||
}
|
||||
|
@ -100,11 +101,11 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
|||
|
||||
let gdtr = GDTR {
|
||||
address: ptr as *const u8 as usize as u32,
|
||||
size: (ptr.len()-1) as u16
|
||||
size: (ptr.len() - 1) as u16,
|
||||
};
|
||||
|
||||
let addr = &gdtr as *const GDTR as *const () as usize as u32;
|
||||
|
||||
|
||||
asm!(
|
||||
"lgdt eax",
|
||||
in("eax") addr
|
||||
|
@ -124,10 +125,10 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
|||
}
|
||||
|
||||
if entry.access & 0b11000 == 0b11000 && !code_set {
|
||||
code_segment = i-1;
|
||||
code_segment = i - 1;
|
||||
code_set = true;
|
||||
} else if entry.access & 0b10000 == 0b10000 && !data_set {
|
||||
data_segment = i-1;
|
||||
data_segment = i - 1;
|
||||
data_set = true;
|
||||
}
|
||||
}
|
||||
|
@ -156,16 +157,19 @@ pub struct MemorySectionBuilder {
|
|||
}
|
||||
|
||||
impl MemorySectionBuilder {
|
||||
/// Create a new MemorySectionBuilder.
|
||||
pub fn new() -> Self {
|
||||
MemorySectionBuilder { sections: vec![] }
|
||||
}
|
||||
|
||||
/// Adds a section to this MemorySectionBuilder.
|
||||
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
||||
self.sections.push(section);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes this MemorySectionBuilder and returns a MemorySections.
|
||||
pub fn finish(self) -> MemorySections {
|
||||
MemorySections {
|
||||
sections: self.sections,
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
use core::arch::asm;
|
||||
|
||||
pub mod interrupts;
|
||||
pub mod ports;
|
||||
pub mod output;
|
||||
pub mod egatext;
|
||||
pub mod paging;
|
||||
mod gdt;
|
||||
pub mod interrupts;
|
||||
pub mod memory;
|
||||
pub mod output;
|
||||
pub mod paging;
|
||||
pub mod ports;
|
||||
|
||||
mod constants;
|
||||
|
||||
|
@ -17,15 +17,11 @@ pub(self) use constants::*;
|
|||
use interrupts::{pop_irq, restore_irq};
|
||||
use ports::{inb, outb};
|
||||
|
||||
/// Returns the most specific architecture available.
|
||||
pub const fn get_arch() -> super::Architecture {
|
||||
super::Architecture::X86
|
||||
}
|
||||
|
||||
#[aphrodite_proc_macros::kernel_item(PagingAvailabe)]
|
||||
pub fn paging_available() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns information from the CPUID command in the form
|
||||
/// (ebx, edx, ecx).
|
||||
pub fn cpuid(id: u32) -> (u32, u32, u32) {
|
||||
|
@ -70,12 +66,12 @@ pub fn test_a20() -> bool {
|
|||
|
||||
/// Waits for a keyboard command to complete.
|
||||
pub fn wait_for_keyboard_cmd() {
|
||||
while inb(0x64)&0b10 > 1 {}
|
||||
while inb(0x64) & 0b10 > 1 {}
|
||||
}
|
||||
|
||||
/// Waits for there to be data to read from the keyboard.
|
||||
pub fn wait_for_keyboard_data() {
|
||||
while inb(0x64)&0b1 == 0 {}
|
||||
while inb(0x64) & 0b1 == 0 {}
|
||||
}
|
||||
|
||||
/// Sends a keyboard command.
|
||||
|
@ -111,7 +107,7 @@ pub fn enable_a20_keyboard() {
|
|||
send_keyboard_cmd(0xD1); // write to output
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_data(a|2);
|
||||
send_keyboard_data(a | 2);
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_cmd(0xAE); // enable keyboard
|
||||
|
@ -123,8 +119,8 @@ pub fn enable_a20_keyboard() {
|
|||
/// Note that this may not work or do something unexpected.
|
||||
pub fn enable_a20_fasta20() {
|
||||
let mut a = inb(0x92);
|
||||
if a&0b10 > 0 {
|
||||
return
|
||||
if a & 0b10 > 0 {
|
||||
return;
|
||||
}
|
||||
a |= 0b10;
|
||||
a &= 0xFE;
|
||||
|
@ -145,7 +141,7 @@ pub fn enable_a20() -> bool {
|
|||
|
||||
enable_a20_keyboard();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i<10000 {
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
@ -155,7 +151,7 @@ pub fn enable_a20() -> bool {
|
|||
|
||||
enable_a20_ee_port();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i<10000 {
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
@ -165,7 +161,7 @@ pub fn enable_a20() -> bool {
|
|||
|
||||
enable_a20_fasta20();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i<10000 {
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ macro_rules! message_funcs {
|
|||
ports::outb(super::DEBUG_PORT, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG);
|
||||
|
@ -103,4 +103,3 @@ message_funcs!(warning, "[WARN] ", CONFIG_PREUSER_OUTPUT_WARN);
|
|||
message_funcs!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR);
|
||||
message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
|
||||
message_funcs!(output, "", NONE);
|
||||
|
||||
|
|
|
@ -4,8 +4,11 @@ use core::arch::asm;
|
|||
|
||||
use aphrodite_proc_macros::kernel_item;
|
||||
|
||||
/// One page directory entry. Use [PageDirectoryEntry::create_fourmb] or [PageDirectoryEntry::create_other] to make these.
|
||||
pub enum PageDirectoryEntry {
|
||||
/// A four megabyte page.
|
||||
FourMb(u32),
|
||||
/// A smaller page.
|
||||
Other(u32),
|
||||
}
|
||||
|
||||
|
@ -114,11 +117,9 @@ impl PageDirectoryEntry {
|
|||
static mut PAGE_DIRECTORY: PageDirectoryEntry =
|
||||
PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false);
|
||||
|
||||
/// Initalize paging.
|
||||
#[kernel_item(PagingInit)]
|
||||
pub fn initalize_paging() {
|
||||
|
||||
}
|
||||
|
||||
pub fn initalize_paging() {}
|
||||
|
||||
/// Disables paging by clearing bit 31 in the cr0 register.
|
||||
#[kernel_item(PagingDeinit)]
|
||||
|
|
|
@ -36,4 +36,4 @@ pub fn inb(port: u16) -> u8 {
|
|||
#[inline(always)]
|
||||
pub fn io_wait() {
|
||||
outb(0x80, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,15 +34,14 @@ impl MemoryType {
|
|||
MemoryType::Faulty => crate::arch::output::sdebugsnp("Faulty RAM"),
|
||||
MemoryType::HardwareReserved => crate::arch::output::sdebugsnp("Hardware Reserved"),
|
||||
MemoryType::HardwareSpecific(val, allocatable) => {
|
||||
crate::arch::output::sdebugsnp("Hardware specific ");
|
||||
crate::arch::output::sdebugbnp(&crate::u32_as_u8_slice(*val));
|
||||
if *allocatable {
|
||||
crate::arch::output::sdebugsnp(", allocatable");
|
||||
} else {
|
||||
crate::arch::output::sdebugsnp(", unallocatable");
|
||||
}
|
||||
|
||||
},
|
||||
crate::arch::output::sdebugsnp("Hardware specific ");
|
||||
crate::arch::output::sdebugbnp(&crate::u32_as_u8_slice(*val));
|
||||
if *allocatable {
|
||||
crate::arch::output::sdebugsnp(", allocatable");
|
||||
} else {
|
||||
crate::arch::output::sdebugsnp(", unallocatable");
|
||||
}
|
||||
}
|
||||
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
||||
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
||||
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
||||
|
|
|
@ -11,4 +11,4 @@ macro_rules! cfg_int {
|
|||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@ pub struct Argument {
|
|||
/// The name of an argument.
|
||||
pub name: &'static str,
|
||||
/// The value of an argument.
|
||||
pub value: ArgumentValue
|
||||
pub value: ArgumentValue,
|
||||
}
|
||||
|
||||
/// A single flag in a [Cmdline].
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Flag {
|
||||
/// The name of a flag.
|
||||
pub name: &'static str
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
/// A kernel command line.
|
||||
|
@ -83,7 +83,10 @@ impl Validator for CmdlineValidator {
|
|||
}
|
||||
}
|
||||
if !correct {
|
||||
return Err(crate::Error::new("invalid argument in command line", ERR_INVALID_ARGUMENT));
|
||||
return Err(crate::Error::new(
|
||||
"invalid argument in command line",
|
||||
ERR_INVALID_ARGUMENT,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,9 +99,12 @@ impl Validator for CmdlineValidator {
|
|||
}
|
||||
}
|
||||
if !correct {
|
||||
return Err(crate::Error::new("invalid flag in command line", ERR_INVALID_FLAG));
|
||||
return Err(crate::Error::new(
|
||||
"invalid flag in command line",
|
||||
ERR_INVALID_FLAG,
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
//! Constants used throughout kernel code.
|
||||
//! Constants used throughout kernel code.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use core::fmt::Write;
|
||||
|
||||
/// 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);
|
||||
|
@ -18,7 +18,12 @@ pub const COLOR_DEFAULT: Color = (1, true);
|
|||
/// Some form of display that can be written to with text.
|
||||
pub trait TextDisplay: core::fmt::Write {
|
||||
/// Writes a single character to the specified position.
|
||||
fn write_char(&self, pos: (u32, u32), char: u8, color: Color) -> Result<(), crate::Error<'static>>;
|
||||
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);
|
||||
}
|
||||
|
@ -35,16 +40,21 @@ impl dyn TextDisplay + '_ {
|
|||
}
|
||||
|
||||
/// Writes a &str to the screen.
|
||||
pub fn write_str(&self, pos: (u32, u32), str: &str, color: Color) -> Result<(u32, u32), crate::Error<'static>> {
|
||||
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
|
||||
continue;
|
||||
}
|
||||
x += 1;
|
||||
while x>width {
|
||||
while x > width {
|
||||
x -= width;
|
||||
y += 1;
|
||||
}
|
||||
|
@ -53,16 +63,21 @@ impl dyn TextDisplay + '_ {
|
|||
}
|
||||
|
||||
/// Writes a &\[u8] to the screen.
|
||||
pub fn write_bytes(&self, pos: (u32, u32), str: &[u8], color: Color) -> Result<(u32, u32), crate::Error<'static>> {
|
||||
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
|
||||
continue;
|
||||
}
|
||||
x += 1;
|
||||
while x>width {
|
||||
while x > width {
|
||||
x -= width;
|
||||
y += 1;
|
||||
}
|
||||
|
@ -76,7 +91,7 @@ pub struct NoneTextDisplay {}
|
|||
|
||||
impl TextDisplay for NoneTextDisplay {
|
||||
fn get_size(&self) -> (u32, u32) {
|
||||
(1,1)
|
||||
(1, 1)
|
||||
}
|
||||
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
||||
Ok(())
|
||||
|
@ -90,4 +105,4 @@ impl Write for NoneTextDisplay {
|
|||
fn write_str(&mut self, _: &str) -> core::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::display::TextDisplay;
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct Error<'a> {
|
||||
message: &'a str,
|
||||
code: i16
|
||||
code: i16,
|
||||
}
|
||||
|
||||
impl<'a> Error<'a> {
|
||||
|
@ -17,7 +17,7 @@ impl<'a> Error<'a> {
|
|||
}
|
||||
|
||||
impl Error<'_> {
|
||||
/// Display the contents of the error on a [TextDisplay].
|
||||
/// Display the contents of the error on a [TextDisplay] with no prefix.
|
||||
pub fn display_np(&self, display: &dyn TextDisplay) {
|
||||
crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display).unwrap();
|
||||
crate::output::terrorsnp(": ", display).unwrap();
|
||||
|
@ -41,4 +41,4 @@ impl core::fmt::Display for Error<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl core::error::Error for Error<'_> {}
|
||||
impl core::error::Error for Error<'_> {}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
|
||||
use core::alloc::{Allocator, Layout};
|
||||
|
||||
use crate::{display::{NoneTextDisplay, COLOR_DEFAULT}, output::*};
|
||||
use crate::{
|
||||
display::{COLOR_DEFAULT, NoneTextDisplay},
|
||||
output::*,
|
||||
};
|
||||
|
||||
use aphrodite_proc_macros::*;
|
||||
|
||||
|
@ -17,7 +20,10 @@ fn indep_boot_entry(
|
|||
display: Option<&dyn crate::display::TextDisplay>,
|
||||
#[allow(non_snake_case)] BI: &crate::boot::BootInfo,
|
||||
) -> ! {
|
||||
assert_ne!(crate::arch::get_arch(), crate::arch::Architecture::ExampleDummy);
|
||||
assert_ne!(
|
||||
crate::arch::get_arch(),
|
||||
crate::arch::Architecture::ExampleDummy
|
||||
);
|
||||
crate::arch::output::sdebugsln("IndepBootEntry called");
|
||||
|
||||
let display = display.unwrap_or(&NoneTextDisplay {});
|
||||
|
@ -64,6 +70,8 @@ fn indep_boot_entry(
|
|||
terrors("Failed to deallocate: ", display).unwrap();
|
||||
err.display_np(display);
|
||||
panic!("Deallocation failure");
|
||||
} else {
|
||||
tdebugsln("Successfully deallocated!", display).unwrap();
|
||||
}
|
||||
}
|
||||
tdebugsln("", display).unwrap();
|
||||
|
|
|
@ -48,8 +48,6 @@ struct AllocationIter {
|
|||
impl Iterator for AllocationIter {
|
||||
type Item = *mut Allocation;
|
||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(self.num_allocations));
|
||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(self.idx));
|
||||
self.idx += 1;
|
||||
if self.idx > self.num_allocations {
|
||||
return None;
|
||||
|
@ -139,7 +137,11 @@ impl<'a> Debug for MemoryMapAlloc<'a> {
|
|||
|
||||
impl<'a> MemoryMapAlloc<'a> {
|
||||
/// Creates a new [MemoryMapAlloc]. Please call this method instead of creating it manually!
|
||||
/// This method uses the memory mapping to
|
||||
///
|
||||
/// This method internally stores the memory map in the outputted MemoryMapAlloc.
|
||||
///
|
||||
/// Note that this function will return an error only if there isn't enough allocatable space
|
||||
/// for at least 32 allocations.
|
||||
pub fn new(
|
||||
memory_map: &'a mut crate::boot::MemoryMap,
|
||||
) -> Result<MemoryMapAlloc<'a>, crate::Error<'a>> {
|
||||
|
@ -222,6 +224,9 @@ impl<'a> MemoryMapAlloc<'a> {
|
|||
|
||||
/// Add an allocation to [MemoryMapAlloc::allocations]. It will overwrite allocations with `used` set to false.
|
||||
fn add_allocation(&self, allocation: Allocation) -> Result<(), crate::Error<'static>> {
|
||||
if !allocation.used {
|
||||
crate::arch::output::swarningsln("Adding unused allocation");
|
||||
}
|
||||
for alloc in self.allocations_iter() {
|
||||
if !unsafe { *alloc }.used {
|
||||
unsafe { (*alloc) = allocation }
|
||||
|
@ -355,7 +360,7 @@ pub const MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED: i16 = -8;
|
|||
|
||||
struct MaybeMemoryMapAlloc<'a> {
|
||||
alloc: MaybeUninit<MemoryMapAlloc<'a>>,
|
||||
initalized: bool
|
||||
initalized: bool,
|
||||
}
|
||||
impl<'a> MaybeMemoryMapAlloc<'a> {
|
||||
const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self {
|
||||
|
@ -363,7 +368,7 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
|
|||
return MaybeMemoryMapAlloc {
|
||||
alloc: MaybeUninit::uninit(),
|
||||
initalized: false,
|
||||
}
|
||||
};
|
||||
}
|
||||
MaybeMemoryMapAlloc {
|
||||
alloc: MaybeUninit::new(alloc.unwrap()),
|
||||
|
@ -385,7 +390,9 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
|
|||
if !self.initalized {
|
||||
return;
|
||||
}
|
||||
unsafe { self.alloc.assume_init_drop(); }
|
||||
unsafe {
|
||||
self.alloc.assume_init_drop();
|
||||
}
|
||||
self.initalized = false;
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +425,10 @@ unsafe impl<'a> GlobalAlloc for MaybeMemoryMapAlloc<'a> {
|
|||
}
|
||||
|
||||
unsafe impl<'a> Allocator for MaybeMemoryMapAlloc<'a> {
|
||||
fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
|
||||
fn allocate(
|
||||
&self,
|
||||
layout: core::alloc::Layout,
|
||||
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
|
||||
if !self.initalized {
|
||||
unsafe {
|
||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||
|
@ -545,6 +555,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
}
|
||||
return;
|
||||
}
|
||||
crate::arch::output::sdebugsln("Searching for allocation");
|
||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
|
||||
unsafe { *self.allocationheader }.num_allocations,
|
||||
));
|
||||
|
@ -552,6 +563,17 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
crate::arch::output::sdebugsln("Allocation");
|
||||
let alloc = unsafe { *allocation }.clone();
|
||||
if !alloc.used {
|
||||
crate::arch::output::sdebugs("Unused, addr is ");
|
||||
if alloc.addr == addr {
|
||||
crate::arch::output::sdebugsnp("correct and ");
|
||||
} else {
|
||||
crate::arch::output::sdebugsnp("incorrect and ");
|
||||
}
|
||||
if alloc.addr == 0 {
|
||||
crate::arch::output::sdebugsnpln("null");
|
||||
} else {
|
||||
crate::arch::output::sdebugsnpln("non-null");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
crate::arch::output::sdebugsln("Used");
|
||||
|
@ -560,6 +582,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
crate::arch::output::sdebugsln("Memory unallocated");
|
||||
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
|
||||
unsafe {
|
||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! Architecture-independt memory section stuff.
|
||||
//!
|
||||
//!
|
||||
//! arch::*::memory is the architecture-dependent counterpart.
|
||||
|
||||
/// Section types for [MemorySection].
|
||||
|
@ -12,7 +12,7 @@ pub enum SectionType {
|
|||
CodeSection {
|
||||
/// Whether more powerful owners can jump to this if the owner
|
||||
/// is less powerful.
|
||||
can_powerful_sections_jump: bool
|
||||
can_powerful_sections_jump: bool,
|
||||
},
|
||||
/// A data section. Generally at least one of these for the kernel.
|
||||
DataSection,
|
||||
|
@ -21,7 +21,7 @@ pub enum SectionType {
|
|||
/// if they aren't directly supported by the hardware.
|
||||
TaskSection {
|
||||
/// Whether the section is busy.
|
||||
busy: bool
|
||||
busy: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ pub struct MemorySection {
|
|||
/// is called, which is not supposed to happen.
|
||||
pub unsafe trait MemorySections {
|
||||
/// Write the sections to an allocated region and then activate them.
|
||||
///
|
||||
///
|
||||
/// This intentionally takes ownership of the MemorySections as it
|
||||
/// shouldn't be used after this is called.
|
||||
unsafe fn write(self) -> Result<(), crate::Error<'static>>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ pub mod display;
|
|||
mod errors;
|
||||
pub mod indep_boot_entry;
|
||||
pub mod mem;
|
||||
pub mod memsections;
|
||||
pub mod multiboot2;
|
||||
pub mod output;
|
||||
pub mod psfont;
|
||||
mod traits;
|
||||
mod util;
|
||||
pub mod memsections;
|
||||
|
||||
#[macro_use]
|
||||
pub(crate) mod cfg;
|
||||
|
@ -47,3 +47,11 @@ pub use util::*;
|
|||
|
||||
#[allow(unused_imports)] // if there are no traits, then it gives a warning
|
||||
pub use traits::*;
|
||||
|
||||
pub const fn version() -> &'static str {
|
||||
env!("VERSION")
|
||||
}
|
||||
|
||||
pub const fn cfg_version() -> &'static str {
|
||||
env!("CFG_VERSION")
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Tag {
|
|||
/// The type of the tag.
|
||||
pub tag_type: u32,
|
||||
/// The length of the tag.
|
||||
pub tag_len: u32
|
||||
pub tag_len: u32,
|
||||
}
|
||||
|
||||
/// The root tag. The official Multiboot2 name is literally the "fixed part" of the tags, so I made a better name.
|
||||
|
@ -32,7 +32,7 @@ pub struct Module {
|
|||
pub mod_end: *const u8,
|
||||
/// A string that should be in the format `module_name (command line arguments)`.
|
||||
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
||||
pub mod_str: &'static core::ffi::CStr
|
||||
pub mod_str: &'static core::ffi::CStr,
|
||||
}
|
||||
|
||||
/// One memory section provided by a Multiboot2 bootloader.
|
||||
|
@ -58,10 +58,10 @@ impl Into<crate::boot::MemoryMapping> for MemorySection {
|
|||
2 => crate::boot::MemoryType::HardwareReserved,
|
||||
3 => crate::boot::MemoryType::HardwareSpecific(3, false),
|
||||
5 => crate::boot::MemoryType::Faulty,
|
||||
_ => crate::boot::MemoryType::Reserved
|
||||
_ => crate::boot::MemoryType::Reserved,
|
||||
},
|
||||
start: self.base_addr,
|
||||
len: self.length
|
||||
len: self.length,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ pub struct RawMemoryMap {
|
|||
/// The version of the memory map. Should be disregarded as it's 0.
|
||||
pub entry_version: u32, // currently is 0, future Multiboot2 versions may increment
|
||||
/// The sections. This is the reason that [Clone] can't be implemented for [RawMemoryMap].
|
||||
pub sections: [MemorySection]
|
||||
pub sections: [MemorySection],
|
||||
}
|
||||
|
||||
/// A full memory map provided by a Multiboot2 bootloader.
|
||||
|
@ -119,7 +119,7 @@ pub struct PaletteColorDescriptor {
|
|||
/// The green value
|
||||
pub green: u8,
|
||||
/// The blue value
|
||||
pub blue: u8
|
||||
pub blue: u8,
|
||||
}
|
||||
|
||||
/// Information about color, for use in [FramebufferInfo].
|
||||
|
@ -131,7 +131,7 @@ pub enum ColorInfo {
|
|||
/// The number of colors in the palette.
|
||||
num_colors: u32,
|
||||
/// The first color in the palette.
|
||||
palette: *const PaletteColorDescriptor
|
||||
palette: *const PaletteColorDescriptor,
|
||||
},
|
||||
/// RGB information for use on the framebuffer.
|
||||
RGBColor {
|
||||
|
@ -151,7 +151,7 @@ pub enum ColorInfo {
|
|||
blue_mask_size: u8,
|
||||
},
|
||||
/// Text information, no metadata
|
||||
EGAText
|
||||
EGAText,
|
||||
}
|
||||
|
||||
/// Information about the framebuffer.
|
||||
|
@ -172,7 +172,6 @@ pub struct FramebufferInfo {
|
|||
pub fb_type: u8,
|
||||
/// Reserved space. Ignore.
|
||||
reserved: u8,
|
||||
|
||||
// Color info after this; we need separate structs for each colorinfo as
|
||||
// we have to understand the format the bootloader gives us.
|
||||
}
|
||||
|
@ -190,7 +189,6 @@ pub struct Multiboot2BootInfo {
|
|||
// Multiboot2 bootloaders may provide us with the BIOS device and partition, but we're not interested.
|
||||
// To ensure future developers don't get any ideas, I'm leaving it out here.
|
||||
// If you need it, good luck.
|
||||
|
||||
/// 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://aphrodite-os.github.io/book/command-line.html> for the format.
|
||||
|
@ -201,7 +199,6 @@ pub struct Multiboot2BootInfo {
|
|||
|
||||
// Multiboot2 bootloaders may provide us with ELF symbols, but I'm feeling lazy and right now it's mostly
|
||||
// unnecessary, so I don't care. Sorry if you are affected by this.
|
||||
|
||||
/// The memory map provided by the bootloader.
|
||||
pub memory_map: Option<MemoryMap>,
|
||||
|
||||
|
@ -212,12 +209,10 @@ pub struct Multiboot2BootInfo {
|
|||
// APM table is ignored as APM has been superseded by ACPI. If your system doesn't support ACPI, good luck.
|
||||
|
||||
// VBE table is ignored for a similar reason to above: it's deprecated. Good luck if you need it.
|
||||
|
||||
/// Provides information on the framebuffer.
|
||||
pub framebuffer_info: Option<FramebufferInfo>,
|
||||
/// Color info, stored separately from [FramebufferInfo] because rust
|
||||
pub color_info: Option<ColorInfo>,
|
||||
|
||||
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search for it ourselves.
|
||||
// This is because right now I cannot figure out what format it provides the SMBIOS table in.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Architecture-independent output functions.
|
||||
|
||||
use paste::paste;
|
||||
use crate::display::COLOR_DEFAULT;
|
||||
use paste::paste;
|
||||
|
||||
/// The position to output stuff to.
|
||||
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);
|
||||
|
@ -157,4 +157,4 @@ pub fn sreset() {
|
|||
unsafe {
|
||||
OUTPUT_TERM_POSITION = (0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,17 +82,13 @@ pub fn parse_raw_pc_screen_font(data: Vec<u8>) -> Result<RawPCScreenFont, crate:
|
|||
}
|
||||
|
||||
/// Parses a PC Screen Font into a [PCScreenFont].
|
||||
pub fn parse_pc_screen_font(
|
||||
data: RawPCScreenFont,
|
||||
) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||
unsafe {
|
||||
if data.flags == 0 {
|
||||
let mut unitable: Vec<Vec<u8>> = Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>());
|
||||
let mut unitable: Vec<Vec<u8>> =
|
||||
Vec::with_capacity(data.num_glyphs as usize * core::mem::size_of::<Vec<u8>>());
|
||||
|
||||
let unistr = (data
|
||||
.glyphs
|
||||
.as_slice()
|
||||
as *const [u8])
|
||||
let unistr = (data.glyphs.as_slice() as *const [u8])
|
||||
.byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize);
|
||||
|
||||
let mut i = 0usize;
|
||||
|
@ -136,9 +132,7 @@ pub fn parse_pc_screen_font(
|
|||
}
|
||||
|
||||
/// Parses a Vec<u8> into a [PCScreenFont].
|
||||
pub fn parse_psfu(
|
||||
data: Vec<u8>,
|
||||
) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||
pub fn parse_psfu(data: Vec<u8>) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||
let data = parse_raw_pc_screen_font(data)?;
|
||||
parse_pc_screen_font(data)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub const fn i16_as_u8_slice(mut value: i16) -> [u8; 6] {
|
|||
}
|
||||
i = 5;
|
||||
while value > 0 {
|
||||
let digit = value%10;
|
||||
let digit = value % 10;
|
||||
let char = b'0' + digit as u8;
|
||||
buf[i] = char;
|
||||
value = value / 10;
|
||||
|
@ -30,7 +30,7 @@ pub const fn u32_as_u8_slice(mut value: u32) -> [u8; 10] {
|
|||
buf[0] = b'0';
|
||||
}
|
||||
while value > 0 {
|
||||
let digit = value%10;
|
||||
let digit = value % 10;
|
||||
let char = b'0' + digit as u8;
|
||||
buf[i] = char;
|
||||
value = value / 10;
|
||||
|
@ -47,7 +47,7 @@ pub const fn u8_as_u8_slice(mut value: u8) -> [u8; 3] {
|
|||
buf[0] = b'0';
|
||||
}
|
||||
while value > 0 {
|
||||
let digit = value%10;
|
||||
let digit = value % 10;
|
||||
let char = b'0' + digit as u8;
|
||||
buf[i] = char;
|
||||
value = value / 10;
|
||||
|
@ -64,7 +64,7 @@ pub const fn usize_as_u8_slice(mut value: usize) -> [u8; 20] {
|
|||
buf[0] = b'0';
|
||||
}
|
||||
while value > 0 {
|
||||
let digit = value%10;
|
||||
let digit = value % 10;
|
||||
let char = b'0' + digit as u8;
|
||||
buf[i] = char;
|
||||
value = value / 10;
|
||||
|
@ -81,7 +81,7 @@ pub const fn u64_as_u8_slice(mut value: u64) -> [u8; 20] {
|
|||
buf[0] = b'0';
|
||||
}
|
||||
while value > 0 {
|
||||
let digit = value%10;
|
||||
let digit = value % 10;
|
||||
let char = b'0' + digit as u8;
|
||||
buf[i] = char;
|
||||
value = value / 10;
|
||||
|
@ -103,7 +103,7 @@ pub fn str_as_i16(mut value: &[u8]) -> i16 {
|
|||
continue;
|
||||
}
|
||||
out *= 10;
|
||||
out += (byte-b'0') as i16;
|
||||
out += (byte - b'0') as i16;
|
||||
}
|
||||
|
||||
let mut reversed = 0;
|
||||
|
@ -125,7 +125,7 @@ pub fn str_as_u32(value: &[u8]) -> u32 {
|
|||
continue;
|
||||
}
|
||||
out *= 10;
|
||||
out += (byte-b'0') as u32;
|
||||
out += (byte - b'0') as u32;
|
||||
}
|
||||
|
||||
let mut reversed = 0;
|
||||
|
@ -147,7 +147,7 @@ pub fn str_as_u128(value: &[u8]) -> u128 {
|
|||
continue;
|
||||
}
|
||||
out *= 10;
|
||||
out += (byte-b'0') as u128;
|
||||
out += (byte - b'0') as u128;
|
||||
}
|
||||
|
||||
let mut reversed = 0;
|
||||
|
@ -169,7 +169,7 @@ pub fn str_as_u64(value: &[u8]) -> u64 {
|
|||
continue;
|
||||
}
|
||||
out *= 10;
|
||||
out += (byte-b'0') as u64;
|
||||
out += (byte - b'0') as u64;
|
||||
}
|
||||
|
||||
let mut reversed = 0;
|
||||
|
@ -180,4 +180,4 @@ pub fn str_as_u64(value: &[u8]) -> u64 {
|
|||
}
|
||||
|
||||
reversed
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue