This commit is contained in:
2024-06-10 23:57:38 +03:00
parent 6de42c3dba
commit 1b2dd2bfbe
21 changed files with 1066 additions and 31 deletions

View File

@@ -1,14 +1,22 @@
[package]
name = "poppin-kernel"
name = "kernel"
version = "0.1.0"
edition = "2021"
test=false
[lib]
name="poppin_kernel"
name="kernel"
test=false
crate-type=["staticlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
log = "0.4.21"
multiboot2 = "0.20.2"
pc-keyboard = "0.7.0"
pic8259 = "0.11.0"
spin = "0.9.8"
uart_16550 = "0.3.0"
x86 = "0.52.0"
x86_64 = "0.15.1"

12
kernel/src/events/mod.rs Normal file
View File

@@ -0,0 +1,12 @@
pub struct KernelEventHandler {
}
impl KernelEventHandler {
}

50
kernel/src/gdt/mod.rs Normal file
View File

@@ -0,0 +1,50 @@
use core::ptr::addr_of;
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
use x86_64::VirtAddr;
use x86_64::structures::tss::TaskStateSegment;
use lazy_static::lazy_static;
pub const DOUBLE_FAULT_IST_INDEX: u16 = 0;
lazy_static! {
static ref TSS: TaskStateSegment = {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE];
let stack_start = VirtAddr::from_ptr(unsafe { addr_of!(STACK) });
let stack_end = stack_start + STACK_SIZE as u64;
stack_end
};
tss
};
}
lazy_static! {
static ref GDT: (GlobalDescriptorTable, Selectors) = {
let mut gdt = GlobalDescriptorTable::new();
let code_selector = gdt.append(Descriptor::kernel_code_segment());
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
(gdt, Selectors { code_selector, tss_selector })
};
}
struct Selectors {
code_selector: SegmentSelector,
tss_selector: SegmentSelector,
}
pub fn init() {
log::debug!("GDT init");
use x86_64::instructions::tables::load_tss;
use x86_64::instructions::segmentation::{CS, Segment};
GDT.0.load();
unsafe {
CS::set_reg(GDT.1.code_selector);
load_tss(GDT.1.tss_selector);
}
}

View File

@@ -0,0 +1,31 @@
use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode};
use crate::interrupts::InterruptIndex;
mod ps2_keyboard;
pub use ps2_keyboard::ps2_kb_int;
pub extern "x86-interrupt" fn breakpoint(sf: InterruptStackFrame){
log::error!("EXCEPT: BREAKPOINT\n{:#?}", sf);
}
pub extern "x86-interrupt" fn timer_interrupt(_: InterruptStackFrame){
//log::debug!("INT: TIMER\n{:#?}", sf);
// print!(".");
unsafe {
super::PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Timer as u8);
}
}
pub extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, _: u64) -> ! {
panic!("EXCEPT: DOUBLE FAULT \n{:#?}", stack_frame);
}
pub extern "x86-interrupt" fn page_fault(stack_frame: InterruptStackFrame, error_code: PageFaultErrorCode) {
use x86_64::registers::control::Cr2;
log::error!("EXCEPT: PAGE FAULT");
log::debug!("Addr: {:?}", Cr2::read());
log::debug!("ErrCo: {:?}\n{:#?}", error_code, stack_frame);
crate::utils::hcf();
}

View File

@@ -0,0 +1,35 @@
use x86_64::structures::idt::InterruptStackFrame;
use crate::interrupts::PICS;
pub extern "x86-interrupt" fn ps2_kb_int(_sf: InterruptStackFrame){
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
use spin::Mutex;
use x86_64::instructions::port::Port;
lazy_static::lazy_static! {
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
Mutex::new(Keyboard::new(ScancodeSet1::new(),
layouts::Us104Key, HandleControl::Ignore)
);
}
let mut keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60);
let scancode: u8 = unsafe { port.read() };
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
if let Some(key) = keyboard.process_keyevent(key_event) {
if false {
match key {
DecodedKey::Unicode(character) => print!("{}", character),
DecodedKey::RawKey(key) => print!("{:?}", key),
}
}
}
}
unsafe {
PICS.lock()
.notify_end_of_interrupt(super::InterruptIndex::Keyboard as u8);
}
}

