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

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

View file

@ -13,12 +13,12 @@ spin = "0.4"
slab_allocator = "0.3.1" 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"

View file

@ -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(())

View file

@ -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
} }
} }

View file

@ -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(())
} }

View file

@ -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()
} }

View file

@ -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)
} }

View file

@ -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)
} }

View file

@ -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);

View file

@ -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!("");
} }

View file

@ -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 {

View file

@ -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;

View file

@ -1,47 +1,64 @@
use ::io::{Io, Pio}; use io::{Io, Pio};
pub static mut MASTER: Pic = Pic::new(0x20); pub static mut 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();

View file

@ -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);

View file

@ -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);

View file

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

View file

@ -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();
} }

View file

@ -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()

View file

@ -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(&section.flags()); let flags = elf_to_pagetable_flags(&section.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();

View file

@ -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")
} }

View file

@ -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) }
}
} }

View file

@ -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() };

View file

@ -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(())

View file

@ -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")
}
} }

View file

@ -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
} }

View file

@ -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 => {}
} }
} }
} }

View file

@ -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);

View file

@ -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!();
} }
} }

View file

@ -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);

View file

@ -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));
} }
} }

View file

@ -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();
}
} }