updated + alignment does not exist
This commit is contained in:
@@ -8,7 +8,7 @@ rustflags = [
|
||||
"-C", "link-arg=-Tsrc/arch/riscv64/link.ld",
|
||||
"-C", "link-arg=--omagic",
|
||||
]
|
||||
runner = "qemu-system-riscv64 -nographic -semihosting -cpu rv64 -machine virt -bios none -smp 4 -m 1G -device virtio-blk-pci,drive=test -drive file=test.raw,format=raw,id=test -kernel"
|
||||
runner = "qemu-system-riscv64 -nographic -semihosting -cpu rv64 -machine virt -bios none -smp 4 -m 1G -device virtio-blk-pci,drive=mewhen -drive file=test.raw,format=raw,id=mewhen -kernel"
|
||||
|
||||
[unstable]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use core::{arch::asm, ops::Range};
|
||||
use core::{arch::naked_asm, ops::Range};
|
||||
|
||||
use crate::{
|
||||
arch::{asm, csr, interrupts, paging, wait},
|
||||
@@ -8,9 +8,9 @@ use crate::{
|
||||
|
||||
#[no_mangle]
|
||||
#[link_section = ".text.init"]
|
||||
#[naked]
|
||||
unsafe extern "C" fn _start() -> ! {
|
||||
asm!(
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn _start() {
|
||||
naked_asm!(
|
||||
// disable interrupts
|
||||
"csrw mie, zero",
|
||||
// set up gp & sp
|
||||
@@ -31,15 +31,13 @@ unsafe extern "C" fn _start() -> ! {
|
||||
"la t0, {init}",
|
||||
"csrw mepc, t0",
|
||||
"mret",
|
||||
|
||||
init = sym init,
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[unsafe(naked)]
|
||||
pub unsafe extern "C" fn to_supervisor() {
|
||||
asm!(
|
||||
naked_asm!(
|
||||
"li t0, (1 << 8) | (1 << 5)",
|
||||
"csrw sstatus, t0",
|
||||
"li t0, (7 << 0) | (1 << 3)",
|
||||
@@ -53,7 +51,6 @@ pub unsafe extern "C" fn to_supervisor() {
|
||||
"csrw sepc, t0",
|
||||
"sfence.vma",
|
||||
"sret",
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,7 +61,7 @@ pub unsafe fn init() -> ! {
|
||||
wait();
|
||||
}
|
||||
interrupts::init();
|
||||
let fdt = FDT::from_addr(dt_addr);
|
||||
let fdt = FDT::from_addr(dt_addr).expect("Failed to parse fdt");
|
||||
let raw_mem_range = fdt.mem_range().expect("we lost guys");
|
||||
let heap_start = paging::init(raw_mem_range.end());
|
||||
let heap_mem = Range {
|
||||
|
||||
@@ -4,7 +4,7 @@ pub fn init() {
|
||||
csr::mtvec::init!(stuff);
|
||||
}
|
||||
|
||||
#[repr(align(4))]
|
||||
#[rustc_align(4)]
|
||||
pub fn stuff() -> ! {
|
||||
let mcause = csr::mcause::read();
|
||||
crate::println!("interrupt triggered: {mcause:?}");
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
use crate::util::mutex::Mutex;
|
||||
use core::arch::asm;
|
||||
|
||||
// --machine sifive_u
|
||||
// const UART_BASE: u32 = 0x10010000;
|
||||
// --machine virt
|
||||
const UART_BASE: u32 = 0x10000000;
|
||||
static UART: Mutex<Uart> = Mutex::new(Uart::new(UART_BASE));
|
||||
|
||||
struct Uart {
|
||||
base: u32,
|
||||
}
|
||||
|
||||
impl Uart {
|
||||
pub const fn new(base: u32) -> Self {
|
||||
Self { base }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for Uart {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for b in s.as_bytes() {
|
||||
#[allow(clippy::while_immutable_condition)]
|
||||
while unsafe { *(self.base as *mut i32) } < 0 {}
|
||||
unsafe { *(self.base as *mut i32) = *b as i32 }
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(code: usize) -> ! {
|
||||
let data = [0x20026, code];
|
||||
unsafe {
|
||||
@@ -53,14 +23,3 @@ unsafe fn semihost(call: usize, data: *const u8) {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn _print(args: core::fmt::Arguments<'_>) {
|
||||
// NOTE: something really dumb can happen here;
|
||||
// if you evaluate an expression in a print statement, and that
|
||||
// causes an interrupt, this will be left locked...
|
||||
// Should I set up the heap before interrupts? or just avoid printing until both...?
|
||||
// or maybe force unlock if there's an interrupt?
|
||||
// or store the hart in the lock, and unlock if that hart was interrupted??
|
||||
// or just have a constant-sized buffer?
|
||||
// or create a "locked writer"?
|
||||
UART.lock().write_fmt(args).unwrap();
|
||||
}
|
||||
|
||||
@@ -58,31 +58,28 @@ pub struct RawProp {
|
||||
|
||||
pub struct FDT {
|
||||
pub header: &'static Header,
|
||||
pub nodes: &'static [u8],
|
||||
pub root: Node,
|
||||
pub strings: &'static [u8],
|
||||
}
|
||||
|
||||
impl FDT {
|
||||
pub fn nodes(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.nodes,
|
||||
strings: self.strings,
|
||||
}
|
||||
}
|
||||
pub fn root(&self) -> Option<Node> {
|
||||
self.nodes().next()
|
||||
}
|
||||
pub unsafe fn from_addr(addr: *mut u8) -> Self {
|
||||
pub unsafe fn from_addr(addr: *mut u8) -> Result<Self, &'static str> {
|
||||
let header: &Header = &*(addr as *const Header);
|
||||
if header.magic.get() != MAGIC {
|
||||
panic!("fdt magic wrong");
|
||||
return Err("fdt magic wrong");
|
||||
}
|
||||
let data = slice::from_raw_parts(addr, header.totalsize.get() as usize);
|
||||
Self {
|
||||
let strings = &data[header.off_dt_strings.get() as usize..];
|
||||
let node_data = &data[header.off_dt_struct.get() as usize..];
|
||||
let root = match Node::from_bytes(node_data, strings) {
|
||||
Some((node, _)) => node,
|
||||
None => return Err("Could not parse nodes")
|
||||
};
|
||||
Ok(Self {
|
||||
header,
|
||||
nodes: &data[header.off_dt_struct.get() as usize..],
|
||||
strings: &data[header.off_dt_strings.get() as usize..],
|
||||
}
|
||||
root,
|
||||
strings,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +104,82 @@ impl Debug for Node {
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn from_bytes(bytes: &'static [u8], strings: &'static [u8]) -> Option<(Self, &'static [u8])> {
|
||||
// first make sure this is actually a node
|
||||
let mut pos = bytes;
|
||||
if pos.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let token: Token = Token::from_bytes(pos)?;
|
||||
let Token::BeginNode = token else {
|
||||
return None;
|
||||
};
|
||||
pos = &pos[4..];
|
||||
// then get the name
|
||||
let name_start = pos;
|
||||
let extra;
|
||||
'outer: loop {
|
||||
let bytes = &pos[..4];
|
||||
pos = &pos[4..];
|
||||
for (i, byte) in bytes.iter().enumerate() {
|
||||
if *byte == 0 {
|
||||
extra = 4 - i;
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
let name = core::str::from_utf8(&name_start[..name_start.len() - pos.len() - extra])
|
||||
.expect("har har har har har har har har har har. RAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// then props
|
||||
let node_start = pos;
|
||||
let node_data = if let Some(prop) = (PropIter {
|
||||
strings,
|
||||
pos,
|
||||
})
|
||||
.last()
|
||||
{
|
||||
let node_len =
|
||||
(prop.data.as_ptr() as usize + prop.data.len()) - pos.as_ptr() as usize;
|
||||
pos = &pos[node_len..];
|
||||
&node_start[..node_len]
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
// then children
|
||||
let children = match Token::from_bytes(pos) {
|
||||
Some(Token::EndNode | Token::End) => {
|
||||
pos = &pos[4..];
|
||||
&[]
|
||||
}
|
||||
Some(Token::BeginNode) => {
|
||||
let children = pos;
|
||||
let mut iter = NodeIter {
|
||||
pos: children,
|
||||
strings,
|
||||
};
|
||||
// skip children pos
|
||||
for _ in iter.by_ref() {}
|
||||
pos = iter.pos;
|
||||
match Token::from_bytes(pos) {
|
||||
Some(Token::EndNode | Token::End) => pos = &pos[4..],
|
||||
_ => panic!("wut du heeeeeal (toaken)"),
|
||||
}
|
||||
children
|
||||
}
|
||||
_ => {
|
||||
println!("WARNING: token stuff XD");
|
||||
&[]
|
||||
}
|
||||
};
|
||||
// done
|
||||
Some((Node {
|
||||
name,
|
||||
props: node_data,
|
||||
strings,
|
||||
children,
|
||||
},pos))
|
||||
}
|
||||
|
||||
pub fn children(&self) -> NodeIter {
|
||||
NodeIter {
|
||||
pos: self.children,
|
||||
@@ -191,85 +264,16 @@ impl Iterator for PropIter {
|
||||
pub struct NodeIter {
|
||||
// I should make a type called ByteCursor or something for this
|
||||
// so dealing with it is not cursed and dependent on data type
|
||||
pub pos: &'static [u8],
|
||||
pub strings: &'static [u8],
|
||||
pos: &'static [u8],
|
||||
strings: &'static [u8],
|
||||
}
|
||||
|
||||
impl Iterator for NodeIter {
|
||||
type Item = Node;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// first make sure this is actually a node
|
||||
if self.pos.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let token: Token = Token::from_bytes(self.pos)?;
|
||||
let Token::BeginNode = token else {
|
||||
return None;
|
||||
};
|
||||
self.pos = &self.pos[4..];
|
||||
// then get the name
|
||||
let name_start = self.pos;
|
||||
let extra;
|
||||
'outer: loop {
|
||||
let bytes = &self.pos[..4];
|
||||
self.pos = &self.pos[4..];
|
||||
for (i, byte) in bytes.iter().enumerate() {
|
||||
if *byte == 0 {
|
||||
extra = 4 - i;
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
let name = core::str::from_utf8(&name_start[..name_start.len() - self.pos.len() - extra])
|
||||
.expect("har har har har har har har har har har. RAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
// then props
|
||||
let node_start = self.pos;
|
||||
let node_data = if let Some(prop) = (PropIter {
|
||||
strings: self.strings,
|
||||
pos: self.pos,
|
||||
})
|
||||
.last()
|
||||
{
|
||||
let node_len =
|
||||
(prop.data.as_ptr() as usize + prop.data.len()) - self.pos.as_ptr() as usize;
|
||||
self.pos = &self.pos[node_len..];
|
||||
&node_start[..node_len]
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
// then children
|
||||
let children = match Token::from_bytes(self.pos) {
|
||||
Some(Token::EndNode | Token::End) => {
|
||||
self.pos = &self.pos[4..];
|
||||
&[]
|
||||
}
|
||||
Some(Token::BeginNode) => {
|
||||
let children = self.pos;
|
||||
let mut iter = Self {
|
||||
pos: children,
|
||||
strings: self.strings,
|
||||
};
|
||||
// skip children bytes
|
||||
for _ in iter.by_ref() {}
|
||||
self.pos = iter.pos;
|
||||
match Token::from_bytes(self.pos) {
|
||||
Some(Token::EndNode | Token::End) => self.pos = &self.pos[4..],
|
||||
_ => panic!("wut du heeeeeal (toaken)"),
|
||||
}
|
||||
children
|
||||
}
|
||||
_ => {
|
||||
println!("WARNING: token stuff XD");
|
||||
&[]
|
||||
}
|
||||
};
|
||||
// done
|
||||
Some(Node {
|
||||
name,
|
||||
props: node_data,
|
||||
strings: self.strings,
|
||||
children,
|
||||
})
|
||||
let (node, pos) = Node::from_bytes(self.pos, self.strings)?;
|
||||
self.pos = pos;
|
||||
Some(node)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ use super::fdt::FDT;
|
||||
|
||||
impl FDT {
|
||||
pub fn mem_range(&self) -> Option<FDTMemRange> {
|
||||
let reg = self.root()?.child("memory")?.prop("reg")?;
|
||||
let reg = self.root.child("memory")?.prop("reg")?;
|
||||
let data = reg.data.chunks(size_of::<FDTMemRange>()).next()?;
|
||||
// for now just get first
|
||||
let data: [u8; size_of::<FDTMemRange>()] = data.try_into().unwrap();
|
||||
unsafe { Some(transmute::<[u8; 16], FDTMemRange>(data)) }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod fdt;
|
||||
pub mod mem;
|
||||
pub mod uart;
|
||||
pub mod pci;
|
||||
pub mod uart;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
use crate::println;
|
||||
|
||||
use super::fdt::FDT;
|
||||
|
||||
impl FDT {
|
||||
pub fn pci_devs(&self) -> Option<()> {
|
||||
// for dev in self.nodes() {
|
||||
// println!("{:#?}", dev);
|
||||
// }
|
||||
let node = self.root()?.child("soc")?.child("pci")?;
|
||||
println!("{:#?}", node);
|
||||
None
|
||||
}
|
||||
}
|
||||
98
kernel/src/dev/pci/class.rs
Normal file
98
kernel/src/dev/pci/class.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use super::header::HeaderStart;
|
||||
|
||||
// this is technically less performant than making 16^2 values,
|
||||
// but that cannot be worth it lmao +
|
||||
// Reserved(u8) is a lot nicer than literally hundreds of enum values
|
||||
#[derive(Debug)]
|
||||
pub enum Class {
|
||||
Unclassified,
|
||||
MassStorageController,
|
||||
NetworkController,
|
||||
DisplayController,
|
||||
MultimediaController,
|
||||
MemoryController,
|
||||
Bridge(Bridge),
|
||||
SimpleCommunicationController,
|
||||
BaseSystemPeripheral,
|
||||
InputDeviceController,
|
||||
DockingStation,
|
||||
Processor,
|
||||
SerialBusController,
|
||||
WirelessController,
|
||||
IntelligentController,
|
||||
SatelliteCommunicationController,
|
||||
EncryptionController,
|
||||
SignalProcessingController,
|
||||
ProcessingAccelerator,
|
||||
NonEssentialInstrumentation,
|
||||
CoProcessor,
|
||||
UnassignedClass,
|
||||
Reserved(u8),
|
||||
}
|
||||
|
||||
impl Class {
|
||||
pub fn from_header(header: &HeaderStart) -> Self {
|
||||
match header.class_code {
|
||||
0x0 => Self::Unclassified,
|
||||
0x1 => Self::MassStorageController,
|
||||
0x2 => Self::NetworkController,
|
||||
0x3 => Self::DisplayController,
|
||||
0x4 => Self::MultimediaController,
|
||||
0x5 => Self::MemoryController,
|
||||
0x6 => Self::Bridge(Bridge::from_header(header)),
|
||||
0x7 => Self::SimpleCommunicationController,
|
||||
0x8 => Self::BaseSystemPeripheral,
|
||||
0x9 => Self::InputDeviceController,
|
||||
0xa => Self::DockingStation,
|
||||
0xb => Self::Processor,
|
||||
0xc => Self::SerialBusController,
|
||||
0xd => Self::WirelessController,
|
||||
0xe => Self::IntelligentController,
|
||||
0xf => Self::SatelliteCommunicationController,
|
||||
0x10 => Self::EncryptionController,
|
||||
0x11 => Self::SignalProcessingController,
|
||||
0x12 => Self::ProcessingAccelerator,
|
||||
0x13 => Self::NonEssentialInstrumentation,
|
||||
0x40 => Self::CoProcessor,
|
||||
0xff => Self::UnassignedClass,
|
||||
c => Self::Reserved(c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Bridge {
|
||||
Host,
|
||||
ISA,
|
||||
EISA,
|
||||
MCA,
|
||||
PCIToPCI,
|
||||
PCMCIA,
|
||||
NuBus,
|
||||
CardBus,
|
||||
RACEway,
|
||||
PCIToPCISemiTransparent,
|
||||
InfiniBandtoPCIHost,
|
||||
Other,
|
||||
Unknown(u8),
|
||||
}
|
||||
|
||||
impl Bridge {
|
||||
pub fn from_header(header: &HeaderStart) -> Self {
|
||||
match header.subclass {
|
||||
0x0 => Self::Host,
|
||||
0x1 => Self::ISA,
|
||||
0x2 => Self::EISA,
|
||||
0x3 => Self::MCA,
|
||||
0x4 => Self::PCIToPCI,
|
||||
0x5 => Self::PCMCIA,
|
||||
0x6 => Self::NuBus,
|
||||
0x7 => Self::CardBus,
|
||||
0x8 => Self::RACEway,
|
||||
0x9 => Self::PCIToPCISemiTransparent,
|
||||
0x0A => Self::InfiniBandtoPCIHost,
|
||||
0x80 => Self::Other,
|
||||
s => Self::Unknown(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
84
kernel/src/dev/pci/header.rs
Normal file
84
kernel/src/dev/pci/header.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use super::class::Class;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct HeaderStart {
|
||||
pub vendor_id: u16,
|
||||
pub device_id: u16,
|
||||
pub command: u16,
|
||||
pub status: u16,
|
||||
pub rev_id: u8,
|
||||
pub prog_if: u8,
|
||||
pub subclass: u8,
|
||||
pub class_code: u8,
|
||||
pub cache_line_size: u8,
|
||||
pub latency_timer: u8,
|
||||
pub header_type: u8,
|
||||
pub bist: u8,
|
||||
}
|
||||
|
||||
impl HeaderStart {
|
||||
pub fn class(&self) -> Class {
|
||||
Class::from_header(self)
|
||||
}
|
||||
pub fn vendor(&self) -> Vendor {
|
||||
Vendor::from_header(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct GeneralHeader {
|
||||
pub start: HeaderStart,
|
||||
pub bar0: u32,
|
||||
pub bar1: u32,
|
||||
pub bar2: u32,
|
||||
pub bar3: u32,
|
||||
pub bar4: u32,
|
||||
pub bar5: u32,
|
||||
pub cardbus_cis_pointer: u32,
|
||||
pub subsystem_vendor_id: u16,
|
||||
pub subsystem_id: u16,
|
||||
pub expansion_rom_base_addr: u32,
|
||||
pub capabilities: u8,
|
||||
pub reserved: [u8; 7],
|
||||
pub interrupt_line: u8,
|
||||
pub interrupt_pin: u8,
|
||||
pub min_grant: u8,
|
||||
pub max_latency: u8,
|
||||
}
|
||||
|
||||
// due to how large this is and how it can change,
|
||||
// this seems like not the best use case for enums
|
||||
// but that's entirely a later problem
|
||||
#[derive(Debug)]
|
||||
pub enum Vendor {
|
||||
RedHat(RedHatDevice),
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
impl Vendor {
|
||||
pub fn from_header(header: &HeaderStart) -> Self {
|
||||
let id = header.device_id;
|
||||
match header.vendor_id {
|
||||
0x1b36 => Self::RedHat(RedHatDevice::from_id(id)),
|
||||
i => Self::Unknown(i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RedHatDevice {
|
||||
QemuPCIeHostBridge,
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
impl RedHatDevice {
|
||||
pub fn from_id(id: u16) -> Self {
|
||||
match id {
|
||||
0x0008 => Self::QemuPCIeHostBridge,
|
||||
id => Self::Unknown(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
kernel/src/dev/pci/mod.rs
Normal file
45
kernel/src/dev/pci/mod.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
use super::fdt::FDT;
|
||||
use crate::{dev::pci::header::{GeneralHeader, HeaderStart}, println, util::bits::Be};
|
||||
use core::mem::transmute;
|
||||
|
||||
pub mod header;
|
||||
pub mod class;
|
||||
|
||||
impl FDT {
|
||||
pub fn pci_devs(&self) -> Option<()> {
|
||||
// for dev in self.nodes() {
|
||||
// println!("{:#?}", dev);
|
||||
// }
|
||||
let node = self.root.child("soc")?.child("pci")?;
|
||||
// should make handling reg field nicer
|
||||
let data = node.prop("reg")?.data;
|
||||
println!("{:#?}", node);
|
||||
let addr = unsafe {
|
||||
transmute::<[u8; 8], Be<u64>>([
|
||||
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
|
||||
])
|
||||
};
|
||||
let addr = addr.get() as *mut u8;
|
||||
let len = unsafe {
|
||||
transmute::<[u8; 8], Be<u64>>([
|
||||
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
|
||||
])
|
||||
};
|
||||
let len = len.get() as usize;
|
||||
println!("{:?}..{:?}", addr, unsafe { addr.byte_add(len) });
|
||||
unsafe {
|
||||
let header = *(addr as *mut HeaderStart);
|
||||
if header.header_type != 0 {
|
||||
panic!("nooooooooooooo");
|
||||
}
|
||||
let header = addr as *mut GeneralHeader;
|
||||
println!("device: {:?}", (*header).start.vendor());
|
||||
println!("class: {:?}", (*header).start.class());
|
||||
println!("{:#?}", *header);
|
||||
(*header).start.command = 0b0000_0000_0000_0110;
|
||||
for _ in 0..1000000 {}
|
||||
println!("{:b}", (*header).start.status);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use core::fmt;
|
||||
|
||||
pub struct Uart {
|
||||
base: u32,
|
||||
}
|
||||
|
||||
impl Uart {
|
||||
pub const fn new(base: u32) -> Self {
|
||||
Self { base }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for Uart {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for b in s.as_bytes() {
|
||||
#[allow(clippy::while_immutable_condition)]
|
||||
while unsafe { *(self.base as *mut i32) } < 0 {}
|
||||
unsafe { *(self.base as *mut i32) = *b as i32 }
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
40
kernel/src/log.rs
Normal file
40
kernel/src/log.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use core::fmt::Write;
|
||||
|
||||
use crate::{dev::{fdt::FDT, uart::Uart}, util::mutex::Mutex};
|
||||
|
||||
// ok now it uses soc->serial, might be chillin?
|
||||
// --machine sifive_u
|
||||
// const UART_BASE: u32 = 0x10010000;
|
||||
// --machine virt
|
||||
const UART_BASE: u32 = 0x10000000;
|
||||
static UART: Mutex<Uart> = Mutex::new(Uart::new(UART_BASE));
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::log::_print(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
pub fn init(dt: &FDT) -> Option<()> {
|
||||
let node = dt.root.child("soc")?.child("serial")?;
|
||||
let addr = u32::from_str_radix(node.address()?, 16).ok()?;
|
||||
*UART.lock() = Uart::new(addr);
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn _print(args: core::fmt::Arguments<'_>) {
|
||||
// NOTE: something really dumb can happen here;
|
||||
// if you evaluate an expression in a print statement, and that
|
||||
// causes an interrupt, this will be left locked...
|
||||
// Should I set up the heap before interrupts? or just avoid printing until both...?
|
||||
// or maybe force unlock if there's an interrupt?
|
||||
// or store the hart in the lock, and unlock if that hart was interrupted??
|
||||
// or just have a constant-sized buffer?
|
||||
// or create a "locked writer"?
|
||||
UART.lock().write_fmt(args).unwrap();
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(fn_align)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::test::test_runner)]
|
||||
@@ -15,6 +14,7 @@ extern crate alloc;
|
||||
|
||||
pub mod arch;
|
||||
pub mod dev;
|
||||
pub mod log;
|
||||
pub mod mem;
|
||||
pub mod qemu;
|
||||
#[cfg(test)]
|
||||
@@ -23,7 +23,7 @@ pub mod util;
|
||||
|
||||
pub struct StartInfo {
|
||||
mem_range: Range<*mut u8>,
|
||||
dt: FDT
|
||||
dt: FDT,
|
||||
}
|
||||
|
||||
pub fn start(info: StartInfo) -> ! {
|
||||
@@ -39,12 +39,18 @@ pub fn start(info: StartInfo) -> ! {
|
||||
}
|
||||
|
||||
pub fn main(info: StartInfo) {
|
||||
log::init(&info.dt);
|
||||
println!("we out here vibin");
|
||||
println!("memory range: {:?}", info.mem_range);
|
||||
// println!("memory range: {:?}", info.mem_range);
|
||||
unsafe {
|
||||
ALLOCATOR.init(&info.mem_range);
|
||||
}
|
||||
info.dt.pci_devs();
|
||||
// info.dt.pci_devs();
|
||||
// println!("{:#?}", info.dt.root);
|
||||
let test = alloc::vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||
let test2 = alloc::vec![1u8, 2, 3, 4];
|
||||
drop(test);
|
||||
ALLOCATOR.heap().print();
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
|
||||
@@ -157,7 +157,7 @@ impl Heap {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return null_mut();
|
||||
null_mut()
|
||||
}
|
||||
|
||||
pub unsafe fn dealloc(&mut self, ptr: *mut u8, _: core::alloc::Layout) {
|
||||
|
||||
@@ -1,12 +1 @@
|
||||
pub use crate::arch::qemu::*;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::arch::qemu::_print(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
() => ($crate::print!("\n"));
|
||||
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ pub fn run_tests() -> ! {
|
||||
}
|
||||
|
||||
fn prepare(info: &StartInfo) {
|
||||
crate::log::init(&info.dt);
|
||||
unsafe {
|
||||
ALLOCATOR.reset(&info.mem_range);
|
||||
}
|
||||
|
||||
1128
kernel/stuff
1128
kernel/stuff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user