View File

@@ -0,0 +1,48 @@
use pic8259::ChainedPics;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
mod handlers;
pub const PIC_1_OFFSET: u8 = 32;
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
lazy_static::lazy_static! {
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(handlers::breakpoint);
idt.page_fault.set_handler_fn(handlers::page_fault);
idt[InterruptIndex::Timer as u8]
.set_handler_fn(handlers::timer_interrupt);
idt[InterruptIndex::Keyboard as u8]
.set_handler_fn(handlers::ps2_kb_int);
unsafe {
idt.double_fault.set_handler_fn(handlers::double_fault)
.set_stack_index(crate::gdt::DOUBLE_FAULT_IST_INDEX);
}
idt
};
}
pub static PICS: spin::Mutex<ChainedPics> =
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum InterruptIndex {
Timer = PIC_1_OFFSET,
Keyboard, // PS/2
}
pub fn init_idt() {
log::debug!("IDT init");
IDT.load();
unsafe { PICS.lock().initialize() };
x86_64::instructions::interrupts::enable();
}

View File

@@ -1,20 +1,50 @@
#![no_std]
#![no_main]
#![feature(abi_x86_interrupt)]
use multiboot2::BootInformationHeader;
use x86_64::registers::control::Cr3;
use crate::mem::FrameAllocator;
#[macro_use]
mod logger;
mod interrupts;
mod gdt;
mod utils;
mod events;
mod mem;
#[no_mangle]
extern "C" fn kmain() -> ! {
loop {
extern "C" fn kmain(mb2_info_addr: usize) -> ! {
logger::init(log::LevelFilter::Trace).unwrap();
gdt::init();
interrupts::init_idt();
let mem_info = mem::MemInfo::load(mb2_info_addr);
let mut alloc = mem::area_frame_alloc::AreaFrameAllocator::new(mem_info);
for i in 0.. {
if let None = alloc.allocate_frame() {
println!("allocated {} frames", i);
break;
}
}
// let (level_4_page_table, _) = Cr3::read();
// println!("Level 4 page table at: {:?}", level_4_page_table.start_address());
utils::hcf();
}
#[panic_handler]
fn panic(_pi: &core::panic::PanicInfo) -> ! {
loop {}
fn panic(pi: &core::panic::PanicInfo) -> ! {
log::error!("{pi}");
utils::hcf();
}

View File

@@ -1,19 +0,0 @@
use log::{Record, Level, Metadata};
struct SimpleLogger {
}
impl log::Log for SimpleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= Level::Info
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
println!("{} - {}", record.level(), record.args());
}
}
fn flush(&self) {}
}

View File

87
kernel/src/logger/mod.rs Normal file
View File

