code doesnt work anymore but i'm commiting anyway, shoot me
This commit is contained in:
parent
bea6a729fe
commit
a0ad3689f3
30 changed files with 725 additions and 476 deletions
|
|
@ -13,12 +13,12 @@ spin = "0.4"
|
||||||
slab_allocator = "0.3.1"
|
slab_allocator = "0.3.1"
|
||||||
multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag
|
multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag
|
||||||
x86 = { path = "x86" } # forked for IA32
|
x86 = { path = "x86" } # forked for IA32
|
||||||
raw-cpuid = { path = "rust-cpuid" }
|
# raw-cpuid = { path = "rust-cpuid" }
|
||||||
|
|
||||||
# [dependencies.raw-cpuid]
|
[dependencies.raw-cpuid]
|
||||||
# # need to use github/master because of features not yet on crates.io
|
# need to use github/master because of features not yet on crates.io
|
||||||
# git = "https://github.com/gz/rust-cpuid"
|
git = "https://github.com/gz/rust-cpuid"
|
||||||
# features = ["nightly"]
|
features = ["nightly"]
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{check_signature,ACPISDTHeader};
|
use super::{check_signature, ACPISDTHeader};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use cpuio;
|
use cpuio;
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ static mut DSDT: DSDT = DSDT {
|
||||||
dsdt: None,
|
dsdt: None,
|
||||||
s5_ptr: 0,
|
s5_ptr: 0,
|
||||||
slp_typ_a: 0,
|
slp_typ_a: 0,
|
||||||
slp_typ_b: 0
|
slp_typ_b: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DSDT {
|
struct DSDT {
|
||||||
|
|
@ -15,24 +15,26 @@ struct DSDT {
|
||||||
dsdt: Option<&'static ACPISDTHeader>,
|
dsdt: Option<&'static ACPISDTHeader>,
|
||||||
s5_ptr: u32,
|
s5_ptr: u32,
|
||||||
slp_typ_a: u16,
|
slp_typ_a: u16,
|
||||||
slp_typ_b: u16
|
slp_typ_b: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DSDT {
|
impl DSDT {
|
||||||
fn init(&mut self, addr: u32) -> Result <(), &'static str> {
|
fn init(&mut self, addr: u32) -> Result<(), &'static str> {
|
||||||
self.dsdt = Some(unsafe{ &(*(addr as *const ACPISDTHeader)) });
|
self.dsdt = Some(unsafe { &(*(addr as *const ACPISDTHeader)) });
|
||||||
self.s5_ptr = self.find_s5(addr)?;
|
self.s5_ptr = self.find_s5(addr)?;
|
||||||
self.parse_s5();
|
self.parse_s5();
|
||||||
self.valid = true;
|
self.valid = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_s5(&self, addr: u32) -> Result <u32, &'static str> {
|
fn find_s5(&self, addr: u32) -> Result<u32, &'static str> {
|
||||||
let dsdt_start = addr + mem::size_of::<ACPISDTHeader>() as u32;
|
let dsdt_start = addr + mem::size_of::<ACPISDTHeader>() as u32;
|
||||||
let dsdt_end = dsdt_start + self.dsdt.unwrap().length;
|
let dsdt_end = dsdt_start + self.dsdt.unwrap().length;
|
||||||
for addr in dsdt_start..dsdt_end {
|
for addr in dsdt_start..dsdt_end {
|
||||||
if check_signature(addr, "_S5_") {
|
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);
|
return Ok(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,43 +44,51 @@ impl DSDT {
|
||||||
|
|
||||||
fn parse_s5(&mut self) {
|
fn parse_s5(&mut self) {
|
||||||
let ptr = self.s5_ptr + 5;
|
let ptr = self.s5_ptr + 5;
|
||||||
let ptr = ((unsafe{*(ptr as *const u8)} & 0xC0) >> 6) + 2;
|
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 {
|
||||||
self.slp_typ_a = (unsafe {*(ptr as *const u8)} as u16) << 10;
|
ptr + 1
|
||||||
|
} else {
|
||||||
|
ptr
|
||||||
|
}; // Skip bytePrefix
|
||||||
|
self.slp_typ_a = (unsafe { *(ptr as *const u8) } as u16) << 10;
|
||||||
let ptr = ptr + 1;
|
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 {
|
||||||
self.slp_typ_b = (unsafe {*(ptr as *const u8)} as u16) << 10;
|
ptr + 1
|
||||||
|
} else {
|
||||||
|
ptr
|
||||||
|
}; // Skip bytePrefix
|
||||||
|
self.slp_typ_b = (unsafe { *(ptr as *const u8) } as u16) << 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_init() -> Result <(), &'static str> {
|
fn is_init() -> Result<(), &'static str> {
|
||||||
match unsafe {DSDT.valid} {
|
match unsafe { DSDT.valid } {
|
||||||
true => Ok(()),
|
true => Ok(()),
|
||||||
false => match unsafe {DSDT.dsdt} {
|
false => match unsafe { DSDT.dsdt } {
|
||||||
Some(_) => Err("Differentiated System Description Pointer (DSDP) is not valid"),
|
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"),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Initialize Differentiated System Description Table (DSDT)
|
/// ## Initialize Differentiated System Description Table (DSDT)
|
||||||
/// input param addr is contain in FADT
|
/// input param addr is contain in FADT
|
||||||
pub fn init(addr: u32) -> Result <(), &'static str> {
|
pub fn init(addr: u32) -> Result<(), &'static str> {
|
||||||
if ACPISDTHeader::valid(addr, "DSDT") {
|
if ACPISDTHeader::valid(addr, "DSDT") {
|
||||||
return unsafe {DSDT.init(addr)};
|
return unsafe { DSDT.init(addr) };
|
||||||
}
|
}
|
||||||
return Err("Can not find Differentiated System Description Table (DSDT).");
|
return Err("Can not find Differentiated System Description Table (DSDT).");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOT COMPATIBLE WITH VIRTUALBOX
|
/// NOT COMPATIBLE WITH VIRTUALBOX
|
||||||
/// Send shutdown signal
|
/// Send shutdown signal
|
||||||
/// outw(PM1a_CNT_BLK, SLP_TYPx | SLP_EN)
|
/// outw(PM1a_CNT_BLK, SLP_TYPx | SLP_EN)
|
||||||
pub fn shutdown(pm1_cnt: [u16; 2]) -> Result <(), &'static str> {
|
pub fn shutdown(pm1_cnt: [u16; 2]) -> Result<(), &'static str> {
|
||||||
is_init()?;
|
is_init()?;
|
||||||
let slp_typ = unsafe{ DSDT.slp_typ_a } | (1 << 13);
|
let slp_typ = unsafe { DSDT.slp_typ_a } | (1 << 13);
|
||||||
cpuio::outw(pm1_cnt[0], slp_typ);
|
cpuio::outw(pm1_cnt[0], slp_typ);
|
||||||
if pm1_cnt[1] != 0 {
|
if pm1_cnt[1] != 0 {
|
||||||
let slp_typ = unsafe{ DSDT.slp_typ_b } | (1 << 13);
|
let slp_typ = unsafe { DSDT.slp_typ_b } | (1 << 13);
|
||||||
cpuio::outw(pm1_cnt[1], slp_typ);
|
cpuio::outw(pm1_cnt[1], slp_typ);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{ACPISDTHeader,ACPISDTIter};
|
use super::{ACPISDTHeader, ACPISDTIter};
|
||||||
use cpuio;
|
use cpuio;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -9,13 +9,12 @@ struct GenericAddressStructure {
|
||||||
bitoffset: u8,
|
bitoffset: u8,
|
||||||
accesssize: u8,
|
accesssize: u8,
|
||||||
noused: u32,
|
noused: u32,
|
||||||
address: u64
|
address: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct FADT
|
struct FADT {
|
||||||
{
|
|
||||||
header: ACPISDTHeader,
|
header: ACPISDTHeader,
|
||||||
firmwarectrl: u32,
|
firmwarectrl: u32,
|
||||||
dsdt: u32,
|
dsdt: u32,
|
||||||
|
|
@ -28,33 +27,33 @@ struct FADT
|
||||||
smi_commandport: u32,
|
smi_commandport: u32,
|
||||||
acpi_enable: u8,
|
acpi_enable: u8,
|
||||||
acpidisable: u8,
|
acpidisable: u8,
|
||||||
s4bios_req: u8, //no use
|
s4bios_req: u8, //no use
|
||||||
pstate_control: u8, //no use
|
pstate_control: u8, //no use
|
||||||
pm1aeventblock: u32, //no use
|
pm1aeventblock: u32, //no use
|
||||||
pm1beventblock: u32, //no use
|
pm1beventblock: u32, //no use
|
||||||
pm1acontrolblock: u32,
|
pm1acontrolblock: u32,
|
||||||
pm1bcontrolblock: u32,
|
pm1bcontrolblock: u32,
|
||||||
pm2controlblock: u32, //no use
|
pm2controlblock: u32, //no use
|
||||||
pmtimerblock: u32, //no use
|
pmtimerblock: u32, //no use
|
||||||
gpe0block: u32, //no use
|
gpe0block: u32, //no use
|
||||||
gpe1block: u32, //no use
|
gpe1block: u32, //no use
|
||||||
pm1eventlength: u8, //no use
|
pm1eventlength: u8, //no use
|
||||||
pm1controllength: u8,
|
pm1controllength: u8,
|
||||||
pm2controllength: u8, //no use
|
pm2controllength: u8, //no use
|
||||||
pmtimerlength: u8, //no use
|
pmtimerlength: u8, //no use
|
||||||
gpe0length: u8, //no use
|
gpe0length: u8, //no use
|
||||||
gpe1length: u8, //no use
|
gpe1length: u8, //no use
|
||||||
gpe1base: u8, //no use
|
gpe1base: u8, //no use
|
||||||
cstatecontrol: u8, //no use
|
cstatecontrol: u8, //no use
|
||||||
worstc2latency: u16, //no use
|
worstc2latency: u16, //no use
|
||||||
worstc3latency: u16, //no use
|
worstc3latency: u16, //no use
|
||||||
flushsize: u16, //no use
|
flushsize: u16, //no use
|
||||||
flushstride: u16, //no use
|
flushstride: u16, //no use
|
||||||
dutyoffset: u8, //no use
|
dutyoffset: u8, //no use
|
||||||
dutywidth: u8, //no use
|
dutywidth: u8, //no use
|
||||||
dayalarm: u8, //no use
|
dayalarm: u8, //no use
|
||||||
monthalarm: u8, //no use
|
monthalarm: u8, //no use
|
||||||
century: u8, //no use
|
century: u8, //no use
|
||||||
|
|
||||||
// reserved in acpi 1.0; used since acpi 2.0+
|
// reserved in acpi 1.0; used since acpi 2.0+
|
||||||
bootarchitectureflags: u16,
|
bootarchitectureflags: u16,
|
||||||
|
|
@ -80,19 +79,20 @@ struct FADT
|
||||||
x_pmtimerblock: GenericAddressStructure,
|
x_pmtimerblock: GenericAddressStructure,
|
||||||
x_gpe0block: GenericAddressStructure,
|
x_gpe0block: GenericAddressStructure,
|
||||||
x_gpe1block: GenericAddressStructure,
|
x_gpe1block: GenericAddressStructure,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut FADT: Option<FADT> = None;
|
static mut FADT: Option<FADT> = None;
|
||||||
|
|
||||||
/// ## Initialize Fixed ACPI Description Table (FADT)
|
/// ## Initialize Fixed ACPI Description Table (FADT)
|
||||||
/// input param addr is contain in other ptr of rsdt
|
/// input param addr is contain in other ptr of rsdt
|
||||||
pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> {
|
pub fn init(sdt_iter: ACPISDTIter) -> Result<(), &'static str> {
|
||||||
for sdt_ptr in sdt_iter {
|
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") {
|
||||||
let fadt_tmp: FADT = unsafe{ (*(sdt_ptr as *const FADT)).clone() };
|
// Where is "FADT"? Shut up is magic
|
||||||
unsafe {FADT = Some(fadt_tmp.clone())};
|
let fadt_tmp: FADT = unsafe { (*(sdt_ptr as *const FADT)).clone() };
|
||||||
if !is_enable()? { // TODO do i have to check if enabled before init ???
|
unsafe { FADT = Some(fadt_tmp.clone()) };
|
||||||
|
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 smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST
|
||||||
let acpi_enable = fadt_tmp.acpi_enable;
|
let acpi_enable = fadt_tmp.acpi_enable;
|
||||||
cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command
|
cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command
|
||||||
|
|
@ -103,16 +103,16 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> {
|
||||||
return Err("Can not find Fixed ACPI Description Table (FADT).");
|
return Err("Can not find Fixed ACPI Description Table (FADT).");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_init() -> Result <FADT, &'static str> {
|
fn is_init() -> Result<FADT, &'static str> {
|
||||||
match unsafe {FADT.clone()} {
|
match unsafe { FADT.clone() } {
|
||||||
Some(fadt) => Ok(fadt),
|
Some(fadt) => Ok(fadt),
|
||||||
None => Err("Fixed ACPI Description Table (FADT) is not initialized")
|
None => Err("Fixed ACPI Description Table (FADT) is not initialized"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return Dsdt address
|
/// Return Dsdt address
|
||||||
/// FADT must have been initialized first
|
/// FADT must have been initialized first
|
||||||
pub fn dsdtaddr() -> Result <u32, &'static str> {
|
pub fn dsdtaddr() -> Result<u32, &'static str> {
|
||||||
let fadt = is_init()?;
|
let fadt = is_init()?;
|
||||||
return Ok(fadt.dsdt);
|
return Ok(fadt.dsdt);
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ fn get_cnt(fadt: FADT) -> [u16; 2] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true/false depending of acpi is enable
|
/// Return true/false depending of acpi is enable
|
||||||
pub fn is_enable() -> Result <bool, &'static str> {
|
pub fn is_enable() -> Result<bool, &'static str> {
|
||||||
let fadt = is_init()?;
|
let fadt = is_init()?;
|
||||||
let pm1_cnt = get_cnt(fadt);
|
let pm1_cnt = get_cnt(fadt);
|
||||||
if pm1_cnt[1] == 0 {
|
if pm1_cnt[1] == 0 {
|
||||||
|
|
@ -134,13 +134,13 @@ pub fn is_enable() -> Result <bool, &'static str> {
|
||||||
|
|
||||||
/// Return a array with [pm1a, pm1b]
|
/// Return a array with [pm1a, pm1b]
|
||||||
/// FADT must have been initialized first
|
/// FADT must have been initialized first
|
||||||
pub fn get_controlblock() -> Result <[u16; 2], &'static str> {
|
pub fn get_controlblock() -> Result<[u16; 2], &'static str> {
|
||||||
if !is_enable()? {
|
if !is_enable()? {
|
||||||
Err("ACPI is not enabled")
|
Err("ACPI is not enabled")
|
||||||
} else {
|
} else {
|
||||||
// println!("HALT");
|
// println!("HALT");
|
||||||
// flush!();
|
// flush!();
|
||||||
// cpuio::halt();
|
// cpuio::halt();
|
||||||
Ok(get_cnt(is_init()?)) // TODO redondant call to is_init
|
Ok(get_cnt(is_init()?)) // TODO redondant call to is_init
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ impl ACPISDTHeader {
|
||||||
pub fn valid(addr: u32, signature: &str) -> bool {
|
pub fn valid(addr: u32, signature: &str) -> bool {
|
||||||
if check_signature(addr, signature) {
|
if check_signature(addr, signature) {
|
||||||
let ptr_tmp = addr as *const ACPISDTHeader;
|
let ptr_tmp = addr as *const ACPISDTHeader;
|
||||||
if check_checksum(addr, unsafe {(*ptr_tmp).length} as usize) {
|
if check_checksum(addr, unsafe { (*ptr_tmp).length } as usize) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,16 +36,16 @@ impl ACPISDTHeader {
|
||||||
|
|
||||||
static mut ACPI: Acpi = Acpi {
|
static mut ACPI: Acpi = Acpi {
|
||||||
valid: false,
|
valid: false,
|
||||||
v2: false
|
v2: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Acpi {
|
struct Acpi {
|
||||||
valid: bool,
|
valid: bool,
|
||||||
v2: bool
|
v2: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Acpi {
|
impl Acpi {
|
||||||
fn common_init(&mut self) -> Result <(), &'static str> {
|
fn common_init(&mut self) -> Result<(), &'static str> {
|
||||||
if self.v2 {
|
if self.v2 {
|
||||||
// Xsdt Address:
|
// Xsdt Address:
|
||||||
// 64-bit physical address of the XSDT table. If you detect ACPI Version 2.0 you should use this table instead of RSDT even on x86, casting the address to uint32_t.
|
// 64-bit physical address of the XSDT table. If you detect ACPI Version 2.0 you should use this table instead of RSDT even on x86, casting the address to uint32_t.
|
||||||
|
|
@ -58,20 +58,21 @@ impl Acpi {
|
||||||
dsdt::init(fadt::dsdtaddr()?)?;
|
dsdt::init(fadt::dsdtaddr()?)?;
|
||||||
self.valid = true;
|
self.valid = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
fn init(&mut self) -> Result <(), &'static str> {
|
fn init(&mut self) -> Result<(), &'static str> {
|
||||||
self.v2 = rsdp::init()?;
|
self.v2 = rsdp::init()?;
|
||||||
self.common_init()
|
self.common_init()
|
||||||
}
|
}
|
||||||
fn load(&mut self, rsdp_addr: u32) -> Result <(), &'static str> {
|
fn load(&mut self, rsdp_addr: u32) -> Result<(), &'static str> {
|
||||||
self.v2 = rsdp::load(rsdp_addr)?;
|
self.v2 = rsdp::load(rsdp_addr)?;
|
||||||
self.common_init()
|
self.common_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_signature(addr: u32, id: &str) -> bool {
|
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,
|
Ok(y) => y,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
|
|
@ -79,7 +80,7 @@ fn check_signature(addr: u32, id: &str) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_checksum(addr: u32, len: usize) -> bool {
|
fn check_checksum(addr: u32, len: usize) -> bool {
|
||||||
let byte_array = unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, len)};
|
let byte_array = unsafe { core::slice::from_raw_parts_mut(addr as *mut u8, len) };
|
||||||
let mut sum: u32 = 0;
|
let mut sum: u32 = 0;
|
||||||
for byte in byte_array {
|
for byte in byte_array {
|
||||||
sum += *byte as u32;
|
sum += *byte as u32;
|
||||||
|
|
@ -91,19 +92,23 @@ pub struct ACPISDTIter {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
width: usize,
|
width: usize,
|
||||||
sdt: u32,
|
sdt: u32,
|
||||||
len: usize
|
len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ACPISDTIter {
|
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 {
|
match acpi_sdt {
|
||||||
None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."),
|
None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."),
|
||||||
Some(ptr) => Ok(ACPISDTIter {
|
Some(ptr) => Ok(ACPISDTIter {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
width: ptr_len,
|
width: ptr_len,
|
||||||
sdt: ptr as u32 + mem::size_of::<ACPISDTHeader>() as u32,
|
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,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -116,47 +121,53 @@ impl Iterator for ACPISDTIter {
|
||||||
if self.pos > self.len {
|
if self.pos > self.len {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ret = Some(unsafe {*(self.sdt as *const u32)});
|
let ret = Some(unsafe { *(self.sdt as *const u32) });
|
||||||
self.sdt += self.width as u32;
|
self.sdt += self.width as u32;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_init() -> Result <(), &'static str> {
|
fn is_init() -> Result<(), &'static str> {
|
||||||
if unsafe {ACPI.valid} {
|
if unsafe { ACPI.valid } {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("ACPI is not initialized")
|
Err("ACPI is not initialized")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Initalized the ACPI module
|
/// Initalized the ACPI module
|
||||||
pub fn init() -> Result <(), &'static str> {
|
pub fn init() -> Result<(), &'static str> {
|
||||||
if let Ok(()) = is_init() {
|
if let Ok(()) = is_init() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
unsafe {ACPI.init()}
|
unsafe { ACPI.init() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load the ACPI module, addr given is a ptr to RSDP
|
/// Load the ACPI module, addr given is a ptr to RSDP
|
||||||
pub fn load(rsdp_addr: u32) -> Result <(), &'static str> {
|
pub fn load(rsdp_addr: u32) -> Result<(), &'static str> {
|
||||||
if let Ok(()) = is_init() {
|
if let Ok(()) = is_init() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
unsafe {ACPI.load(rsdp_addr)}
|
unsafe { ACPI.load(rsdp_addr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Proceed to ACPI shutdown
|
/// Proceed to ACPI shutdown
|
||||||
/// This function doesn't work with Virtual Box yet
|
/// This function doesn't work with Virtual Box yet
|
||||||
pub fn shutdown() -> Result <(), &'static str> {
|
pub fn shutdown() -> Result<(), &'static str> {
|
||||||
is_init()?;
|
is_init()?;
|
||||||
dsdt::shutdown(fadt::get_controlblock()?)
|
dsdt::shutdown(fadt::get_controlblock()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Display state of ACPI
|
/// Display state of ACPI
|
||||||
pub fn info() -> Result <(), &'static str> {
|
pub fn info() -> Result<(), &'static str> {
|
||||||
is_init()?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{check_signature,check_checksum};
|
use super::{check_checksum, check_signature};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -27,39 +27,41 @@ static mut RSDPTR: Option<RSDP20> = None;
|
||||||
/// Return a bool
|
/// Return a bool
|
||||||
/// true => RSDP is V2
|
/// true => RSDP is V2
|
||||||
/// false => RSDP is V1
|
/// false => RSDP is V1
|
||||||
pub fn load(addr: u32) -> Result <bool, &'static str> {
|
pub fn load(addr: u32) -> Result<bool, &'static str> {
|
||||||
if check_signature(addr, "RSD PTR ") {
|
if check_signature(addr, "RSD PTR ") {
|
||||||
let rsdp_tmp: RSDP20 = unsafe{ (*(addr as *const RSDP20)).clone() };
|
let rsdp_tmp: RSDP20 = unsafe { (*(addr as *const RSDP20)).clone() };
|
||||||
let revision = rsdp_tmp.rsdp.revision;
|
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>()))
|
||||||
unsafe {RSDPTR = Some(rsdp_tmp)};
|
|| (revision == 2 && check_checksum(addr, mem::size_of::<RSDP20>()))
|
||||||
|
{
|
||||||
|
unsafe { RSDPTR = Some(rsdp_tmp) };
|
||||||
return Ok(revision == 2);
|
return Ok(revision == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err("Not a valid RSD ptr")
|
Err("Not a valid RSD ptr")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn memory_finding() -> Result <bool, &'static str> {
|
fn memory_finding() -> Result<bool, &'static str> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < 0x1000000 {
|
while i < 0x1000000 {
|
||||||
i += 8;
|
i += 8;
|
||||||
if let Ok(result) = load(i) {
|
if let Ok(result) = load(i) {
|
||||||
return Ok(result)
|
return Ok(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err("Can not find Root System Description Pointer (RSDP).")
|
Err("Can not find Root System Description Pointer (RSDP).")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_init() -> Result <RSDP20, &'static str> {
|
fn is_init() -> Result<RSDP20, &'static str> {
|
||||||
match unsafe {RSDPTR.clone()} {
|
match unsafe { RSDPTR.clone() } {
|
||||||
Some(rsdptr) => Ok(rsdptr),
|
Some(rsdptr) => Ok(rsdptr),
|
||||||
None => Err("Root System Description Pointer (RSDP) is not initialized")
|
None => Err("Root System Description Pointer (RSDP) is not initialized"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a ptr on xsdt
|
/// Return a ptr on xsdt
|
||||||
/// RSDP must have been initialized first
|
/// RSDP must have been initialized first
|
||||||
pub fn xsdtaddr() -> Result <u64, &'static str> {
|
pub fn xsdtaddr() -> Result<u64, &'static str> {
|
||||||
let rsdptr = is_init()?;
|
let rsdptr = is_init()?;
|
||||||
let revision = rsdptr.rsdp.revision;
|
let revision = rsdptr.rsdp.revision;
|
||||||
if revision != 2 {
|
if revision != 2 {
|
||||||
|
|
@ -70,7 +72,7 @@ pub fn xsdtaddr() -> Result <u64, &'static str> {
|
||||||
|
|
||||||
/// Return a ptr on rsdt
|
/// Return a ptr on rsdt
|
||||||
/// RSDP must have been initialized first
|
/// RSDP must have been initialized first
|
||||||
pub fn rsdtaddr() -> Result <u32, &'static str> {
|
pub fn rsdtaddr() -> Result<u32, &'static str> {
|
||||||
let rsdptr = is_init()?;
|
let rsdptr = is_init()?;
|
||||||
return Ok(rsdptr.rsdp.rsdtaddr);
|
return Ok(rsdptr.rsdp.rsdtaddr);
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +80,6 @@ pub fn rsdtaddr() -> Result <u32, &'static str> {
|
||||||
/// RSDP init will iter on addr in [0x0 - 0x1000000] to find "RSDP PTR "
|
/// RSDP init will iter on addr in [0x0 - 0x1000000] to find "RSDP PTR "
|
||||||
/// if you already know the location, you should prefer to use load function
|
/// if you already know the location, you should prefer to use load function
|
||||||
/// return an Error if there is no RSDP in memory, or return the value of load function
|
/// return an Error if there is no RSDP in memory, or return the value of load function
|
||||||
pub fn init() -> Result <bool, &'static str> {
|
pub fn init() -> Result<bool, &'static str> {
|
||||||
memory_finding()
|
memory_finding()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
use super::{ACPISDTHeader,ACPISDTIter};
|
use super::{ACPISDTHeader, ACPISDTIter};
|
||||||
|
|
||||||
//TODO this can work only if pagging is disabled
|
//TODO this can work only if pagging is disabled
|
||||||
static mut RSDT: Option<*const ACPISDTHeader> = None;
|
static mut RSDT: Option<*const ACPISDTHeader> = None;
|
||||||
|
|
||||||
/// ## Initialize Root System Description Table (RSDT)
|
/// ## Initialize Root System Description Table (RSDT)
|
||||||
/// input param addr is contain in RSDP
|
/// input param addr is contain in RSDP
|
||||||
pub fn init(addr: u32) -> Result <(), &'static str> {
|
pub fn init(addr: u32) -> Result<(), &'static str> {
|
||||||
if ACPISDTHeader::valid(addr, "RSDT") {
|
if ACPISDTHeader::valid(addr, "RSDT") {
|
||||||
unsafe {RSDT = Some(addr as *const ACPISDTHeader)};
|
unsafe { RSDT = Some(addr as *const ACPISDTHeader) };
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
return Err("Can not find Root System Description Table (RSDT).");
|
return Err("Can not find Root System Description Table (RSDT).");
|
||||||
|
|
@ -15,6 +15,6 @@ pub fn init(addr: u32) -> Result <(), &'static str> {
|
||||||
|
|
||||||
/// Return a iterable of ptr contained in RSDT
|
/// Return a iterable of ptr contained in RSDT
|
||||||
/// RSDT must have been initialized first
|
/// RSDT must have been initialized first
|
||||||
pub fn iter() -> Result <ACPISDTIter, &'static str> {
|
pub fn iter() -> Result<ACPISDTIter, &'static str> {
|
||||||
ACPISDTIter::new(unsafe {RSDT}, 4)
|
ACPISDTIter::new(unsafe { RSDT }, 4)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use super::{ACPISDTHeader,ACPISDTIter};
|
use super::{ACPISDTHeader, ACPISDTIter};
|
||||||
|
|
||||||
//TODO this can work only if pagging is disabled
|
//TODO this can work only if pagging is disabled
|
||||||
static mut XSDT: Option<*const ACPISDTHeader> = None;
|
static mut XSDT: Option<*const ACPISDTHeader> = None;
|
||||||
|
|
||||||
/// ## Initialize Root System Description Table (XSDT)
|
/// ## Initialize Root System Description Table (XSDT)
|
||||||
/// input param addr is contain in RSDP
|
/// input param addr is contain in RSDP
|
||||||
pub fn init(addr: u64) -> Result <(), &'static str> {
|
pub fn init(addr: u64) -> Result<(), &'static str> {
|
||||||
assert!((addr as u32) as u64 == addr);
|
assert!((addr as u32) as u64 == addr);
|
||||||
let addr: u32 = addr as u32;
|
let addr: u32 = addr as u32;
|
||||||
if ACPISDTHeader::valid(addr, "XSDT") {
|
if ACPISDTHeader::valid(addr, "XSDT") {
|
||||||
unsafe {XSDT = Some(addr as *const ACPISDTHeader)};
|
unsafe { XSDT = Some(addr as *const ACPISDTHeader) };
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
return Err("Can not find eXtended System Descriptor Table (XSDT).");
|
return Err("Can not find eXtended System Descriptor Table (XSDT).");
|
||||||
|
|
@ -17,6 +17,6 @@ pub fn init(addr: u64) -> Result <(), &'static str> {
|
||||||
|
|
||||||
/// Return a iterable of ptr contained in XSDT
|
/// Return a iterable of ptr contained in XSDT
|
||||||
/// XSDT must have been initialized first
|
/// XSDT must have been initialized first
|
||||||
pub fn iter() -> Result <ACPISDTIter, &'static str> {
|
pub fn iter() -> Result<ACPISDTIter, &'static str> {
|
||||||
ACPISDTIter::new(unsafe {XSDT}, 8)
|
ACPISDTIter::new(unsafe { XSDT }, 8)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,9 @@ use x86::*;
|
||||||
use x86::structures::paging::*;
|
use x86::structures::paging::*;
|
||||||
use arch::x86::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_start_page = Page::containing_address(VirtAddr::new(offset as u32));
|
||||||
let heap_end_page = Page::containing_address(VirtAddr::new(
|
let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1));
|
||||||
offset as u32 + size as u32 - 1));
|
|
||||||
|
|
||||||
for page in heap_start_page..heap_end_page + 1 {
|
for page in heap_start_page..heap_end_page + 1 {
|
||||||
active_table.map(page, PageTableFlags::WRITABLE);
|
active_table.map(page, PageTableFlags::WRITABLE);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
extern crate raw_cpuid;
|
extern crate raw_cpuid;
|
||||||
|
|
||||||
use core::fmt::{Result};
|
use core::fmt::Result;
|
||||||
|
|
||||||
use self::raw_cpuid::CpuId;
|
use self::raw_cpuid::CpuId;
|
||||||
|
|
||||||
|
|
@ -29,102 +29,260 @@ pub fn cpu_info() -> Result {
|
||||||
|
|
||||||
if let Some(info) = cpuid.get_feature_info() {
|
if let Some(info) = cpuid.get_feature_info() {
|
||||||
print!("Features:");
|
print!("Features:");
|
||||||
if info.has_fpu() { print!(" fpu") };
|
if info.has_fpu() {
|
||||||
if info.has_vme() { print!(", vme") };
|
print!(" fpu")
|
||||||
if info.has_de() { print!(", de") };
|
};
|
||||||
if info.has_pse() { print!(", pse") };
|
if info.has_vme() {
|
||||||
if info.has_tsc() { print!(", tsc") };
|
print!(", vme")
|
||||||
if info.has_msr() { print!(", msr") };
|
};
|
||||||
if info.has_pae() { print!(", pae") };
|
if info.has_de() {
|
||||||
if info.has_mce() { print!(", mce") };
|
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_cmpxchg8b() {
|
||||||
if info.has_apic() { print!(", apic") };
|
print!(", cx8")
|
||||||
if info.has_sysenter_sysexit() { print!(", sep") };
|
};
|
||||||
if info.has_mtrr() { print!(", mtrr") };
|
if info.has_apic() {
|
||||||
if info.has_pge() { print!(", pge") };
|
print!(", apic")
|
||||||
if info.has_mca() { print!(", mca") };
|
};
|
||||||
if info.has_cmov() { print!(", cmov") };
|
if info.has_sysenter_sysexit() {
|
||||||
if info.has_pat() { print!(", pat") };
|
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_pse36() {
|
||||||
if info.has_psn() { print!(", psn") };
|
print!(", pse36")
|
||||||
if info.has_clflush() { print!(", clflush") };
|
};
|
||||||
if info.has_ds() { print!(", ds") };
|
if info.has_psn() {
|
||||||
if info.has_acpi() { print!(", acpi") };
|
print!(", psn")
|
||||||
if info.has_mmx() { print!(", mmx") };
|
};
|
||||||
if info.has_fxsave_fxstor() { print!(", fxsr") };
|
if info.has_clflush() {
|
||||||
if info.has_sse() { print!(", sse") };
|
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_sse2() {
|
||||||
if info.has_ss() { print!(", ss") };
|
print!(", sse2")
|
||||||
if info.has_htt() { print!(", ht") };
|
};
|
||||||
if info.has_tm() { print!(", tm") };
|
if info.has_ss() {
|
||||||
if info.has_pbe() { print!(", pbe") };
|
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_sse3() {
|
||||||
if info.has_pclmulqdq() { print!(", pclmulqdq") };
|
print!(", sse3")
|
||||||
if info.has_ds_area() { print!(", dtes64") };
|
};
|
||||||
if info.has_monitor_mwait() { print!(", monitor") };
|
if info.has_pclmulqdq() {
|
||||||
if info.has_cpl() { print!(", ds_cpl") };
|
print!(", pclmulqdq")
|
||||||
if info.has_vmx() { print!(", vmx") };
|
};
|
||||||
if info.has_smx() { print!(", smx") };
|
if info.has_ds_area() {
|
||||||
if info.has_eist() { print!(", est") };
|
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_tm2() {
|
||||||
if info.has_ssse3() { print!(", ssse3") };
|
print!(", tm2")
|
||||||
if info.has_cnxtid() { print!(", cnxtid") };
|
};
|
||||||
if info.has_fma() { print!(", fma") };
|
if info.has_ssse3() {
|
||||||
if info.has_cmpxchg16b() { print!(", cx16") };
|
print!(", ssse3")
|
||||||
if info.has_pdcm() { print!(", pdcm") };
|
};
|
||||||
if info.has_pcid() { print!(", pcid") };
|
if info.has_cnxtid() {
|
||||||
if info.has_dca() { print!(", dca") };
|
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_sse41() {
|
||||||
if info.has_sse42() { print!(", sse4_2") };
|
print!(", sse4_1")
|
||||||
if info.has_x2apic() { print!(", x2apic") };
|
};
|
||||||
if info.has_movbe() { print!(", movbe") };
|
if info.has_sse42() {
|
||||||
if info.has_popcnt() { print!(", popcnt") };
|
print!(", sse4_2")
|
||||||
if info.has_tsc_deadline() { print!(", tsc_deadline_timer") };
|
};
|
||||||
if info.has_aesni() { print!(", aes") };
|
if info.has_x2apic() {
|
||||||
if info.has_xsave() { print!(", xsave") };
|
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_oxsave() {
|
||||||
if info.has_avx() { print!(", avx") };
|
print!(", xsaveopt")
|
||||||
if info.has_f16c() { print!(", f16c") };
|
};
|
||||||
if info.has_rdrand() { print!(", rdrand") };
|
if info.has_avx() {
|
||||||
|
print!(", avx")
|
||||||
|
};
|
||||||
|
if info.has_f16c() {
|
||||||
|
print!(", f16c")
|
||||||
|
};
|
||||||
|
if info.has_rdrand() {
|
||||||
|
print!(", rdrand")
|
||||||
|
};
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(info) = cpuid.get_extended_function_info() {
|
if let Some(info) = cpuid.get_extended_function_info() {
|
||||||
print!("Extended function:");
|
print!("Extended function:");
|
||||||
if info.has_64bit_mode() { print!(" lm") };
|
if info.has_64bit_mode() {
|
||||||
if info.has_rdtscp() { print!(", rdtscp") };
|
print!(" lm")
|
||||||
if info.has_1gib_pages() { print!(", pdpe1gb") };
|
};
|
||||||
if info.has_execute_disable() { print!(", nx") };
|
if info.has_rdtscp() {
|
||||||
if info.has_syscall_sysret() { print!(", syscall") };
|
print!(", rdtscp")
|
||||||
if info.has_prefetchw() { print!(", prefetchw") };
|
};
|
||||||
if info.has_lzcnt() { print!(", lzcnt") };
|
if info.has_1gib_pages() {
|
||||||
if info.has_lahf_sahf() { print!(", lahf_lm") };
|
print!(", pdpe1gb")
|
||||||
if info.has_invariant_tsc() { print!(", constant_tsc") };
|
};
|
||||||
|
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!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(info) = cpuid.get_extended_feature_info() {
|
if let Some(info) = cpuid.get_extended_feature_info() {
|
||||||
print!("Extended features:");
|
print!("Extended features:");
|
||||||
if info.has_fsgsbase() { print!(" fsgsbase") };
|
if info.has_fsgsbase() {
|
||||||
if info.has_tsc_adjust_msr() { print!(", tsc_adjust") };
|
print!(" fsgsbase")
|
||||||
if info.has_bmi1() { print!(", bmi1") };
|
};
|
||||||
if info.has_hle() { print!(", hle") };
|
if info.has_tsc_adjust_msr() {
|
||||||
if info.has_avx2() { print!(", avx2") };
|
print!(", tsc_adjust")
|
||||||
if info.has_smep() { print!(", smep") };
|
};
|
||||||
if info.has_bmi2() { print!(", bmi2") };
|
if info.has_bmi1() {
|
||||||
if info.has_rep_movsb_stosb() { print!(", erms") };
|
print!(", bmi1")
|
||||||
if info.has_invpcid() { print!(", invpcid") };
|
};
|
||||||
if info.has_rtm() { print!(", rtm") };
|
if info.has_hle() {
|
||||||
if info.has_qm() { print!(", qm") };
|
print!(", hle")
|
||||||
if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") };
|
};
|
||||||
if info.has_mpx() { print!(", mpx") };
|
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!("");
|
println!("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use ::arch::x86::paging::ActivePageTable;
|
use arch::x86::paging::ActivePageTable;
|
||||||
|
|
||||||
pub static mut LOCAL_APIC: LocalApic = LocalApic {
|
pub static mut LOCAL_APIC: LocalApic = LocalApic {
|
||||||
address: 0,
|
address: 0,
|
||||||
x2: false
|
x2: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||||
|
|
@ -11,7 +11,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) {
|
||||||
|
|
||||||
pub struct LocalApic {
|
pub struct LocalApic {
|
||||||
pub address: usize,
|
pub address: usize,
|
||||||
pub x2: bool
|
pub x2: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalApic {
|
impl LocalApic {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use ::arch::x86::paging::ActivePageTable;
|
use arch::x86::paging::ActivePageTable;
|
||||||
pub mod pic;
|
pub mod pic;
|
||||||
pub mod local_apic;
|
pub mod local_apic;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,64 @@
|
||||||
use ::io::{Io, Pio};
|
use io::{Io, Pio};
|
||||||
|
|
||||||
pub static mut MASTER: Pic = Pic::new(0x20);
|
pub static mut MASTER: Pic = Pic::new(0x20);
|
||||||
pub static mut SLAVE: Pic = Pic::new(0xA0);
|
pub static mut SLAVE: Pic = Pic::new(0xA0);
|
||||||
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
|
pub static mut WAIT_PORT: Pio<u8> = Pio::new(0x80);
|
||||||
|
|
||||||
pub unsafe fn init() {
|
pub unsafe fn init() {
|
||||||
let wait = || {WAIT_PORT.write(0)};
|
let wait = || WAIT_PORT.write(0);
|
||||||
let master_mask = MASTER.data.read();
|
let master_mask = MASTER.data.read();
|
||||||
let slave_mask = SLAVE.data.read();
|
let slave_mask = SLAVE.data.read();
|
||||||
|
|
||||||
// Start initialization
|
// Start initialization
|
||||||
MASTER.cmd.write(0x11); wait();
|
MASTER.cmd.write(0x11);
|
||||||
SLAVE.cmd.write(0x11); wait();
|
wait();
|
||||||
|
SLAVE.cmd.write(0x11);
|
||||||
|
wait();
|
||||||
|
|
||||||
// Set offsets
|
// Set offsets
|
||||||
MASTER.data.write(0x20); wait();
|
MASTER.data.write(0x20);
|
||||||
SLAVE.data.write(0x28); wait();
|
wait();
|
||||||
|
SLAVE.data.write(0x28);
|
||||||
|
wait();
|
||||||
|
|
||||||
// Set up cascade
|
// Set up cascade
|
||||||
MASTER.data.write(4); wait();
|
MASTER.data.write(4);
|
||||||
SLAVE.data.write(2); wait();
|
wait();
|
||||||
|
SLAVE.data.write(2);
|
||||||
|
wait();
|
||||||
|
|
||||||
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
// Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI)
|
||||||
MASTER.data.write(1); wait();
|
MASTER.data.write(1);
|
||||||
SLAVE.data.write(1); wait();
|
wait();
|
||||||
|
SLAVE.data.write(1);
|
||||||
|
wait();
|
||||||
|
|
||||||
// Unmask interrupts
|
// Unmask interrupts
|
||||||
MASTER.data.write(0); wait();
|
MASTER.data.write(0);
|
||||||
SLAVE.data.write(0); wait();
|
wait();
|
||||||
|
SLAVE.data.write(0);
|
||||||
|
wait();
|
||||||
|
|
||||||
// Ack remaining interrupts
|
// Ack remaining interrupts
|
||||||
MASTER.ack(); wait();
|
MASTER.ack();
|
||||||
SLAVE.ack(); wait();
|
wait();
|
||||||
|
SLAVE.ack();
|
||||||
|
wait();
|
||||||
|
|
||||||
MASTER.data.write(master_mask); wait();
|
MASTER.data.write(master_mask);
|
||||||
SLAVE.data.write(slave_mask); wait();
|
wait();
|
||||||
|
SLAVE.data.write(slave_mask);
|
||||||
|
wait();
|
||||||
|
|
||||||
// disable all irqs
|
// disable all irqs
|
||||||
MASTER.data.write(!0); wait();
|
MASTER.data.write(!0);
|
||||||
SLAVE.data.write(!0); wait();
|
wait();
|
||||||
|
SLAVE.data.write(!0);
|
||||||
|
wait();
|
||||||
|
|
||||||
// keyboard active
|
// keyboard active
|
||||||
MASTER.mask_clear(1); wait();
|
MASTER.mask_clear(1);
|
||||||
|
wait();
|
||||||
|
|
||||||
// asm!("sti");
|
// asm!("sti");
|
||||||
::x86::instructions::interrupts::enable();
|
::x86::instructions::interrupts::enable();
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@ use x86::instructions::segmentation::set_cs;
|
||||||
use x86::instructions::tables::load_tss;
|
use x86::instructions::tables::load_tss;
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
|
|
||||||
static GDT: Once<gdt::Gdt> = Once::new();
|
// static GDT: Once<gdt::Gdt> = Once::new();
|
||||||
static TSS: Once<tss::TaskStateSegment> = Once::new();
|
// static TSS: Once<tss::TaskStateSegment> = Once::new();
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
// let tss = tss::TaskStateSegment::new();
|
// let tss = tss::TaskStateSegment::new();
|
||||||
let tss = TSS.call_once(|| {
|
// let tss = TSS.call_once(|| {
|
||||||
let mut tss = tss::TaskStateSegment::new();
|
// let mut tss = tss::TaskStateSegment::new();
|
||||||
tss
|
// tss
|
||||||
});
|
// });
|
||||||
|
|
||||||
// let mut code_selector = gdt::SegmentSelector(0);
|
// let mut code_selector = gdt::SegmentSelector(0);
|
||||||
// let mut tss_selector = gdt::SegmentSelector(0);
|
// let mut tss_selector = gdt::SegmentSelector(0);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// https://wiki.osdev.org/Exceptions
|
// https://wiki.osdev.org/Exceptions
|
||||||
|
|
||||||
use ::arch::x86::pti;
|
use arch::x86::pti;
|
||||||
|
|
||||||
macro_rules! exception {
|
macro_rules! exception {
|
||||||
($name:ident, $func:block) => {
|
($name:ident, $func:block) => {
|
||||||
|
|
@ -62,8 +62,9 @@ exception_err!(stack_segment, {});
|
||||||
exception_err!(general_protection, {});
|
exception_err!(general_protection, {});
|
||||||
|
|
||||||
pub extern "x86-interrupt" fn page_fault(
|
pub extern "x86-interrupt" fn page_fault(
|
||||||
stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode)
|
stack_frame: &mut ExceptionStackFrame,
|
||||||
{
|
code: PageFaultErrorCode,
|
||||||
|
) {
|
||||||
println!("Exception: page_fault");
|
println!("Exception: page_fault");
|
||||||
println!("Error code: {:#b}", code);
|
println!("Error code: {:#b}", code);
|
||||||
println!("{:#?}", stack_frame);
|
println!("{:#?}", stack_frame);
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
#[macro_use] pub mod exception;
|
#[macro_use]
|
||||||
#[macro_use] pub mod irq;
|
pub mod exception;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod irq;
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ pub mod interrupt;
|
||||||
pub mod device;
|
pub mod device;
|
||||||
pub mod pti;
|
pub mod pti;
|
||||||
|
|
||||||
pub mod gdt;
|
// pub mod gdt;
|
||||||
pub mod idt;
|
pub mod idt;
|
||||||
|
|
||||||
use multiboot2;
|
use multiboot2;
|
||||||
use acpi;
|
use acpi;
|
||||||
|
|
||||||
#[no_mangle]
|
#[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
|
// parse multiboot2 info
|
||||||
let boot_info = multiboot2::load(multiboot_info_addr);
|
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");
|
acpi::init().expect("ACPI failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill and load idt (exceptions + irqs)
|
||||||
|
idt::init();
|
||||||
|
|
||||||
// set up physical allocator
|
// set up physical allocator
|
||||||
::memory::init(&boot_info);
|
::memory::init(&boot_info);
|
||||||
|
|
||||||
// set up virtual mapping
|
// set up virtual mapping
|
||||||
let mut active_table = paging::init(&boot_info);
|
let mut active_table = paging::init(&boot_info);
|
||||||
|
|
||||||
|
asm!("hlt");
|
||||||
|
|
||||||
// set up heap
|
// set up heap
|
||||||
::allocator::init(&mut active_table);
|
::allocator::init(&mut active_table);
|
||||||
|
|
||||||
// set up memory segmentation
|
|
||||||
// gdt::init();
|
|
||||||
|
|
||||||
// set up interrupts
|
|
||||||
idt::init();
|
|
||||||
|
|
||||||
// set up pic & apic
|
// set up pic & apic
|
||||||
device::init(&mut active_table);
|
device::init(&mut active_table);
|
||||||
|
|
||||||
|
// fill and load gdt
|
||||||
|
// gdt::init();
|
||||||
|
|
||||||
// primary CPU entry point
|
// primary CPU entry point
|
||||||
::kmain();
|
::kmain();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@ impl Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// virtual addr to physical addr translation
|
/// 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;
|
let offset = virtual_address.as_u32() % PAGE_SIZE as u32;
|
||||||
self.translate_page(Page::containing_address(virtual_address))
|
self.translate_page(Page::containing_address(virtual_address))
|
||||||
.map(|frame| frame.start_address() + offset)
|
.map(|frame| frame.start_address() + offset)
|
||||||
|
|
@ -54,33 +53,29 @@ impl Mapper {
|
||||||
};
|
};
|
||||||
|
|
||||||
p1.and_then(|p1| p1[page.p1_index()].pointed_frame())
|
p1.and_then(|p1| p1[page.p1_index()].pointed_frame())
|
||||||
.or_else(huge_page)
|
.or_else(huge_page)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// map a virtual page to a physical frame in the page tables
|
/// 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 p2 = self.p2_mut();
|
||||||
let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())));
|
let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())));
|
||||||
assert!(p1[page.p1_index()].is_unused());
|
assert!(p1[page.p1_index()].is_unused());
|
||||||
p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT);
|
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");
|
let frame = ::memory::allocate_frames(1).expect("out of frames");
|
||||||
self.map_to(page, frame, flags)
|
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 virt_addr = VirtAddr::new(frame.start_address().as_u32());
|
||||||
let page = Page::containing_address(virt_addr);
|
let page = Page::containing_address(virt_addr);
|
||||||
self.map_to(page, frame, flags);
|
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());
|
assert!(self.translate(page.start_address()).is_some());
|
||||||
|
|
||||||
let p1 = self.p2_mut()
|
let p1 = self.p2_mut()
|
||||||
|
|
|
||||||
|
|
@ -51,34 +51,40 @@ impl ActivePageTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with<F>(&mut self,
|
pub fn with<F>(
|
||||||
table: &mut InactivePageTable,
|
&mut self,
|
||||||
temporary_page: &mut temporary_page::TemporaryPage,
|
table: &mut InactivePageTable,
|
||||||
f: F)
|
temporary_page: &mut temporary_page::TemporaryPage,
|
||||||
where F: FnOnce(&mut Mapper)
|
f: F,
|
||||||
{
|
) where
|
||||||
let (cr3_back, _cr3flags_back) = Cr3::read();
|
F: FnOnce(&mut Mapper),
|
||||||
|
{
|
||||||
|
let (cr3_back, _cr3flags_back) = Cr3::read();
|
||||||
|
|
||||||
// map temp page to current p2
|
// map temp page to current p2
|
||||||
let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self);
|
let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self);
|
||||||
|
|
||||||
// overwrite recursive map
|
// overwrite recursive map
|
||||||
self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
self.p2_mut()[1023].set(
|
||||||
tlb::flush_all();
|
table.p2_frame.clone(),
|
||||||
|
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
|
||||||
|
);
|
||||||
|
tlb::flush_all();
|
||||||
|
|
||||||
// execute f in the new context
|
// execute f in the new context
|
||||||
f(self);
|
f(self);
|
||||||
|
|
||||||
// restore recursive mapping to original p2 table
|
// restore recursive mapping to original p2 table
|
||||||
p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
|
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
|
||||||
|
|
||||||
let (p2_frame, cr3_flags) = Cr3::read();
|
let (p2_frame, cr3_flags) = Cr3::read();
|
||||||
let old_table = InactivePageTable { p2_frame };
|
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
|
old_table
|
||||||
}
|
}
|
||||||
|
|
@ -89,39 +95,44 @@ pub struct InactivePageTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InactivePageTable {
|
impl InactivePageTable {
|
||||||
pub fn new(frame: PhysFrame,
|
pub fn new(
|
||||||
active_table: &mut ActivePageTable,
|
frame: PhysFrame,
|
||||||
temporary_page: &mut TemporaryPage)
|
active_table: &mut ActivePageTable,
|
||||||
-> InactivePageTable {
|
temporary_page: &mut TemporaryPage,
|
||||||
{
|
) -> InactivePageTable {
|
||||||
let table = temporary_page.map_table_frame(frame.clone(), active_table);
|
{
|
||||||
|
let table = temporary_page.map_table_frame(frame.clone(), active_table);
|
||||||
|
|
||||||
table.zero();
|
table.zero();
|
||||||
// set up recursive mapping for the table
|
// set up recursive mapping for the table
|
||||||
table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE)
|
table[1023].set(
|
||||||
}
|
frame.clone(),
|
||||||
temporary_page.unmap(active_table);
|
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
|
||||||
InactivePageTable { p2_frame: frame }
|
)
|
||||||
}
|
}
|
||||||
|
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 temporary_page = TemporaryPage::new(Page{number: 0xcafe});
|
|
||||||
let mut active_table = unsafe { ActivePageTable::new() };
|
let mut active_table = unsafe { ActivePageTable::new() };
|
||||||
let mut new_table = {
|
let mut new_table = {
|
||||||
let frame = ::memory::allocate_frames(1).expect("no more frames");
|
let frame = ::memory::allocate_frames(1).expect("no more frames");
|
||||||
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
||||||
};
|
};
|
||||||
|
unsafe {
|
||||||
|
asm!("hlt");
|
||||||
|
}
|
||||||
|
|
||||||
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
||||||
|
|
||||||
// id map vga buffer
|
// id map vga buffer
|
||||||
let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
|
let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
|
||||||
mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE);
|
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");
|
.expect("Memory map tag required");
|
||||||
|
|
||||||
// id map kernel sections
|
// id map kernel sections
|
||||||
|
|
@ -129,24 +140,26 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable
|
||||||
if !section.is_allocated() {
|
if !section.is_allocated() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert!(section.start_address() % PAGE_SIZE as u64 == 0,
|
assert!(
|
||||||
"sections need to be page aligned");
|
section.start_address() % PAGE_SIZE as u64 == 0,
|
||||||
|
"sections need to be page aligned"
|
||||||
|
);
|
||||||
|
|
||||||
let flags = elf_to_pagetable_flags(§ion.flags());
|
let flags = elf_to_pagetable_flags(§ion.flags());
|
||||||
let start_frame = PhysFrame::containing_address(
|
let start_frame =
|
||||||
PhysAddr::new(section.start_address() as u32));
|
PhysFrame::containing_address(PhysAddr::new(section.start_address() as u32));
|
||||||
let end_frame = PhysFrame::containing_address(
|
let end_frame =
|
||||||
PhysAddr::new(section.end_address() as u32 - 1));
|
PhysFrame::containing_address(PhysAddr::new(section.end_address() as u32 - 1));
|
||||||
for frame in start_frame..end_frame + 1 {
|
for frame in start_frame..end_frame + 1 {
|
||||||
mapper.identity_map(frame, flags);
|
mapper.identity_map(frame, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// id map multiboot
|
// id map multiboot
|
||||||
let multiboot_start = PhysFrame::containing_address(
|
let multiboot_start =
|
||||||
PhysAddr::new(boot_info.start_address() as u32));
|
PhysFrame::containing_address(PhysAddr::new(boot_info.start_address() as u32));
|
||||||
let multiboot_end = PhysFrame::containing_address(
|
let multiboot_end =
|
||||||
PhysAddr::new(boot_info.end_address() as u32 - 1));
|
PhysFrame::containing_address(PhysAddr::new(boot_info.end_address() as u32 - 1));
|
||||||
for frame in multiboot_start..multiboot_end + 1 {
|
for frame in multiboot_start..multiboot_end + 1 {
|
||||||
mapper.identity_map(frame, PageTableFlags::PRESENT);
|
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_table = active_table.switch(new_table);
|
||||||
|
|
||||||
let old_p2_page = Page::containing_address(
|
let old_p2_page =
|
||||||
VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
|
Page::containing_address(VirtAddr::new(old_table.p2_frame.start_address().as_u32()));
|
||||||
|
|
||||||
active_table.unmap(old_p2_page);
|
active_table.unmap(old_p2_page);
|
||||||
|
|
||||||
active_table
|
active_table
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags)
|
fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) -> PageTableFlags {
|
||||||
-> PageTableFlags
|
|
||||||
{
|
|
||||||
use multiboot2::ElfSectionFlags;
|
use multiboot2::ElfSectionFlags;
|
||||||
|
|
||||||
let mut flags = PageTableFlags::empty();
|
let mut flags = PageTableFlags::empty();
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
use x86::structures::paging::*;
|
use x86::structures::paging::*;
|
||||||
|
|
||||||
pub trait RecTable
|
pub trait RecTable {
|
||||||
{
|
|
||||||
fn next_table_address(&self, index: usize) -> Option<u32>;
|
fn next_table_address(&self, index: usize) -> Option<u32>;
|
||||||
fn next_table(&self, index: usize) -> Option<&PageTable>;
|
fn next_table(&self, index: usize) -> Option<&PageTable>;
|
||||||
fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>;
|
fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>;
|
||||||
fn next_table_create(&mut self,
|
fn next_table_create(&mut self, index: usize) -> &mut PageTable;
|
||||||
index: usize)
|
|
||||||
-> &mut PageTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecTable for PageTable
|
impl RecTable for PageTable {
|
||||||
{
|
|
||||||
fn next_table_address(&self, index: usize) -> Option<u32> {
|
fn next_table_address(&self, index: usize) -> Option<u32> {
|
||||||
let entry_flags = self[index].flags();
|
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;
|
let table_address = self as *const _ as usize;
|
||||||
Some((table_address << 10 | index << 12) as u32)
|
Some((table_address << 10 | index << 12) as u32)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -32,16 +30,17 @@ impl RecTable for PageTable
|
||||||
.map(|address| unsafe { &mut *(address as *mut _) })
|
.map(|address| unsafe { &mut *(address as *mut _) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_table_create(&mut self,
|
fn next_table_create(&mut self, index: usize) -> &mut PageTable {
|
||||||
index: usize) -> &mut PageTable
|
|
||||||
{
|
|
||||||
if self.next_table(index).is_none() {
|
if self.next_table(index).is_none() {
|
||||||
assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
|
assert!(
|
||||||
"mapping code does not support huge pages");
|
!self[index].flags().contains(PageTableFlags::HUGE_PAGE),
|
||||||
let frame = ::memory::allocate_frames(1)
|
"mapping code does not support huge pages"
|
||||||
.expect("out of memory");
|
);
|
||||||
|
let frame = ::memory::allocate_frames(1).expect("out of memory");
|
||||||
self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE);
|
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")
|
self.next_table_mut(index).expect("no next table 2")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,25 @@ pub struct TemporaryPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TemporaryPage {
|
impl TemporaryPage {
|
||||||
pub fn new(page: Page) -> TemporaryPage
|
pub fn new(page: Page) -> TemporaryPage {
|
||||||
{
|
|
||||||
TemporaryPage { page: page }
|
TemporaryPage { page: page }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps the temporary page to the given frame in the active table.
|
/// Maps the temporary page to the given frame in the active table.
|
||||||
/// Returns the start address of the temporary page.
|
/// Returns the start address of the temporary page.
|
||||||
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable)
|
pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) -> VirtAddr {
|
||||||
-> VirtAddr
|
assert!(
|
||||||
{
|
active_table.translate_page(self.page).is_none(),
|
||||||
assert!(active_table.translate_page(self.page).is_none(),
|
"temporary page is already mapped"
|
||||||
"temporary page is already mapped");
|
);
|
||||||
active_table.map_to(self.page, frame, PageTableFlags::WRITABLE);
|
active_table.map_to(self.page, frame, PageTableFlags::WRITABLE);
|
||||||
// this kind of check should be done in a test routine
|
// this kind of check should be done in a test routine
|
||||||
assert!(active_table.translate_page(self.page).is_some(),
|
assert!(
|
||||||
"temporary page was not mapped");
|
active_table.translate_page(self.page).is_some(),
|
||||||
self.page.start_address()
|
"temporary page was not mapped"
|
||||||
}
|
);
|
||||||
|
self.page.start_address()
|
||||||
|
}
|
||||||
|
|
||||||
/// Unmaps the temporary page in the active table.
|
/// Unmaps the temporary page in the active table.
|
||||||
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
|
pub fn unmap(&mut self, active_table: &mut ActivePageTable) {
|
||||||
|
|
@ -33,10 +34,11 @@ impl TemporaryPage {
|
||||||
|
|
||||||
/// Maps the temporary page to the given page table frame in the active
|
/// Maps the temporary page to the given page table frame in the active
|
||||||
/// table. Returns a reference to the now mapped table.
|
/// table. Returns a reference to the now mapped table.
|
||||||
pub fn map_table_frame(&mut self,
|
pub fn map_table_frame(
|
||||||
frame: PhysFrame,
|
&mut self,
|
||||||
active_table: &mut ActivePageTable)
|
frame: PhysFrame,
|
||||||
-> &mut PageTable {
|
active_table: &mut ActivePageTable,
|
||||||
unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) }
|
) -> &mut PageTable {
|
||||||
}
|
unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,7 @@ unsafe fn switch_stack(old: usize, new: usize) {
|
||||||
|
|
||||||
let new_esp = new - offset_esp;
|
let new_esp = new - offset_esp;
|
||||||
|
|
||||||
ptr::copy_nonoverlapping(
|
ptr::copy_nonoverlapping(old_esp as *const u8, new_esp as *mut u8, offset_esp);
|
||||||
old_esp as *const u8,
|
|
||||||
new_esp as *mut u8,
|
|
||||||
offset_esp
|
|
||||||
);
|
|
||||||
|
|
||||||
// switch the esp with the new one
|
// switch the esp with the new one
|
||||||
asm!("" : : "{esp}"(new_esp) : : "intel", "volatile");
|
asm!("" : : "{esp}"(new_esp) : : "intel", "volatile");
|
||||||
|
|
@ -47,13 +43,19 @@ pub unsafe fn map() {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Switch to per-context stack
|
// 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)]
|
#[inline(always)]
|
||||||
pub unsafe fn unmap() {
|
pub unsafe fn unmap() {
|
||||||
// Switch to per-CPU stack
|
// 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() };
|
// let mut active_table = unsafe { ActivePageTable::new() };
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ use cpuio;
|
||||||
use core::char;
|
use core::char;
|
||||||
use vga::*;
|
use vga::*;
|
||||||
|
|
||||||
fn dispatch(command: &str) -> Result <(), &'static str> {
|
fn dispatch(command: &str) -> Result<(), &'static str> {
|
||||||
match command {
|
match command {
|
||||||
"help" | "h" => self::help(),
|
"help" | "h" => self::help(),
|
||||||
|
|
||||||
// multiboot
|
// multiboot
|
||||||
// "memory" => self::mb2_memory(),
|
// "memory" => self::mb2_memory(),
|
||||||
|
|
@ -16,20 +16,20 @@ fn dispatch(command: &str) -> Result <(), &'static str> {
|
||||||
// "sections" => self::mb2_sections(),
|
// "sections" => self::mb2_sections(),
|
||||||
|
|
||||||
// ACPI
|
// ACPI
|
||||||
"acpi" => self::acpi_info(),
|
"acpi" => self::acpi_info(),
|
||||||
"reboot" => self::reboot(),
|
"reboot" => self::reboot(),
|
||||||
"shutdown" | "halt" | "q" => self::shutdown(),
|
"shutdown" | "halt" | "q" => self::shutdown(),
|
||||||
|
|
||||||
// x86 specific
|
// x86 specific
|
||||||
"stack" => self::print_stack(),
|
"stack" => self::print_stack(),
|
||||||
"regs" => self::regs(),
|
"regs" => self::regs(),
|
||||||
"cpu" => self::cpu(),
|
"cpu" => self::cpu(),
|
||||||
|
|
||||||
_ => Err("Command unknown. (h|help for help)"),
|
_ => Err("Command unknown. (h|help for help)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(cli: &Writer) -> Result <(), &'static str> {
|
pub fn exec(cli: &Writer) -> Result<(), &'static str> {
|
||||||
let command = cli.get_command()?;
|
let command = cli.get_command()?;
|
||||||
if let Err(msg) = self::dispatch(command) {
|
if let Err(msg) = self::dispatch(command) {
|
||||||
set_color!(Red);
|
set_color!(Red);
|
||||||
|
|
@ -39,7 +39,7 @@ pub fn exec(cli: &Writer) -> Result <(), &'static str> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help() -> Result <(), &'static str> {
|
fn help() -> Result<(), &'static str> {
|
||||||
println!("acpi => Return acpi state (ENABLED|DISABLE)");
|
println!("acpi => Return acpi state (ENABLED|DISABLE)");
|
||||||
println!("help | h => Print this help");
|
println!("help | h => Print this help");
|
||||||
// println!("memory => Print memory areas");
|
// println!("memory => Print memory areas");
|
||||||
|
|
@ -59,14 +59,14 @@ fn help() -> Result <(), &'static str> {
|
||||||
/// If reboot failed, will loop on a halt cmd
|
/// If reboot failed, will loop on a halt cmd
|
||||||
///
|
///
|
||||||
fn reboot() -> ! {
|
fn reboot() -> ! {
|
||||||
unsafe {asm!("cli")}; //TODO volatile ?????
|
unsafe { asm!("cli") }; //TODO volatile ?????
|
||||||
// I will now clear the keyboard buffer
|
// I will now clear the keyboard buffer
|
||||||
let mut buffer: u8 = 0x02;
|
let mut buffer: u8 = 0x02;
|
||||||
while buffer & 0x02 != 0 {
|
while buffer & 0x02 != 0 {
|
||||||
cpuio::inb(0x60);
|
cpuio::inb(0x60);
|
||||||
buffer = cpuio::inb(0x64);
|
buffer = cpuio::inb(0x64);
|
||||||
}
|
}
|
||||||
cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot
|
cpuio::outb(0x64, 0xFE); //Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot
|
||||||
println!("Unable to perform reboot. Kernel will be halted");
|
println!("Unable to perform reboot. Kernel will be halted");
|
||||||
cpuio::halt();
|
cpuio::halt();
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ fn reboot() -> ! {
|
||||||
/// If shutdown is performed but failed, will loop on a halt cmd
|
/// If shutdown is performed but failed, will loop on a halt cmd
|
||||||
/// If shutdown cannot be called, return a Err(&str)
|
/// If shutdown cannot be called, return a Err(&str)
|
||||||
///
|
///
|
||||||
fn shutdown() -> Result <(), &'static str> {
|
fn shutdown() -> Result<(), &'static str> {
|
||||||
acpi::shutdown()?;
|
acpi::shutdown()?;
|
||||||
println!("Unable to perform ACPI shutdown. Kernel will be halted");
|
println!("Unable to perform ACPI shutdown. Kernel will be halted");
|
||||||
cpuio::halt();
|
cpuio::halt();
|
||||||
|
|
@ -102,14 +102,14 @@ fn print_line(line: &[u8], address: usize) {
|
||||||
for byte in line {
|
for byte in line {
|
||||||
print!("{:02x} ", *byte);
|
print!("{:02x} ", *byte);
|
||||||
}
|
}
|
||||||
let length : usize = 16 - line.len();
|
let length: usize = 16 - line.len();
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
print!(" ");
|
print!(" ");
|
||||||
}
|
}
|
||||||
print!("|");
|
print!("|");
|
||||||
for byte in line {
|
for byte in line {
|
||||||
match is_control(*byte as char) {
|
match is_control(*byte as char) {
|
||||||
true => print!("."),
|
true => print!("."),
|
||||||
false => print!("{}", *byte as char),
|
false => print!("{}", *byte as char),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ fn print_line(line: &[u8], address: usize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print the kernel stack
|
/// Print the kernel stack
|
||||||
fn print_stack() -> Result <(), &'static str> {
|
fn print_stack() -> Result<(), &'static str> {
|
||||||
let esp: usize;
|
let esp: usize;
|
||||||
let ebp: usize;
|
let ebp: usize;
|
||||||
unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) };
|
unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) };
|
||||||
|
|
@ -172,14 +172,14 @@ fn print_stack() -> Result <(), &'static str> {
|
||||||
// Ok(())
|
// Ok(())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn acpi_info() -> Result <(), &'static str> {
|
pub fn acpi_info() -> Result<(), &'static str> {
|
||||||
acpi::info()?;
|
acpi::info()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump control registers
|
/// Dump control registers
|
||||||
pub fn regs() -> Result <(), &'static str> {
|
pub fn regs() -> Result<(), &'static str> {
|
||||||
use ::x86::registers::control::*;
|
use x86::registers::control::*;
|
||||||
println!("cr0 = {:?}", Cr0::read());
|
println!("cr0 = {:?}", Cr0::read());
|
||||||
println!("cr3 = {:?}", Cr3::read());
|
println!("cr3 = {:?}", Cr3::read());
|
||||||
println!("cr4 = {:?}", Cr4::read());
|
println!("cr4 = {:?}", Cr4::read());
|
||||||
|
|
@ -188,8 +188,8 @@ pub fn regs() -> Result <(), &'static str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dump cpu info, should add power management info
|
/// Dump cpu info, should add power management info
|
||||||
pub fn cpu() -> Result <(), &'static str> {
|
pub fn cpu() -> Result<(), &'static str> {
|
||||||
use ::arch::x86::device::cpu;
|
use arch::x86::device::cpu;
|
||||||
cpu::cpu_info().expect("cpu info not available");
|
cpu::cpu_info().expect("cpu info not available");
|
||||||
flush!();
|
flush!();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -5,50 +5,52 @@ pub fn inb(port: u16) -> u8 {
|
||||||
// The registers for the `in` and `out` instructions are always the
|
// The registers for the `in` and `out` instructions are always the
|
||||||
// same: `a` for value, and `d` for the port address.
|
// same: `a` for value, and `d` for the port address.
|
||||||
let result: u8;
|
let result: u8;
|
||||||
unsafe {asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile")};
|
unsafe { asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile") };
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a `u8`-sized `value` to `port`.
|
/// Write a `u8`-sized `value` to `port`.
|
||||||
pub fn outb(port: u16, value: u8) {
|
pub fn outb(port: u16, value: u8) {
|
||||||
unsafe {asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile")};
|
unsafe { asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile") };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a `u16`-sized value from `port`.
|
/// Read a `u16`-sized value from `port`.
|
||||||
pub fn inw(port: u16) -> u16 {
|
pub fn inw(port: u16) -> u16 {
|
||||||
let result: u16;
|
let result: u16;
|
||||||
unsafe {asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile")};
|
unsafe { asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile") };
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a `u8`-sized `value` to `port`.
|
/// Write a `u8`-sized `value` to `port`.
|
||||||
pub fn outw(port: u16, value: u16) {
|
pub fn outw(port: u16, value: u16) {
|
||||||
unsafe {asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile")};
|
unsafe { asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile") };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a `u32`-sized value from `port`.
|
/// Read a `u32`-sized value from `port`.
|
||||||
pub fn inl(port: u16) -> u32 {
|
pub fn inl(port: u16) -> u32 {
|
||||||
let result: u32;
|
let result: u32;
|
||||||
unsafe {asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile")};
|
unsafe { asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile") };
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a `u32`-sized `value` to `port`.
|
/// Write a `u32`-sized `value` to `port`.
|
||||||
pub fn outl(port: u16, value: u32) {
|
pub fn outl(port: u16, value: u32) {
|
||||||
unsafe {asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile")};
|
unsafe { asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile") };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Halt system
|
/// Halt system
|
||||||
pub fn halt() -> ! {
|
pub fn halt() -> ! {
|
||||||
unsafe {asm!("cli" : : : : "volatile")};
|
unsafe { asm!("cli" : : : : "volatile") };
|
||||||
loop {
|
loop {
|
||||||
unsafe {asm!("hlt" : : : : "volatile")};
|
unsafe { asm!("hlt" : : : : "volatile") };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// wait for an io operation to complete
|
/// wait for an io operation to complete
|
||||||
pub fn io_wait() {
|
pub fn io_wait() {
|
||||||
unsafe { asm!("jmp 1f\n\t
|
unsafe {
|
||||||
|
asm!("jmp 1f\n\t
|
||||||
1:jmp 2f\n\t
|
1:jmp 2f\n\t
|
||||||
2:" : : : : "volatile")}
|
2:" : : : : "volatile")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,17 @@ pub use self::pio::*;
|
||||||
use core::ops::{BitAnd, BitOr, Not};
|
use core::ops::{BitAnd, BitOr, Not};
|
||||||
|
|
||||||
pub trait Io {
|
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 read(&self) -> Self::Value;
|
||||||
fn write(&mut self, value: Self::Value);
|
fn write(&mut self, value: Self::Value);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn readf(&self, flags: Self::Value) -> bool {
|
fn readf(&self, flags: Self::Value) -> bool {
|
||||||
(self.read() & flags) as Self::Value == flags
|
(self.read() & flags) as Self::Value == flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use cpuio;
|
||||||
use vga;
|
use vga;
|
||||||
|
|
||||||
const MAX_KEYS: usize = 59;
|
const MAX_KEYS: usize = 59;
|
||||||
const KEYMAP_US: [[u8;2]; MAX_KEYS] = [
|
const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [
|
||||||
*b"\0\0",
|
*b"\0\0",
|
||||||
*b"\0\0",//escape
|
*b"\0\0",//escape
|
||||||
*b"1!",
|
*b"1!",
|
||||||
|
|
@ -84,25 +84,24 @@ pub fn kbd_callback() {
|
||||||
if (control & 1) == 1 {
|
if (control & 1) == 1 {
|
||||||
let scancode = cpuio::inb(0x60);
|
let scancode = cpuio::inb(0x60);
|
||||||
let (is_release, scancode) = check_key_state(scancode);
|
let (is_release, scancode) = check_key_state(scancode);
|
||||||
unsafe {//TODO remove unsafe
|
unsafe {
|
||||||
|
//TODO remove unsafe
|
||||||
match self::KEYMAP_US.get(scancode as usize) {
|
match self::KEYMAP_US.get(scancode as usize) {
|
||||||
Some(b"\0\0") => {
|
Some(b"\0\0") => match scancode {
|
||||||
match scancode {
|
0x2A | 0x36 => SHIFT = !is_release,
|
||||||
0x2A | 0x36 => {SHIFT = !is_release},
|
0x38 => ALT = !is_release,
|
||||||
0x38 => {ALT = !is_release},
|
0x1D => CTRL = !is_release,
|
||||||
0x1D => {CTRL = !is_release},
|
0x0E if !is_release => {
|
||||||
0x0E if !is_release => {
|
vga::VGA.backspace();
|
||||||
vga::VGA.backspace();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
},
|
},
|
||||||
Some(ascii) if !is_release => {
|
Some(ascii) if !is_release => {
|
||||||
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
let sym = if SHIFT { ascii[1] } else { ascii[0] };
|
||||||
vga::VGA.keypress(sym);
|
vga::VGA.keypress(sym);
|
||||||
},
|
}
|
||||||
Some(_) => {},
|
Some(_) => {}
|
||||||
None =>{},
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,28 +7,28 @@
|
||||||
#![feature(ptr_internals)]
|
#![feature(ptr_internals)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
|
|
||||||
// home made heap
|
// home made heap
|
||||||
#![feature(alloc)]
|
#![feature(alloc)]
|
||||||
#![feature(allocator_api)]
|
#![feature(allocator_api)]
|
||||||
#![feature(global_allocator)]
|
#![feature(global_allocator)]
|
||||||
|
|
||||||
// x86 specific
|
// x86 specific
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
|
|
||||||
extern crate rlibc;
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
extern crate spin;
|
#[macro_use]
|
||||||
#[macro_use] extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate multiboot2;
|
extern crate multiboot2;
|
||||||
extern crate slab_allocator;
|
|
||||||
extern crate raw_cpuid;
|
extern crate raw_cpuid;
|
||||||
|
extern crate rlibc;
|
||||||
|
extern crate slab_allocator;
|
||||||
|
extern crate spin;
|
||||||
|
|
||||||
// used by arch/x86, need conditional compilation here
|
// used by arch/x86, need conditional compilation here
|
||||||
extern crate x86;
|
extern crate x86;
|
||||||
|
|
||||||
/// 80x25 terminal driver
|
/// 80x25 terminal driver
|
||||||
#[macro_use] pub mod vga;
|
#[macro_use]
|
||||||
|
pub mod vga;
|
||||||
/// PS/2 detection and processing
|
/// PS/2 detection and processing
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
/// simplisitc kernel commands
|
/// simplisitc kernel commands
|
||||||
|
|
@ -45,9 +45,10 @@ pub mod memory;
|
||||||
/// arch specific entry points
|
/// arch specific entry points
|
||||||
pub mod arch;
|
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() -> ! {
|
pub fn kmain() -> ! {
|
||||||
// core is loaded now
|
// heap avalaible for tracking free'd frames
|
||||||
memory::init_noncore();
|
memory::init_noncore();
|
||||||
|
|
||||||
// x86::instructions::interrupts::int3();
|
// x86::instructions::interrupts::int3();
|
||||||
|
|
@ -66,12 +67,13 @@ pub fn kmain() -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[lang = "eh_personality"] #[no_mangle]
|
#[lang = "eh_personality"]
|
||||||
pub extern fn eh_personality() {}
|
#[no_mangle]
|
||||||
|
pub extern "C" fn eh_personality() {}
|
||||||
|
|
||||||
#[lang = "panic_fmt"] #[no_mangle]
|
#[lang = "panic_fmt"]
|
||||||
pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32)
|
#[no_mangle]
|
||||||
-> ! {
|
pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
|
||||||
println!("PANIC: {}", fmt);
|
println!("PANIC: {}", fmt);
|
||||||
println!("FILE: {}", file);
|
println!("FILE: {}", file);
|
||||||
println!("LINE: {}", line);
|
println!("LINE: {}", line);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use multiboot2::{MemoryAreaIter, MemoryArea};
|
use multiboot2::{MemoryArea, MemoryAreaIter};
|
||||||
use x86::*;
|
use x86::*;
|
||||||
use x86::structures::paging::PhysFrame;
|
use x86::structures::paging::PhysFrame;
|
||||||
use super::FrameAllocator;
|
use super::FrameAllocator;
|
||||||
|
|
@ -14,21 +14,21 @@ pub struct BumpFrameAllocator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BumpFrameAllocator {
|
impl BumpFrameAllocator {
|
||||||
pub fn new(kernel_start: usize, kernel_end: usize,
|
pub fn new(
|
||||||
multiboot_start: usize, multiboot_end: usize,
|
kernel_start: usize,
|
||||||
memory_areas: MemoryAreaIter) -> BumpFrameAllocator {
|
kernel_end: usize,
|
||||||
|
multiboot_start: usize,
|
||||||
|
multiboot_end: usize,
|
||||||
|
memory_areas: MemoryAreaIter,
|
||||||
|
) -> BumpFrameAllocator {
|
||||||
let mut allocator = BumpFrameAllocator {
|
let mut allocator = BumpFrameAllocator {
|
||||||
next_free_frame: PhysFrame { number: 0 },
|
next_free_frame: PhysFrame { number: 0 },
|
||||||
current_area: None,
|
current_area: None,
|
||||||
areas: memory_areas,
|
areas: memory_areas,
|
||||||
kernel_start: PhysFrame::containing_address(
|
kernel_start: PhysFrame::containing_address(PhysAddr::new(kernel_start as u32)),
|
||||||
PhysAddr::new(kernel_start as u32)),
|
kernel_end: PhysFrame::containing_address(PhysAddr::new(kernel_end as u32)),
|
||||||
kernel_end: PhysFrame::containing_address(
|
multiboot_start: PhysFrame::containing_address(PhysAddr::new(multiboot_start as u32)),
|
||||||
PhysAddr::new(kernel_end as u32)),
|
multiboot_end: PhysFrame::containing_address(PhysAddr::new(multiboot_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.choose_next_area();
|
||||||
allocator
|
allocator
|
||||||
|
|
@ -36,13 +36,16 @@ impl BumpFrameAllocator {
|
||||||
|
|
||||||
fn choose_next_area(&mut self) {
|
fn choose_next_area(&mut self) {
|
||||||
// get next area with free frames
|
// get next area with free frames
|
||||||
self.current_area = self.areas.clone().filter(|area| {
|
self.current_area = self.areas
|
||||||
area.end_address() >= self.next_free_frame.start_address().as_u32() as usize
|
.clone()
|
||||||
}).min_by_key(|area| area.start_address());
|
.filter(|area| {
|
||||||
|
area.end_address() >= self.next_free_frame.start_address().as_u32() as usize
|
||||||
|
})
|
||||||
|
.min_by_key(|area| area.start_address());
|
||||||
|
|
||||||
if let Some(area) = self.current_area {
|
if let Some(area) = self.current_area {
|
||||||
let start_frame = PhysFrame::containing_address(
|
let start_frame =
|
||||||
PhysAddr::new(area.start_address() as u32));
|
PhysFrame::containing_address(PhysAddr::new(area.start_address() as u32));
|
||||||
if self.next_free_frame < start_frame {
|
if self.next_free_frame < start_frame {
|
||||||
self.next_free_frame = start_frame;
|
self.next_free_frame = start_frame;
|
||||||
}
|
}
|
||||||
|
|
@ -52,22 +55,32 @@ impl BumpFrameAllocator {
|
||||||
|
|
||||||
impl FrameAllocator for BumpFrameAllocator {
|
impl FrameAllocator for BumpFrameAllocator {
|
||||||
fn allocate_frames(&mut self, count: usize) -> Option<PhysFrame> {
|
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 {
|
if let Some(area) = self.current_area {
|
||||||
let start_frame = PhysFrame { number: self.next_free_frame.number };
|
let start_frame = PhysFrame {
|
||||||
let end_frame = PhysFrame { number: self.next_free_frame.number + count as u32 - 1 };
|
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(
|
let current_area_last_frame =
|
||||||
PhysAddr::new(area.end_address() as u32));
|
PhysFrame::containing_address(PhysAddr::new(area.end_address() as u32));
|
||||||
if end_frame > current_area_last_frame {
|
if end_frame > current_area_last_frame {
|
||||||
// all frames are taken in this area
|
// all frames are taken in this area
|
||||||
self.choose_next_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
|
// frame used by kernel
|
||||||
self.next_free_frame = PhysFrame {
|
self.next_free_frame = PhysFrame {
|
||||||
number: self.kernel_end.number + 1,
|
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
|
// frame used by multiboot
|
||||||
self.next_free_frame = PhysFrame {
|
self.next_free_frame = PhysFrame {
|
||||||
number: self.multiboot_end.number + 1,
|
number: self.multiboot_end.number + 1,
|
||||||
|
|
@ -79,13 +92,17 @@ impl FrameAllocator for BumpFrameAllocator {
|
||||||
// try again with next_free_frame
|
// try again with next_free_frame
|
||||||
self.allocate_frames(count)
|
self.allocate_frames(count)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) {
|
fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) {
|
||||||
// bump doesnt deallocate, must be used inside of a recycler
|
// 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!();
|
// unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,20 +24,27 @@ pub fn init(boot_info: &multiboot2::BootInformation) {
|
||||||
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
|
let elf_sections_tag = boot_info.elf_sections_tag().unwrap();
|
||||||
let memory_map_tag = boot_info.memory_map_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())
|
.filter(|s| s.is_allocated())
|
||||||
.map(|s| s.start_address())
|
.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())
|
.filter(|s| s.is_allocated())
|
||||||
.map(|s| s.start_address() + s.size())
|
.map(|s| s.start_address() + s.size())
|
||||||
.max().unwrap();
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let bump_allocator = BumpFrameAllocator::new(
|
let bump_allocator = BumpFrameAllocator::new(
|
||||||
kernel_start as usize, kernel_end as usize,
|
kernel_start as usize,
|
||||||
boot_info.start_address(), boot_info.end_address(),
|
kernel_end as usize,
|
||||||
memory_map_tag.memory_areas());
|
boot_info.start_address(),
|
||||||
|
boot_info.end_address(),
|
||||||
|
memory_map_tag.memory_areas(),
|
||||||
|
);
|
||||||
|
|
||||||
let frame_allocator = RecycleAllocator::new(bump_allocator);
|
let frame_allocator = RecycleAllocator::new(bump_allocator);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ impl<T: FrameAllocator> RecycleAllocator<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge(&mut self, address: usize, count: usize) -> bool {
|
fn merge(&mut self, address: usize, count: usize) -> bool {
|
||||||
for i in 0 .. self.free.len() {
|
for i in 0..self.free.len() {
|
||||||
let changed = {
|
let changed = {
|
||||||
let free = &mut self.free[i];
|
let free = &mut self.free[i];
|
||||||
if address + count * 4096 == free.0 {
|
if address + count * 4096 == free.0 {
|
||||||
|
|
@ -97,7 +97,7 @@ impl<T: FrameAllocator> FrameAllocator for RecycleAllocator<T> {
|
||||||
self.inner.deallocate_frames(frame, count);
|
self.inner.deallocate_frames(frame, count);
|
||||||
} else {
|
} else {
|
||||||
let address = frame.start_address().as_u32() as usize;
|
let address = frame.start_address().as_u32() as usize;
|
||||||
if ! self.merge(address, count) {
|
if !self.merge(address, count) {
|
||||||
self.free.push((address, count));
|
self.free.push((address, count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ macro_rules! set_color {
|
||||||
|
|
||||||
pub fn print(args: fmt::Arguments) {
|
pub fn print(args: fmt::Arguments) {
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
unsafe { self::VGA.write_fmt(args).unwrap(); }
|
unsafe {
|
||||||
|
self::VGA.write_fmt(args).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
@ -51,7 +53,8 @@ const BUFFER_COLS: usize = 80 * 2;
|
||||||
pub struct Writer {
|
pub struct Writer {
|
||||||
pub buffer_pos: usize,
|
pub buffer_pos: usize,
|
||||||
pub color_code: ColorCode,
|
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,
|
command_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,13 +83,11 @@ impl Writer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_command(&self) -> Result <&str, &'static str> {
|
pub fn get_command(&self) -> Result<&str, &'static str> {
|
||||||
|
|
||||||
match core::str::from_utf8(&self.command) {
|
match core::str::from_utf8(&self.command) {
|
||||||
Ok(y) => Ok(&y[..self.command_len]),
|
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) {
|
pub fn keypress(&mut self, ascii: u8) {
|
||||||
|
|
@ -106,9 +107,11 @@ impl Writer {
|
||||||
self.prompt();
|
self.prompt();
|
||||||
}
|
}
|
||||||
_ if self.command_len >= 10 => (),
|
_ if self.command_len >= 10 => (),
|
||||||
byte if self.command_len == 0 && byte == b' ' => (),
|
byte if self.command_len == 0 && byte == b' ' => (),
|
||||||
byte => {
|
byte => {
|
||||||
if self.command_len >= 10 { return };
|
if self.command_len >= 10 {
|
||||||
|
return;
|
||||||
|
};
|
||||||
self.command[self.command_len] = byte;
|
self.command[self.command_len] = byte;
|
||||||
self.write_byte(byte);
|
self.write_byte(byte);
|
||||||
self.command_len += 1;
|
self.command_len += 1;
|
||||||
|
|
@ -130,7 +133,6 @@ impl Writer {
|
||||||
let i = self.buffer_pos;
|
let i = self.buffer_pos;
|
||||||
|
|
||||||
match byte {
|
match byte {
|
||||||
|
|
||||||
b'\n' => {
|
b'\n' => {
|
||||||
let current_line = self.buffer_pos / (BUFFER_COLS);
|
let current_line = self.buffer_pos / (BUFFER_COLS);
|
||||||
self.buffer_pos = (current_line + 1) * BUFFER_COLS;
|
self.buffer_pos = (current_line + 1) * BUFFER_COLS;
|
||||||
|
|
@ -178,7 +180,7 @@ impl Writer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for col in 0..BUFFER_COLS/2 {
|
for col in 0..BUFFER_COLS / 2 {
|
||||||
self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' ';
|
self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,22 +201,28 @@ impl fmt::Write for Writer {
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
set_color!(White, Cyan);
|
set_color!(White, Cyan);
|
||||||
print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
print!(
|
||||||
format_args!("{: ^80}", r#" ,--, "#),
|
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||||
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
format_args!("{: ^80}", r#" ,--, "#),
|
||||||
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
format_args!("{: ^80}", r#" ,--.'| ,----, "#),
|
||||||
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
format_args!("{: ^80}", r#" ,--, | : .' .' \ "#),
|
||||||
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#),
|
||||||
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
format_args!("{: ^80}", r#"; : | | ; | : . ; "#),
|
||||||
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
format_args!("{: ^80}", r#"| | : _' | ; |.' / "#),
|
||||||
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
format_args!("{: ^80}", r#": : |.' | `----'/ ; "#),
|
||||||
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
format_args!("{: ^80}", r#"| ' ' ; : / ; / "#),
|
||||||
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#),
|
||||||
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#),
|
||||||
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
format_args!("{: ^80}", r#" ' ; |./__; : "#),
|
||||||
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
format_args!("{: ^80}", r#" | : ;| : .' "#),
|
||||||
format_args!("{: ^80}", r#" '--' `---' "#));
|
format_args!("{: ^80}", r#" ' ,/ ; | .' "#),
|
||||||
|
format_args!("{: ^80}", r#" '--' `---' "#)
|
||||||
|
);
|
||||||
set_color!();
|
set_color!();
|
||||||
unsafe { VGA.prompt(); }
|
unsafe {
|
||||||
unsafe { VGA.flush(); }
|
VGA.prompt();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
VGA.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue