code doesnt work anymore but i'm commiting anyway, shoot me

This commit is contained in:
Jack Halford 2018-04-09 13:33:16 +02:00
parent bea6a729fe
commit a0ad3689f3
30 changed files with 725 additions and 476 deletions

View file

@ -13,12 +13,12 @@ spin = "0.4"
slab_allocator = "0.3.1"
multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag
x86 = { path = "x86" } # forked for IA32
raw-cpuid = { path = "rust-cpuid" }
# raw-cpuid = { path = "rust-cpuid" }
# [dependencies.raw-cpuid]
# # need to use github/master because of features not yet on crates.io
# git = "https://github.com/gz/rust-cpuid"
# features = ["nightly"]
[dependencies.raw-cpuid]
# need to use github/master because of features not yet on crates.io
git = "https://github.com/gz/rust-cpuid"
features = ["nightly"]
[dependencies.lazy_static]
version = "1.0.0"

View file

@ -7,7 +7,7 @@ static mut DSDT: DSDT = DSDT {
dsdt: None,
s5_ptr: 0,
slp_typ_a: 0,
slp_typ_b: 0
slp_typ_b: 0,
};
struct DSDT {
@ -15,7 +15,7 @@ struct DSDT {
dsdt: Option<&'static ACPISDTHeader>,
s5_ptr: u32,
slp_typ_a: u16,
slp_typ_b: u16
slp_typ_b: u16,
}
impl DSDT {
@ -32,7 +32,9 @@ impl DSDT {
let dsdt_end = dsdt_start + self.dsdt.unwrap().length;
for addr in dsdt_start..dsdt_end {
if check_signature(addr, "_S5_") {
if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) && check_signature(addr + 4, "\x12") {
if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\"))
&& check_signature(addr + 4, "\x12")
{
return Ok(addr);
}
}
@ -43,10 +45,18 @@ impl DSDT {
fn parse_s5(&mut self) {
let ptr = self.s5_ptr + 5;
let ptr = ((unsafe { *(ptr as *const u8) } & 0xC0) >> 6) + 2;
let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix
let ptr = if unsafe { *(ptr as *const u8) } == 0x0A {
ptr + 1
} else {
ptr
}; // Skip bytePrefix
self.slp_typ_a = (unsafe { *(ptr as *const u8) } as u16) << 10;
let ptr = ptr + 1;
let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix
let ptr = if unsafe { *(ptr as *const u8) } == 0x0A {
ptr + 1
} else {
ptr
}; // Skip bytePrefix
self.slp_typ_b = (unsafe { *(ptr as *const u8) } as u16) << 10;
}
}
@ -56,8 +66,8 @@ fn is_init() -> Result <(), &'static str> {
true => Ok(()),
false => match unsafe { DSDT.dsdt } {
Some(_) => Err("Differentiated System Description Pointer (DSDP) is not valid"),
None => Err("Differentiated System Description Pointer (DSDP) is not initialized")
}
None => Err("Differentiated System Description Pointer (DSDP) is not initialized"),
},
}
}

View file

@ -9,13 +9,12 @@ struct GenericAddressStructure {
bitoffset: u8,
accesssize: u8,
noused: u32,
address: u64
address: u64,
}
#[repr(C)]
#[derive(Debug, Clone)]
struct FADT
{
struct FADT {
header: ACPISDTHeader,
firmwarectrl: u32,
dsdt: u32,
@ -80,7 +79,6 @@ struct FADT
x_pmtimerblock: GenericAddressStructure,
x_gpe0block: GenericAddressStructure,
x_gpe1block: GenericAddressStructure,
}
static mut FADT: Option<FADT> = None;
@ -89,10 +87,12 @@ static mut FADT: Option<FADT> = None;
/// input param addr is contain in other ptr of rsdt
pub fn init(sdt_iter: ACPISDTIter) -> Result<(), &'static str> {
for sdt_ptr in sdt_iter {
if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic
if ACPISDTHeader::valid(sdt_ptr, "FACP") {
// Where is "FADT"? Shut up is magic
let fadt_tmp: FADT = unsafe { (*(sdt_ptr as *const FADT)).clone() };
unsafe { FADT = Some(fadt_tmp.clone()) };
if !is_enable()? { // TODO do i have to check if enabled before init ???
if !is_enable()? {
// TODO do i have to check if enabled before init ???
let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST
let acpi_enable = fadt_tmp.acpi_enable;
cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command
@ -106,7 +106,7 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> {
fn is_init() -> Result<FADT, &'static str> {
match unsafe { FADT.clone() } {
Some(fadt) => Ok(fadt),
None => Err("Fixed ACPI Description Table (FADT) is not initialized")
None => Err("Fixed ACPI Description Table (FADT) is not initialized"),
}
}

View file

@ -36,12 +36,12 @@ impl ACPISDTHeader {
static mut ACPI: Acpi = Acpi {
valid: false,
v2: false
v2: false,
};
struct Acpi {
valid: bool,
v2: bool
v2: bool,
}
impl Acpi {
@ -58,7 +58,6 @@ impl Acpi {
dsdt::init(fadt::dsdtaddr()?)?;
self.valid = true;
Ok(())
}
fn init(&mut self) -> Result<(), &'static str> {
self.v2 = rsdp::init()?;
@ -71,7 +70,9 @@ impl Acpi {
}
fn check_signature(addr: u32, id: &str) -> bool {
let signature = match core::str::from_utf8(unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, id.len())}) {
let signature = match core::str::from_utf8(unsafe {
core::slice::from_raw_parts_mut(addr as *mut u8, id.len())
}) {
Ok(y) => y,
Err(_) => return false,
};
@ -91,19 +92,23 @@ pub struct ACPISDTIter {
pos: usize,
width: usize,
sdt: u32,
len: usize
len: usize,
}
impl ACPISDTIter {
fn new(acpi_sdt: Option<*const ACPISDTHeader>, ptr_len: usize) -> Result <ACPISDTIter, &'static str> {
fn new(
acpi_sdt: Option<*const ACPISDTHeader>,
ptr_len: usize,
) -> Result<ACPISDTIter, &'static str> {
match acpi_sdt {
None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."),
Some(ptr) => Ok(ACPISDTIter {
pos: 0,
width: ptr_len,
sdt: ptr as u32 + mem::size_of::<ACPISDTHeader>() as u32,
len: (unsafe {(*ptr).length} as usize - mem::size_of::<ACPISDTHeader>()) / ptr_len
})
len: (unsafe { (*ptr).length } as usize - mem::size_of::<ACPISDTHeader>())
/ ptr_len,
}),
}
}
}
@ -130,7 +135,6 @@ fn is_init() -> Result <(), &'static str> {
}
}
/// Initalized the ACPI module
pub fn init() -> Result<(), &'static str> {
if let Ok(()) = is_init() {
@ -157,6 +161,13 @@ pub fn shutdown() -> Result <(), &'static str> {
/// Display state of ACPI
pub fn info() -> Result<(), &'static str> {
is_init()?;
println!("ACPI STATE:\n {}", if fadt::is_enable()? {"ENABLED"} else {"DISABLED"});
println!(
"ACPI STATE:\n {}",
if fadt::is_enable()? {
"ENABLED"
} else {
"DISABLED"
}
);
Ok(())
}

View file

@ -1,4 +1,4 @@
use super::{check_signature,check_checksum};
use super::{check_checksum, check_signature};
use core::mem;
#[repr(C)]
@ -31,7 +31,9 @@ pub fn load(addr: u32) -> Result <bool, &'static str> {
if check_signature(addr, "RSD PTR ") {
let rsdp_tmp: RSDP20 = unsafe { (*(addr as *const RSDP20)).clone() };
let revision = rsdp_tmp.rsdp.revision;
if (revision == 0 && check_checksum(addr, mem::size_of::<RSDP>())) || (revision == 2 && check_checksum(addr, mem::size_of::<RSDP20>())) {
if (revision == 0 && check_checksum(addr, mem::size_of::<RSDP>()))
|| (revision == 2 && check_checksum(addr, mem::size_of::<RSDP20>()))
{
unsafe { RSDPTR = Some(rsdp_tmp) };
return Ok(revision == 2);
}
@ -44,7 +46,7 @@ fn memory_finding() -> Result <bool, &'static str> {
while i < 0x1000000 {
i += 8;
if let Ok(result) = load(i) {
return Ok(result)
return Ok(result);
}
}
Err("Can not find Root System Description Pointer (RSDP).")
@ -53,7 +55,7 @@ fn memory_finding() -> Result <bool, &'static str> {
fn is_init() -> Result<RSDP20, &'static str> {
match unsafe { RSDPTR.clone() } {
Some(rsdptr) => Ok(rsdptr),
None => Err("Root System Description Pointer (RSDP) is not initialized")
None => Err("Root System Description Pointer (RSDP) is not initialized"),
}
}

View file

@ -5,11 +5,9 @@ use x86::*;
use x86::structures::paging::*;
use arch::x86::paging::*;
fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize)
{
fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) {
let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32));
let heap_end_page = Page::containing_address(VirtAddr::new(
offset as u32 + size as u32 - 1));
let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1));
for page in heap_start_page..heap_end_page + 1 {
active_table.map(page, PageTableFlags::WRITABLE);

View file

@ -1,6 +1,6 @@
extern crate raw_cpuid;
use core::fmt::{Result};
use core::fmt::Result;
use self::raw_cpuid::CpuId;
@ -29,102 +29,260 @@ pub fn cpu_info() -> Result {
if let Some(info) = cpuid.get_feature_info() {
print!("Features:");
if info.has_fpu() { print!(" fpu") };
if info.has_vme() { print!(", vme") };
if info.has_de() { print!(", de") };
if info.has_pse() { print!(", pse") };
if info.has_tsc() { print!(", tsc") };
if info.has_msr() { print!(", msr") };
if info.has_pae() { print!(", pae") };
if info.has_mce() { print!(", mce") };
if info.has_fpu() {
print!(" fpu")
};
if info.has_vme() {
print!(", vme")
};
if info.has_de() {
print!(", de")
};
if info.has_pse() {
print!(", pse")
};
if info.has_tsc() {
print!(", tsc")
};
if info.has_msr() {
print!(", msr")
};
if info.has_pae() {
print!(", pae")
};
if info.has_mce() {
print!(", mce")
};
if info.has_cmpxchg8b() { print!(", cx8") };
if info.has_apic() { print!(", apic") };
if info.has_sysenter_sysexit() { print!(", sep") };
if info.has_mtrr() { print!(", mtrr") };
if info.has_pge() { print!(", pge") };
if info.has_mca() { print!(", mca") };
if info.has_cmov() { print!(", cmov") };
if info.has_pat() { print!(", pat") };
if info.has_cmpxchg8b() {
print!(", cx8")
};
if info.has_apic() {
print!(", apic")
};
if info.has_sysenter_sysexit() {
print!(", sep")
};
if info.has_mtrr() {
print!(", mtrr")
};
if info.has_pge() {
print!(", pge")
};
if info.has_mca() {
print!(", mca")
};
if info.has_cmov() {
print!(", cmov")
};
if info.has_pat() {
print!(", pat")
};
if info.has_pse36() { print!(", pse36") };
if info.has_psn() { print!(", psn") };
if info.has_clflush() { print!(", clflush") };
if info.has_ds() { print!(", ds") };
if info.has_acpi() { print!(", acpi") };
if info.has_mmx() { print!(", mmx") };
if info.has_fxsave_fxstor() { print!(", fxsr") };
if info.has_sse() { print!(", sse") };
if info.has_pse36() {
print!(", pse36")
};
if info.has_psn() {
print!(", psn")
};
if info.has_clflush() {
print!(", clflush")
};
if info.has_ds() {
print!(", ds")
};
if info.has_acpi() {
print!(", acpi")
};
if info.has_mmx() {
print!(", mmx")
};
if info.has_fxsave_fxstor() {
print!(", fxsr")
};
if info.has_sse() {
print!(", sse")
};
if info.has_sse2() { print!(", sse2") };
if info.has_ss() { print!(", ss") };
if info.has_htt() { print!(", ht") };
if info.has_tm() { print!(", tm") };
if info.has_pbe() { print!(", pbe") };
if info.has_sse2() {
print!(", sse2")
};
if info.has_ss() {
print!(", ss")
};
if info.has_htt() {
print!(", ht")
};
if info.has_tm() {
print!(", tm")
};
if info.has_pbe() {
print!(", pbe")
};
if info.has_sse3() { print!(", sse3") };
if info.has_pclmulqdq() { print!(", pclmulqdq") };
if info.has_ds_area() { print!(", dtes64") };
if info.has_monitor_mwait() { print!(", monitor") };
if info.has_cpl() { print!(", ds_cpl") };
if info.has_vmx() { print!(", vmx") };
if info.has_smx() { print!(", smx") };
if info.has_eist() { print!(", est") };
if info.has_sse3() {
print!(", sse3")
};
if info.has_pclmulqdq() {
print!(", pclmulqdq")
};
if info.has_ds_area() {
print!(", dtes64")
};
if info.has_monitor_mwait() {
print!(", monitor")
};
if info.has_cpl() {
print!(", ds_cpl")
};
if info.has_vmx() {
print!(", vmx")
};
if info.has_smx() {
print!(", smx")
};
if info.has_eist() {
print!(", est")
};
if info.has_tm2() { print!(", tm2") };
if info.has_ssse3() { print!(", ssse3") };
if info.has_cnxtid() { print!(", cnxtid") };
if info.has_fma() { print!(", fma") };
if info.has_cmpxchg16b() { print!(", cx16") };
if info.has_pdcm() { print!(", pdcm") };
if info.has_pcid() { print!(", pcid") };
if info.has_dca() { print!(", dca") };
if info.has_tm2() {
print!(", tm2")
};
if info.has_ssse3() {
print!(", ssse3")
};
if info.has_cnxtid() {
print!(", cnxtid")
};
if info.has_fma() {
print!(", fma")
};
if info.has_cmpxchg16b() {
print!(", cx16")
};
if info.has_pdcm() {
print!(", pdcm")
};
if info.has_pcid() {
print!(", pcid")
};
if info.has_dca() {
print!(", dca")
};
if info.has_sse41() { print!(", sse4_1") };
if info.has_sse42() { print!(", sse4_2") };
if info.has_x2apic() { print!(", x2apic") };
if info.has_movbe() { print!(", movbe") };
if info.has_popcnt() { print!(", popcnt") };
if info.has_tsc_deadline() { print!(", tsc_deadline_timer") };
if info.has_aesni() { print!(", aes") };
if info.has_xsave() { print!(", xsave") };
if info.has_sse41() {
print!(", sse4_1")
};
if info.has_sse42() {
print!(", sse4_2")
};
if info.has_x2apic() {
print!(", x2apic")
};
if info.has_movbe() {
print!(", movbe")
};
if info.has_popcnt() {
print!(", popcnt")
};
if info.has_tsc_deadline() {
print!(", tsc_deadline_timer")
};
if info.has_aesni() {
print!(", aes")
};
if info.has_xsave() {
print!(", xsave")
};
if info.has_oxsave() { print!(", xsaveopt") };
if info.has_avx() { print!(", avx") };
if info.has_f16c() { print!(", f16c") };
if info.has_rdrand() { print!(", rdrand") };
if info.has_oxsave() {
print!(", xsaveopt")
};
if info.has_avx() {
print!(", avx")
};
if info.has_f16c() {
print!(", f16c")
};
if info.has_rdrand() {
print!(", rdrand")
};
println!("");
}
if let Some(info) = cpuid.get_extended_function_info() {
print!("Extended function:");
if info.has_64bit_mode() { print!(" lm") };
if info.has_rdtscp() { print!(", rdtscp") };
if info.has_1gib_pages() { print!(", pdpe1gb") };
if info.has_execute_disable() { print!(", nx") };
if info.has_syscall_sysret() { print!(", syscall") };
if info.has_prefetchw() { print!(", prefetchw") };
if info.has_lzcnt() { print!(", lzcnt") };
if info.has_lahf_sahf() { print!(", lahf_lm") };
if info.has_invariant_tsc() { print!(", constant_tsc") };
if info.has_64bit_mode() {
print!(" lm")
};
if info.has_rdtscp() {
print!(", rdtscp")
};
if info.has_1gib_pages() {
print!(", pdpe1gb")
};
if info.has_execute_disable() {
print!(", nx")
};
if info.has_syscall_sysret() {
print!(", syscall")
};
if info.has_prefetchw() {
print!(", prefetchw")
};
if info.has_lzcnt() {
print!(", lzcnt")
};
if info.has_lahf_sahf() {
print!(", lahf_lm")
};
if info.has_invariant_tsc() {
print!(", constant_tsc")
};
println!("");
}
if let Some(info) = cpuid.get_extended_feature_info() {
print!("Extended features:");
if info.has_fsgsbase() { print!(" fsgsbase") };
if info.has_tsc_adjust_msr() { print!(", tsc_adjust") };
if info.has_bmi1() { print!(", bmi1") };
if info.has_hle() { print!(", hle") };
if info.has_avx2() { print!(", avx2") };
if info.has_smep() { print!(", smep") };
if info.has_bmi2() { print!(", bmi2") };
if info.has_rep_movsb_stosb() { print!(", erms") };
if info.has_invpcid() { print!(", invpcid") };
if info.has_rtm() { print!(", rtm") };
if info.has_qm() { print!(", qm") };
if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") };
if info.has_mpx() { print!(", mpx") };
if info.has_fsgsbase() {
print!(" fsgsbase")
};
if info.has_tsc_adjust_msr() {
print!(", tsc_adjust")
};
if info.has_bmi1() {
print!(", bmi1")
};
if info.has_hle() {
print!(", hle")
};
if info.has_avx2() {
print!(", avx2")
};
if info.has_smep() {
print!(", smep")
};
if info.has_bmi2() {
print!(", bmi2")
};
if info.has_rep_movsb_stosb() {
print!(", erms")
};
if info.has_invpcid() {
print!(", invpcid")
};
if info.has_rtm() {
print!(", rtm")
};
if info.has_qm() {
print!(", qm")
};
if info.has_fpu_cs_ds_deprecated() {
print!(", fpu_seg")
};
if info.has_mpx() {
print!(", mpx")
};
println!("");
}

View file

@ -1,8 +1,8 @@
use ::arch::x86::paging::ActivePageTable;
use arch::x86::paging::ActivePageTable;
pub static mut LOCAL_APIC: LocalApic = LocalApic {
address: 0,
x2: false
x2: false,
};
pub unsafe fn init(active_table: &mut ActivePageTable) {
@ -11,7 +11,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
pub struct LocalApic {
pub address: usize,
pub x2: bool
pub x2: bool,
}
impl LocalApic {

View file

@ -1,4 +1,4 @@
use ::arch::x86::paging::ActivePageTable;
use arch::x86::paging::ActivePageTable;
pub mod pic;
pub mod local_apic;
pub mod cpu;

View file

@ -1,47 +1,64 @@
use ::io::{Io, Pio};
use io::{Io, Pio};
pub static mut MASTER: Pic = Pic::new(0x20);
pub static mut SLAVE: Pic = Pic::new(0xA0);
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
pub unsafe fn init() {
let wait = || {WAIT_PORT.write(0)};
let wait = || WAIT_PORT.write(0);
let master_mask = MASTER.data.read();
let slave_mask = SLAVE.data.read();
// Start initialization
MASTER.cmd.write(0x11); wait();
SLAVE.cmd.write(0x11); wait();
MASTER.cmd.write(0x11);
wait();
SLAVE.cmd.write(0x11);
wait();
// Set offsets
MASTER.data.write(0x20); wait();
SLAVE.data.write(0x28); wait();
MASTER.data.write(0x20);
wait();
SLAVE.data.write(0x28);
wait();
// Set up cascade
MASTER.data.write(4); wait();
SLAVE.data.write(2); wait();
MASTER.data.write(4);
wait();
SLAVE.data.write(2);
wait();
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
MASTER.data.write(1); wait();
SLAVE.data.write(1); wait();
MASTER.data.write(1);
wait();
SLAVE.data.write(1);
wait();
// Unmask interrupts
MASTER.data.write(0); wait();
SLAVE.data.write(0); wait();
MASTER.data.write(0);
wait();
SLAVE.data.write(0);
wait();
// Ack remaining interrupts
MASTER.ack(); wait();
SLAVE.ack(); wait();
MASTER.ack();
wait();
SLAVE.ack();
wait();
MASTER.data.write(master_mask); wait();
SLAVE.data.write(slave_mask); wait();
MASTER.data.write(master_mask);
wait();
SLAVE.data.write(slave_mask);
wait();
// disable all irqs
MASTER.data.write(!0); wait();
SLAVE.data.write(!0); wait();
MASTER.data.write(!0);
wait();
SLAVE.data.write(!0);
wait();
// keyboard active
MASTER.mask_clear(1); wait();
MASTER.mask_clear(1);
wait();
// asm!("sti");
::x86::instructions::interrupts::enable();

View file

@ -4,15 +4,15 @@ use x86::instructions::segmentation::set_cs;
use x86::instructions::tables::load_tss;
use spin::Once;
static GDT: Once<gdt::Gdt> = Once::new();
static TSS: Once<tss::TaskStateSegment> = Once::new();
// static GDT: Once<gdt::Gdt> = Once::new();
// static TSS: Once<tss::TaskStateSegment> = Once::new();
pub fn init() {
// let tss = tss::TaskStateSegment::new();
let tss = TSS.call_once(|| {
let mut tss = tss::TaskStateSegment::new();
tss
});
// let tss = TSS.call_once(|| {
// let mut tss = tss::TaskStateSegment::new();
// tss
// });
// let mut code_selector = gdt::SegmentSelector(0);
// let mut tss_selector = gdt::SegmentSelector(0);

View file

@ -1,6 +1,6 @@
// https://wiki.osdev.org/Exceptions
use ::arch::x86::pti;
use arch::x86::pti;
macro_rules! exception {
($name:ident, $func:block) => {
@ -62,8 +62,9 @@ exception_err!(stack_segment, {});
exception_err!(general_protection, {});
pub extern "x86-interrupt" fn page_fault(
stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode)
{
stack_frame: &mut ExceptionStackFrame,
code: PageFaultErrorCode,
) {
println!("Exception: page_fault");
println!("Error code: {:#b}", code);
println!("{:#?}", stack_frame);

View file

@ -1,2 +1,4 @@
#[macro_use] pub mod exception;
#[macro_use] pub mod irq;
#[macro_use]
pub mod exception;
#[macro_use]
pub mod irq;

View file

@ -6,14 +6,14 @@ pub mod interrupt;
pub mod device;
pub mod pti;
pub mod gdt;
// pub mod gdt;
pub mod idt;
use multiboot2;
use acpi;
#[no_mangle]
pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) {
// parse multiboot2 info
let boot_info = multiboot2::load(multiboot_info_addr);
@ -26,24 +26,26 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) {
acpi::init().expect("ACPI failed");
}
// fill and load idt (exceptions + irqs)
idt::init();
// set up physical allocator
::memory::init(&boot_info);
// set up virtual mapping
let mut active_table = paging::init(&boot_info);
asm!("hlt");
// set up heap
::allocator::init(&mut active_table);
// set up memory segmentation
// gdt::init();
// set up interrupts
idt::init();
// set up pic & apic
device::init(&mut active_table);
// fill and load gdt
// gdt::init();
// primary CPU entry point
::kmain();
}

View file

@ -31,8 +31,7 @@ impl Mapper {
}
/// virtual addr to physical addr translation
pub fn translate(&self, virtual_address: VirtAddr) -> Option<PhysAddr>
{
pub fn translate(&self, virtual_address: VirtAddr) -> Option<PhysAddr> {
let offset = virtual_address.as_u32() % PAGE_SIZE as u32;
self.translate_page(Page::containing_address(virtual_address))
.map(|frame| frame.start_address() + offset)
@ -58,29 +57,25 @@ impl Mapper {
}
/// map a virtual page to a physical frame in the page tables
pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags)
{
pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags) {
let p2 = self.p2_mut();
let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())));
assert!(p1[page.p1_index()].is_unused());
p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT);
}
pub fn map(&mut self, page: Page, flags: PageTableFlags)
{
pub fn map(&mut self, page: Page, flags: PageTableFlags) {
let frame = ::memory::allocate_frames(1).expect("out of frames");
self.map_to(page, frame, flags)
}
pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags)
{
pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags) {
let virt_addr = VirtAddr::new(frame.start_address().as_u32());
let page = Page::containing_address(virt_addr);
self.map_to(page, frame, flags);
}
pub fn unmap(&mut self, page: Page)
{
pub fn unmap(&mut self, page: Page) {
assert!(self.translate(page.start_address()).is_some());
let p1 = self.p2_mut()

View file

@ -51,11 +51,13 @@ impl ActivePageTable {
}
}
pub fn with<F>(&mut self,
pub fn with<F>(
&mut self,
table: &mut InactivePageTable,
temporary_page: &mut temporary_page::TemporaryPage,
f: F)
where F: FnOnce(&mut Mapper)
f: F,
) where
F: FnOnce(&mut Mapper),
{
let (cr3_back, _cr3flags_back) = Cr3::read();
@ -63,7 +65,10 @@ impl ActivePageTable {
let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self);
// overwrite recursive map
self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
self.p2_mut()[1023].set(
table.p2_frame.clone(),
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
);
tlb::flush_all();
// execute f in the new context
@ -74,11 +79,12 @@ impl ActivePageTable {
}
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
let (p2_frame, cr3_flags) = Cr3::read();
let old_table = InactivePageTable { p2_frame };
unsafe { Cr3::write(new_table.p2_frame, cr3_flags); }
unsafe {
Cr3::write(new_table.p2_frame, cr3_flags);
}
old_table
}
@ -89,39 +95,44 @@ pub struct InactivePageTable {
}
impl InactivePageTable {
pub fn new(frame: PhysFrame,
pub fn new(
frame: PhysFrame,
active_table: &mut ActivePageTable,
temporary_page: &mut TemporaryPage)
-> InactivePageTable {
temporary_page: &mut TemporaryPage,
) -> InactivePageTable {
{
let table = temporary_page.map_table_frame(frame.clone(), active_table);
table.zero();
// set up recursive mapping for the table
table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE)
table[1023].set(
frame.clone(),
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
)
}
temporary_page.unmap(active_table);
InactivePageTable { p2_frame: frame }
}
}
pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
{
pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable {
let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe });
let mut active_table = unsafe { ActivePageTable::new() };
let mut new_table = {
let frame = ::memory::allocate_frames(1).expect("no more frames");
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
};
unsafe {
asm!("hlt");
}
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
// id map vga buffer
let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE);
let elf_sections_tag = boot_info.elf_sections_tag()
let elf_sections_tag = boot_info
.elf_sections_tag()
.expect("Memory map tag required");
// id map kernel sections
@ -129,24 +140,26 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
if !section.is_allocated() {
continue;
}
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
"sections need to be page aligned");
assert!(
section.start_address() % PAGE_SIZE as u64 == 0,
"sections need to be page aligned"
);
let flags = elf_to_pagetable_flags(&section.flags());
let start_frame = PhysFrame::containing_address(
PhysAddr::new(section.start_address() as u32));
let end_frame = PhysFrame::containing_address(
PhysAddr::new(section.end_address() as u32 - 1));
let start_frame =
PhysFrame::containing_address(PhysAddr::new(section.start_address() as u32));
let end_frame =
PhysFrame::containing_address(PhysAddr::new(section.end_address() as u32 - 1));
for frame in start_frame..end_frame + 1 {
mapper.identity_map(frame, flags);
}
}
// id map multiboot
let multiboot_start = PhysFrame::containing_address(
PhysAddr::new(boot_info.start_address() as u32));
let multiboot_end = PhysFrame::containing_address(
PhysAddr::new(boot_info.end_address() as u32 - 1));
let multiboot_start =
PhysFrame::containing_address(PhysAddr::new(boot_info.start_address() as u32));
let multiboot_end =
PhysFrame::containing_address(PhysAddr::new(boot_info.end_address() as u32 - 1));
for frame in multiboot_start..multiboot_end + 1 {
mapper.identity_map(frame, PageTableFlags::PRESENT);
}
@ -154,17 +167,15 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
let old_table = active_table.switch(new_table);
let old_p2_page = Page::containing_address(
VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
let old_p2_page =
Page::containing_address(VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
active_table.unmap(old_p2_page);
active_table
}
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags)
-> PageTableFlags
{
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) -> PageTableFlags {
use multiboot2::ElfSectionFlags;
let mut flags = PageTableFlags::empty();

View file

@ -1,20 +1,18 @@
use x86::structures::paging::*;
pub trait RecTable
{
pub trait RecTable {
fn next_table_address(&self, index: usize) -> Option<u32>;
fn next_table(&self, index: usize) -> Option<&PageTable>;
fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>;
fn next_table_create(&mut self,
index: usize)
-> &mut PageTable;
fn next_table_create(&mut self, index: usize) -> &mut PageTable;
}
impl RecTable for PageTable
{
impl RecTable for PageTable {
fn next_table_address(&self, index: usize) -> Option<u32> {
let entry_flags = self[index].flags();
if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) {
if entry_flags.contains(PageTableFlags::PRESENT)
&& !entry_flags.contains(PageTableFlags::HUGE_PAGE)
{
let table_address = self as *const _ as usize;
Some((table_address << 10 | index << 12) as u32)
} else {
@ -32,16 +30,17 @@ impl RecTable for PageTable
.map(|address| unsafe { &mut *(address as *mut _) })
}
fn next_table_create(&mut self,
index: usize) -> &mut PageTable
{
fn next_table_create(&mut self, index: usize) -> &mut PageTable {
if self.next_table(index).is_none() {
assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
"mapping code does not support huge pages");
let frame = ::memory::allocate_frames(1)
.expect("out of memory");
assert!(
!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
"mapping code does not support huge pages"
);
let frame = ::memory::allocate_frames(1).expect("out of memory");
self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
self.next_table_mut(index).expect("next_table_mut gave None").zero()
self.next_table_mut(index)
.expect("next_table_mut gave None")
.zero()
}
self.next_table_mut(index).expect("no next table 2")
}

View file

@ -7,22 +7,23 @@ pub struct TemporaryPage {
}
impl TemporaryPage {
pub fn new(page: Page) -> TemporaryPage
{
pub fn new(page: Page) -> TemporaryPage {
TemporaryPage { page: page }
}
/// Maps the temporary page to the given frame in the active table.
/// Returns the start address of the temporary page.
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable)
-> VirtAddr
{
assert!(active_table.translate_page(self.page).is_none(),
"temporary page is already mapped");
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) -> VirtAddr {
assert!(
active_table.translate_page(self.page).is_none(),
"temporary page is already mapped"
);
active_table.map_to(self.page, frame, PageTableFlags::WRITABLE);
// this kind of check should be done in a test routine
assert!(active_table.translate_page(self.page).is_some(),
"temporary page was not mapped");
assert!(
active_table.translate_page(self.page).is_some(),
"temporary page was not mapped"
);
self.page.start_address()
}
@ -33,10 +34,11 @@ impl TemporaryPage {
/// Maps the temporary page to the given page table frame in the active
/// table. Returns a reference to the now mapped table.
pub fn map_table_frame(&mut self,
pub fn map_table_frame(
&mut self,
frame: PhysFrame,
active_table: &mut ActivePageTable)
-> &mut PageTable {
active_table: &mut ActivePageTable,
) -> &mut PageTable {
unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) }
}
}

View file

@ -20,11 +20,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
let new_esp = new - offset_esp;
ptr::copy_nonoverlapping(
old_esp as *const u8,
new_esp as *mut u8,
offset_esp
);
ptr::copy_nonoverlapping(old_esp as *const u8, new_esp as *mut u8, offset_esp);
// switch the esp with the new one
asm!("" : : "{esp}"(new_esp) : : "intel", "volatile");
@ -47,13 +43,19 @@ pub unsafe fn map() {
// }
// Switch to per-context stack
switch_stack(PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), PTI_CONTEXT_STACK);
switch_stack(
PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(),
PTI_CONTEXT_STACK,
);
}
#[inline(always)]
pub unsafe fn unmap() {
// Switch to per-CPU stack
switch_stack(PTI_CONTEXT_STACK, PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len());
switch_stack(
PTI_CONTEXT_STACK,
PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(),
);
// {
// let mut active_table = unsafe { ActivePageTable::new() };

View file

@ -179,7 +179,7 @@ pub fn acpi_info() -> Result <(), &'static str> {
/// Dump control registers
pub fn regs() -> Result<(), &'static str> {
use ::x86::registers::control::*;
use x86::registers::control::*;
println!("cr0 = {:?}", Cr0::read());
println!("cr3 = {:?}", Cr3::read());
println!("cr4 = {:?}", Cr4::read());
@ -189,7 +189,7 @@ pub fn regs() -> Result <(), &'static str> {
/// Dump cpu info, should add power management info
pub fn cpu() -> Result<(), &'static str> {
use ::arch::x86::device::cpu;
use arch::x86::device::cpu;
cpu::cpu_info().expect("cpu info not available");
flush!();
Ok(())

View file

@ -48,7 +48,9 @@ pub fn halt() -> ! {
/// wait for an io operation to complete
pub fn io_wait() {
unsafe { asm!("jmp 1f\n\t
unsafe {
asm!("jmp 1f\n\t
1:jmp 2f\n\t
2:" : : : : "volatile")}
2:" : : : : "volatile")
}
}

View file

@ -5,7 +5,11 @@ pub use self::pio::*;
use core::ops::{BitAnd, BitOr, Not};
pub trait Io {
type Value: Copy + PartialEq + BitAnd<Output = Self::Value> + BitOr<Output = Self::Value> + Not<Output = Self::Value>;
type Value: Copy
+ PartialEq
+ BitAnd<Output = Self::Value>
+ BitOr<Output = Self::Value>
+ Not<Output = Self::Value>;
fn read(&self) -> Self::Value;
fn write(&mut self, value: Self::Value);

View file

@ -84,25 +84,24 @@ pub fn kbd_callback() {
if (control & 1) == 1 {
let scancode = cpuio::inb(0x60);
let (is_release, scancode) = check_key_state(scancode);
unsafe {//TODO remove unsafe
unsafe {
//TODO remove unsafe
match self::KEYMAP_US.get(scancode as usize) {
Some(b"\0\0") => {
match scancode {
0x2A | 0x36 => {SHIFT = !is_release},
0x38 => {ALT = !is_release},
0x1D => {CTRL = !is_release},
Some(b"\0\0") => match scancode {
0x2A | 0x36 => SHIFT = !is_release,
0x38 => ALT = !is_release,
0x1D => CTRL = !is_release,
0x0E if !is_release => {
vga::VGA.backspace();
}
_ => {}
}
},
Some(ascii) if !is_release => {
let sym = if SHIFT { ascii[1] } else { ascii[0] };
vga::VGA.keypress(sym);
},
Some(_) => {},
None =>{},
}
Some(_) => {}
None => {}
}
}
}

View file

@ -7,28 +7,28 @@
#![feature(ptr_internals)]
#![feature(asm)]
#![feature(thread_local)]
// home made heap
#![feature(alloc)]
#![feature(allocator_api)]
#![feature(global_allocator)]
// x86 specific
#![feature(abi_x86_interrupt)]
extern crate rlibc;
extern crate alloc;
extern crate spin;
#[macro_use] extern crate lazy_static;
#[macro_use]
extern crate lazy_static;
extern crate multiboot2;
extern crate slab_allocator;
extern crate raw_cpuid;
extern crate rlibc;
extern crate slab_allocator;
extern crate spin;
// used by arch/x86, need conditional compilation here
extern crate x86;
/// 80x25 terminal driver
#[macro_use] pub mod vga;
#[macro_use]
pub mod vga;
/// PS/2 detection and processing
pub mod keyboard;
/// simplisitc kernel commands
@ -45,9 +45,10 @@ pub mod memory;
/// arch specific entry points
pub mod arch;
/// kernel entry point. arch module is responsible for calling this
/// kernel entry point. arch module is responsible for
/// calling this once the core has loaded
pub fn kmain() -> ! {
// core is loaded now
// heap avalaible for tracking free'd frames
memory::init_noncore();
// x86::instructions::interrupts::int3();
@ -66,12 +67,13 @@ pub fn kmain() -> ! {
loop {}
}
#[lang = "eh_personality"] #[no_mangle]
pub extern fn eh_personality() {}
#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn eh_personality() {}
#[lang = "panic_fmt"] #[no_mangle]
pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32)
-> ! {
#[lang = "panic_fmt"]
#[no_mangle]
pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
println!("PANIC: {}", fmt);
println!("FILE: {}", file);
println!("LINE: {}", line);

View file

@ -1,4 +1,4 @@
use multiboot2::{MemoryAreaIter, MemoryArea};
use multiboot2::{MemoryArea, MemoryAreaIter};
use x86::*;
use x86::structures::paging::PhysFrame;
use super::FrameAllocator;
@ -14,21 +14,21 @@ pub struct BumpFrameAllocator {
}
impl BumpFrameAllocator {
pub fn new(kernel_start: usize, kernel_end: usize,
multiboot_start: usize, multiboot_end: usize,
memory_areas: MemoryAreaIter) -> BumpFrameAllocator {
pub fn new(
kernel_start: usize,
kernel_end: usize,
multiboot_start: usize,
multiboot_end: usize,
memory_areas: MemoryAreaIter,
) -> BumpFrameAllocator {
let mut allocator = BumpFrameAllocator {
next_free_frame: PhysFrame { number: 0 },
current_area: None,
areas: memory_areas,
kernel_start: PhysFrame::containing_address(
PhysAddr::new(kernel_start as u32)),
kernel_end: PhysFrame::containing_address(
PhysAddr::new(kernel_end as u32)),
multiboot_start: PhysFrame::containing_address(
PhysAddr::new(multiboot_start as u32)),
multiboot_end: PhysFrame::containing_address(
PhysAddr::new(multiboot_end as u32)),
kernel_start: PhysFrame::containing_address(PhysAddr::new(kernel_start as u32)),
kernel_end: PhysFrame::containing_address(PhysAddr::new(kernel_end as u32)),
multiboot_start: PhysFrame::containing_address(PhysAddr::new(multiboot_start as u32)),
multiboot_end: PhysFrame::containing_address(PhysAddr::new(multiboot_end as u32)),
};
allocator.choose_next_area();
allocator
@ -36,13 +36,16 @@ impl BumpFrameAllocator {
fn choose_next_area(&mut self) {
// get next area with free frames
self.current_area = self.areas.clone().filter(|area| {
self.current_area = self.areas
.clone()
.filter(|area| {
area.end_address() >= self.next_free_frame.start_address().as_u32() as usize
}).min_by_key(|area| area.start_address());
})
.min_by_key(|area| area.start_address());
if let Some(area) = self.current_area {
let start_frame = PhysFrame::containing_address(
PhysAddr::new(area.start_address() as u32));
let start_frame =
PhysFrame::containing_address(PhysAddr::new(area.start_address() as u32));
if self.next_free_frame < start_frame {
self.next_free_frame = start_frame;
}
@ -52,22 +55,32 @@ impl BumpFrameAllocator {
impl FrameAllocator for BumpFrameAllocator {
fn allocate_frames(&mut self, count: usize) -> Option<PhysFrame> {
if count == 0 { return None };
if count == 0 {
return None;
};
if let Some(area) = self.current_area {
let start_frame = PhysFrame { number: self.next_free_frame.number };
let end_frame = PhysFrame { number: self.next_free_frame.number + count as u32 - 1 };
let start_frame = PhysFrame {
number: self.next_free_frame.number,
};
let end_frame = PhysFrame {
number: self.next_free_frame.number + count as u32 - 1,
};
let current_area_last_frame = PhysFrame::containing_address(
PhysAddr::new(area.end_address() as u32));
let current_area_last_frame =
PhysFrame::containing_address(PhysAddr::new(area.end_address() as u32));
if end_frame > current_area_last_frame {
// all frames are taken in this area
self.choose_next_area();
} else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) {
} else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end)
|| (end_frame >= self.kernel_start && end_frame <= self.kernel_end)
{
// frame used by kernel
self.next_free_frame = PhysFrame {
number: self.kernel_end.number + 1,
};
} else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end) || (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end) {
} else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end)
|| (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end)
{
// frame used by multiboot
self.next_free_frame = PhysFrame {
number: self.multiboot_end.number + 1,
@ -85,7 +98,11 @@ impl FrameAllocator for BumpFrameAllocator {
fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) {
// bump doesnt deallocate, must be used inside of a recycler
println!("lost frames {:#x} ({})", frame.start_address().as_u32(), count);
println!(
"lost frames {:#x} ({})",
frame.start_address().as_u32(),
count
);
// unimplemented!();
}
}

View file

@ -24,20 +24,27 @@ pub fn init(boot_info: &multiboot2::BootInformation) {
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
let memory_map_tag = boot_info.memory_map_tag().unwrap();
let kernel_start = elf_sections_tag.sections()
let kernel_start = elf_sections_tag
.sections()
.filter(|s| s.is_allocated())
.map(|s| s.start_address())
.min().unwrap();
.min()
.unwrap();
let kernel_end = elf_sections_tag.sections()
let kernel_end = elf_sections_tag
.sections()
.filter(|s| s.is_allocated())
.map(|s| s.start_address() + s.size())
.max().unwrap();
.max()
.unwrap();
let bump_allocator = BumpFrameAllocator::new(
kernel_start as usize, kernel_end as usize,
boot_info.start_address(), boot_info.end_address(),
memory_map_tag.memory_areas());
kernel_start as usize,
kernel_end as usize,
boot_info.start_address(),
boot_info.end_address(),
memory_map_tag.memory_areas(),
);
let frame_allocator = RecycleAllocator::new(bump_allocator);

View file

@ -40,7 +40,9 @@ macro_rules! set_color {
pub fn print(args: fmt::Arguments) {
use core::fmt::Write;
unsafe { self::VGA.write_fmt(args).unwrap(); }
unsafe {
self::VGA.write_fmt(args).unwrap();
}
}
extern crate core;
@ -51,7 +53,8 @@ const BUFFER_COLS: usize = 80 * 2;
pub struct Writer {
pub buffer_pos: usize,
pub color_code: ColorCode,
buffer: [u8; BUFFER_ROWS * BUFFER_COLS], command: [u8; 10],
buffer: [u8; BUFFER_ROWS * BUFFER_COLS],
command: [u8; 10],
command_len: usize,
}
@ -81,12 +84,10 @@ impl Writer {
}
pub fn get_command(&self) -> Result<&str, &'static str> {
match core::str::from_utf8(&self.command) {
Ok(y) => Ok(&y[..self.command_len]),
Err(_) => Err("Command is not utf8 char")
Err(_) => Err("Command is not utf8 char"),
}
}
pub fn keypress(&mut self, ascii: u8) {
@ -108,7 +109,9 @@ impl Writer {
_ if self.command_len >= 10 => (),
byte if self.command_len == 0 && byte == b' ' => (),
byte => {
if self.command_len >= 10 { return };
if self.command_len >= 10 {
return;
};
self.command[self.command_len] = byte;
self.write_byte(byte);
self.command_len += 1;
@ -130,7 +133,6 @@ impl Writer {
let i = self.buffer_pos;
match byte {
b'\n' => {
let current_line = self.buffer_pos / (BUFFER_COLS);
self.buffer_pos = (current_line + 1) * BUFFER_COLS;
@ -199,7 +201,8 @@ impl fmt::Write for Writer {
pub fn init() {
set_color!(White, Cyan);
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
print!(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
format_args!("{: ^80}", r#" ,--, "#),
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
@ -213,8 +216,13 @@ pub fn init() {
format_args!("{: ^80}", r#" ' ; |./__; : "#),
format_args!("{: ^80}", r#" | : ;| : .' "#),
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
format_args!("{: ^80}", r#" '--' `---' "#));
format_args!("{: ^80}", r#" '--' `---' "#)
);
set_color!();
unsafe { VGA.prompt(); }
unsafe { VGA.flush(); }
unsafe {
VGA.prompt();
}
unsafe {
VGA.flush();
}
}