@@ -0,0 +1,87 @@
use log::{Level, LevelFilter, Metadata, Record, SetLoggerError};
use crate::logger::serial::{write_com, ANSI_COLORS, COM0};
use self::vga::{Color, ColorCode, WRITER};
#[macro_use]
pub mod vga;
pub mod serial;
#[macro_use]
pub mod macros;
pub static LOGGER: KLogger = KLogger;
pub struct KLogger;
const C_TRACE: ColorCode = ColorCode::new(Color::Cyan, Color::Black);
const C_DEBUG: ColorCode = ColorCode::new(Color::Blue, Color::Black);
const C_INFO: ColorCode = ColorCode::new(Color::Green, Color::Black);
const C_WARN: ColorCode = ColorCode::new(Color::Yellow, Color::Black);
const C_ERROR: ColorCode = ColorCode::new(Color::Red, Color::Black);
const C_NORMAL: ColorCode = ColorCode::new(Color::White, Color::Black);
impl log::Log for KLogger {
fn enabled(&self, _: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
{WRITER.lock().set_color(Color::Magenta, Color::Black); }
print!("[");
write_com(&COM0, format_args!("{}[", ANSI_COLORS::MAGENTA));
match record.level() {
Level::Trace => {
{WRITER.lock().set_color_code(C_TRACE); }
print!("TRACE");
write_com(&COM0, format_args!("{}TRACE", ANSI_COLORS::BLUE2));
}
Level::Debug => {
{WRITER.lock().set_color_code(C_DEBUG); }
print!("DEBUG");
write_com(&COM0, format_args!("{}DEBUG", ANSI_COLORS::BLUE));
}
Level::Info => {
{WRITER.lock().set_color_code(C_INFO); }
print!("INFO");
write_com(&COM0, format_args!("{}INFO", ANSI_COLORS::GREEN));
}
Level::Warn => {
{WRITER.lock().set_color_code(C_WARN); }
print!("WARN");
write_com(&COM0, format_args!("{}WARN", ANSI_COLORS::YELLOW));
}
Level::Error => {
{WRITER.lock().set_color_code(C_ERROR); }
print!("ERROR");
write_com(&COM0, format_args!("{}ERROR", ANSI_COLORS::RED));
}
}
{WRITER.lock().set_color(Color::Magenta, Color::Black); }
print!("]");
{WRITER.lock().set_color_code(C_NORMAL); }
write_com(&COM0, format_args!("{}]", ANSI_COLORS::MAGENTA));
println!(" {}: {}", record.module_path().unwrap_or(""), record.args());
write_com(&COM0, format_args!(" {}{}: {}\n", ANSI_COLORS::RESET, record.module_path().unwrap_or(""), record.args()));
}
}
fn flush(&self) {}
}
pub fn init(lvl: LevelFilter) -> Result<(), SetLoggerError> {
log::set_logger(&LOGGER)?;
log::set_max_level(lvl);
log::info!("Logger init OK");
Ok(())
}

View File

@@ -0,0 +1,64 @@
use core::fmt::Write;
use spin::Mutex;
use uart_16550::SerialPort;
const COM_PORTS: [u16; 8] = [0x3F8, 0x2F8, 0x3E8, 0x2E8, 0x5F8, 0x4F8, 0x5E8, 0x4E8];
fn init_com_port(port_no: u16) -> Mutex<SerialPort> {
let mut p = unsafe {SerialPort::new(port_no)};
p.init();
Mutex::new(p)
}
lazy_static::lazy_static!(
pub static ref COM0: Mutex<SerialPort> = init_com_port(COM_PORTS[0]);
pub static ref COM1: Mutex<SerialPort> = init_com_port(COM_PORTS[1]);
pub static ref COM2: Mutex<SerialPort> = init_com_port(COM_PORTS[2]);
);
pub fn write_com(cp: &'static Mutex<SerialPort>, args: core::fmt::Arguments) {
use x86_64::instructions::interrupts::without_interrupts;
without_interrupts(|| {
cp.lock().write_fmt(args).unwrap();
})
}
#[allow(non_snake_case)]
#[allow(dead_code)]
pub mod ANSI_COLORS {
pub const RESET: &str = "\x1b[0m";
pub const BOLD: &str = "\x1b[1m";
pub const ITALIC: &str = "\x1b[3m";
pub const UNDERLINE: &str = "\x1b[4m";
pub const BLINK: &str = "\x1b[5m";
pub const BLINK2: &str = "\x1b[6m";
pub const SELECTED: &str = "\x1b[7m";
pub const BLACK: &str = "\x1b[30m";
pub const RED: &str = "\x1b[31m";
pub const GREEN: &str = "\x1b[32m";
pub const YELLOW: &str = "\x1b[33m";
pub const BLUE: &str = "\x1b[34m";
pub const MAGENTA: &str = "\x1b[35m";
pub const BEIGE: &str = "\x1b[36m";
pub const WHITE: &str = "\x1b[37m";
pub const BLACKBG: &str = "\x1b[40m";
pub const REDBG: &str = "\x1b[41m";
pub const GREENBG: &str = "\x1b[42m";
pub const YELLOWBG: &str = "\x1b[43m";
pub const BLUEBG: &str = "\x1b[44m";
pub const MAGENTABG: &str = "\x1b[45m";
pub const BEIGEBG: &str = "\x1b[46m";
pub const WHITEBG: &str = "\x1b[47m";
pub const GREY: &str = "\x1b[90m";
pub const RED2: &str = "\x1b[91m";
pub const GREEN2: &str = "\x1b[92m";
pub const YELLOW2: &str = "\x1b[93m";
pub const BLUE2: &str = "\x1b[94m";
pub const MAGENTA2: &str = "\x1b[95m";
pub const BEIGE2: &str = "\x1b[96m";
pub const WHITE2: &str = "\x1b[97m";
}

