From f074527e42bc36faa85ca681fe8f444d77d1e38b Mon Sep 17 00:00:00 2001
From: able <abl3theabove@gmail.com>
Date: Mon, 13 Nov 2023 23:51:30 -0600
Subject: [PATCH] Arguments are actually passed into programs

---
 kernel/src/arch/riscv64/mod.rs                |  50 ++++--
 kernel/src/arch/x86_64/graphics.rs            |  71 ---------
 kernel/src/arch/x86_64/mod.rs                 |  85 +++++-----
 kernel/src/holeybytes/mod.rs                  |   5 +
 kernel/src/kmain.rs                           |  53 +++++--
 kernel/src/main.rs                            |   1 +
 repbuild/src/main.rs                          |   5 +-
 sysdata/limine.cfg                            |   2 +-
 .../limine_framebuffer_driver.rhai            | 148 +++++++++++++++---
 9 files changed, 257 insertions(+), 163 deletions(-)

diff --git a/kernel/src/arch/riscv64/mod.rs b/kernel/src/arch/riscv64/mod.rs
index 0c7e966..2caa6c3 100644
--- a/kernel/src/arch/riscv64/mod.rs
+++ b/kernel/src/arch/riscv64/mod.rs
@@ -1,37 +1,46 @@
 mod memory;
 
-use core::{arch::{asm, global_asm}, fmt::Write};
-use alloc::boxed::Box;
-use sbi::system_reset::{ResetType, ResetReason, system_reset};
-use spin::{Mutex, Once};
-use uart_16550::MmioSerialPort;
+use {
+    alloc::boxed::Box,
+    core::{
+        arch::{asm, global_asm},
+        fmt::Write,
+    },
+    sbi::system_reset::{system_reset, ResetReason, ResetType},
+    spin::{Mutex, Once},
+    uart_16550::MmioSerialPort,
+};
 
-use crate::{allocator, memory::PhysicalAddress, arch::riscv64::memory::{PAGE_TABLE, PageEntryFlags, PageSize, PageTable}};
+use crate::{
+    allocator,
+    arch::riscv64::memory::{PageEntryFlags, PageSize, PageTable, PAGE_TABLE},
+    memory::PhysicalAddress,
+};
 
 global_asm!(include_str!("entry.s"));
 global_asm!(include_str!("memory_regions.s"));
 
 pub const PAGE_SIZE: usize = 4096;
 
