Skip to content

Commit 8a140b9

Browse files
aarch64: setup logging and DTB structure
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 0e417cb commit 8a140b9

File tree

7 files changed

+227
-86
lines changed

7 files changed

+227
-86
lines changed

src/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#[derive(Debug)]
2+
#[repr(C)]
3+
struct FdtHeader {
4+
magic: u32,
5+
totalsize: u32,
6+
off_dt_struct: u32,
7+
off_dt_strings: u32,
8+
off_mem_rsvmap: u32,
9+
version: u32,
10+
last_comp_version: u32,
11+
boot_cpuid_phys: u32,
12+
size_dt_strings: u32,
13+
size_dt_struct: u32,
14+
}
15+
16+
pub struct Dtb<'a> {
17+
header: &'a FdtHeader,
18+
}
19+
20+
impl<'a> Dtb<'a> {
21+
pub fn new(blob: *const u8) -> Self {
22+
let header = unsafe { &*(blob as *const FdtHeader) };
23+
// assert_eq!(header.magic, 0xd00dfeed);
24+
25+
log::debug!("{header:#x?}");
26+
27+
Self { header }
28+
}
29+
}

src/aero_kernel/src/arch/aarch64/interrupts.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,22 @@ pub fn register_handler(vector: u8, handler: fn(&mut InterruptStack)) {
4545
unimplemented!()
4646
}
4747

48-
pub unsafe fn disable_interrupts() {
49-
unimplemented!()
48+
pub fn is_enabled() -> bool {
49+
let v: u64;
50+
unsafe {
51+
asm!("mrs {}, daif", out(reg) v, options(nostack, nomem));
52+
}
53+
(!v) != 0
5054
}
5155

52-
pub fn is_enabled() -> bool {
53-
unimplemented!()
56+
pub unsafe fn disable_interrupts() {
57+
asm!("msr daifset, #15", options(nomem, nostack))
5458
}
5559

5660
pub unsafe fn enable_interrupts() {
57-
unimplemented!()
61+
asm!("msr daifclr, #15", options(nomem, nostack))
5862
}
5963

6064
pub unsafe fn halt() {
61-
asm!("wfi");
65+
asm!("wfi", options(nomem, nostack));
6266
}

src/aero_kernel/src/arch/aarch64/mod.rs

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,72 @@
1717
* along with Aero. If not, see <https://www.gnu.org/licenses/>.
1818
*/
1919

20+
pub mod dtb;
2021
pub mod interrupts;
2122
pub mod task;
2223
pub mod time;
2324
pub mod tls;
2425

26+
use crate::{drivers, logger};
27+
2528
use limine::*;
2629

30+
use crate::mem::paging::VirtAddr;
31+
2732
static TERMINAL: LimineTerminalRequest = LimineTerminalRequest::new(0);
33+
static HHDM: LimineHhdmRequest = LimineHhdmRequest::new(0);
34+
static KERNEL_FILE: LimineKernelFileRequest = LimineKernelFileRequest::new(0);
35+
static DTB: LimineDtbRequest = LimineDtbRequest::new(0);
2836

2937
#[no_mangle]
3038
extern "C" fn arch_aero_main() -> ! {
31-
let response = TERMINAL.get_response().get().unwrap();
32-
let terminal = &response.terminals()[0];
33-
let writer = response.write().unwrap();
39+
unsafe {
40+
interrupts::disable_interrupts();
41+
}
42+
43+
unsafe {
44+
crate::PHYSICAL_MEMORY_OFFSET = VirtAddr::new(HHDM.get_response().get().unwrap().offset);
45+
}
46+
47+
let kernel_file_resp = KERNEL_FILE
48+
.get_response()
49+
.get()
50+
.expect("limine: invalid kernel file response");
51+
52+
let kernel_file = kernel_file_resp
53+
.kernel_file
54+
.get()
55+
.expect("limine: invalid kernel file pointer");
56+
57+
// Before we start the initialization process, we need to make sure
58+
// the unwind info is avaliable; just in case if there is a kernel
59+
// panic, it will be able to unwind the stack.
60+
crate::unwind::UNWIND_INFO.call_once(|| {
61+
use crate::unwind::UnwindInfo;
62+
use xmas_elf::ElfFile;
63+
64+
let start = kernel_file
65+
.base
66+
.as_ptr()
67+
.expect("limine: invalid kernel file base");
68+
69+
// SAFETY: The bootloader will provide a valid pointer to the kernel file.
70+
let elf_slice = unsafe { core::slice::from_raw_parts(start, kernel_file.length as usize) };
71+
let elf = ElfFile::new(elf_slice).expect("limine: invalid kernel file");
72+
73+
UnwindInfo::new(elf)
74+
});
75+
76+
// Now that we have unwind info, we can initialize the COM ports. This
77+
// will be used to print panic messages/logs before the debug renderer is
78+
// initialized to the serial output (if avaliable).
79+
drivers::uart::init();
80+
logger::init();
3481

35-
writer(&terminal, "Hello Aero from unbased64 booted by limine :^)");
82+
log::debug!("lmao");
83+
let dtb_response = DTB.get_response().get().unwrap();
84+
let dtb_blob = dtb_response.dtb_ptr.as_ptr().unwrap();
85+
let dtb = dtb::Dtb::new(dtb_blob);
3686

3787
loop {}
3888
}

src/aero_kernel/src/drivers/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ cfg_if::cfg_if! {
3737
pub mod uart_16550;
3838
pub use self::uart_16550 as uart;
3939
} else if #[cfg(target_arch = "aarch64")] {
40-
pub mod uart_mmio32;
41-
pub use self::uart_mmio32 as uart;
40+
pub mod uart_pl011;
41+
pub use self::uart_pl011 as uart;
4242
}
4343
}

