From 23c355762c6b617e11f7e3c6009fa4dca17f4e79 Mon Sep 17 00:00:00 2001
From: TheOddGarlic <umutinanerdogan@pm.me>
Date: Sat, 20 Aug 2022 09:27:37 +0300
Subject: [PATCH] progress on porting to limine

---
 Cargo.lock                             | 14 ++---
 ableos/Cargo.toml                      |  2 +-
 ableos/json_targets/x86_64-ableos.json |  9 +++-
 ableos/src/arch/x86_64/init.rs         | 16 ++++--
 ableos/src/arch/x86_64/kernel.ld       | 48 +++++++++++++++++
 ableos/src/arch/x86_64/memory.rs       | 74 ++++----------------------
 ableos/src/arch/x86_64/mod.rs          | 27 +++++-----
 ableos/src/scratchpad.rs               | 12 ++++-
 kernel/src/allocator.rs                |  5 +-
 9 files changed, 111 insertions(+), 96 deletions(-)
 create mode 100644 ableos/src/arch/x86_64/kernel.ld

diff --git a/Cargo.lock b/Cargo.lock
index 3a0df9f..6a23161 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,7 +30,6 @@ dependencies = [
  "acpi",
  "axel",
  "bitflags",
- "bootloader",
  "clparse",
  "cpuio",
  "ext2",
@@ -41,6 +40,7 @@ dependencies = [
  "kernel",
  "lazy_static",
  "libwasm",
+ "limine",
  "linked_list_allocator",
  "lliw",
  "log",
@@ -150,12 +150,6 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "bootloader"
-version = "0.9.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de78decc37247c7cfac5dbf3495c7298c6ac97cb355161caa7e15969c6648e6c"
-
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -348,6 +342,12 @@ name = "libwasm"
 version = "0.1.0"
 source = "git+https://git.ablecorp.us/able/libwasm.git#4ffcd290f8bc918ca4adf5e23ce2097968e4a8b2"
 
+[[package]]
+name = "limine"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac64618e505bab2387986e5b1014f5d344130d609685bbd8b71a10af3ee599d"
+
 [[package]]
 name = "linked_list_allocator"
 version = "0.9.1"
diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml
index 9536237..48ffc68 100644
--- a/ableos/Cargo.toml
+++ b/ableos/Cargo.toml
@@ -108,7 +108,7 @@ git = "https://git.ablecorp.us:443/able/externc-libm.git"
 riscv = "*"
 
 [target.'cfg(target_arch = "x86_64")'.dependencies]
-bootloader = { version = "0.9.8", features = ["map_physical_memory"] }
+limine = "0.1"
 cpuio = { git = "https://git.ablecorp.us/ondra05/cpuio.git" }
 pic8259 = "0.10.1"
 uart_16550 = "0.2.0"
diff --git a/ableos/json_targets/x86_64-ableos.json b/ableos/json_targets/x86_64-ableos.json
index 346fefd..e400195 100644
--- a/ableos/json_targets/x86_64-ableos.json
+++ b/ableos/json_targets/x86_64-ableos.json
@@ -11,5 +11,12 @@
     "linker": "rust-lld",
     "panic-strategy": "abort",
     "disable-redzone": true,
-    "features": "-mmx,-sse,+soft-float"
+    "features": "-mmx,-sse,+soft-float",
+    "code-model": "kernel",
+    "pre-link-args": {
+        "ld.lld": [
+            "--gc-sections",
+            "--script=ableos/src/arch/x86_64/kernel.ld"
+        ]
+    }
 }
\ No newline at end of file
diff --git a/ableos/src/arch/x86_64/init.rs b/ableos/src/arch/x86_64/init.rs
index 88344bc..d607d78 100644
--- a/ableos/src/arch/x86_64/init.rs
+++ b/ableos/src/arch/x86_64/init.rs
@@ -17,15 +17,21 @@ pub fn init() {
         Err(err) => serial_println!("{}", err),
     }
 
-    let mut term = TERM.lock();
+    trace!("gdt");
+    gdt::init();
+
+    trace!("idt");
+    interrupts::init_idt();
+    unsafe { interrupts::PICS.lock().initialize() };
+
+    trace!("term");
+    let term = &*TERM;
+    trace!("term.lock()");
+    let mut term = term.lock();
     // term.initialize();
     term.set_dirty(true);
     term.draw_term();
     drop(term);
 
-    gdt::init();
-
-    interrupts::init_idt();
-    unsafe { interrupts::PICS.lock().initialize() };
     x86_64::instructions::interrupts::enable();
 }