-extern {
+extern "C" {
     static TEXT_START: PhysicalAddress;
     static TEXT_END: PhysicalAddress;
 
     static RODATA_START: PhysicalAddress;
     static RODATA_END: PhysicalAddress;
-    
+
     static DATA_START: PhysicalAddress;
     static DATA_END: PhysicalAddress;
 
     static SDATA_START: PhysicalAddress;
     static SDATA_END: PhysicalAddress;
-    
+
     static BSS_START: PhysicalAddress;
     static BSS_END: PhysicalAddress;
-    
+
     static INITIAL_KERNEL_HEAP_START: PhysicalAddress;
     static INITIAL_KERNEL_HEAP_SIZE: usize;
-    
+
     static USABLE_MEMORY_START: PhysicalAddress;
     static USABLE_MEMORY_SIZE: usize;
 }
@@ -39,12 +48,15 @@ extern {
 static SERIAL_CONSOLE: Once<Mutex<MmioSerialPort>> = Once::new();
 
 #[no_mangle]
-unsafe extern fn _kernel_start() -> ! {
+unsafe extern "C" fn _kernel_start() -> ! {
     SERIAL_CONSOLE.call_once(|| Mutex::new(unsafe { MmioSerialPort::new(0x1000_0000) }));
     crate::logger::init().expect("failed to set logger");
     log::info!("Initialising AKern {}", crate::VERSION);
 
-    allocator::init(INITIAL_KERNEL_HEAP_START.as_mut_ptr::<u8>(), INITIAL_KERNEL_HEAP_SIZE);
+    allocator::init(
+        INITIAL_KERNEL_HEAP_START.as_mut_ptr::<u8>(),
+        INITIAL_KERNEL_HEAP_SIZE,
+    );
     memory::init(USABLE_MEMORY_START.into(), USABLE_MEMORY_SIZE / PAGE_SIZE);
 
     let mut page_table_addr = PAGE_TABLE.get().unwrap().lock();
@@ -61,9 +73,17 @@ unsafe extern fn _kernel_start() -> ! {
     // Map bss section (includes stack and initial kernel heap)
     page_table.identity_map_range(BSS_START, BSS_END, PageEntryFlags::ReadWrite);
     // Map usable memory range (as rw so not executable)
-    page_table.identity_map_range(USABLE_MEMORY_START, USABLE_MEMORY_START + USABLE_MEMORY_SIZE.into(), PageEntryFlags::ReadWrite);
+    page_table.identity_map_range(
+        USABLE_MEMORY_START,
+        USABLE_MEMORY_START + USABLE_MEMORY_SIZE.into(),
+        PageEntryFlags::ReadWrite,
+    );
     // Map Uart so we can continue using serial
-    page_table.identity_map(0x1000_0000_usize.into(), PageEntryFlags::ReadWrite, PageSize::Size4KiB);
+    page_table.identity_map(
+        0x1000_0000_usize.into(),
+        PageEntryFlags::ReadWrite,
+        PageSize::Size4KiB,
+    );
 
     let table_ppn = page_table_addr.as_addr() as usize >> 12;
     let satp_value = 8 << 60 | table_ppn;
diff --git a/kernel/src/arch/x86_64/graphics.rs b/kernel/src/arch/x86_64/graphics.rs
index 2f36627..8b13789 100644
--- a/kernel/src/arch/x86_64/graphics.rs
+++ b/kernel/src/arch/x86_64/graphics.rs
@@ -1,72 +1 @@
-use {
-    crate::kmain::DEVICE_TREE,
-    able_graphics_library::raw_pixel::Display,
-    embedded_graphics::{pixelcolor::Rgb888, prelude::*},
-    limine::{Framebuffer, FramebufferRequest, NonNullPtr},
-    spin::{Lazy, Mutex},
-};
 
-pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
-    static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
-    let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
-
-    {
-        use crate::alloc::string::ToString;
-        let mut dt = DEVICE_TREE.lock();
-        let mut disp = xml::XMLElement::new("display_0");
-
-        disp.set_attribute("width", fb1.width);
-        disp.set_attribute("height", fb1.height);
-        disp.set_attribute("bits per pixel", fb1.bpp);
-        disp.set_attribute("pitch", fb1.pitch);
-        // disp.set_attribute("fb ptr", fb1.address.as_ptr().unwrap());
-        dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
-    }
-    let _size: usize = (fb1.width * fb1.height).try_into().unwrap();
-    let back_buffer: alloc::vec::Vec<u32> = alloc::vec![0;  800*600];
-
-    let m = Mutex::new(Display {
-        fb:    fb1.address.as_ptr().unwrap().cast(),
-        bb:    back_buffer.as_slice().as_ptr() as *mut u32,
-        size:  Size::new(fb1.width as u32, fb1.height as u32),
-        color: Rgb888::WHITE,
-    });
-    log::info!("Graphics initialised");
-    log::info!(
-        "Graphics front ptr {:?}",
-        fb1.address.as_ptr().unwrap() as *const u8
-    );
-    m
-});
-
-pub fn init() {
-    Lazy::force(&DISPLAY);
-}
-// pub fn virtio_gpu<T: Transport>(transport: T) {
-//     let mut gpu = VirtIOGpu::<AbleosHal, T>::new(transport).expect("failed to create gpu driver");
-//     let (width, height) = gpu.resolution().expect("failed to get resolution");
-//     let width = width as usize;
-//     let height = height as usize;
-//     log::info!("GPU resolution is {}x{}", width, height);
-//     let fb = gpu.setup_framebuffer().expect("failed to get fb");
-//     for y in 0..height {
-//         for x in 0..width {
-//             let idx = (y * width + x) * 4;
-//             fb[idx] = x as u8;
-//             fb[idx + 1] = y as u8;
-//             fb[idx + 2] = (x + y) as u8;
-//         }
-//     }
-//     gpu.flush().expect("failed to flush");
-//     //delay some time
-//     log::info!("virtio-gpu show graphics....");
-//     for _ in 0..100000 {
-//         for _ in 0..100000 {
-//             unsafe {
-//                 core::arch::asm!("nop");
-//             }
-//         }
-//     }
-
-//     log::info!("virtio-gpu test finished");
-// }
diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs
index a8bae23..a67a7ed 100644
--- a/kernel/src/arch/x86_64/mod.rs
+++ b/kernel/src/arch/x86_64/mod.rs
@@ -1,9 +1,6 @@
 use {
-    crate::{arch::x86_64::graphics::DISPLAY, bootmodules::BootModule},
-    core::arch::asm,
-    embedded_graphics::pixelcolor::Rgb888,
-    log::warn,
-    rdrand::RdSeed,
+    crate::bootmodules::BootModule, core::arch::asm, embedded_graphics::pixelcolor::Rgb888,
+    log::warn, rdrand::RdSeed,
 };
 pub mod memory;
 
@@ -83,51 +80,51 @@ unsafe extern "C" fn start() -> ! {
     device_info_collector::collect_device_info();
 
     // Graphics test
-    {
-        graphics::init();
-        let mut dis = DISPLAY.lock();
-        use embedded_graphics::prelude::RgbColor;
+    // {
+    //     graphics::init();
+    //     let mut dis = DISPLAY.lock();
+    //     use embedded_graphics::prelude::RgbColor;
 
-        let _ = dis.set_color(Rgb888::YELLOW);
-        let thick = 6;
-        let p1 = (400, 30);
-        let p2 = (200, 150);
-        let p3 = (600, 150);
-        let p4 = (200, 350);
-        let p5 = (600, 350);
-        let p6 = (400, 470);
+    //     let _ = dis.set_color(Rgb888::YELLOW);
+    //     let thick = 6;
+    //     let p1 = (400, 30);
+    //     let p2 = (200, 150);
+    //     let p3 = (600, 150);
+    //     let p4 = (200, 350);
+    //     let p5 = (600, 350);
+    //     let p6 = (400, 470);
 
-        {
-            //HEXAGON
+    //     {
+    //         //HEXAGON
 
-            let _ = dis.line(p1.0, p1.1, p2.0, p2.1, thick);
-            let _ = dis.line(p1.0, p1.1, p3.0, p3.1, thick);
-            let _ = dis.line(p2.0, p2.1, p4.0, p4.1, thick);
-            let _ = dis.line(p3.0, p3.1, p5.0, p5.1, thick);
-            let _ = dis.line(p6.0, p6.1, p4.0, p4.1, thick);
-            let _ = dis.line(p6.0, p6.1, p5.0, p5.1, thick);
-        }
-        {
-            let _ = dis.line(600, 150, 200, 350, thick);
-            let _ = dis.line(600, 350, 400, 250, thick);
-        }
+    //         let _ = dis.line(p1.0, p1.1, p2.0, p2.1, thick);
+    //         let _ = dis.line(p1.0, p1.1, p3.0, p3.1, thick);
+    //         let _ = dis.line(p2.0, p2.1, p4.0, p4.1, thick);
+    //         let _ = dis.line(p3.0, p3.1, p5.0, p5.1, thick);
+    //         let _ = dis.line(p6.0, p6.1, p4.0, p4.1, thick);
+    //         let _ = dis.line(p6.0, p6.1, p5.0, p5.1, thick);
+    //     }
+    //     {
+    //         let _ = dis.line(600, 150, 200, 350, thick);
+    //         let _ = dis.line(600, 350, 400, 250, thick);
+    //     }
 
-        {
-            let _ = dis.set_color(Rgb888::WHITE);
-            let hp1 = (350, 150);
-            let hp2 = (350, 350);
-            let hp3 = (450, 250);
-            let hp4 = (350, 250);
-            let hp5 = (450, 150);
-            let hp6 = (450, 350);
+    //     {
+    //         let _ = dis.set_color(Rgb888::WHITE);
+    //         let hp1 = (350, 150);
+    //         let hp2 = (350, 350);
+    //         let hp3 = (450, 250);
+    //         let hp4 = (350, 250);
+    //         let hp5 = (450, 150);
+    //         let hp6 = (450, 350);
 
-            let _ = dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
-            let _ = dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
-            let _ = dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
-        }
+    //         let _ = dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
+    //         let _ = dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
+    //         let _ = dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
+    //     }
 
-        dis.swap_buffers();
-    };
+    //     dis.swap_buffers();
+    // };
 
     // TODO: Add in rdseed and rdrand as sources for randomness
     let _rand = xml::XMLElement::new("Random");
diff --git a/kernel/src/holeybytes/mod.rs b/kernel/src/holeybytes/mod.rs
index 3b79f5e..7161648 100644
--- a/kernel/src/holeybytes/mod.rs
+++ b/kernel/src/holeybytes/mod.rs
@@ -25,6 +25,11 @@ pub struct ExecThread<'p> {
 
 unsafe impl<'p> Send for ExecThread<'p> {}
 impl<'p> ExecThread<'p> {
+    pub fn set_arguments(&mut self, ptr: u64, length: u64) {
+        self.vm.registers[1] = hbvm::value::Value(ptr);
+        self.vm.registers[2] = hbvm::value::Value(length);
+    }
+
     pub unsafe fn new(program: &'p [u8], entrypoint: Address) -> Self {
         ExecThread {
             vm: unsafe {
diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs
index 21de41f..4c9648c 100644
--- a/kernel/src/kmain.rs
+++ b/kernel/src/kmain.rs
@@ -1,19 +1,17 @@
 //! AbleOS Kernel Entrypoint
 
-use {hashbrown::HashMap, hbvm::mem::Address};
-
-use crate::{
-    capabilities,
-    holeybytes::ExecThread,
-    ipc::buffer::{self, IpcBuffer},
-};
-// use crate::arch::sloop;
 use {
     crate::{
         bootmodules::{build_cmd, BootModules},
+        capabilities,
         device_tree::DeviceTree,
+        holeybytes::ExecThread,
+        ipc::buffer::{self, IpcBuffer},
     },
     alloc::format,
+    hashbrown::HashMap,
+    hbvm::mem::Address,
+    limine::{Framebuffer, FramebufferRequest, NonNullPtr},
     log::{debug, info, trace},
     spin::{Lazy, Mutex},
     xml::XMLElement,
@@ -32,6 +30,7 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
             // TODO: pass into the program
             // Pass CMDLine into an IPCBuffer and put the ptr to the IPCBuffer in r200
             _bmcmd = build_cmd(name, bm.cmd.clone());
+            log::info!("{:?}", _bmcmd);
         }
     }
 
@@ -47,12 +46,47 @@ pub fn kmain(cmdline: &str, boot_modules: BootModules) -> ! {
     // TODO: Schedule the VFS from initramfs
     // TODO: schedule the init system from the initramfs
 
+    drop(dt);
+
+    let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
+
+    {
+        use crate::alloc::string::ToString;
+        let mut dt = DEVICE_TREE.lock();
+        let mut disp = xml::XMLElement::new("display_0");
+
+        disp.set_attribute("width", fb1.width);
+        disp.set_attribute("height", fb1.height);
+        disp.set_attribute("bits per pixel", fb1.bpp);
+        disp.set_attribute("pitch", fb1.pitch);
+        dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
+    }
+    log::info!("Graphics initialised");
+    log::info!(
+        "Graphics front ptr {:?}",
+        fb1.address.as_ptr().unwrap() as *const u8
+    );
+
     let mut executor = crate::task::Executor::default();
     let bm_take = boot_modules.len();
     unsafe {
         for module in boot_modules.into_iter().take(bm_take) {
+            let mut cmd = module.cmd;
+            {
+                // Remove the quotes
+                cmd.remove(0);
+                cmd.pop();
+            }
+            let cmd_len = cmd.as_bytes().len() as u64;
+
+            log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
+
             executor.spawn(async move {
-                if let Err(e) = ExecThread::new(&module.bytes, Address::new(0)).await {
+                let mut thr = ExecThread::new(&module.bytes, Address::new(0));
+                if cmd_len > 0 {
+                    thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len);
+                }
+                if let Err(e) = thr.await {
                     log::error!("{e:?}");
                 }
             });
@@ -68,6 +102,7 @@ pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
     let dt = DeviceTree::new();
     Mutex::new(dt)
 });
+pub static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
 
 use alloc::vec::Vec;
 pub type IpcBuffers = HashMap<u64, IpcBuffer>;
diff --git a/kernel/src/main.rs b/kernel/src/main.rs
index 308e166..973e301 100644
--- a/kernel/src/main.rs
+++ b/kernel/src/main.rs
@@ -1,3 +1,4 @@
 #![no_std]
 #![no_main]
+
 extern crate kernel;
diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs
index a0e6caf..f9c0691 100644
--- a/repbuild/src/main.rs
+++ b/repbuild/src/main.rs
@@ -139,9 +139,7 @@ fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
     io::copy(
         &mut File::open("limine/BOOTAA64.EFI")
             .map_err(Report::from)
-            .attach_printable(
-                "Copying Limine (ARM): have you pulled the submodule?",
-            )?,
+            .attach_printable("Copying Limine (ARM): have you pulled the submodule?")?,
         &mut bootdir.create_file("bootaa64.efi")?,
     )?;
 
@@ -233,6 +231,7 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
                 "-drive", "file=target/disk.img,format=raw",
                 "-m", "4G",
                 "-smp", "cores=4",
+                // "-enable-kvm",
                 "-cpu", "Broadwell-v4"
             ]);
         }
diff --git a/sysdata/limine.cfg b/sysdata/limine.cfg
index e1acf4e..8e5699f 100644
--- a/sysdata/limine.cfg
+++ b/sysdata/limine.cfg
@@ -31,4 +31,4 @@ TERM_BACKDROP=008080
     MODULE_CMDLINE=""
 
     MODULE_PATH=boot:///limine_framebuffer_driver.hbf
-    MODULE_CMDLINE=""
\ No newline at end of file
+    MODULE_CMDLINE="height=10 width=10 arch=${ARCH}"
\ No newline at end of file
diff --git a/sysdata/test-programs/limine_framebuffer_driver.rhai b/sysdata/test-programs/limine_framebuffer_driver.rhai
index 10e2214..d005cbc 100644
--- a/sysdata/test-programs/limine_framebuffer_driver.rhai
+++ b/sysdata/test-programs/limine_framebuffer_driver.rhai
@@ -4,26 +4,134 @@
 // Use std abstractions if they exist like logging functionality
 import "sysdata/test-programs/hblib/std" as std;
 
-// Define main
-fn main(){
-    std::Info("Starting the limine framebuffer driver.");
-    // Color
-    li64(r1, 0xffffffff);
-    // iterator
-    li32(r2, 0);
-    // count
-    li64(r3, 12);
-    // Label here
-    let start = label();
-    // Write to the memory
-    st(r1, r2, 0xFFFF8000C0000000, 1);
-    // Increment 
-    addi64(r2, r2, 1);
-    // std::Info("abc");
-    jltu(r2, r3, start);
 
-    // Terminate execution.
-    tx();
+fn rect(reg_x, reg_y, w, h, color) {
+  li64(r3, 0);
+  li64(r4, 0);
+  li64(r5, w);
+  li64(r6, h);
+
+  let start_y = label();
+
+  let start_x = label();
+
+  add64(r9, r3, reg_x);
+  add64(r10, r4, reg_y);
+  pixel(r9, r10, color);
+
+  li64(r1, 1);
+  add64(r3, r3, r1);
+
+  jltu(r3, r5, start_x);
+
+  li64(r1, 1);
+  add64(r4, r4, r1);
+
+  li64(r3, 0);
+
+  jltu(r4, r6, start_y);
 }
 
-main();
\ No newline at end of file
+fn pixel(reg_x, reg_y, color) {
+  let BUFFER = 0xFFFF8000C0000000;
+  let WIDTH = 1024;
+
+  // r1 = y * WIDTH
+  li64(r1, WIDTH);
+  mul64(r1, reg_y, r1);
+
+  // r2 = x + r2
+  add64(r2, reg_x, r1);
+
+  // r2 = r2 * 4
+  li64(r1, 4);
+  mul64(r2, r2, r1);
+  
+  // store pixel value
+  li64(r1, color);
+  st(r1, r2, BUFFER, 4);
+}
+
+fn clear() {
+//   rect(r0, r0, 1024, 768, 0xff222222);
+
+  let BUFFER = 0xFFFF8000C0000000;
+  // on arm the FB is at 0xFFFF8000BC430000
+  // FIXME: get the framebuffer pointer from the starting arguments
+
+  li64(r1, 0xff222222);
+  li64(r2, 0);
+  li64(r3, 1);
+  li64(r4, 1024 * 768);
+  li64(r5, 4);
+  let start = label();
+  mul64(r6, r2, r5);
+  st(r1, r6, BUFFER, 4);
+  add64(r2, r2, r3);
+  jltu(r2, r4, start);
+}
+
+// Define main
+fn main(){
+  std::Info("Starting the limine framebuffer driver.");
+
+  li64(r100, 300);
+  li64(r101, 300);
+  li64(r102, 1);
+  li64(r103, 1);
+  li64(r104, 1024 - 20);
+  li64(r105, 768 - 20);
+  li64(r106, 0);
+  li64(r107, 0);
+
+  clear();
+
+  let start = label();
+
+  rect(r100, r101, 20, 20, 0xff222222);
+  //clear();
+
+  add64(r100, r100, r102);
+  add64(r101, r101, r103);
+
+  let after_x_right = declabel();
+  jltu(r100, r104, after_x_right);
+  li64(r102, -1);
+  here(after_x_right);
+
+  let after_x_left = declabel();
+  jgtu(r100, r106, after_x_left);
+  li64(r102, 1);
+  li64(r100, 0);
+  here(after_x_left);
+
+  let after_y_right = declabel();
+  jltu(r101, r105, after_y_right);
+  li64(r103, -1);
+  here(after_y_right);
+
+  let after_y_left = declabel();
+  jgtu(r101, r107, after_y_left);
+  li64(r103, 1);
+  li64(r101, 0);
+  here(after_y_left);
+
+  rect(r100, r101, 20, 20, 0xffffffff);
+
+  li64(r200, 0);
+  li64(r201, 1);
+  li64(r202, 10000);
+  let wait = label();
+  add64(r200, r200, r201);
+  jltu(r200, r202, wait);
+
+  jeq(r0, r0, start);
+  //jmp(start);
+
+  std::Info("done");
+
+  // Terminate execution.
+  tx();
+}
+
+main();