View File

@@ -0,0 +1,30 @@
use core::fmt;
use x86_64::instructions::interrupts;
use crate::logger::vga::Writer;
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_string(s);
Ok(())
}
}
#[macro_export]
macro_rules! print {
($($arg:tt)*) => ($crate::logger::vga::macros::_print(format_args!($($arg)*)));
}
#[macro_export]
macro_rules! println {
() => ($crate::print!("\n"));
($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*)));
}
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
use core::fmt::Write;
interrupts::without_interrupts(|| {
crate::logger::vga::WRITER.lock().write_fmt(args).unwrap();
});
}

View File

@@ -0,0 +1,199 @@
use x86::io::{outb, inb};
use spin::Mutex;
#[macro_use]
pub mod macros;
lazy_static::lazy_static!{
pub static ref WRITER: Mutex<Writer> = Mutex::new(Writer::new());
}
const BUFFER_HEIGHT: usize = 25;
const BUFFER_WIDTH: usize = 80;
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
Black = 0,
Blue = 1,
Green = 2,
Cyan = 3,
Red = 4,
Magenta = 5,
Brown = 6,
LightGray = 7,
DarkGray = 8,
LightBlue = 9,
LightGreen = 10,
LightCyan = 11,
LightRed = 12,
Pink = 13,
Yellow = 14,
White = 15,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct ColorCode(u8);
impl ColorCode {
pub const fn new(foreground: Color, background: Color) -> ColorCode {
ColorCode((background as u8) << 4 | (foreground as u8))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct VgaChar {
pub chr: u8,
pub color: ColorCode,
}
#[repr(transparent)]
pub struct Buffer {
chars: [[VgaChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
}
pub struct Writer {
col: usize,
line: usize,
buffer: &'static mut Buffer,
color: ColorCode
}
impl Writer {
pub fn new() -> Self {
let mut s = Self {
col: 0,
line: 0,
buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
color: ColorCode::new(Color::White, Color::Black)
};
s.clear_screen();
s
}
fn write_byte(&mut self, chr: u8) {
match chr {
b'\n' => self.new_line(),
_ => {
if self.col >= BUFFER_WIDTH {
self.new_line();
}
self.buffer.chars[self.line][self.col] = VgaChar {
chr,
color: self.color,
};
self.col += 1;
}
}
}
pub fn write_string(&mut self, s: &str) {
for c in s.as_bytes() {
match c {
// printable ASCII byte or newline
0x20..=0x7e | b'\n' => self.write_byte(*c),
// not part of printable ASCII range
_ => self.write_byte(0xfe),
}
}
update_cursor(self.col as u16, self.line as u16);
}
#[allow(dead_code)]
pub fn set_color(&mut self, fg: Color, bg: Color) {
self.color = ColorCode::new(fg, bg);
}
pub fn set_color_code(&mut self, c: ColorCode) {
self.color = c;
}
pub fn clear_screen(&mut self) {
let color = ColorCode::new(Color::White, Color::Black);
for line in 0..BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
self.buffer.chars[line][col] = VgaChar {
chr: 0,
color,
};
}
}
}
pub fn clear_line(&mut self, line: usize) {
let color = ColorCode::new(Color::White, Color::Black);
for col in 0..BUFFER_WIDTH {
self.buffer.chars[line][col] = VgaChar {
chr: 0,
color,
};
}
}
pub fn new_line(&mut self) {
if self.line >= BUFFER_HEIGHT - 1{
for row in 1..BUFFER_HEIGHT {
for col in 0..BUFFER_WIDTH {
let chr = self.buffer.chars[row][col];
self.buffer.chars[row - 1][col] = chr;
}
}
self.clear_line(BUFFER_HEIGHT - 1);
} else {
self.line += 1;
}
self.col = 0;
}
}
#[allow(dead_code)]
pub fn enable_cursor(cur_start: u8, cur_end: u8) {
unsafe {
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | cur_start);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | cur_end);
}
}
#[allow(dead_code)]
pub fn disable_cursor() {
unsafe {
outb(0x3D4, 0x0A);
outb(0x3D5, 0x20);
}
}
pub fn update_cursor(x: u16, y: u16) {
unsafe {
let pos: u16 = y * ( BUFFER_WIDTH as u16) + x;
outb(0x3D4, 0x0F);
outb(0x3D5, (pos & 0xFF) as u8);
outb(0x3D4, 0x0E);
outb(0x3D5, ((pos >> 8 ) & 0xFF) as u8);
}
}
#[allow(dead_code)]
pub fn get_cursor_position() -> (u16, u16) {
let mut pos: u16 = 0;
unsafe {
outb(0x3D4, 0x0F);
pos |= inb(0x3D5) as u16;
outb(0x3D4, 0x0E);
pos |= (inb(0x3D5) as u16) << 8;
}
(pos / (BUFFER_WIDTH as u16), pos % (BUFFER_WIDTH as u16))
}

View File

@@ -0,0 +1,86 @@
use core::slice::Iter;
use super::{Frame, FrameAllocator, MemInfo, MemoryAreaIter};
use multiboot2::MemoryArea;
pub struct AreaFrameAllocator<'a> {
next_free_frame: Frame,
current_area: Option<&'a MemoryArea>,
areas: MemoryAreaIter,
kernel_start: Frame,
kernel_end: Frame,
multiboot_start: Frame,
multiboot_end: Frame,
}
impl<'a> FrameAllocator for AreaFrameAllocator<'a> {
fn allocate_frame(&mut self) -> Option<Frame> {
if let Some(area) = self.current_area {
// "Clone" the frame to return it if it's free. Frame doesn't
// implement Clone, but we can construct an identical frame.
let frame = Frame{ number: self.next_free_frame.number };
// the last frame of the current area
let current_area_last_frame = {
let address = area.start_address() + area.size() - 1;
Frame::containing_address(address as usize)
};
if frame > current_area_last_frame {
// all frames of current area are used, switch to next area
self.choose_next_area();
} else if frame >= self.kernel_start && frame <= self.kernel_end {
// `frame` is used by the kernel
self.next_free_frame = Frame {
number: self.kernel_end.number + 1
};
} else if frame >= self.multiboot_start && frame <= self.multiboot_end {
// `frame` is used by the multiboot information structure
self.next_free_frame = Frame {
number: self.multiboot_end.number + 1
};
} else {
// frame is unused, increment `next_free_frame` and return it
self.next_free_frame.number += 1;
return Some(frame);
}
// `frame` was not valid, try it again with the updated `next_free_frame`
self.allocate_frame()
} else {
None // no free frames left
}
}
fn deallocate_frame(&mut self, _: Frame) {
unimplemented!()
}
}
impl<'a> AreaFrameAllocator<'a> {
fn choose_next_area(&mut self) {
self.current_area = self.areas.clone().filter(|area| {
let address = area.start_address() + area.size() - 1;
Frame::containing_address(address as usize) >= self.next_free_frame
}).min_by_key(|area| area.start_address());
if let Some(area) = self.current_area {
let start_frame = Frame::containing_address(area.start_address() as usize);
if self.next_free_frame < start_frame {
self.next_free_frame = start_frame;
}
}
}
pub fn new(mi: MemInfo) -> AreaFrameAllocator<'a> {
let mut allocator = AreaFrameAllocator {
next_free_frame: Frame::containing_address(0),
current_area: None,
areas: mi.mem_area_iter,
kernel_start: Frame::containing_address(mi.kernel_start),
kernel_end: Frame::containing_address(mi.kernel_end),
multiboot_start: Frame::containing_address(mi.mb_start),
multiboot_end: Frame::containing_address(mi.mb_end),
};
allocator.choose_next_area();
allocator
}
}