diff --git a/ableos/src/arch/x86_64/kernel.ld b/ableos/src/arch/x86_64/kernel.ld
new file mode 100644
index 0000000..a3af617
--- /dev/null
+++ b/ableos/src/arch/x86_64/kernel.ld
@@ -0,0 +1,48 @@
+/* Tell the linker that we want an x86_64 ELF64 output file */
+OUTPUT_FORMAT(elf64-x86-64)
+OUTPUT_ARCH(i386:x86-64)
+
+/* We want the symbol `x86_64_start` to be our entry point */
+ENTRY(x86_64_start)
+
+/* Define the program headers we want so the bootloader gives us the right */
+/* MMU permissions */
+PHDRS
+{
+    null    PT_NULL    FLAGS(0) ;                   /* Null segment */
+    text    PT_LOAD    FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
+    rodata  PT_LOAD    FLAGS((1 << 2)) ;            /* Read only */
+    data    PT_LOAD    FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
+}
+
+SECTIONS
+{
+    /* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
+    /* and because that is what the Limine spec mandates. */
+    /* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
+    /* that is the beginning of the region. */
+    . = 0xffffffff80000000;
+
+    .text : {
+        *(.text .text.*)
+    } :text
+
+    /* Move to the next memory page for .rodata */
+    . += CONSTANT(MAXPAGESIZE);
+
+    .rodata : {
+        *(.rodata .rodata.*)
+    } :rodata
+
+    /* Move to the next memory page for .data */
+    . += CONSTANT(MAXPAGESIZE);
+
+    .data : {
+        *(.data .data.*)
+    } :data
+
+    .bss : {
+        *(COMMON)
+        *(.bss .bss.*)
+    } :data
+}
diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs
index df43bb3..c349404 100644
--- a/ableos/src/arch/x86_64/memory.rs
+++ b/ableos/src/arch/x86_64/memory.rs
@@ -1,7 +1,7 @@
-use bootloader::bootinfo::{MemoryMap, MemoryRegionType};
+use limine::{LimineMemmapResponse, LimineMemoryMapEntryType};
 use x86_64::{
     structures::paging::{
-        FrameAllocator, FrameDeallocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame,
+        FrameAllocator, FrameDeallocator, OffsetPageTable, PageTable, PhysFrame,
         Size4KiB,
     },
     PhysAddr, VirtAddr,
@@ -25,69 +25,13 @@ unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut
     &mut *page_table_ptr
 }
 
-fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> {
-    use x86_64::registers::control::Cr3;
-    use x86_64::structures::paging::page_table::FrameError;
-
-    let (level_4_table_frame, _) = Cr3::read();
-
-    let table_indexes = [
-        addr.p4_index(),
-        addr.p3_index(),
-        addr.p2_index(),
-        addr.p1_index(),
-    ];
-    let mut frame = level_4_table_frame;
-
-    for &index in &table_indexes {
-        // convert the frame into a page table reference
-        let virt = physical_memory_offset + frame.start_address().as_u64();
-        let table_ptr: *const PageTable = virt.as_ptr();
-        let table = unsafe { &*table_ptr };
-
-        let entry = &table[index];
-        frame = match entry.frame() {
-            Ok(frame) => frame,
-            Err(FrameError::FrameNotPresent) => return None,
-            Err(FrameError::HugeFrame) => panic!["huge pages not supported"],
-        };
-    }
-
-    Some(frame.start_address() + u64::from(addr.page_offset()))
-}
-
-pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> {
-    translate_addr_inner(addr, physical_memory_offset)
-}
-
-pub fn create_example_mapping(
-    page: Page,
-    mapper: &mut OffsetPageTable,
-    frame_allocator: &mut impl FrameAllocator<Size4KiB>,
-) {
-    use x86_64::structures::paging::PageTableFlags as Flags;
-
-    let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
-    let flags = Flags::PRESENT | Flags::WRITABLE;
-
-    let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) };
-    map_to_result.expect("map_to failed").flush();
-}
-
-pub struct EmptyFrameAllocator;
-unsafe impl FrameAllocator<Size4KiB> for EmptyFrameAllocator {
-    fn allocate_frame(&mut self) -> Option<PhysFrame<Size4KiB>> {
-        None
-    }
-}
-
 pub struct BootInfoFrameAllocator {
-    memory_map: &'static MemoryMap,
+    memory_map: &'static LimineMemmapResponse,
     next: usize,
 }
 
 impl BootInfoFrameAllocator {
-    pub unsafe fn init(memory_map: &'static MemoryMap) -> Self {
+    pub unsafe fn init(memory_map: &'static LimineMemmapResponse) -> Self {
         Self {
             memory_map,
             next: 0,
@@ -95,11 +39,11 @@ impl BootInfoFrameAllocator {
     }
 
     fn usable_frames(&self) -> impl Iterator<Item = PhysFrame> {
-        let regions = self.memory_map.iter();
-        let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable);
-        let addr_range = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr());
-        let frame_address = addr_range.flat_map(|r| r.step_by(4096));
-        frame_address.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)))
+        self.memory_map.mmap().unwrap().iter()
+            .filter(|r| r.typ == LimineMemoryMapEntryType::Usable)
+            .map(|r| r.base..r.base + r.len)
+            .flat_map(|r| r.step_by(4096))
+            .map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)))
     }
 }
 
diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs
index cabb6bb..b88e0e3 100644
--- a/ableos/src/arch/x86_64/mod.rs
+++ b/ableos/src/arch/x86_64/mod.rs
@@ -10,27 +10,24 @@ pub mod init;
 pub mod interrupts;
 pub mod memory;
 
-use crate::arch::drivers::allocator;
-use bootloader::{entry_point, BootInfo};
+use limine::*;
 use x86_64::{instructions::hlt, VirtAddr};
 
-#[cfg(not(test))]
-entry_point![start];
+use crate::serial_println;
+
+use self::drivers::allocator;
+
+static HHDM: LimineHhdmRequest = LimineHhdmRequest::new(0);
+static MMAP: LimineMmapRequest = LimineMmapRequest::new(0);
 
-#[cfg(not(test))]
 #[no_mangle]
-pub fn start(boot_info: &'static BootInfo) -> ! {
-    let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
+pub fn x86_64_start() -> ! {
+    let hhdm = HHDM.get_response().get().unwrap();
+    let mmap = MMAP.get_response().get().unwrap();
+    let phys_mem_offset = VirtAddr::new(hhdm.offset);
 
     let mut mapper = unsafe { memory::init(phys_mem_offset) };
-    let mut frame_allocator =
-        unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) };
-
-    // let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000));
-    // memory::create_example_mapping(page, &mut mapper, &mut frame_allocator);
-    //
-    // let page_ptr: *mut u64 = page.start_address().as_mut_ptr();
-    // unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_804e) };
+    let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(mmap) };
 
     allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
 
diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs
index dbe877a..a6d6431 100644
--- a/ableos/src/scratchpad.rs
+++ b/ableos/src/scratchpad.rs
@@ -43,7 +43,17 @@ impl acpi::AcpiHandler for AcpiStruct {
     }
 }
 
-pub static TERM: Lazy<spin::Mutex<VTerm>> = Lazy::new(|| spin::Mutex::new(VTerm::new()));
+pub static TERM: Lazy<spin::Mutex<VTerm>> = Lazy::new(|| {
+    trace!("mutex");
+    let mutex = spin::Mutex::new({
+        trace!("vterm");
+        let vterm = VTerm::new();
+        trace!("vterm-done");
+        vterm
+    });
+    trace!("mutex-done");
+    mutex
+});
 
 #[derive(Debug)]
 pub struct Path {
diff --git a/kernel/src/allocator.rs b/kernel/src/allocator.rs
index 3c177d4..3c98c5d 100644
--- a/kernel/src/allocator.rs
+++ b/kernel/src/allocator.rs
@@ -1,6 +1,7 @@
 //! Memory allocator
 
 use linked_list_allocator::LockedHeap;
+use log::trace;
 
 ///
 pub const HEAP_START: usize = 0x_4444_4444_0000;
@@ -20,5 +21,7 @@ pub static ALLOCATOR: LockedHeap = LockedHeap::empty();
 
 #[alloc_error_handler]
 fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
-    panic!("allocation error: {:?}", layout)
+    trace!("allocation error: {:?}", layout);
+    loop {}
+    // panic!("allocation error: {:?}", layout)
 }