src/aero_kernel/src/drivers/uart_mmio32.rs

Lines changed: 0 additions & 73 deletions
This file was deleted.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (C) 2021-2022 The Aero Project Developers.
3+
*
4+
* This file is part of The Aero Project.
5+
*
6+
* Aero is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Aero is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with Aero. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
// REFRENCE: PrimeCell UART (PL011) Technical Reference Manual
21+
22+
use core::fmt;
23+
use core::fmt::Write;
24+
25+
use spin::Once;
26+
27+
use core::sync::atomic::{AtomicPtr, Ordering};
28+
29+
use crate::mem::paging::VirtAddr;
30+
use crate::utils::sync::Mutex;
31+
32+
static SERIAL: Once<Mutex<PrimeCellSerialPort>> = Once::new();
33+
34+
pub struct PrimeCellSerialPort(*mut u8);
35+
36+
impl PrimeCellSerialPort {
37+
pub unsafe fn new(base: usize) -> Self {
38+
let base_pointer = base as *mut u8;
39+
Self(base_pointer)
40+
}
41+
42+
unsafe fn write(&mut self, register: u8, value: u16) {
43+
core::ptr::write_volatile(self.0.offset(register as isize) as *mut u16, value);
44+
}
45+
46+
unsafe fn read(&self, register: u8) -> u16 {
47+
core::ptr::read_volatile(self.0.offset(register as isize) as *mut u16)
48+
}
49+
50+
pub fn init(mut self) -> Self {
51+
unsafe {
52+
// Enable RXE, TXE, UARTEN
53+
self.write(0x30, 1 << 9 | 1 << 8 | 1 << 0);
54+
55+
// Disable FIFOs (use character mode instead)
56+
let mut flags = self.read(0x2c);
57+
flags &= !(1 << 4);
58+
59+
// Enable IRQs
60+
self.write(0x38, 1 << 4);
61+
62+
// Clear pending interrupts
63+
self.write(0x44, 0x7ff);
64+
}
65+
66+
self
67+
}
68+
69+
fn wait_transmit(&self) {
70+
// TXFE - this bit is set when the transmit holding register is empty.
71+
while unsafe { self.read(0x18) } & 1 << 7 != 1 << 7 {
72+
core::hint::spin_loop();
73+
}
74+
}
75+
76+
pub fn send(&mut self, byte: u8) {
77+
unsafe {
78+
match byte {
79+
8 | 0x7F => {
80+
self.wait_transmit();
81+
self.write(0, 8);
82+
83+
self.wait_transmit();
84+
self.write(0, b' ' as _);
85+
86+
self.wait_transmit();
87+
self.write(0, 8);
88+
}
89+
90+
_ => {
91+
self.wait_transmit();
92+
self.write(0, byte as u16);
93+
}
94+
}
95+
}
96+
}
97+
}
98+
99+
unsafe impl Send for PrimeCellSerialPort {}
100+
101+
impl fmt::Write for PrimeCellSerialPort {
102+
fn write_str(&mut self, s: &str) -> fmt::Result {
103+
for byte in s.bytes() {
104+
self.send(byte);
105+
}
106+
Ok(())
107+
}
108+
}
109+
pub fn init() {
110+
// CC: https://github.com/limine-bootloader/limine/issues/215
111+
let mut serial = unsafe { PrimeCellSerialPort::new(0x9000000) }.init();
112+
SERIAL.call_once(|| Mutex::new(serial));
113+
}
114+
115+
pub macro serial_print($($arg:tt)*) {
116+
crate::drivers::uart_pl011::_serial_print(format_args!($($arg)*))
117+
}
118+
119+
pub macro serial_println {
120+
() => ($crate::drivers::uart_pl011::serial_print!("\n")),
121+
($($arg:tt)*) => ($crate::drivers::uart_pl011::serial_print!("{}\n", format_args!($($arg)*)))
122+
}
123+
124+
#[doc(hidden)]
125+
pub fn _serial_print(args: fmt::Arguments) {
126+
SERIAL.get().map(|c| {
127+
c.lock_irq()
128+
.write_fmt(args)
129+
.expect("failed to write to serial")
130+
});
131+
}

0 commit comments

Comments
 (0)