From 0435902579e56950e7d6846a09ffcd03c8e1f20f Mon Sep 17 00:00:00 2001 From: Yuke Peng Date: Sun, 5 Mar 2023 22:19:23 -0800 Subject: [PATCH] Replace bootloader with limine --- src/Cargo.toml | 18 ++--- src/{jinux-boot => boot}/Cargo.toml | 8 +- src/boot/limine/conf/limine.cfg | 18 +++++ src/boot/limine/conf/linker.ld | 81 +++++++++++++++++++ src/boot/limine/scripts/limine-build.sh | 37 +++++++++ src/{jinux-boot => boot}/src/main.rs | 68 +++++----------- src/build.rs | 20 +++++ src/framework/jinux-frame/Cargo.toml | 21 +++-- src/framework/jinux-frame/src/boot/limine.rs | 26 ++++++ src/framework/jinux-frame/src/boot/mod.rs | 9 +++ src/framework/jinux-frame/src/config.rs | 3 +- .../jinux-frame/src/device/framebuffer.rs | 66 ++++++++++----- src/framework/jinux-frame/src/device/mod.rs | 11 +-- src/framework/jinux-frame/src/driver/acpi.rs | 20 +++-- src/framework/jinux-frame/src/driver/mod.rs | 4 +- src/framework/jinux-frame/src/lib.rs | 51 ++++-------- src/framework/jinux-frame/src/linker.ld | 40 --------- src/framework/jinux-frame/src/mm/mod.rs | 52 +++++++++--- src/framework/jinux-frame/src/trap/mod.rs | 9 --- src/src/main.rs | 13 +-- src/x86_64-custom.json | 3 - 21 files changed, 364 insertions(+), 214 deletions(-) rename src/{jinux-boot => boot}/Cargo.toml (54%) create mode 100644 src/boot/limine/conf/limine.cfg create mode 100644 src/boot/limine/conf/linker.ld create mode 100755 src/boot/limine/scripts/limine-build.sh rename src/{jinux-boot => boot}/src/main.rs (63%) create mode 100644 src/build.rs create mode 100644 src/framework/jinux-frame/src/boot/limine.rs create mode 100644 src/framework/jinux-frame/src/boot/mod.rs delete mode 100644 src/framework/jinux-frame/src/linker.ld diff --git a/src/Cargo.toml b/src/Cargo.toml index 6c03e61e..6adc3578 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -4,15 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] -bootloader = {version="0.10.12"} -jinux-frame = {path = "framework/jinux-frame"} -jinux-std = {path = "services/libs/jinux-std"} -component = {path = "services/comp-sys/component"} +limine = "0.1.10" +jinux-frame = { path = "framework/jinux-frame" } +jinux-std = { path = "services/libs/jinux-std" } +component = { path = "services/comp-sys/component" } [workspace] members = [ - "jinux-boot", + "boot", "framework/jinux-frame", "framework/pod", "framework/pod-derive", @@ -28,11 +28,5 @@ members = [ "services/libs/cpio-decoder", ] -exclude = [ - "services/comp-sys/controlled", - "services/comp-sys/cargo-component", -] +exclude = ["services/comp-sys/controlled", "services/comp-sys/cargo-component"] -[package.metadata.bootloader] -map-physical-memory = true -physical-memory-offset = "0xFFFF800000000000" diff --git a/src/jinux-boot/Cargo.toml b/src/boot/Cargo.toml similarity index 54% rename from src/jinux-boot/Cargo.toml rename to src/boot/Cargo.toml index 333eb44f..1fa7c73a 100644 --- a/src/jinux-boot/Cargo.toml +++ b/src/boot/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bootloader-locator = "0.0.4" # for locating the `bootloader` dependency on disk -locate-cargo-manifest = "0.2.0" # for locating the kernel's `Cargo.toml` runner-utils = "0.0.2" -anyhow = "1.0.32" \ No newline at end of file +anyhow = "1.0.32" + +[features] +default = ["limine"] +limine= [] \ No newline at end of file diff --git a/src/boot/limine/conf/limine.cfg b/src/boot/limine/conf/limine.cfg new file mode 100644 index 00000000..228216bf --- /dev/null +++ b/src/boot/limine/conf/limine.cfg @@ -0,0 +1,18 @@ + +# For a detailed description of the limine.cfg format, see CONFIG.md in the Limine repo: +# https://github.com/limine-bootloader/limine/blob/trunk/CONFIG.md + +TIMEOUT=1 +SERIAL=yes +VERBOSE=yes + +# The name of kernel +: Jinux + +PROTOCOL=limine +# Tell Limine where to look for the kernel. +# The runner (.cargo/runner.sh) will use the name of the package from Cargo.toml, +# so change this path if you change that. +KERNEL_PATH=boot:///jinux +# The path to the module +MODULE_PATH=boot:///ramdisk.cpio \ No newline at end of file diff --git a/src/boot/limine/conf/linker.ld b/src/boot/limine/conf/linker.ld new file mode 100644 index 00000000..b1dade80 --- /dev/null +++ b/src/boot/limine/conf/linker.ld @@ -0,0 +1,81 @@ +ENTRY(_start) +OUTPUT_ARCH(i386:x86-64) +OUTPUT_FORMAT(elf64-x86-64) + +KERNEL_BASE = 0xffffffff80000000; + +SECTIONS { + . = KERNEL_BASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rela : { *(.rela*) } + .rodata : { *(.rodata .rodata.*) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .eh_frame_hdr : { + PROVIDE(__eh_frame_hdr = .); + KEEP(*(.eh_frame_hdr)) + PROVIDE(__eh_frame_hdr_end = .); + } + .eh_frame : { + PROVIDE(__eh_frame = .); + KEEP(*(.eh_frame)) + PROVIDE(__eh_frame_end = .); + } + .gcc_except_table : { KEEP(*(.gcc_except_table .gcc_except_table.*)) } + + . += CONSTANT(MAXPAGESIZE); + + .plt : { *(.plt .plt.*) } + .text : { *(.text .text.*) } + + . += CONSTANT(MAXPAGESIZE); + + .tdata : { *(.tdata .tdata.*) } + .tbss : { *(.tbss .tbss.*) } + + .data.rel.ro : { *(.data.rel.ro .data.rel.ro.*) } + .dynamic : { *(.dynamic) } + + . = ALIGN(4K); + sinit_array = .; + .init_array : { + *(.init_array .init_array.*) + } + einit_array = .; + + . = DATA_SEGMENT_RELRO_END(0, .); + + .got : { *(.got .got.*) } + .got.plt : { *(.got.plt .got.plt.*) } + .data : { *(.data .data.*) } + .bss : { *(.bss .bss.*) *(COMMON) } + + . = DATA_SEGMENT_END(.); + + .comment 0 : { *(.comment) } + .debug 0 : { *(.debug) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_frame 0 : { *(.debug_frame) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_line 0 : { *(.debug_line) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_str 0 : { *(.debug_str) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .line 0 : { *(.line) } + .shstrtab 0 : { *(.shstrtab) } + .strtab 0 : { *(.strtab) } + .symtab 0 : { *(.symtab) } +} diff --git a/src/boot/limine/scripts/limine-build.sh b/src/boot/limine/scripts/limine-build.sh new file mode 100755 index 00000000..1fbd9b6a --- /dev/null +++ b/src/boot/limine/scripts/limine-build.sh @@ -0,0 +1,37 @@ +#! /bin/sh + +set -xe + +LIMINE_GIT_URL="https://github.com/limine-bootloader/limine.git" + +# Cargo passes the path to the built executable as the first argument. +KERNEL=$1 + +# Clone the `limine` repository if we don't have it yet. +if [ ! -d target/limine ]; then + git clone $LIMINE_GIT_URL --depth=1 --branch v4.x-branch-binary target/limine +fi + +cd target/limine +make +cd - + +# Copy the needed files into an ISO image. +mkdir -p target/iso_root +cp $KERNEL boot/limine/conf/limine.cfg target/iso_root +cp target/limine/limine.sys target/iso_root +cp target/limine/limine-cd.bin target/iso_root +cp target/limine/limine-cd-efi.bin target/iso_root + +# Copy ramdisk +cp ramdisk/build/ramdisk.cpio target/iso_root + +xorriso -as mkisofs \ + -b limine-cd.bin \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + --efi-boot limine-cd-efi.bin \ + -efi-boot-part --efi-boot-image --protective-msdos-label \ + target/iso_root -o $KERNEL.iso + +# For the image to be bootable on BIOS systems, we must run `limine-deploy` on it. +target/limine/limine-deploy $KERNEL.iso diff --git a/src/jinux-boot/src/main.rs b/src/boot/src/main.rs similarity index 63% rename from src/jinux-boot/src/main.rs rename to src/boot/src/main.rs index 86e91d45..3d0f3961 100644 --- a/src/jinux-boot/src/main.rs +++ b/src/boot/src/main.rs @@ -25,7 +25,7 @@ const RUN_ARGS: &[&str] = &["-s"]; const TEST_ARGS: &[&str] = &[]; const TEST_TIMEOUT_SECS: u64 = 10; fn main() -> anyhow::Result<()> { - let mut args = std::env::args().skip(1); // skip executable name + let mut args = std::env::args().skip(1); let kernel_binary_path = { let path = PathBuf::from(args.next().unwrap()); path.canonicalize().unwrap() @@ -40,25 +40,31 @@ fn main() -> anyhow::Result<()> { false }; - let bios = create_disk_images(&kernel_binary_path); + #[cfg(feature = "limine")] + call_limine_build_script(&kernel_binary_path).unwrap(); + // add .iso + + let kernel_iso_path = { + let a = kernel_binary_path.parent().unwrap(); + a.join("jinux.iso") + }; + // let bios = create_disk_images(&kernel_binary_path); if no_boot { - println!("Created disk image at `{}`", bios.display()); + println!("Created disk image at `{}`", kernel_iso_path.display()); return Ok(()); } #[cfg(windows)] let mut run_cmd = Command::new("qemu-system-x86_64.exe"); #[cfg(not(windows))] let mut run_cmd = Command::new("qemu-system-x86_64"); - run_cmd - .arg("-drive") - .arg(format!("format=raw,file={}", bios.display())); let binary_kind = runner_utils::binary_kind(&kernel_binary_path); let mut args = COMMON_ARGS.clone().to_vec(); args.push("-drive"); let binding = create_fs_image(kernel_binary_path.as_path())?; args.push(binding.as_str()); + run_cmd.arg(kernel_iso_path.to_str().unwrap()); if binary_kind.is_test() { args.append(&mut TEST_ARGS.to_vec()); run_cmd.args(args); @@ -80,6 +86,16 @@ fn main() -> anyhow::Result<()> { Ok(()) } +fn call_limine_build_script(path: &PathBuf) -> anyhow::Result<()> { + let mut cmd = Command::new("boot/limine/scripts/limine-build.sh"); + cmd.arg(path.to_str().unwrap()); + let exit_status = cmd.status()?; + if !exit_status.success() { + std::process::exit(exit_status.code().unwrap_or(1)); + } + Ok(()) +} + fn create_fs_image(path: &Path) -> anyhow::Result { let mut fs_img_path = path.parent().unwrap().to_str().unwrap().to_string(); #[cfg(windows)] @@ -106,46 +122,6 @@ fn create_fs_image(path: &Path) -> anyhow::Result { )) } -pub fn create_disk_images(kernel_binary_path: &Path) -> PathBuf { - let bootloader_manifest_path = bootloader_locator::locate_bootloader("bootloader").unwrap(); - let kernel_manifest_path = locate_cargo_manifest::locate_manifest().unwrap(); - - let mut build_cmd = Command::new(env!("CARGO")); - build_cmd.current_dir(bootloader_manifest_path.parent().unwrap()); - build_cmd.arg("builder"); - build_cmd - .arg("--kernel-manifest") - .arg(&kernel_manifest_path); - build_cmd.arg("--kernel-binary").arg(&kernel_binary_path); - build_cmd - .arg("--target-dir") - .arg(kernel_manifest_path.parent().unwrap().join("target")); - build_cmd - .arg("--out-dir") - .arg(kernel_binary_path.parent().unwrap()); - build_cmd.arg("--quiet"); - - // println!("current dir = {:?}", build_cmd.get_current_dir()); - // println!("args = {:?}", build_cmd.get_args()); - - if !build_cmd.status().unwrap().success() { - panic!("build failed"); - } - - let kernel_binary_name = kernel_binary_path.file_name().unwrap().to_str().unwrap(); - let disk_image = kernel_binary_path - .parent() - .unwrap() - .join(format!("boot-bios-{}.img", kernel_binary_name)); - if !disk_image.exists() { - panic!( - "Disk image does not exist at {} after bootloader build", - disk_image.display() - ); - } - disk_image -} - fn run_test_command(mut cmd: Command) -> anyhow::Result { let status = runner_utils::run_with_timeout(&mut cmd, Duration::from_secs(TEST_TIMEOUT_SECS))?; Ok(status) diff --git a/src/build.rs b/src/build.rs new file mode 100644 index 00000000..88d3e8c2 --- /dev/null +++ b/src/build.rs @@ -0,0 +1,20 @@ +use std::{env, error::Error}; + +fn main() -> Result<(), Box> { + limine_build_script()?; + Ok(()) +} + +fn limine_build_script() -> Result<(), Box> { + // Get the name of the package. + let kernel_name = env::var("CARGO_PKG_NAME")?; + + // Tell rustc to pass the linker script to the linker. + println!("cargo:rustc-link-arg-bin={kernel_name}=--script=boot/limine/conf/linker.ld"); + + // Have cargo rerun this script if the linker script or CARGO_PKG_ENV changes. + println!("cargo:rerun-if-changed=boot/limine/conf/linker.ld"); + println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME"); + + Ok(()) +} diff --git a/src/framework/jinux-frame/Cargo.toml b/src/framework/jinux-frame/Cargo.toml index 7168cdb5..c5ac8f42 100644 --- a/src/framework/jinux-frame/Cargo.toml +++ b/src/framework/jinux-frame/Cargo.toml @@ -9,23 +9,20 @@ edition = "2021" bitflags = "1.3" x86_64 = "0.14.2" spin = "0.9.4" -volatile = {version="0.4.5", features = ["unstable"] } +volatile = { version = "0.4.5", features = ["unstable"] } buddy_system_allocator = "0.6" linked_list_allocator = "0.9.0" -bootloader = {version="0.10.12"} -font8x8 = { version = "0.2.5", default-features = false, features = ["unicode"]} +font8x8 = { version = "0.2.5", default-features = false, features = [ + "unicode", +] } uart_16550 = "0.2.0" -pod = {path = "../pod"} -acpi= "4.1.1" +pod = { path = "../pod" } +acpi = "4.1.1" intrusive-collections = "0.9.5" -log= "0.4" - -[dependencies.lazy_static] -version = "1.0" -features = ["spin_no_std"] - +log = "0.4" +limine = { version = "0.1.10", features = ["into-uuid"] } +lazy_static = { version = "1.0", features = ["spin_no_std"] } [features] default = ["serial_print"] serial_print = [] - diff --git a/src/framework/jinux-frame/src/boot/limine.rs b/src/framework/jinux-frame/src/boot/limine.rs new file mode 100644 index 00000000..8aaaf7cc --- /dev/null +++ b/src/framework/jinux-frame/src/boot/limine.rs @@ -0,0 +1,26 @@ +use crate::config::{self, PAGE_SIZE}; +use limine::{LimineBootInfoRequest, LimineHhdmRequest, LimineStackSizeRequest}; +use log::info; + +pub(crate) fn init() { + if let Some(bootinfo) = BOOTLOADER_INFO_REQUEST.get_response().get() { + info!( + "booted by {} v{}", + bootinfo.name.to_str().unwrap().to_str().unwrap(), + bootinfo.version.to_str().unwrap().to_str().unwrap(), + ); + } + let response = HHDM_REQUEST + .get_response() + .get() + .expect("Not found HHDM Features"); + assert_eq!(config::PHYS_OFFSET as u64, response.offset); +} + +static BOOTLOADER_INFO_REQUEST: LimineBootInfoRequest = LimineBootInfoRequest::new(0); +static HHDM_REQUEST: LimineHhdmRequest = LimineHhdmRequest::new(0); +static STACK_REQUEST: LimineStackSizeRequest = { + let a = LimineStackSizeRequest::new(0); + // 64 * 4096(PAGE_SIZE) + a.stack_size(64 * PAGE_SIZE as u64) +}; diff --git a/src/framework/jinux-frame/src/boot/mod.rs b/src/framework/jinux-frame/src/boot/mod.rs new file mode 100644 index 00000000..44515ac0 --- /dev/null +++ b/src/framework/jinux-frame/src/boot/mod.rs @@ -0,0 +1,9 @@ +mod limine; + +pub(crate) const MEMORY_MAP_MAX_COUNT: usize = 30; +pub(crate) const MODULE_MAX_COUNT: usize = 10; + +/// init bootloader +pub(crate) fn init() { + limine::init(); +} diff --git a/src/framework/jinux-frame/src/config.rs b/src/framework/jinux-frame/src/config.rs index 27588148..a4d13d33 100644 --- a/src/framework/jinux-frame/src/config.rs +++ b/src/framework/jinux-frame/src/config.rs @@ -6,7 +6,8 @@ pub const USER_STACK_SIZE: usize = PAGE_SIZE * 4; pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE * 64; pub const KERNEL_HEAP_SIZE: usize = 0x2_000_000; -pub const KERNEL_OFFSET: usize = 0xffffff00_00000000; +pub const KERNEL_OFFSET: usize = 0xffffffff80000000; + pub const PHYS_OFFSET: usize = 0xFFFF800000000000; pub const ENTRY_COUNT: usize = 512; diff --git a/src/framework/jinux-frame/src/device/framebuffer.rs b/src/framework/jinux-frame/src/device/framebuffer.rs index 2e2f6c47..4f850550 100644 --- a/src/framework/jinux-frame/src/device/framebuffer.rs +++ b/src/framework/jinux-frame/src/device/framebuffer.rs @@ -1,17 +1,45 @@ -use bootloader::boot_info::PixelFormat; +use alloc::slice; use core::fmt; use font8x8::UnicodeFonts; +use limine::{LimineFramebufferRequest, LimineMemoryMapEntryType}; use spin::Mutex; use volatile::Volatile; -pub(crate) static WRITER: Mutex> = Mutex::new(None); +use crate::mm; -pub fn init(framebuffer: &'static mut bootloader::boot_info::FrameBuffer) { - let mut writer = Writer { - info: framebuffer.info(), - buffer: Volatile::new(framebuffer.buffer_mut()), - x_pos: 0, - y_pos: 0, +pub(crate) static WRITER: Mutex> = Mutex::new(None); +static FRAMEBUFFER_REUEST: LimineFramebufferRequest = LimineFramebufferRequest::new(0); + +pub(crate) fn init() { + let mut writer = { + let response = FRAMEBUFFER_REUEST + .get_response() + .get() + .expect("Not found framebuffer"); + assert_eq!(response.framebuffer_count, 1); + let mut writer = None; + let mut size = 0; + for i in mm::MEMORY_REGIONS.get().unwrap().iter() { + if i.typ == LimineMemoryMapEntryType::Framebuffer { + size = i.len as usize; + } + } + for i in response.framebuffers() { + let buffer_mut = unsafe { + let start = i.address.as_ptr().unwrap().addr(); + slice::from_raw_parts_mut(start as *mut u8, size) + }; + + writer = Some(Writer { + buffer: Volatile::new(buffer_mut), + x_pos: 0, + y_pos: 0, + bytes_per_pixel: i.bpp as usize, + width: i.width as usize, + height: i.height as usize, + }) + } + writer.unwrap() }; writer.clear(); @@ -23,7 +51,11 @@ pub fn init(framebuffer: &'static mut bootloader::boot_info::FrameBuffer) { pub(crate) struct Writer { buffer: Volatile<&'static mut [u8]>, - info: bootloader::boot_info::FrameBufferInfo, + + bytes_per_pixel: usize, + width: usize, + height: usize, + x_pos: usize, y_pos: usize, } @@ -46,17 +78,17 @@ impl Writer { } fn shift_lines_up(&mut self) { - let offset = self.info.stride * self.info.bytes_per_pixel * 8; + let offset = self.bytes_per_pixel * 8; self.buffer.copy_within(offset.., 0); self.y_pos -= 8; } fn width(&self) -> usize { - self.info.horizontal_resolution + self.width } fn height(&self) -> usize { - self.info.vertical_resolution + self.height } fn write_char(&mut self, c: char) { @@ -89,17 +121,13 @@ impl Writer { } fn write_pixel(&mut self, x: usize, y: usize, on: bool) { - let pixel_offset = y * self.info.stride + x; + let pixel_offset = y + x; let color = if on { - match self.info.pixel_format { - PixelFormat::RGB => [0x33, 0xff, 0x66, 0], - PixelFormat::BGR => [0x66, 0xff, 0x33, 0], - _other => [0xff, 0xff, 0xff, 0], - } + [0x33, 0xff, 0x66, 0] } else { [0, 0, 0, 0] }; - let bytes_per_pixel = self.info.bytes_per_pixel; + let bytes_per_pixel = self.bytes_per_pixel; let byte_offset = pixel_offset * bytes_per_pixel; self.buffer .index_mut(byte_offset..(byte_offset + bytes_per_pixel)) diff --git a/src/framework/jinux-frame/src/device/mod.rs b/src/framework/jinux-frame/src/device/mod.rs index 605a501f..6bb240b3 100644 --- a/src/framework/jinux-frame/src/device/mod.rs +++ b/src/framework/jinux-frame/src/device/mod.rs @@ -7,13 +7,8 @@ pub mod serial; pub use self::io_port::IoPort; -/// first step to init device, call before the memory allocator init -pub(crate) fn first_init(framebuffer: &'static mut bootloader::boot_info::FrameBuffer) { - framebuffer::init(framebuffer); - serial::init(); -} - -/// second step to init device, call after the memory allocator init -pub(crate) fn second_init() { +/// Call after the memory allocator init +pub(crate) fn init() { + framebuffer::init(); serial::register_serial_input_irq_handler(|trap| {}); } diff --git a/src/framework/jinux-frame/src/driver/acpi.rs b/src/framework/jinux-frame/src/driver/acpi.rs index ef4be970..ce544cf7 100644 --- a/src/framework/jinux-frame/src/driver/acpi.rs +++ b/src/framework/jinux-frame/src/driver/acpi.rs @@ -1,8 +1,9 @@ use core::ptr::NonNull; -use crate::mm::address::phys_to_virt; +use crate::{config, mm::address::phys_to_virt}; use acpi::{AcpiHandler, AcpiTables}; use lazy_static::lazy_static; +use limine::LimineRsdpRequest; use log::info; use spin::Mutex; @@ -34,12 +35,19 @@ impl AcpiHandler for AcpiMemoryHandler { fn unmap_physical_region(region: &acpi::PhysicalMapping) {} } -pub fn init(rsdp: u64) { - let a = unsafe { AcpiTables::from_rsdp(AcpiMemoryHandler {}, rsdp as usize).unwrap() }; - *ACPI_TABLES.lock() = a; +static RSDP_REQUEST: LimineRsdpRequest = LimineRsdpRequest::new(0); - let c = ACPI_TABLES.lock(); - for (signature, sdt) in c.sdts.iter() { +pub fn init() { + let response = RSDP_REQUEST + .get_response() + .get() + .expect("Need RSDP address"); + let rsdp = response.address.as_ptr().unwrap().addr() - config::PHYS_OFFSET; + *ACPI_TABLES.lock() = + unsafe { AcpiTables::from_rsdp(AcpiMemoryHandler {}, rsdp as usize).unwrap() }; + + let lock = ACPI_TABLES.lock(); + for (signature, sdt) in lock.sdts.iter() { info!("ACPI found signature:{:?}", signature); } info!("acpi init complete"); diff --git a/src/framework/jinux-frame/src/driver/mod.rs b/src/framework/jinux-frame/src/driver/mod.rs index 71d476fc..a8bafb16 100644 --- a/src/framework/jinux-frame/src/driver/mod.rs +++ b/src/framework/jinux-frame/src/driver/mod.rs @@ -14,8 +14,8 @@ use log::info; pub use timer::TimerCallback; pub(crate) use timer::{add_timeout_list, TICK}; -pub(crate) fn init(rsdp: Option) { - acpi::init(rsdp.unwrap()); +pub(crate) fn init() { + acpi::init(); timer::init(); if apic::has_apic() { ioapic::init(); diff --git a/src/framework/jinux-frame/src/lib.rs b/src/framework/jinux-frame/src/lib.rs index 9592751d..932f0bdd 100644 --- a/src/framework/jinux-frame/src/lib.rs +++ b/src/framework/jinux-frame/src/lib.rs @@ -9,9 +9,11 @@ #![feature(core_intrinsics)] #![feature(new_uninit)] #![feature(link_llvm_intrinsics)] +#![feature(strict_provenance)] extern crate alloc; +mod boot; pub(crate) mod cell; pub mod config; pub mod cpu; @@ -31,21 +33,13 @@ mod util; pub mod vm; pub(crate) mod x86_64_util; -use core::{mem, panic::PanicInfo}; -pub use driver::ack as apic_ack; - pub use self::error::Error; pub use self::prelude::Result; pub(crate) use self::sync::up::UPSafeCell; -pub use trap::interrupt_ack; -pub use x86_64_util::{disable_interrupts, enable_interrupts, hlt}; - use alloc::vec::Vec; -use bootloader::{ - boot_info::{FrameBuffer, MemoryRegionKind}, - BootInfo, -}; +use core::{mem, panic::PanicInfo}; pub use device::serial::receive_char; +pub use limine::LimineModuleRequest; pub use mm::address::{align_down, align_up, is_aligned, virt_to_phys}; pub use mm::page_table::translate_not_offset_virtual_address; pub use trap::{allocate_irq, IrqAllocateHandle, TrapFrame}; @@ -54,6 +48,7 @@ pub use util::AlignExt; pub use x86_64::registers::rflags::read as get_rflags; pub use x86_64::registers::rflags::RFlags; use x86_64_util::enable_common_cpu_features; +pub use x86_64_util::{disable_interrupts, enable_interrupts, hlt}; static mut IRQ_CALLBACK_LIST: Vec = Vec::new(); @@ -67,40 +62,26 @@ pub use crate::console_print as print; #[cfg(feature = "serial_print")] pub use crate::console_println as println; -pub fn init(boot_info: &'static mut BootInfo) { +pub fn init() { + device::serial::init(); logger::init(); - let siz = boot_info.framebuffer.as_ref().unwrap() as *const FrameBuffer as usize; - let mut memory_init = false; - // memory - device::first_init(boot_info.framebuffer.as_mut().unwrap()); - device::framebuffer::WRITER.lock().as_mut().unwrap().clear(); - for region in boot_info.memory_regions.iter() { - if region.kind == MemoryRegionKind::Usable { - let start: u64 = region.start; - let size: u64 = region.end - region.start; - println!( - "[kernel] physical frames start = {:x}, size = {:x}", - start, size - ); - mm::init(start, size); - memory_init = true; - break; - } - } - if !memory_init { - panic!("memory init failed"); - } + boot::init(); + mm::init(); trap::init(); - device::second_init(); - driver::init(boot_info.rsdp_addr.into_option()); + device::init(); + driver::init(); enable_common_cpu_features(); + register_irq_common_callback(); + invoke_c_init_funcs(); +} + +fn register_irq_common_callback() { unsafe { for i in 0..256 { IRQ_CALLBACK_LIST.push(IrqLine::acquire(i as u8).on_active(general_handler)) } let value = x86_64_util::cpuid(1); } - invoke_c_init_funcs(); } fn invoke_c_init_funcs() { diff --git a/src/framework/jinux-frame/src/linker.ld b/src/framework/jinux-frame/src/linker.ld deleted file mode 100644 index 8a60c924..00000000 --- a/src/framework/jinux-frame/src/linker.ld +++ /dev/null @@ -1,40 +0,0 @@ -ENTRY(_start) - -KERNEL_BEGIN = 0xffffff0000000000; - -SECTIONS { - . = KERNEL_BEGIN; - - .rodata ALIGN(4K): { - *(.rodata .rodata.*) - } - - .got ALIGN(4K):{ - *(.got .got.*) - } - - . = ALIGN(4K); - sinit_array = .; - .init_array : { - *(.init_array .init_array.*) - } - einit_array = .; - - .text ALIGN(4K): { - *(.text .text.*) - } - - .data ALIGN(4K): { - *(.data .data.*) - *(.sdata .sdata.*) - } - - .got ALIGN(4K): { - *(.got .got.*) - } - - .bss ALIGN(4K): { - *(.bss .bss.*) - *(.sbss .sbss.*) - } -} diff --git a/src/framework/jinux-frame/src/mm/mod.rs b/src/framework/jinux-frame/src/mm/mod.rs index 9f1c8f5c..c58ccedb 100644 --- a/src/framework/jinux-frame/src/mm/mod.rs +++ b/src/framework/jinux-frame/src/mm/mod.rs @@ -6,16 +6,18 @@ mod heap_allocator; mod memory_set; pub(crate) mod page_table; -use core::sync::atomic::AtomicUsize; +pub use self::{ + frame_allocator::PhysFrame, + memory_set::{MapArea, MemorySet}, + page_table::PageTable, +}; use address::PhysAddr; use address::VirtAddr; - -use crate::x86_64_util; - -pub use self::{frame_allocator::*, memory_set::*, page_table::*}; - -pub(crate) static ORIGINAL_CR3: AtomicUsize = AtomicUsize::new(0); +use alloc::vec::Vec; +use limine::LimineMemmapRequest; +use log::debug; +use spin::Once; bitflags::bitflags! { /// Possible flags for a page table entry. @@ -39,12 +41,36 @@ bitflags::bitflags! { } } -pub(crate) fn init(start: u64, size: u64) { +/// Only available inside jinux-frame +pub(crate) static MEMORY_REGIONS: Once> = Once::new(); +static MEMMAP_REQUEST: LimineMemmapRequest = LimineMemmapRequest::new(0); + +pub(crate) fn init() { heap_allocator::init(); - frame_allocator::init(start as usize, size as usize); + let mut memory_regions = Vec::new(); + let response = MEMMAP_REQUEST + .get_response() + .get() + .expect("Not found memory region information"); + for i in response.memmap() { + debug!("Found memory region:{:x?}", **i); + memory_regions.push(&**i); + } + let mut biggest_region_size = 0; + let mut biggest_region_start = 0; + for i in memory_regions.iter() { + if i.len > biggest_region_size { + biggest_region_size = i.len; + biggest_region_start = i.base; + } + } + if biggest_region_size == 0 { + panic!("Cannot find usable memory region"); + } + + // TODO: pass the memory regions to the frame allocator. The frame allocator should use multiple usable area + frame_allocator::init(biggest_region_start as usize, biggest_region_size as usize); page_table::init(); - ORIGINAL_CR3.store( - x86_64_util::get_cr3_raw(), - core::sync::atomic::Ordering::Relaxed, - ) + + MEMORY_REGIONS.call_once(|| memory_regions); } diff --git a/src/framework/jinux-frame/src/trap/mod.rs b/src/framework/jinux-frame/src/trap/mod.rs index ed67cc8b..3caf392b 100644 --- a/src/framework/jinux-frame/src/trap/mod.rs +++ b/src/framework/jinux-frame/src/trap/mod.rs @@ -120,15 +120,6 @@ struct IDT { entries: [[usize; 2]; 256], } -#[inline] -pub fn interrupt_ack() { - if crate::driver::apic::has_apic() { - crate::driver::apic::ack(); - } else { - crate::driver::pic::ack(); - } -} - impl IDT { const fn default() -> Self { Self { diff --git a/src/src/main.rs b/src/src/main.rs index 6ac4098a..a37fcc0f 100644 --- a/src/src/main.rs +++ b/src/src/main.rs @@ -1,21 +1,24 @@ #![no_std] #![no_main] #![feature(custom_test_frameworks)] -#![forbid(unsafe_code)] +// The no_mangle macro need to remove the `forbid(unsafe_code)` macro. The bootloader needs the _start function +// to be no mangle so that it can jump into the entry point. +// #![forbid(unsafe_code)] #![test_runner(jinux_frame::test_runner)] #![reexport_test_harness_main = "test_main"] extern crate jinux_frame; -use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; use jinux_frame::println; +use limine::LimineBootInfoRequest; -entry_point!(kernel_main); +static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0); -fn kernel_main(boot_info: &'static mut BootInfo) -> ! { +#[no_mangle] +pub extern "C" fn _start() -> ! { #[cfg(test)] test_main(); - jinux_frame::init(boot_info); + jinux_frame::init(); println!("[kernel] finish init jinux_frame"); component::init_all(component::parse_metadata!()).unwrap(); jinux_std::init(); diff --git a/src/x86_64-custom.json b/src/x86_64-custom.json index 75974997..a8d940d7 100644 --- a/src/x86_64-custom.json +++ b/src/x86_64-custom.json @@ -10,9 +10,6 @@ "linker-flavor": "ld.lld", "linker": "rust-lld", "pre-link-args": { - "ld.lld": [ - "-Tframework/jinux-frame/src/linker.ld" - ] }, "panic-strategy": "abort", "disable-redzone": true,