115
kernel/src/mem/mod.rs Normal file
View File

@@ -0,0 +1,115 @@
use core::{alloc::{GlobalAlloc, Layout}, ops::Deref};
use multiboot2::{BootInformation, BootInformationHeader, MemoryArea, MemoryAreaType, MemoryMapTag, TagTrait};
pub mod area_frame_alloc;
#[global_allocator]
static GLOBAL_ALLOCATOR: DummyAlloc = DummyAlloc;
pub struct DummyAlloc;
unsafe impl GlobalAlloc for DummyAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 0 as *mut u8 }
unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {}
}
pub const PAGE_SIZE: usize = 4096;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Frame {
number: usize,
}
impl Frame {
fn containing_address(address: usize) -> Frame {
Frame{ number: address / PAGE_SIZE }
}
}
pub trait FrameAllocator {
fn allocate_frame(&mut self) -> Option<Frame>;
fn deallocate_frame(&mut self, frame: Frame);
}
#[derive(Clone, Debug)]
pub struct MemoryAreaIter {
current_area: *const MemoryArea,
last_area: *const MemoryArea,
entry_size: u32,
}
impl Iterator for MemoryAreaIter {
type Item = &'static MemoryArea;
fn next(&mut self) -> Option<&'static MemoryArea> {
if self.current_area > self.last_area {
None
} else {
let area = unsafe{&*self.current_area};
self.current_area = ((self.current_area as u32) + self.entry_size)
as *const MemoryArea;
if area.typ() == MemoryAreaType::Available {
Some(area)
} else {self.next()}
}
}
}
impl MemoryAreaIter {
pub fn new(mmap_tag: &MemoryMapTag) -> Self {
let self_ptr = mmap_tag as *const MemoryMapTag;
let start_area = (mmap_tag.memory_areas().first().unwrap()) as *const MemoryArea;
MemoryAreaIter {
current_area: start_area,
last_area: ((self_ptr as *const () as usize) + mmap_tag.size() - mmap_tag.entry_size() as usize) as *const MemoryArea,
entry_size: mmap_tag.entry_size(),
}
}
}
#[derive(Debug, Clone)]
pub struct MemInfo{
mem_area_iter: MemoryAreaIter,
pub kernel_start: usize,
pub kernel_end: usize,
pub mb_start: usize,
pub mb_end: usize,
}
impl MemInfo {
pub fn load(mb_ptr: usize) -> Self {
let boot_info = unsafe {
multiboot2::BootInformation::load(mb_ptr as *const BootInformationHeader).unwrap()
};
let mmap_tag = boot_info.memory_map_tag().unwrap().clone();
// log::debug!("Memory areas:");
// for area in mmap_tag.memory_areas() {
// log::debug!(" start: 0x{:x}, sz: 0x{:x}", area.start_address(), area.size());
// }
// log::debug!("kernel sections:");
// for section in boot_info.elf_sections().unwrap() {
// log::debug!("{}: start: 0x{:x}, sz: 0x{:x}, flags: 0b{:b}", section.name().unwrap_or("NONE"),
// section.start_address(), section.size(), section.flags());
// }
let kernel_start = boot_info.elf_sections().unwrap().clone().map(|s| s.start_address()).min().unwrap() as usize;
let kernel_end = boot_info.elf_sections().unwrap().clone().map(|s| s.end_address()).max().unwrap() as usize;
let mb_start = boot_info.start_address();
let mb_end = boot_info.end_address();
//log::debug!("Kernel: start: 0x{:x} sz: 0x{:x}", mi.kernel_start, mi.kernel_end - mi.kernel_start);
//log::debug!("Multiboot: start: 0x{:x} sz: 0x{:x}", mi.mb_start, mi.mb_end - mi.mb_start);
Self {
mem_area_iter: MemoryAreaIter::new(mmap_tag),
kernel_start,
kernel_end,
mb_start,
mb_end,
}
}
}

12
kernel/src/utils.rs Normal file
View File

@@ -0,0 +1,12 @@
use x86_64::instructions;
pub fn hcf() -> ! {
loop {
instructions::hlt();
core::hint::spin_loop();
}
}