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]
|
[lib]
|
||||||
name = "aphrodite"
|
name = "aphrodite"
|
||||||
path = "src/kernel/mod.rs"
|
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
|
#!/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
|
getopt --test > /dev/null && true
|
||||||
if [[ $? -ne 4 ]]; then
|
if [[ $? -ne 4 && $HAVE_GETOPT ]]; then
|
||||||
if [[ -n "EXIT_WITHOUT_GETOPT" ]]; then
|
if [[ -n "EXIT_WITHOUT_GETOPT" ]]; then
|
||||||
echo '`getopt --test` failed. Exiting.'
|
echo '[ERROR] `getopt --test` failed. Exiting.'
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
echo '`getopt --test` failed. Continuing and ignoring command line flags. (note that $1 will still be used for the target)'
|
echo '[WARN] `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] (to exit instead of ignoring, set the environment variable `EXIT_WITHOUT_GETOPT` to a non-null value)'
|
||||||
HAVE_GETOPT=false
|
HAVE_GETOPT=false
|
||||||
fi
|
fi
|
||||||
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
|
check=false
|
||||||
|
format=false
|
||||||
|
|
||||||
if [[ "$HAVE_GETOPT" = "true" ]]; then
|
if [[ "$HAVE_GETOPT" = "true" ]]; then
|
||||||
LONGOPTS=check
|
LONGOPTS=check,format
|
||||||
OPTIONS=c
|
OPTIONS=cf
|
||||||
|
|
||||||
PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || (
|
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
|
exit 1
|
||||||
)
|
)
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
@ -34,6 +38,10 @@
|
||||||
check=true
|
check=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
-f|--format)
|
||||||
|
format=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
|
@ -44,6 +52,12 @@
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
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
|
fi
|
||||||
|
|
||||||
export KERNEL_DIR=$(readlink -e .)
|
export KERNEL_DIR=$(readlink -e .)
|
||||||
|
@ -79,11 +93,11 @@
|
||||||
function compile_one {
|
function compile_one {
|
||||||
target=$1
|
target=$1
|
||||||
real_target=${!target}
|
real_target=${!target}
|
||||||
real_target=$(basename $real_target)
|
|
||||||
echo "Compiling target $target(with rust target of $real_target)"
|
|
||||||
if [[ $check = "true" ]]; then
|
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
|
cargo check --target "$real_target" --release -Zbuild-std=core,alloc --bin entrypoint_$target
|
||||||
else
|
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
|
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
|
cp "target/$(echo $real_target | sed 's/\.json//')/release/entrypoint_$target" kernel-$target
|
||||||
|
|
||||||
|
@ -103,6 +117,12 @@
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [[ $format = "true" ]]; then
|
||||||
|
echo "[INFO] Formatting"
|
||||||
|
cargo fmt --all
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $# -ge 1 ]]; then
|
if [[ $# -ge 1 ]]; then
|
||||||
echo "[INFO] Compiling only target $1"
|
echo "[INFO] Compiling only target $1"
|
||||||
compile_one $1
|
compile_one $1
|
||||||
|
@ -114,4 +134,5 @@
|
||||||
done
|
done
|
||||||
|
|
||||||
reset_version_vars
|
reset_version_vars
|
||||||
|
set +$flags
|
||||||
)
|
)
|
|
@ -2,21 +2,41 @@ fn main() {
|
||||||
let env = std::env::vars();
|
let env = std::env::vars();
|
||||||
|
|
||||||
// Begin checks
|
// 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_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_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!(
|
||||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH, values("true", "false", none()))"#);
|
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_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_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!(
|
||||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_INFO, values("true", "false", none()))"#);
|
r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_DEBUG, 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!(
|
||||||
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_PREUSER_OUTPUT_FATAL, values("true", "false", none()))"#);
|
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()))"#);
|
println!(r#"cargo:rustc-check-cfg=cfg(CONFIG_BUILD_GRUB, values("true", "false", none()))"#);
|
||||||
// End checks
|
// End checks
|
||||||
|
@ -26,7 +46,7 @@ fn main() {
|
||||||
|
|
||||||
for (var, val) in env {
|
for (var, val) in env {
|
||||||
if !var.starts_with("CONFIG_") {
|
if !var.starts_with("CONFIG_") {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
println!("cargo:rerun-if-env-changed={}", var);
|
println!("cargo:rerun-if-env-changed={}", var);
|
||||||
println!("cargo:rustc-cfg={}=\"{}\"", var, val);
|
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() {
|
function get_version() {
|
||||||
local TEMP_SUFFIX
|
local TEMP_SUFFIX
|
||||||
if git add . && git diff --quiet && git diff --cached --quiet
|
if git add . && git diff --quiet && git diff --cached --quiet
|
||||||
|
|
|
@ -9,15 +9,17 @@
|
||||||
#![feature(cfg_match)]
|
#![feature(cfg_match)]
|
||||||
#![feature(formatting_options)]
|
#![feature(formatting_options)]
|
||||||
|
|
||||||
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
use core::{arch::asm, ffi::CStr, panic::PanicInfo};
|
||||||
|
|
||||||
use aphrodite::boot::{BootInfo, MemoryMapping};
|
use aphrodite::arch::egatext;
|
||||||
use aphrodite::multiboot2::{FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag};
|
|
||||||
use aphrodite::arch::output::*;
|
use aphrodite::arch::output::*;
|
||||||
use aphrodite::arch::egatext as egatext;
|
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||||
use aphrodite::output::*;
|
|
||||||
use aphrodite::display::COLOR_DEFAULT;
|
use aphrodite::display::COLOR_DEFAULT;
|
||||||
|
use aphrodite::multiboot2::{
|
||||||
|
FramebufferInfo, MemoryMap, MemorySection, RawMemoryMap, RootTag, Tag,
|
||||||
|
};
|
||||||
|
use aphrodite::output::*;
|
||||||
|
|
||||||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
||||||
#[unsafe(link_section = ".bootheader")]
|
#[unsafe(link_section = ".bootheader")]
|
||||||
|
@ -27,7 +29,6 @@ static MULTIBOOT2_HEADER: [u8; 24] = [
|
||||||
0x00, 0x00, 0x00, 0x00, // Architecture
|
0x00, 0x00, 0x00, 0x00, // Architecture
|
||||||
0x18, 0x00, 0x00, 0x00, // Size
|
0x18, 0x00, 0x00, 0x00, // Size
|
||||||
0x12, 0xaf, 0xad, 0x17, // Checksum
|
0x12, 0xaf, 0xad, 0x17, // Checksum
|
||||||
|
|
||||||
0x00, 0x00, // End tag
|
0x00, 0x00, // End tag
|
||||||
0x00, 0x00, // Flags
|
0x00, 0x00, // Flags
|
||||||
0x08, 0x00, 0x00, 0x00, // Size
|
0x08, 0x00, 0x00, 0x00, // Size
|
||||||
|
@ -45,14 +46,15 @@ static mut MM: MemoryMap = MemoryMap {
|
||||||
sections: &[],
|
sections: &[],
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut FBI: aphrodite::arch::egatext::FramebufferInfo = aphrodite::arch::egatext::FramebufferInfo {
|
static mut FBI: aphrodite::arch::egatext::FramebufferInfo =
|
||||||
|
aphrodite::arch::egatext::FramebufferInfo {
|
||||||
address: 0,
|
address: 0,
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
bpp: 0,
|
bpp: 0,
|
||||||
change_cursor: false,
|
change_cursor: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The magic number in eax. 0x36D76289 for multiboot2.
|
// The magic number in eax. 0x36D76289 for multiboot2.
|
||||||
static mut MAGIC: u32 = 0xFFFFFFFF;
|
static mut MAGIC: u32 = 0xFFFFFFFF;
|
||||||
|
@ -61,7 +63,8 @@ static mut MAGIC: u32 = 0xFFFFFFFF;
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
#[aphrodite_proc_macros::kernel_item(ArchBootEntry)]
|
#[aphrodite_proc_macros::kernel_item(ArchBootEntry)]
|
||||||
extern "C" fn _start() -> ! {
|
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.
|
// 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)
|
// (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.
|
// 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 {
|
unsafe {
|
||||||
match MAGIC {
|
match MAGIC {
|
||||||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
#[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*
|
RT = O as *const RootTag; // This is unsafe rust! We can do whatever we want! *manical laughter*
|
||||||
|
|
||||||
sdebugs("Total boot info length is ");
|
sdebugs("Total boot info length is ");
|
||||||
|
@ -92,11 +96,12 @@ extern "C" fn _start() -> ! {
|
||||||
sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
|
sdebugbnp(&aphrodite::usize_as_u8_slice(O as usize));
|
||||||
sdebugunp(b'\n');
|
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")
|
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');
|
sdebugunp(b'\n');
|
||||||
|
|
||||||
|
@ -116,24 +121,32 @@ extern "C" fn _start() -> ! {
|
||||||
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
|
sdebugbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_len));
|
||||||
|
|
||||||
match current_tag.tag_type {
|
match current_tag.tag_type {
|
||||||
0 => { // Ending tag
|
0 => {
|
||||||
if current_tag.tag_len != 8 { // Unexpected size, something is probably up
|
// Ending tag
|
||||||
|
if current_tag.tag_len != 8 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of ending tag != 8");
|
panic!("size of ending tag != 8");
|
||||||
}
|
}
|
||||||
break
|
break;
|
||||||
},
|
}
|
||||||
4 => { // Basic memory information
|
4 => {
|
||||||
if current_tag.tag_len != 16 { // Unexpected size, something is probably up
|
// Basic memory information
|
||||||
|
if current_tag.tag_len != 16 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of basic memory information tag != 16");
|
panic!("size of basic memory information tag != 16");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
5 => { // BIOS boot device, ignore
|
5 => {
|
||||||
if current_tag.tag_len != 20 { // Unexpected size, something is probably up
|
// BIOS boot device, ignore
|
||||||
|
if current_tag.tag_len != 20 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of bios boot device tag != 20");
|
panic!("size of bios boot device tag != 20");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
1 => { // Command line
|
1 => {
|
||||||
if current_tag.tag_len < 8 { // Unexpected size, something is probably up
|
// Command line
|
||||||
|
if current_tag.tag_len < 8 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of command line tag < 8");
|
panic!("size of command line tag < 8");
|
||||||
}
|
}
|
||||||
let cstring = CStr::from_ptr((ptr + 8) as *const i8);
|
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());
|
BI.cmdline = Some(cstring.to_str().unwrap());
|
||||||
// ...before the BootInfo's commandline is set.
|
// ...before the BootInfo's commandline is set.
|
||||||
},
|
}
|
||||||
6 => { // Memory map tag
|
6 => {
|
||||||
if current_tag.tag_len < 16 { // Unexpected size, something is probably up
|
// Memory map tag
|
||||||
|
if current_tag.tag_len < 16 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of memory map tag < 16");
|
panic!("size of memory map tag < 16");
|
||||||
}
|
}
|
||||||
let rawmemorymap: *mut RawMemoryMap = core::ptr::from_raw_parts_mut(
|
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
|
// 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
|
// and has all of the [aphrodite::multiboot2::MemorySection]s for the memory map
|
||||||
|
@ -169,12 +185,14 @@ extern "C" fn _start() -> ! {
|
||||||
size_pages: 1,
|
size_pages: 1,
|
||||||
page_size: MM.mem_size(),
|
page_size: MM.mem_size(),
|
||||||
sections: MM.sections,
|
sections: MM.sections,
|
||||||
idx: 0
|
idx: 0,
|
||||||
};
|
};
|
||||||
BI.memory_map = Some(mm2);
|
BI.memory_map = Some(mm2);
|
||||||
},
|
}
|
||||||
2 => { // Bootloader name
|
2 => {
|
||||||
if current_tag.tag_len < 8 { // Unexpected size, something is probably up
|
// Bootloader name
|
||||||
|
if current_tag.tag_len < 8 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of command line tag < 8");
|
panic!("size of command line tag < 8");
|
||||||
}
|
}
|
||||||
let cstring = CStr::from_ptr((ptr + 8) as *const i8);
|
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());
|
BI.bootloader_name = Some(cstring.to_str().unwrap());
|
||||||
// ...before the BootInfo's bootloader_name is set.
|
// ...before the BootInfo's bootloader_name is set.
|
||||||
},
|
}
|
||||||
8 => { // Framebuffer info
|
8 => {
|
||||||
if current_tag.tag_len < 32 { // Unexpected size, something is probably up
|
// Framebuffer info
|
||||||
|
if current_tag.tag_len < 32 {
|
||||||
|
// Unexpected size, something is probably up
|
||||||
panic!("size of framebuffer info tag < 32");
|
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 {
|
match (*framebufferinfo).fb_type {
|
||||||
0 => { // Indexed
|
0 => {
|
||||||
|
// Indexed
|
||||||
panic!("Indexed color is unimplemented");
|
panic!("Indexed color is unimplemented");
|
||||||
},
|
}
|
||||||
1 => { // RGB
|
1 => {
|
||||||
|
// RGB
|
||||||
panic!("RGB color is unimplemented");
|
panic!("RGB color is unimplemented");
|
||||||
},
|
}
|
||||||
2 => { // EGA Text
|
2 => { // EGA Text
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unknown color info type")
|
panic!("unknown color info type")
|
||||||
}
|
}
|
||||||
|
@ -212,15 +235,16 @@ extern "C" fn _start() -> ! {
|
||||||
change_cursor: false,
|
change_cursor: false,
|
||||||
};
|
};
|
||||||
BI.output = Some(&FBI)
|
BI.output = Some(&FBI)
|
||||||
},
|
}
|
||||||
_ => { // Unknown/unimplemented tag type, ignore
|
_ => {
|
||||||
|
// Unknown/unimplemented tag type, ignore
|
||||||
swarnings("Unknown tag type ");
|
swarnings("Unknown tag type ");
|
||||||
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
swarningbnpln(&aphrodite::u32_as_u8_slice(current_tag.tag_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sinfounp(b'\n');
|
sinfounp(b'\n');
|
||||||
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
|
||||||
if ptr>end_addr {
|
if ptr > end_addr {
|
||||||
cfg_match! {
|
cfg_match! {
|
||||||
all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
|
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");
|
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);
|
current_tag = core::ptr::read_volatile(ptr as *const Tag);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => { // Unknown bootloader, panic
|
_ => {
|
||||||
|
// Unknown bootloader, panic
|
||||||
panic!("unknown bootloader");
|
panic!("unknown bootloader");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +286,9 @@ extern "C" fn _start() -> ! {
|
||||||
sdebugs("Framebuffer pitch: ");
|
sdebugs("Framebuffer pitch: ");
|
||||||
sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.pitch));
|
sdebugbnpln(&aphrodite::u32_as_u8_slice(framebuffer_info.pitch));
|
||||||
sdebugs("Framebuffer address: ");
|
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: ");
|
sdebugs("Framebuffer bpp: ");
|
||||||
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
|
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
|
||||||
|
|
||||||
|
@ -293,8 +320,9 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
|
||||||
sfatalsnp(":");
|
sfatalsnp(":");
|
||||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
||||||
sfatalsnp(":");
|
sfatalsnp(":");
|
||||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
|
sfatalbnpln(&aphrodite::u32_as_u8_slice(
|
||||||
sfatalsnp(": ");
|
info.location().unwrap().column(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
sfatals("Panic: ");
|
sfatals("Panic: ");
|
||||||
}
|
}
|
||||||
|
@ -308,7 +336,7 @@ fn halt_on_panic(info: &PanicInfo) -> ! {
|
||||||
|
|
||||||
#[unsafe(link_section = ".panic")]
|
#[unsafe(link_section = ".panic")]
|
||||||
#[panic_handler]
|
#[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) -> ! {
|
fn spin_on_panic(info: &PanicInfo) -> ! {
|
||||||
if info.location().is_some() {
|
if info.location().is_some() {
|
||||||
sfatals("Panic at ");
|
sfatals("Panic at ");
|
||||||
|
@ -316,7 +344,9 @@ fn spin_on_panic(info: &PanicInfo) -> ! {
|
||||||
sfatalsnp(":");
|
sfatalsnp(":");
|
||||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().line()));
|
||||||
sfatalsnp(":");
|
sfatalsnp(":");
|
||||||
sfatalbnp(&aphrodite::u32_as_u8_slice(info.location().unwrap().column()));
|
sfatalbnp(&aphrodite::u32_as_u8_slice(
|
||||||
|
info.location().unwrap().column(),
|
||||||
|
));
|
||||||
sfatalsnp(": ");
|
sfatalsnp(": ");
|
||||||
} else {
|
} else {
|
||||||
sfatals("Panic: ");
|
sfatals("Panic: ");
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//! actual architecture, of course):
|
//! actual architecture, of course):
|
||||||
//! #![cfg(any(target_arch = "arch"))]
|
//! #![cfg(any(target_arch = "arch"))]
|
||||||
|
|
||||||
|
/// Returns the most specific architecture available.
|
||||||
pub const fn get_arch() -> super::Architecture {
|
pub const fn get_arch() -> super::Architecture {
|
||||||
super::Architecture::ExampleDummy
|
super::Architecture::ExampleDummy
|
||||||
}
|
}
|
||||||
|
@ -28,15 +29,11 @@ pub mod interrupts {
|
||||||
|
|
||||||
/// Enables interrupts.
|
/// Enables interrupts.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsEnable)]
|
||||||
fn enable_interrupts() {
|
fn enable_interrupts() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Disables interrupts.
|
/// Disables interrupts.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||||
fn disable_interrupts() {
|
fn disable_interrupts() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Disables interrupts and a value that can be used to restore them
|
/// Disables interrupts and a value that can be used to restore them
|
||||||
/// with [restore_irq].
|
/// with [restore_irq].
|
||||||
|
@ -47,21 +44,17 @@ pub mod interrupts {
|
||||||
|
|
||||||
/// Restores interrupts after a [pop_irq] call.
|
/// Restores interrupts after a [pop_irq] call.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsRestore)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsRestore)]
|
||||||
fn restore_irq(irq: u64) {
|
fn restore_irq(_irq: u64) {}
|
||||||
irq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Activates an IDT.
|
/// Activates an IDT.
|
||||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||||
fn activate_idt(idt: Idt) {
|
fn activate_idt(_idt: Idt) {}
|
||||||
idt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An IDT.
|
/// An IDT.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Idt {
|
pub struct Idt {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn ()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +63,7 @@ pub mod interrupts {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct IdtBuilder {
|
pub struct IdtBuilder {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn ()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +88,7 @@ pub mod interrupts {
|
||||||
Idt {
|
Idt {
|
||||||
vectors: self.vectors,
|
vectors: self.vectors,
|
||||||
funcs: self.funcs,
|
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
|
//! LOT of output functions must be implemented. Using macros to
|
||||||
//! implement these is HIGHLY recommended.
|
//! 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
|
|
||||||
}
|
|
|
@ -2,8 +2,8 @@
|
||||||
//!
|
//!
|
||||||
//! See [example_impl] for everything that has to be implemented by an architecture module.
|
//! See [example_impl] for everything that has to be implemented by an architecture module.
|
||||||
|
|
||||||
mod x86;
|
|
||||||
pub mod example_impl;
|
pub mod example_impl;
|
||||||
|
mod x86;
|
||||||
|
|
||||||
pub use x86::*;
|
pub use x86::*;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,12 @@ impl core::fmt::Write for FramebufferInfo {
|
||||||
|
|
||||||
impl crate::display::TextDisplay for FramebufferInfo {
|
impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
/// Writes a character to the screen.
|
/// 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;
|
let mut clr = color.0;
|
||||||
if color.1 {
|
if color.1 {
|
||||||
match clr {
|
match clr {
|
||||||
|
@ -44,18 +49,18 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let color = clr;
|
let color = clr;
|
||||||
if pos.0>self.width {
|
if pos.0 > self.width {
|
||||||
return Err(crate::Error::new("Invalid X position", ERR_INVALID_X));
|
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));
|
return Err(crate::Error::new("Invalid Y position", ERR_INVALID_Y));
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut addr = self.address as usize;
|
let mut addr = self.address as usize;
|
||||||
addr += (pos.1*self.pitch) as usize;
|
addr += (pos.1 * self.pitch) as usize;
|
||||||
addr += (pos.0*(self.bpp as u32/8)) as usize;
|
addr += (pos.0 * (self.bpp as u32 / 8)) as usize;
|
||||||
let base_ptr = addr as *mut u16;
|
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;
|
pos.1 += 1;
|
||||||
if self.change_cursor {
|
if self.change_cursor {
|
||||||
|
@ -69,7 +74,6 @@ impl crate::display::TextDisplay for FramebufferInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FramebufferInfo {
|
impl FramebufferInfo {
|
||||||
|
|
||||||
/// Disables the cursor.
|
/// Disables the cursor.
|
||||||
pub fn disable_cursor(self) {
|
pub fn disable_cursor(self) {
|
||||||
super::ports::outb(0x3D4, 0x0A);
|
super::ports::outb(0x3D4, 0x0A);
|
||||||
|
|
|
@ -5,15 +5,18 @@ use core::alloc::Layout;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
/// Writes a series of GDT entries to an allocated section of memory and returns a pointer.
|
/// 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>> {
|
pub unsafe fn write_gdt_entries(
|
||||||
let mut mem = unsafe { alloc::alloc::alloc(Layout::from_size_align(8*entries.len(), 1).unwrap()) };
|
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 {
|
for ele in &entries {
|
||||||
let ele: &GDTEntry = ele;
|
let ele: &GDTEntry = ele;
|
||||||
unsafe { ele.write_to_addr(mem as *mut ())? }
|
unsafe { ele.write_to_addr(mem as *mut ())? }
|
||||||
mem = (mem as usize + 8) as *mut u8;
|
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.
|
/// A GDT entry.
|
||||||
|
@ -35,7 +38,10 @@ const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
||||||
impl GDTEntry {
|
impl GDTEntry {
|
||||||
const unsafe fn write_to_addr(self, ptr: *mut ()) -> Result<(), crate::Error<'static>> {
|
const unsafe fn write_to_addr(self, ptr: *mut ()) -> Result<(), crate::Error<'static>> {
|
||||||
if self.limit > 0xFFFFF {
|
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();
|
let mut serialized = (0u64).to_ne_bytes();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
#![cfg(any(target_arch = "x86"))]
|
#![cfg(any(target_arch = "x86"))]
|
||||||
#![allow(static_mut_refs)]
|
#![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.
|
/// The syscall vector.
|
||||||
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
pub const USER_SYSCALL_VECTOR: u16 = 0xA0;
|
||||||
|
@ -23,9 +27,7 @@ pub fn interrupts_enabled() -> bool {
|
||||||
/// Disables interrupts.
|
/// Disables interrupts.
|
||||||
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
#[aphrodite_proc_macros::kernel_item(InterruptsDisable)]
|
||||||
pub fn disable_interrupts() {
|
pub fn disable_interrupts() {
|
||||||
unsafe {
|
unsafe { asm!("cli") }
|
||||||
asm!("cli")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
|
/// PoppedInterrupts implements drop and restores the interrupts upon being dropped.
|
||||||
|
@ -62,9 +64,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
|
||||||
asm!(
|
asm!(
|
||||||
"push {0:e}", in(reg) flags
|
"push {0:e}", in(reg) flags
|
||||||
);
|
);
|
||||||
asm!(
|
asm!("popf");
|
||||||
"popf"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ pub fn restore_irq(flags: PoppedInterrupts) {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct IDTR {
|
struct IDTR {
|
||||||
base: *const u8,
|
base: *const u8,
|
||||||
size: usize
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for IDTR {}
|
unsafe impl Send for IDTR {}
|
||||||
|
@ -83,45 +83,45 @@ unsafe impl Sync for IDTR {}
|
||||||
fn load_idt(base: *const u8, size: usize) {
|
fn load_idt(base: *const u8, size: usize) {
|
||||||
static mut IDTR: MaybeUninit<IDTR> = MaybeUninit::uninit();
|
static mut IDTR: MaybeUninit<IDTR> = MaybeUninit::uninit();
|
||||||
unsafe {
|
unsafe {
|
||||||
IDTR.write(IDTR {
|
IDTR.write(IDTR { base, size });
|
||||||
base,
|
|
||||||
size
|
|
||||||
});
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
asm!("lidt {}", in(reg) IDTR.as_ptr() as usize)
|
|
||||||
}
|
}
|
||||||
|
unsafe { asm!("lidt {}", in(reg) IDTR.as_ptr() as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Activate an IDT.
|
/// Activate an IDT.
|
||||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||||
fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
|
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 {
|
for i in 0..idt.len {
|
||||||
let vector = idt.vectors[i];
|
let _vector = idt.vectors[i];
|
||||||
let func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
let _func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
||||||
let user_callable = idt.user_callable[i];
|
let _user_callable = idt.user_callable[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An Interrupt Descriptor Table.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Idt {
|
pub struct Idt {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn ()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
user_callable: [bool; 256],
|
user_callable: [bool; 256],
|
||||||
len: usize,
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A builder of an [Idt].
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct IdtBuilder {
|
pub struct IdtBuilder {
|
||||||
vectors: [u16; 256],
|
vectors: [u16; 256],
|
||||||
funcs: [MaybeUninit<fn ()>; 256],
|
funcs: [MaybeUninit<fn()>; 256],
|
||||||
user_callable: [bool; 256],
|
user_callable: [bool; 256],
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdtBuilder {
|
impl IdtBuilder {
|
||||||
|
/// Create a new IdtBuilder.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
IdtBuilder {
|
IdtBuilder {
|
||||||
vectors: [0; 256],
|
vectors: [0; 256],
|
||||||
|
@ -130,6 +130,7 @@ impl IdtBuilder {
|
||||||
idx: 0,
|
idx: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Add a function to this IdtBuilder.
|
||||||
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
|
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
|
||||||
self.vectors[self.idx] = vector;
|
self.vectors[self.idx] = vector;
|
||||||
self.funcs[self.idx].write(func);
|
self.funcs[self.idx].write(func);
|
||||||
|
@ -137,12 +138,13 @@ impl IdtBuilder {
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
/// Finish creating this IdtBuilder and return an [Idt].
|
||||||
pub fn finish(&self) -> Idt {
|
pub fn finish(&self) -> Idt {
|
||||||
Idt {
|
Idt {
|
||||||
vectors: self.vectors,
|
vectors: self.vectors,
|
||||||
funcs: self.funcs,
|
funcs: self.funcs,
|
||||||
user_callable: self.user_callable,
|
user_callable: self.user_callable,
|
||||||
len: self.idx
|
len: self.idx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,8 +6,9 @@ use alloc::{vec, vec::Vec};
|
||||||
|
|
||||||
use crate::memsections::*;
|
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 {
|
pub struct MemorySections {
|
||||||
sections: Vec<MemorySection>,
|
sections: Vec<MemorySection>,
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,7 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
||||||
|
|
||||||
let gdtr = GDTR {
|
let gdtr = GDTR {
|
||||||
address: ptr as *const u8 as usize as u32,
|
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;
|
let addr = &gdtr as *const GDTR as *const () as usize as u32;
|
||||||
|
@ -124,10 +125,10 @@ unsafe impl crate::memsections::MemorySections for MemorySections {
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.access & 0b11000 == 0b11000 && !code_set {
|
if entry.access & 0b11000 == 0b11000 && !code_set {
|
||||||
code_segment = i-1;
|
code_segment = i - 1;
|
||||||
code_set = true;
|
code_set = true;
|
||||||
} else if entry.access & 0b10000 == 0b10000 && !data_set {
|
} else if entry.access & 0b10000 == 0b10000 && !data_set {
|
||||||
data_segment = i-1;
|
data_segment = i - 1;
|
||||||
data_set = true;
|
data_set = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,16 +157,19 @@ pub struct MemorySectionBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemorySectionBuilder {
|
impl MemorySectionBuilder {
|
||||||
|
/// Create a new MemorySectionBuilder.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
MemorySectionBuilder { sections: vec![] }
|
MemorySectionBuilder { sections: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a section to this MemorySectionBuilder.
|
||||||
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
pub fn add_section(&mut self, section: MemorySection) -> &mut Self {
|
||||||
self.sections.push(section);
|
self.sections.push(section);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finishes this MemorySectionBuilder and returns a MemorySections.
|
||||||
pub fn finish(self) -> MemorySections {
|
pub fn finish(self) -> MemorySections {
|
||||||
MemorySections {
|
MemorySections {
|
||||||
sections: self.sections,
|
sections: self.sections,
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
pub mod interrupts;
|
|
||||||
pub mod ports;
|
|
||||||
pub mod output;
|
|
||||||
pub mod egatext;
|
pub mod egatext;
|
||||||
pub mod paging;
|
|
||||||
mod gdt;
|
mod gdt;
|
||||||
|
pub mod interrupts;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
pub mod output;
|
||||||
|
pub mod paging;
|
||||||
|
pub mod ports;
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
|
|
||||||
|
@ -17,15 +17,11 @@ pub(self) use constants::*;
|
||||||
use interrupts::{pop_irq, restore_irq};
|
use interrupts::{pop_irq, restore_irq};
|
||||||
use ports::{inb, outb};
|
use ports::{inb, outb};
|
||||||
|
|
||||||
|
/// Returns the most specific architecture available.
|
||||||
pub const fn get_arch() -> super::Architecture {
|
pub const fn get_arch() -> super::Architecture {
|
||||||
super::Architecture::X86
|
super::Architecture::X86
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aphrodite_proc_macros::kernel_item(PagingAvailabe)]
|
|
||||||
pub fn paging_available() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns information from the CPUID command in the form
|
/// Returns information from the CPUID command in the form
|
||||||
/// (ebx, edx, ecx).
|
/// (ebx, edx, ecx).
|
||||||
pub fn cpuid(id: u32) -> (u32, u32, u32) {
|
pub fn cpuid(id: u32) -> (u32, u32, u32) {
|
||||||
|
@ -70,12 +66,12 @@ pub fn test_a20() -> bool {
|
||||||
|
|
||||||
/// Waits for a keyboard command to complete.
|
/// Waits for a keyboard command to complete.
|
||||||
pub fn wait_for_keyboard_cmd() {
|
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.
|
/// Waits for there to be data to read from the keyboard.
|
||||||
pub fn wait_for_keyboard_data() {
|
pub fn wait_for_keyboard_data() {
|
||||||
while inb(0x64)&0b1 == 0 {}
|
while inb(0x64) & 0b1 == 0 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a keyboard command.
|
/// Sends a keyboard command.
|
||||||
|
@ -111,7 +107,7 @@ pub fn enable_a20_keyboard() {
|
||||||
send_keyboard_cmd(0xD1); // write to output
|
send_keyboard_cmd(0xD1); // write to output
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
wait_for_keyboard_cmd();
|
||||||
send_keyboard_data(a|2);
|
send_keyboard_data(a | 2);
|
||||||
|
|
||||||
wait_for_keyboard_cmd();
|
wait_for_keyboard_cmd();
|
||||||
send_keyboard_cmd(0xAE); // enable keyboard
|
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.
|
/// Note that this may not work or do something unexpected.
|
||||||
pub fn enable_a20_fasta20() {
|
pub fn enable_a20_fasta20() {
|
||||||
let mut a = inb(0x92);
|
let mut a = inb(0x92);
|
||||||
if a&0b10 > 0 {
|
if a & 0b10 > 0 {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
a |= 0b10;
|
a |= 0b10;
|
||||||
a &= 0xFE;
|
a &= 0xFE;
|
||||||
|
@ -145,7 +141,7 @@ pub fn enable_a20() -> bool {
|
||||||
|
|
||||||
enable_a20_keyboard();
|
enable_a20_keyboard();
|
||||||
let mut i = 0u32;
|
let mut i = 0u32;
|
||||||
while (!test_a20()) && i<10000 {
|
while (!test_a20()) && i < 10000 {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +151,7 @@ pub fn enable_a20() -> bool {
|
||||||
|
|
||||||
enable_a20_ee_port();
|
enable_a20_ee_port();
|
||||||
let mut i = 0u32;
|
let mut i = 0u32;
|
||||||
while (!test_a20()) && i<10000 {
|
while (!test_a20()) && i < 10000 {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +161,7 @@ pub fn enable_a20() -> bool {
|
||||||
|
|
||||||
enable_a20_fasta20();
|
enable_a20_fasta20();
|
||||||
let mut i = 0u32;
|
let mut i = 0u32;
|
||||||
while (!test_a20()) && i<10000 {
|
while (!test_a20()) && i < 10000 {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ macro_rules! message_funcs {
|
||||||
ports::outb(super::DEBUG_PORT, s);
|
ports::outb(super::DEBUG_PORT, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
message_funcs!(debug, "[DEBUG] ", CONFIG_PREUSER_OUTPUT_DEBUG);
|
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!(error, "[ERROR] ", CONFIG_PREUSER_OUTPUT_ERROR);
|
||||||
message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
|
message_funcs!(fatal, "[FATAL] ", CONFIG_PREUSER_OUTPUT_FATAL);
|
||||||
message_funcs!(output, "", NONE);
|
message_funcs!(output, "", NONE);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,11 @@ use core::arch::asm;
|
||||||
|
|
||||||
use aphrodite_proc_macros::kernel_item;
|
use aphrodite_proc_macros::kernel_item;
|
||||||
|
|
||||||
|
/// One page directory entry. Use [PageDirectoryEntry::create_fourmb] or [PageDirectoryEntry::create_other] to make these.
|
||||||
pub enum PageDirectoryEntry {
|
pub enum PageDirectoryEntry {
|
||||||
|
/// A four megabyte page.
|
||||||
FourMb(u32),
|
FourMb(u32),
|
||||||
|
/// A smaller page.
|
||||||
Other(u32),
|
Other(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,11 +117,9 @@ impl PageDirectoryEntry {
|
||||||
static mut PAGE_DIRECTORY: PageDirectoryEntry =
|
static mut PAGE_DIRECTORY: PageDirectoryEntry =
|
||||||
PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false);
|
PageDirectoryEntry::create_other(0, false, 0, false, false, false, false, false, false, false);
|
||||||
|
|
||||||
|
/// Initalize paging.
|
||||||
#[kernel_item(PagingInit)]
|
#[kernel_item(PagingInit)]
|
||||||
pub fn initalize_paging() {
|
pub fn initalize_paging() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Disables paging by clearing bit 31 in the cr0 register.
|
/// Disables paging by clearing bit 31 in the cr0 register.
|
||||||
#[kernel_item(PagingDeinit)]
|
#[kernel_item(PagingDeinit)]
|
||||||
|
|
|
@ -41,8 +41,7 @@ impl MemoryType {
|
||||||
} else {
|
} else {
|
||||||
crate::arch::output::sdebugsnp(", unallocatable");
|
crate::arch::output::sdebugsnp(", unallocatable");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
|
||||||
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
MemoryType::Kernel => crate::arch::output::sdebugsnp("Kernel loaded"),
|
||||||
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
MemoryType::Permanent => crate::arch::output::sdebugsnp("Flash"),
|
||||||
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
MemoryType::Reserved => crate::arch::output::sdebugsnp("Reserved"),
|
||||||
|
|
|
@ -19,14 +19,14 @@ pub struct Argument {
|
||||||
/// The name of an argument.
|
/// The name of an argument.
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
/// The value of an argument.
|
/// The value of an argument.
|
||||||
pub value: ArgumentValue
|
pub value: ArgumentValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single flag in a [Cmdline].
|
/// A single flag in a [Cmdline].
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
/// The name of a flag.
|
/// The name of a flag.
|
||||||
pub name: &'static str
|
pub name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A kernel command line.
|
/// A kernel command line.
|
||||||
|
@ -83,7 +83,10 @@ impl Validator for CmdlineValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !correct {
|
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,7 +99,10 @@ impl Validator for CmdlineValidator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !correct {
|
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(())
|
Ok(())
|
||||||
|
|
|
@ -18,7 +18,12 @@ pub const COLOR_DEFAULT: Color = (1, true);
|
||||||
/// Some form of display that can be written to with text.
|
/// Some form of display that can be written to with text.
|
||||||
pub trait TextDisplay: core::fmt::Write {
|
pub trait TextDisplay: core::fmt::Write {
|
||||||
/// Writes a single character to the specified position.
|
/// 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.
|
/// Gets the size of the screen.
|
||||||
fn get_size(&self) -> (u32, u32);
|
fn get_size(&self) -> (u32, u32);
|
||||||
}
|
}
|
||||||
|
@ -35,16 +40,21 @@ impl dyn TextDisplay + '_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a &str to the screen.
|
/// 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 (width, _) = self.get_size();
|
||||||
let (mut x, mut y) = pos;
|
let (mut x, mut y) = pos;
|
||||||
for char in str.as_bytes() {
|
for char in str.as_bytes() {
|
||||||
self.write_char((x, y), *char, color)?;
|
self.write_char((x, y), *char, color)?;
|
||||||
if *char == 0 {
|
if *char == 0 {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
x += 1;
|
x += 1;
|
||||||
while x>width {
|
while x > width {
|
||||||
x -= width;
|
x -= width;
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
@ -53,16 +63,21 @@ impl dyn TextDisplay + '_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a &\[u8] to the screen.
|
/// 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 (width, _) = self.get_size();
|
||||||
let (mut x, mut y) = pos;
|
let (mut x, mut y) = pos;
|
||||||
for char in str {
|
for char in str {
|
||||||
self.write_char((x, y), *char, color)?;
|
self.write_char((x, y), *char, color)?;
|
||||||
if *char == 0 {
|
if *char == 0 {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
x += 1;
|
x += 1;
|
||||||
while x>width {
|
while x > width {
|
||||||
x -= width;
|
x -= width;
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +91,7 @@ pub struct NoneTextDisplay {}
|
||||||
|
|
||||||
impl TextDisplay for NoneTextDisplay {
|
impl TextDisplay for NoneTextDisplay {
|
||||||
fn get_size(&self) -> (u32, u32) {
|
fn get_size(&self) -> (u32, u32) {
|
||||||
(1,1)
|
(1, 1)
|
||||||
}
|
}
|
||||||
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
fn write_char(&self, _: (u32, u32), _: u8, _: Color) -> Result<(), crate::Error<'static>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::display::TextDisplay;
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Error<'a> {
|
pub struct Error<'a> {
|
||||||
message: &'a str,
|
message: &'a str,
|
||||||
code: i16
|
code: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Error<'a> {
|
impl<'a> Error<'a> {
|
||||||
|
@ -17,7 +17,7 @@ impl<'a> Error<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error<'_> {
|
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) {
|
pub fn display_np(&self, display: &dyn TextDisplay) {
|
||||||
crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display).unwrap();
|
crate::output::terrorbnp(&crate::i16_as_u8_slice(self.code), display).unwrap();
|
||||||
crate::output::terrorsnp(": ", display).unwrap();
|
crate::output::terrorsnp(": ", display).unwrap();
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
use core::alloc::{Allocator, Layout};
|
use core::alloc::{Allocator, Layout};
|
||||||
|
|
||||||
use crate::{display::{NoneTextDisplay, COLOR_DEFAULT}, output::*};
|
use crate::{
|
||||||
|
display::{COLOR_DEFAULT, NoneTextDisplay},
|
||||||
|
output::*,
|
||||||
|
};
|
||||||
|
|
||||||
use aphrodite_proc_macros::*;
|
use aphrodite_proc_macros::*;
|
||||||
|
|
||||||
|
@ -17,7 +20,10 @@ fn indep_boot_entry(
|
||||||
display: Option<&dyn crate::display::TextDisplay>,
|
display: Option<&dyn crate::display::TextDisplay>,
|
||||||
#[allow(non_snake_case)] BI: &crate::boot::BootInfo,
|
#[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");
|
crate::arch::output::sdebugsln("IndepBootEntry called");
|
||||||
|
|
||||||
let display = display.unwrap_or(&NoneTextDisplay {});
|
let display = display.unwrap_or(&NoneTextDisplay {});
|
||||||
|
@ -64,6 +70,8 @@ fn indep_boot_entry(
|
||||||
terrors("Failed to deallocate: ", display).unwrap();
|
terrors("Failed to deallocate: ", display).unwrap();
|
||||||
err.display_np(display);
|
err.display_np(display);
|
||||||
panic!("Deallocation failure");
|
panic!("Deallocation failure");
|
||||||
|
} else {
|
||||||
|
tdebugsln("Successfully deallocated!", display).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tdebugsln("", display).unwrap();
|
tdebugsln("", display).unwrap();
|
||||||
|
|
|
@ -48,8 +48,6 @@ struct AllocationIter {
|
||||||
impl Iterator for AllocationIter {
|
impl Iterator for AllocationIter {
|
||||||
type Item = *mut Allocation;
|
type Item = *mut Allocation;
|
||||||
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
|
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;
|
self.idx += 1;
|
||||||
if self.idx > self.num_allocations {
|
if self.idx > self.num_allocations {
|
||||||
return None;
|
return None;
|
||||||
|
@ -139,7 +137,11 @@ impl<'a> Debug for MemoryMapAlloc<'a> {
|
||||||
|
|
||||||
impl<'a> MemoryMapAlloc<'a> {
|
impl<'a> MemoryMapAlloc<'a> {
|
||||||
/// Creates a new [MemoryMapAlloc]. Please call this method instead of creating it manually!
|
/// 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(
|
pub fn new(
|
||||||
memory_map: &'a mut crate::boot::MemoryMap,
|
memory_map: &'a mut crate::boot::MemoryMap,
|
||||||
) -> Result<MemoryMapAlloc<'a>, crate::Error<'a>> {
|
) -> 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.
|
/// 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>> {
|
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() {
|
for alloc in self.allocations_iter() {
|
||||||
if !unsafe { *alloc }.used {
|
if !unsafe { *alloc }.used {
|
||||||
unsafe { (*alloc) = allocation }
|
unsafe { (*alloc) = allocation }
|
||||||
|
@ -355,7 +360,7 @@ pub const MAYBE_MEMORY_MAP_ALLOC_UNINITALIZED: i16 = -8;
|
||||||
|
|
||||||
struct MaybeMemoryMapAlloc<'a> {
|
struct MaybeMemoryMapAlloc<'a> {
|
||||||
alloc: MaybeUninit<MemoryMapAlloc<'a>>,
|
alloc: MaybeUninit<MemoryMapAlloc<'a>>,
|
||||||
initalized: bool
|
initalized: bool,
|
||||||
}
|
}
|
||||||
impl<'a> MaybeMemoryMapAlloc<'a> {
|
impl<'a> MaybeMemoryMapAlloc<'a> {
|
||||||
const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self {
|
const fn new(alloc: Option<MemoryMapAlloc<'a>>) -> Self {
|
||||||
|
@ -363,7 +368,7 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
|
||||||
return MaybeMemoryMapAlloc {
|
return MaybeMemoryMapAlloc {
|
||||||
alloc: MaybeUninit::uninit(),
|
alloc: MaybeUninit::uninit(),
|
||||||
initalized: false,
|
initalized: false,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
MaybeMemoryMapAlloc {
|
MaybeMemoryMapAlloc {
|
||||||
alloc: MaybeUninit::new(alloc.unwrap()),
|
alloc: MaybeUninit::new(alloc.unwrap()),
|
||||||
|
@ -385,7 +390,9 @@ impl<'a> MaybeMemoryMapAlloc<'a> {
|
||||||
if !self.initalized {
|
if !self.initalized {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsafe { self.alloc.assume_init_drop(); }
|
unsafe {
|
||||||
|
self.alloc.assume_init_drop();
|
||||||
|
}
|
||||||
self.initalized = false;
|
self.initalized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,7 +425,10 @@ unsafe impl<'a> GlobalAlloc for MaybeMemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'a> Allocator 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 {
|
if !self.initalized {
|
||||||
unsafe {
|
unsafe {
|
||||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||||
|
@ -545,6 +555,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
crate::arch::output::sdebugsln("Searching for allocation");
|
||||||
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
|
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
|
||||||
unsafe { *self.allocationheader }.num_allocations,
|
unsafe { *self.allocationheader }.num_allocations,
|
||||||
));
|
));
|
||||||
|
@ -552,6 +563,17 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
crate::arch::output::sdebugsln("Allocation");
|
crate::arch::output::sdebugsln("Allocation");
|
||||||
let alloc = unsafe { *allocation }.clone();
|
let alloc = unsafe { *allocation }.clone();
|
||||||
if !alloc.used {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
crate::arch::output::sdebugsln("Used");
|
crate::arch::output::sdebugsln("Used");
|
||||||
|
@ -560,6 +582,7 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
|
||||||
return;
|
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
|
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
|
||||||
unsafe {
|
unsafe {
|
||||||
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
LAST_MEMMAP_ERR = Err(crate::Error::new(
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub enum SectionType {
|
||||||
CodeSection {
|
CodeSection {
|
||||||
/// Whether more powerful owners can jump to this if the owner
|
/// Whether more powerful owners can jump to this if the owner
|
||||||
/// is less powerful.
|
/// 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.
|
/// A data section. Generally at least one of these for the kernel.
|
||||||
DataSection,
|
DataSection,
|
||||||
|
@ -21,7 +21,7 @@ pub enum SectionType {
|
||||||
/// if they aren't directly supported by the hardware.
|
/// if they aren't directly supported by the hardware.
|
||||||
TaskSection {
|
TaskSection {
|
||||||
/// Whether the section is busy.
|
/// Whether the section is busy.
|
||||||
busy: bool
|
busy: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@ pub mod display;
|
||||||
mod errors;
|
mod errors;
|
||||||
pub mod indep_boot_entry;
|
pub mod indep_boot_entry;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
|
pub mod memsections;
|
||||||
pub mod multiboot2;
|
pub mod multiboot2;
|
||||||
pub mod output;
|
pub mod output;
|
||||||
pub mod psfont;
|
pub mod psfont;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod memsections;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub(crate) mod cfg;
|
pub(crate) mod cfg;
|
||||||
|
@ -47,3 +47,11 @@ pub use util::*;
|
||||||
|
|
||||||
#[allow(unused_imports)] // if there are no traits, then it gives a warning
|
#[allow(unused_imports)] // if there are no traits, then it gives a warning
|
||||||
pub use traits::*;
|
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.
|
/// The type of the tag.
|
||||||
pub tag_type: u32,
|
pub tag_type: u32,
|
||||||
/// The length of the tag.
|
/// 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.
|
/// 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,
|
pub mod_end: *const u8,
|
||||||
/// A string that should be in the format `module_name (command line arguments)`.
|
/// A string that should be in the format `module_name (command line arguments)`.
|
||||||
/// See <https://aphrodite-os.github.io/book/bootloader-modules.html>.
|
/// 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.
|
/// One memory section provided by a Multiboot2 bootloader.
|
||||||
|
@ -58,10 +58,10 @@ impl Into<crate::boot::MemoryMapping> for MemorySection {
|
||||||
2 => crate::boot::MemoryType::HardwareReserved,
|
2 => crate::boot::MemoryType::HardwareReserved,
|
||||||
3 => crate::boot::MemoryType::HardwareSpecific(3, false),
|
3 => crate::boot::MemoryType::HardwareSpecific(3, false),
|
||||||
5 => crate::boot::MemoryType::Faulty,
|
5 => crate::boot::MemoryType::Faulty,
|
||||||
_ => crate::boot::MemoryType::Reserved
|
_ => crate::boot::MemoryType::Reserved,
|
||||||
},
|
},
|
||||||
start: self.base_addr,
|
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.
|
/// 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
|
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].
|
/// 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.
|
/// A full memory map provided by a Multiboot2 bootloader.
|
||||||
|
@ -119,7 +119,7 @@ pub struct PaletteColorDescriptor {
|
||||||
/// The green value
|
/// The green value
|
||||||
pub green: u8,
|
pub green: u8,
|
||||||
/// The blue value
|
/// The blue value
|
||||||
pub blue: u8
|
pub blue: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about color, for use in [FramebufferInfo].
|
/// Information about color, for use in [FramebufferInfo].
|
||||||
|
@ -131,7 +131,7 @@ pub enum ColorInfo {
|
||||||
/// The number of colors in the palette.
|
/// The number of colors in the palette.
|
||||||
num_colors: u32,
|
num_colors: u32,
|
||||||
/// The first color in the palette.
|
/// The first color in the palette.
|
||||||
palette: *const PaletteColorDescriptor
|
palette: *const PaletteColorDescriptor,
|
||||||
},
|
},
|
||||||
/// RGB information for use on the framebuffer.
|
/// RGB information for use on the framebuffer.
|
||||||
RGBColor {
|
RGBColor {
|
||||||
|
@ -151,7 +151,7 @@ pub enum ColorInfo {
|
||||||
blue_mask_size: u8,
|
blue_mask_size: u8,
|
||||||
},
|
},
|
||||||
/// Text information, no metadata
|
/// Text information, no metadata
|
||||||
EGAText
|
EGAText,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about the framebuffer.
|
/// Information about the framebuffer.
|
||||||
|
@ -172,7 +172,6 @@ pub struct FramebufferInfo {
|
||||||
pub fb_type: u8,
|
pub fb_type: u8,
|
||||||
/// Reserved space. Ignore.
|
/// Reserved space. Ignore.
|
||||||
reserved: u8,
|
reserved: u8,
|
||||||
|
|
||||||
// Color info after this; we need separate structs for each colorinfo as
|
// Color info after this; we need separate structs for each colorinfo as
|
||||||
// we have to understand the format the bootloader gives us.
|
// 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.
|
// 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.
|
// To ensure future developers don't get any ideas, I'm leaving it out here.
|
||||||
// If you need it, good luck.
|
// 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
|
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This should contain the original pointer provided by
|
||||||
/// the bootloader.
|
/// the bootloader.
|
||||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
/// 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
|
// 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.
|
// unnecessary, so I don't care. Sorry if you are affected by this.
|
||||||
|
|
||||||
/// The memory map provided by the bootloader.
|
/// The memory map provided by the bootloader.
|
||||||
pub memory_map: Option<MemoryMap>,
|
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.
|
// 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.
|
// VBE table is ignored for a similar reason to above: it's deprecated. Good luck if you need it.
|
||||||
|
|
||||||
/// Provides information on the framebuffer.
|
/// Provides information on the framebuffer.
|
||||||
pub framebuffer_info: Option<FramebufferInfo>,
|
pub framebuffer_info: Option<FramebufferInfo>,
|
||||||
/// Color info, stored separately from [FramebufferInfo] because rust
|
/// Color info, stored separately from [FramebufferInfo] because rust
|
||||||
pub color_info: Option<ColorInfo>,
|
pub color_info: Option<ColorInfo>,
|
||||||
|
|
||||||
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search for it ourselves.
|
// 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.
|
// 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.
|
//! Architecture-independent output functions.
|
||||||
|
|
||||||
use paste::paste;
|
|
||||||
use crate::display::COLOR_DEFAULT;
|
use crate::display::COLOR_DEFAULT;
|
||||||
|
use paste::paste;
|
||||||
|
|
||||||
/// The position to output stuff to.
|
/// The position to output stuff to.
|
||||||
static mut OUTPUT_TERM_POSITION: (u32, u32) = (0, 0);
|
static mut OUTPUT_TERM_POSITION: (u32, u32) = (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].
|
/// Parses a PC Screen Font into a [PCScreenFont].
|
||||||
pub fn parse_pc_screen_font(
|
pub fn parse_pc_screen_font(data: RawPCScreenFont) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||||
data: RawPCScreenFont,
|
|
||||||
) -> Result<PCScreenFont, crate::Error<'static>> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if data.flags == 0 {
|
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
|
let unistr = (data.glyphs.as_slice() as *const [u8])
|
||||||
.glyphs
|
|
||||||
.as_slice()
|
|
||||||
as *const [u8])
|
|
||||||
.byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize);
|
.byte_add(data.bytes_per_glyph as usize * data.num_glyphs as usize);
|
||||||
|
|
||||||
let mut i = 0usize;
|
let mut i = 0usize;
|
||||||
|
@ -136,9 +132,7 @@ pub fn parse_pc_screen_font(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a Vec<u8> into a [PCScreenFont].
|
/// Parses a Vec<u8> into a [PCScreenFont].
|
||||||
pub fn parse_psfu(
|
pub fn parse_psfu(data: Vec<u8>) -> Result<PCScreenFont, crate::Error<'static>> {
|
||||||
data: Vec<u8>,
|
|
||||||
) -> Result<PCScreenFont, crate::Error<'static>> {
|
|
||||||
let data = parse_raw_pc_screen_font(data)?;
|
let data = parse_raw_pc_screen_font(data)?;
|
||||||
parse_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;
|
i = 5;
|
||||||
while value > 0 {
|
while value > 0 {
|
||||||
let digit = value%10;
|
let digit = value % 10;
|
||||||
let char = b'0' + digit as u8;
|
let char = b'0' + digit as u8;
|
||||||
buf[i] = char;
|
buf[i] = char;
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
|
@ -30,7 +30,7 @@ pub const fn u32_as_u8_slice(mut value: u32) -> [u8; 10] {
|
||||||
buf[0] = b'0';
|
buf[0] = b'0';
|
||||||
}
|
}
|
||||||
while value > 0 {
|
while value > 0 {
|
||||||
let digit = value%10;
|
let digit = value % 10;
|
||||||
let char = b'0' + digit as u8;
|
let char = b'0' + digit as u8;
|
||||||
buf[i] = char;
|
buf[i] = char;
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
|
@ -47,7 +47,7 @@ pub const fn u8_as_u8_slice(mut value: u8) -> [u8; 3] {
|
||||||
buf[0] = b'0';
|
buf[0] = b'0';
|
||||||
}
|
}
|
||||||
while value > 0 {
|
while value > 0 {
|
||||||
let digit = value%10;
|
let digit = value % 10;
|
||||||
let char = b'0' + digit as u8;
|
let char = b'0' + digit as u8;
|
||||||
buf[i] = char;
|
buf[i] = char;
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
|
@ -64,7 +64,7 @@ pub const fn usize_as_u8_slice(mut value: usize) -> [u8; 20] {
|
||||||
buf[0] = b'0';
|
buf[0] = b'0';
|
||||||
}
|
}
|
||||||
while value > 0 {
|
while value > 0 {
|
||||||
let digit = value%10;
|
let digit = value % 10;
|
||||||
let char = b'0' + digit as u8;
|
let char = b'0' + digit as u8;
|
||||||
buf[i] = char;
|
buf[i] = char;
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
|
@ -81,7 +81,7 @@ pub const fn u64_as_u8_slice(mut value: u64) -> [u8; 20] {
|
||||||
buf[0] = b'0';
|
buf[0] = b'0';
|
||||||
}
|
}
|
||||||
while value > 0 {
|
while value > 0 {
|
||||||
let digit = value%10;
|
let digit = value % 10;
|
||||||
let char = b'0' + digit as u8;
|
let char = b'0' + digit as u8;
|
||||||
buf[i] = char;
|
buf[i] = char;
|
||||||
value = value / 10;
|
value = value / 10;
|
||||||
|
@ -103,7 +103,7 @@ pub fn str_as_i16(mut value: &[u8]) -> i16 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as i16;
|
out += (byte - b'0') as i16;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut reversed = 0;
|
let mut reversed = 0;
|
||||||
|
@ -125,7 +125,7 @@ pub fn str_as_u32(value: &[u8]) -> u32 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as u32;
|
out += (byte - b'0') as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut reversed = 0;
|
let mut reversed = 0;
|
||||||
|
@ -147,7 +147,7 @@ pub fn str_as_u128(value: &[u8]) -> u128 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as u128;
|
out += (byte - b'0') as u128;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut reversed = 0;
|
let mut reversed = 0;
|
||||||
|
@ -169,7 +169,7 @@ pub fn str_as_u64(value: &[u8]) -> u64 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out *= 10;
|
out *= 10;
|
||||||
out += (byte-b'0') as u64;
|
out += (byte - b'0') as u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut reversed = 0;
|
let mut reversed = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue