From 47a51eb423fb02a75ab54caf0ec42084edbd3c40 Mon Sep 17 00:00:00 2001 From: Zhang Junyang Date: Wed, 19 Jul 2023 10:08:59 +0800 Subject: [PATCH] Adapt Multiboot2 and switch from Limine to Grub2 --- .cargo/config.toml | 2 +- Cargo.lock | 137 ++++++--- Cargo.toml | 5 +- README.md | 2 +- boot/limine/conf/limine.cfg | 18 -- boot/limine/conf/linker.ld | 81 ----- boot/limine/scripts/limine-build.sh | 38 --- build.rs | 10 +- {boot => build}/Cargo.toml | 5 +- build/build.rs | 5 + build/grub/conf/grub.cfg | 5 + build/grub/conf/linker.ld | 51 ++++ build/grub/scripts/build-grub-image.sh | 16 + {boot => build}/src/main.rs | 19 +- framework/jinux-frame/Cargo.toml | 3 +- .../jinux-frame/src/arch/x86/boot/limine.rs | 27 -- .../src/arch/x86/boot/memory_region.rs | 122 ++++++++ .../jinux-frame/src/arch/x86/boot/mod.rs | 96 +++++- .../src/arch/x86/boot/multiboot2/boot.S | 276 ++++++++++++++++++ .../src/arch/x86/boot/multiboot2/mod.rs | 195 +++++++++++++ .../src/arch/x86/iommu/second_stage.rs | 14 + .../src/arch/x86/kernel/acpi/mod.rs | 25 +- framework/jinux-frame/src/arch/x86/mm/mod.rs | 64 ++-- framework/jinux-frame/src/arch/x86/mod.rs | 2 +- .../src/{vm => }/heap_allocator.rs | 0 framework/jinux-frame/src/lib.rs | 14 +- .../jinux-frame/src/vm/frame_allocator.rs | 16 +- framework/jinux-frame/src/vm/mod.rs | 43 +-- framework/jinux-frame/src/vm/page_table.rs | 11 +- kernel/main.rs | 17 +- services/comps/framebuffer/src/lib.rs | 53 ++-- services/libs/jinux-std/src/lib.rs | 6 +- tests/console_input.rs | 2 +- tests/framebuffer.rs | 2 +- tests/rtc.rs | 2 +- tests/test_example.rs | 2 +- tests/timer_test.rs | 2 +- x86_64-custom.json | 5 - 38 files changed, 992 insertions(+), 401 deletions(-) delete mode 100644 boot/limine/conf/limine.cfg delete mode 100644 boot/limine/conf/linker.ld delete mode 100755 boot/limine/scripts/limine-build.sh rename {boot => build}/Cargo.toml (81%) create mode 100644 build/build.rs create mode 100644 build/grub/conf/grub.cfg create mode 100644 build/grub/conf/linker.ld create mode 100755 build/grub/scripts/build-grub-image.sh rename {boot => build}/src/main.rs (90%) delete mode 100644 framework/jinux-frame/src/arch/x86/boot/limine.rs create mode 100644 framework/jinux-frame/src/arch/x86/boot/memory_region.rs create mode 100644 framework/jinux-frame/src/arch/x86/boot/multiboot2/boot.S create mode 100644 framework/jinux-frame/src/arch/x86/boot/multiboot2/mod.rs rename framework/jinux-frame/src/{vm => }/heap_allocator.rs (100%) diff --git a/.cargo/config.toml b/.cargo/config.toml index c61484f37..e13558992 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,6 @@ [target.'cfg(target_os = "none")'] -runner = "cargo run --package jinux-boot --" +runner = "cargo run --package jinux-build --" [alias] kcheck = "check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem" diff --git a/Cargo.lock b/Cargo.lock index b0e9e2df1..c8ffc0aa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "1.0.1" @@ -110,7 +116,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43f9365b6b0c9e1663ca4ca9440c00eda46bc85a3407070be8b5e0d8d1f29629" dependencies = [ - "spin 0.9.4", + "spin 0.9.8", ] [[package]] @@ -254,7 +260,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956673bd3cb347512bf988d1e8d89ac9a82b64f6eec54d3c01c3529dac019882" dependencies = [ - "bitflags", + "bitflags 1.3.2", "defmt-macros", ] @@ -280,6 +286,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "either" version = "1.8.0" @@ -388,7 +405,7 @@ dependencies = [ "atomic-polyfill", "hash32", "rustc_version", - "spin 0.9.4", + "spin 0.9.8", "stable_deref_trait", ] @@ -471,7 +488,6 @@ dependencies = [ "jinux-framebuffer", "jinux-std", "jinux-time", - "limine", "x86_64", ] @@ -479,7 +495,7 @@ dependencies = [ name = "jinux-block" version = "0.1.0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "component", "jinux-frame", "jinux-pci", @@ -487,11 +503,11 @@ dependencies = [ "jinux-virtio", "lazy_static", "log", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] -name = "jinux-boot" +name = "jinux-build" version = "0.1.0" dependencies = [ "anyhow", @@ -506,16 +522,16 @@ dependencies = [ "acpi", "align_ext", "aml", - "bitflags", + "bitflags 1.3.2", "buddy_system_allocator", "cfg-if", "inherit-methods-macro", "intrusive-collections", "lazy_static", - "limine", "log", + "multiboot2", "pod", - "spin 0.9.4", + "spin 0.9.8", "trapframe", "volatile", "x86", @@ -530,14 +546,14 @@ dependencies = [ "font8x8", "jinux-frame", "log", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] name = "jinux-input" version = "0.1.0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "component", "jinux-frame", "jinux-pci", @@ -545,7 +561,7 @@ dependencies = [ "jinux-virtio", "lazy_static", "log", - "spin 0.9.4", + "spin 0.9.8", "virtio-input-decoder", ] @@ -561,28 +577,28 @@ dependencies = [ "log", "ringbuf", "smoltcp", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] name = "jinux-pci" version = "0.1.0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "component", "jinux-frame", "jinux-util", "lazy_static", "log", "pod", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] name = "jinux-rights" version = "0.1.0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jinux-rights-proc", "typeflags", "typeflags-util", @@ -603,7 +619,7 @@ version = "0.1.0" dependencies = [ "align_ext", "ascii", - "bitflags", + "bitflags 1.3.2", "controlled", "core2", "cpio-decoder", @@ -627,7 +643,7 @@ dependencies = [ "pod", "ringbuf", "smoltcp", - "spin 0.9.4", + "spin 0.9.8", "time", "typeflags", "typeflags-util", @@ -643,7 +659,7 @@ dependencies = [ "component", "jinux-frame", "log", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] @@ -662,7 +678,7 @@ name = "jinux-virtio" version = "0.1.0" dependencies = [ "align_ext", - "bitflags", + "bitflags 1.3.2", "bytes", "component", "int-to-c-enum", @@ -671,7 +687,7 @@ dependencies = [ "jinux-util", "log", "pod", - "spin 0.9.4", + "spin 0.9.8", ] [[package]] @@ -745,15 +761,6 @@ dependencies = [ "rle-decode-fast", ] -[[package]] -name = "limine" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9d0c951056ac044f0e6b09448b9d702f8fb1001db89cffd2bc467bd1c25307" -dependencies = [ - "uuid", -] - [[package]] name = "lock_api" version = "0.4.9" @@ -819,6 +826,19 @@ dependencies = [ "autocfg", ] +[[package]] +name = "multiboot2" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b624a7b3f704734d98d21455b617607eb7043d4509d1c34bf9e7ff7dd47b31a" +dependencies = [ + "bitflags 2.3.3", + "derive_more", + "log", + "ptr_meta", + "uefi-raw", +] + [[package]] name = "never-say-never" version = "6.6.666" @@ -915,6 +935,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quote" version = "1.0.26" @@ -936,7 +976,7 @@ version = "10.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1021,7 +1061,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e9786ac45091b96f946693e05bfa4d8ca93e2d3341237d97a380107a6b38dea" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "cfg-if", "defmt", @@ -1038,9 +1078,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.9.4" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] @@ -1189,6 +1229,23 @@ dependencies = [ name = "typeflags-util" version = "0.1.0" +[[package]] +name = "uefi-raw" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62642516099c6441a5f41b0da8486d5fc3515a0603b0fdaea67b31600e22082e" +dependencies = [ + "bitflags 2.3.3", + "ptr_meta", + "uguid", +] + +[[package]] +name = "uguid" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16dfbd255defbd727b3a30e8950695d2e6d045841ee250ff0f1f7ced17917f8d" + [[package]] name = "unicode-ident" version = "1.0.5" @@ -1201,12 +1258,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" -[[package]] -name = "uuid" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" - [[package]] name = "version_check" version = "0.9.4" @@ -1286,7 +1337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" dependencies = [ "bit_field", - "bitflags", + "bitflags 1.3.2", "raw-cpuid", ] @@ -1297,7 +1348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "100555a863c0092238c2e0e814c1096c1e5cf066a309c696a87e907b5f8c5d69" dependencies = [ "bit_field", - "bitflags", + "bitflags 1.3.2", "rustversion", "volatile", ] diff --git a/Cargo.toml b/Cargo.toml index 1a20aea9a..1b989eeaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,7 @@ name = "jinux" path = "kernel/main.rs" [dependencies] -limine = "0.1.10" -jinux-frame = { path = "framework/jinux-frame" } +jinux-frame = { path = "framework/jinux-frame", features = ["multiboot2"] } jinux-std = { path = "services/libs/jinux-std" } component = { path = "services/libs/comp-sys/component" } @@ -21,7 +20,7 @@ jinux-framebuffer = { path = "services/comps/framebuffer" } [workspace] members = [ - "boot", + "build", "framework/jinux-frame", "services/comps/pci", "services/comps/virtio", diff --git a/README.md b/README.md index ced0c867f..e9a89b452 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Then, we can run the following script inside the OS to run all syscall test case The codebase of Jinux is organized as below. -* `boot/`: creating a bootable Jinux kernel image along with an initramfs image. +* `build/`: creating a bootable Jinux kernel image along with an initramfs image. It also supports `cargo run` since it is the only package with `main()`. * `kernel/`: defining the entry point of the Jinux kernel. * `framework/`: the privileged half of Jinux (allowed to use `unsafe` keyword) * `jinux-frame`: providing the safe Rust abstractions for low-level resources like CPU, memory, interrupts, etc; diff --git a/boot/limine/conf/limine.cfg b/boot/limine/conf/limine.cfg deleted file mode 100644 index f28e96fb6..000000000 --- a/boot/limine/conf/limine.cfg +++ /dev/null @@ -1,18 +0,0 @@ - -# 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.gz \ No newline at end of file diff --git a/boot/limine/conf/linker.ld b/boot/limine/conf/linker.ld deleted file mode 100644 index b1dade80b..000000000 --- a/boot/limine/conf/linker.ld +++ /dev/null @@ -1,81 +0,0 @@ -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/boot/limine/scripts/limine-build.sh b/boot/limine/scripts/limine-build.sh deleted file mode 100755 index e0c58137c..000000000 --- a/boot/limine/scripts/limine-build.sh +++ /dev/null @@ -1,38 +0,0 @@ -#! /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 target/iso_root/jinux -cp 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 regression/build/ramdisk.cpio.gz 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/build.rs b/build.rs index 87cd1ebd0..7c39e2fd1 100644 --- a/build.rs +++ b/build.rs @@ -1,13 +1,9 @@ use std::error::Error; fn main() -> Result<(), Box> { - limine_build_script()?; - Ok(()) -} - -fn limine_build_script() -> Result<(), Box> { - // Have cargo rerun this script if the linker script or CARGO_PKG_ENV changes. - println!("cargo:rerun-if-changed=boot/limine/conf/linker.ld"); + let linker_script_path = "build/grub/conf/linker.ld"; + println!("cargo:rerun-if-changed={}", linker_script_path); + println!("cargo:rustc-link-arg=-T{}", linker_script_path); println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME"); Ok(()) diff --git a/boot/Cargo.toml b/build/Cargo.toml similarity index 81% rename from boot/Cargo.toml rename to build/Cargo.toml index dade9b42c..310190d2a 100644 --- a/boot/Cargo.toml +++ b/build/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "jinux-boot" +name = "jinux-build" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,6 +10,5 @@ anyhow = "1.0.32" cfg-if = "1.0" [features] -default = ["limine"] -limine = [] +default = [] iommu = [] diff --git a/build/build.rs b/build/build.rs new file mode 100644 index 000000000..7d16293b1 --- /dev/null +++ b/build/build.rs @@ -0,0 +1,5 @@ +use std::error::Error; + +fn main() -> Result<(), Box> { + Ok(()) +} diff --git a/build/grub/conf/grub.cfg b/build/grub/conf/grub.cfg new file mode 100644 index 000000000..e98354848 --- /dev/null +++ b/build/grub/conf/grub.cfg @@ -0,0 +1,5 @@ +menuentry 'jinux' { + multiboot2 /jinux + module2 --nounzip /ramdisk.cpio.gz + boot +} diff --git a/build/grub/conf/linker.ld b/build/grub/conf/linker.ld new file mode 100644 index 000000000..ed3735d3f --- /dev/null +++ b/build/grub/conf/linker.ld @@ -0,0 +1,51 @@ +ENTRY(__boot) +OUTPUT_ARCH(i386:x86-64) +OUTPUT_FORMAT(elf64-x86-64) + +KERNEL_LMA = 0x100000; +KERNEL_VMA = 0xffffffff80000000; + +SECTIONS +{ + . = KERNEL_LMA; + + __kernel_start = .; + + .boot : { KEEP(*(.boot)) } + + . += KERNEL_VMA; + + .text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) } + .rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) } + + .data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) } + .bss : AT(ADDR(.bss) - KERNEL_VMA) { + __bss = .; + *(.bss .bss.*) *(COMMON) + __bss_end = .; + } + + .tdata : AT(ADDR(.tdata) - KERNEL_VMA) { *(.tdata .tdata.*) } + .tbss : AT(ADDR(.tbss) - KERNEL_VMA) { *(.tbss .tbss.*) } + + .init_array : AT(ADDR(.init_array) - KERNEL_VMA) { + __sinit_array = .; + *(.init_array .init_array.*) + __einit_array = .; + } + + .data.rel.ro : AT(ADDR(.data.rel.ro) - KERNEL_VMA) { *(.data.rel.ro .data.rel.ro.*) } + .dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) } + .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) { + __eh_frame_hdr = .; + KEEP(*(.eh_frame_hdr)) + __eh_frame_hdr_end = .; + } + .eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) { + __eh_frame = .; + KEEP(*(.eh_frame)) + __eh_frame_end = .; + } + + __kernel_end = . - KERNEL_VMA; +} diff --git a/build/grub/scripts/build-grub-image.sh b/build/grub/scripts/build-grub-image.sh new file mode 100755 index 000000000..fa4c6a16b --- /dev/null +++ b/build/grub/scripts/build-grub-image.sh @@ -0,0 +1,16 @@ +#! /bin/sh + +# Cargo passes the path to the built executable as the first argument. +KERNEL=$1 + +# Copy the needed files into an ISO image. +mkdir -p target/iso_root +cp $KERNEL target/iso_root/jinux +mkdir -p target/iso_root/boot/grub +cp build/grub/conf/grub.cfg target/iso_root/boot/grub + +# Copy ramdisk +cp regression/build/ramdisk.cpio.gz target/iso_root + +# Make boot device .iso image +grub-mkrescue -o $KERNEL.iso target/iso_root diff --git a/boot/src/main.rs b/build/src/main.rs similarity index 90% rename from boot/src/main.rs rename to build/src/main.rs index c857a62f2..31ee13ca4 100644 --- a/boot/src/main.rs +++ b/build/src/main.rs @@ -16,6 +16,7 @@ const COMMON_ARGS: &[&str] = &[ "Icelake-Server,+x2apic", "-m", "2G", + "-nographic", // TODO: figure out why grub can't shown up without it "-monitor", "vc", "-serial", @@ -73,9 +74,11 @@ fn main() -> anyhow::Result<()> { path.canonicalize().unwrap() }; - #[cfg(feature = "limine")] - call_limine_build_script(&kernel_binary_path).unwrap(); - // add .iso + call_bootloader_build_script( + &PathBuf::from("build/grub/scripts/build-grub-image.sh"), + &kernel_binary_path, + ) + .unwrap(); let kernel_iso_path = { let a = kernel_binary_path.parent().unwrap(); @@ -92,6 +95,7 @@ fn main() -> anyhow::Result<()> { let binary_kind = runner_utils::binary_kind(&kernel_binary_path); let mut qemu_args = COMMON_ARGS.clone().to_vec(); + qemu_args.extend(DEVICE_ARGS.clone().to_vec().iter()); qemu_args.extend(OPTION_ARGS.clone().to_vec().iter()); qemu_args.push("-drive"); @@ -123,9 +127,12 @@ 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()); +fn call_bootloader_build_script( + script_path: &PathBuf, + kernel_path: &PathBuf, +) -> anyhow::Result<()> { + let mut cmd = Command::new(script_path.to_str().unwrap()); + cmd.arg(kernel_path.to_str().unwrap()); let exit_status = cmd.status()?; if !exit_status.success() { std::process::exit(exit_status.code().unwrap_or(1)); diff --git a/framework/jinux-frame/Cargo.toml b/framework/jinux-frame/Cargo.toml index 4b28298ab..df8ad4e38 100644 --- a/framework/jinux-frame/Cargo.toml +++ b/framework/jinux-frame/Cargo.toml @@ -18,12 +18,13 @@ log = "0.4" lazy_static = { version = "1.0", features = ["spin_no_std"] } trapframe = { git = "https://github.com/sdww0/trapframe-rs", rev = "e886763" } inherit-methods-macro = { git = "https://github.com/jinzhao-dev/inherit-methods-macro", rev = "98f7e3e" } +multiboot2 = "0.16.0" [target.x86_64-custom.dependencies] -limine = { version = "0.1.10", features = ["into-uuid"] } x86_64 = "0.14.2" x86 = "0.52.0" acpi = "4.1.1" aml = "0.16.3" [features] +multiboot2 = [] diff --git a/framework/jinux-frame/src/arch/x86/boot/limine.rs b/framework/jinux-frame/src/arch/x86/boot/limine.rs deleted file mode 100644 index 3efdc8794..000000000 --- a/framework/jinux-frame/src/arch/x86/boot/limine.rs +++ /dev/null @@ -1,27 +0,0 @@ -use crate::config::{self, PAGE_SIZE}; -use limine::{LimineBootInfoRequest, LimineHhdmRequest, LimineStackSizeRequest}; -use log::info; - -pub 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); - STACK_REQUEST.get_response().get().unwrap(); -} - -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/framework/jinux-frame/src/arch/x86/boot/memory_region.rs b/framework/jinux-frame/src/arch/x86/boot/memory_region.rs new file mode 100644 index 000000000..187a392e2 --- /dev/null +++ b/framework/jinux-frame/src/arch/x86/boot/memory_region.rs @@ -0,0 +1,122 @@ +//! Information of memory regions in the boot phase. +//! + +use align_ext::AlignExt; +use alloc::{vec, vec::Vec}; + +use crate::config::PAGE_SIZE; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +/// The type of initial memory regions that are needed for the kernel. +pub enum MemoryRegionType { + /// Maybe points to an unplugged DIMM module. It's bad anyway. + BadMemory = 0, + /// In ACPI spec, this area needs to be preserved when sleeping. + NonVolatileSleep = 1, + /// Reserved by BIOS or bootloader, do not use. + Reserved = 2, + /// The place where kernel sections are loaded. + Kernel = 3, + /// The place where kernel modules (e.g. initrd) are loaded, could be reused. + Module = 4, + /// The memory region provided as the framebuffer. + Framebuffer = 5, + /// Once used in the boot phase. Kernel can reclaim it after initialization. + Reclaimable = 6, + /// Directly usable by the frame allocator. + Usable = 7, +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +/// The information of initial memory regions that are needed by the kernel. +/// The sections are **not** guaranteed to not overlap. The region must be page aligned. +pub struct MemoryRegion { + base: usize, + len: usize, + typ: MemoryRegionType, +} + +impl MemoryRegion { + /// Construct a page aligned memory region. + pub fn new(base: usize, len: usize, typ: MemoryRegionType) -> Self { + let aligned_base; + let aligned_end; + match typ { + MemoryRegionType::Usable | MemoryRegionType::Reclaimable => { + // Align shrinked. + aligned_base = base.align_up(PAGE_SIZE); + aligned_end = (base + len).align_down(PAGE_SIZE); + } + _ => { + // Align bloated. + aligned_base = base.align_down(PAGE_SIZE); + aligned_end = (base + len).align_up(PAGE_SIZE); + } + } + MemoryRegion { + base: aligned_base, + len: aligned_end - aligned_base, + typ: typ, + } + } + + /// The physical address of the base of the region. + pub fn base(&self) -> usize { + self.base + } + + /// The length in bytes of the region. + pub fn len(&self) -> usize { + self.len + } + + /// The type of the region. + pub fn typ(&self) -> MemoryRegionType { + self.typ + } + + /// Remove range t from self, resulting in 0, 1 or 2 truncated ranges. + /// We need to have this method since memory regions can overlap. + pub fn truncate(&self, t: MemoryRegion) -> Vec { + if self.base < t.base { + if self.base + self.len > t.base { + if self.base + self.len > t.base + t.len { + vec![ + MemoryRegion { + base: self.base, + len: t.base - self.base, + typ: self.typ, + }, + MemoryRegion { + base: t.base + t.len, + len: self.base + self.len - (t.base + t.len), + typ: self.typ, + }, + ] + } else { + vec![MemoryRegion { + base: self.base, + len: t.base - self.base, + typ: self.typ, + }] + } + } else { + vec![*self] + } + } else { + if self.base < t.base + t.len { + if self.base + self.len > t.base + t.len { + vec![MemoryRegion { + base: t.base + t.len, + len: self.base + self.len - (t.base + t.len), + typ: self.typ, + }] + } else { + vec![] + } + } else { + vec![*self] + } + } + } +} diff --git a/framework/jinux-frame/src/arch/x86/boot/mod.rs b/framework/jinux-frame/src/arch/x86/boot/mod.rs index 794997770..f93a3d4cb 100644 --- a/framework/jinux-frame/src/arch/x86/boot/mod.rs +++ b/framework/jinux-frame/src/arch/x86/boot/mod.rs @@ -1,6 +1,94 @@ -mod limine; +//! The boot module defines the entrypoints of Jinux and the corresponding +//! headers for different bootloaders. +//! +//! We currently support Multiboot2 and the Limine Boot Protocol. The +//! support for Linux boot protocol is on its way. +//! +//! In this module, we use println! to print information on screen rather +//! than logging since the logger is not initialized here. +//! -/// init bootloader -pub fn init() { - limine::init(); +#[cfg(feature = "multiboot2")] +pub mod multiboot2; +#[cfg(feature = "multiboot2")] +use self::multiboot2::*; + +pub mod memory_region; +pub use memory_region::*; + +use alloc::{string::String, vec::Vec}; +use spin::Once; + +#[derive(Copy, Clone, Debug)] +/// The boot crate can choose either providing the raw RSDP physical address or +/// providing the RSDT/XSDT physical address after parsing RSDP. +/// This is because bootloaders differ in such behaviors. +pub enum BootloaderAcpiArg { + /// Physical address of the RSDP. + Rsdp(usize), + /// Address of RSDT provided in RSDP v1. + Rsdt(usize), + /// Address of XSDT provided in RSDP v2+. + Xsdt(usize), +} + +#[derive(Copy, Clone, Debug)] +/// The framebuffer arguments. +pub struct BootloaderFramebufferArg { + pub address: usize, + pub width: usize, + pub height: usize, + /// Bits per pixel of the buffer. + pub bpp: usize, +} + +/// After initializing the boot module, the get_* functions could be called. +/// The initialization must be done after the heap is set and before physical +/// mappings are cancelled. +pub fn init() { + init_bootloader_name(); + init_kernel_commandline(); + init_initramfs(); + init_acpi_rsdp(); + init_framebuffer_info(); + init_memory_regions(); +} + +// The public get_* APIs. + +static BOOTLOADER_NAME: Once = Once::new(); +/// Get the name and the version of the bootloader. +pub fn get_bootloader_name() -> String { + BOOTLOADER_NAME.get().unwrap().clone() +} + +static KERNEL_COMMANDLINE: Once = Once::new(); +/// Get the raw unparsed kernel commandline string. +pub fn get_kernel_commandline() -> String { + KERNEL_COMMANDLINE.get().unwrap().clone() +} + +static INITRAMFS: Once<&'static [u8]> = Once::new(); +/// The slice of the bootloader-loaded init ram disk. +pub fn get_initramfs() -> &'static [u8] { + INITRAMFS.get().unwrap() +} + +static ACPI_RSDP: Once = Once::new(); +/// The ACPI RDSP/XSDT address. +pub fn get_acpi_rsdp() -> BootloaderAcpiArg { + ACPI_RSDP.get().unwrap().clone() +} + +static FRAMEBUFFER_INFO: Once = Once::new(); +/// Framebuffer information. +pub fn get_framebuffer_info() -> BootloaderFramebufferArg { + FRAMEBUFFER_INFO.get().unwrap().clone() +} + +static MEMORY_REGIONS: Once> = Once::new(); +/// Get memory regions. +/// The returned usable memory regions are guarenteed to not overlap with other unusable ones. +pub fn get_memory_regions() -> Vec { + MEMORY_REGIONS.get().unwrap().clone() } diff --git a/framework/jinux-frame/src/arch/x86/boot/multiboot2/boot.S b/framework/jinux-frame/src/arch/x86/boot/multiboot2/boot.S new file mode 100644 index 000000000..2977bb4ee --- /dev/null +++ b/framework/jinux-frame/src/arch/x86/boot/multiboot2/boot.S @@ -0,0 +1,276 @@ +// The boot header, initial boot setup code, temporary GDT and page tables are +// in the boot section. The boot section is mapped writable since kernel may +// modify the initial page table. +.section ".boot", "awx" +.code32 + +// The entry point of our ELF target. +.global __boot +__boot: + jmp initial_boot_setup + +// This is the GNU Multiboot 2 header. +// Reference: https://www.gnu.org/software/grub/manual/multiboot2/html_node/Index.html//Index + +// Macros for cleaner code in the header fields. +MB2_MAGIC = 0xE85250D6 +MB2_ARCHITECTURE = 0 // 32-bit (protected) mode of i386 +MB2_HEADERLEN = header_end - header_start +MB2_CHECKSUM = -(MB2_MAGIC + MB2_ARCHITECTURE + MB2_HEADERLEN) + +header_start: + .align 8 + + .long MB2_MAGIC + .long MB2_ARCHITECTURE + .long MB2_HEADERLEN + .long MB2_CHECKSUM + + // Tag: information request + .align 8 +info_request: + .short 1 + .short 0 // Required + .long info_request_end - info_request + .long 6 // Memory map request + .long 15 // ACPI (new) request +info_request_end: + + // Tag: header end + .align 8 + .short 0 // type: tags end + .short 0 // flags + .long 8 // size +header_end: + +initial_boot_setup: + cli + cld + + // Set the kernel call stack. + mov esp, offset boot_stack_top + + // Save the multiboot magic and 64-bit physical address of multiboot info onto the stack. + push 0 // Upper 32-bits. + push eax + push 0 // Upper 32-bits. + push ebx + + // Prepare for far return. We use a far return as a fence after setting GDT. + mov eax, 24 + push eax + lea edx, [protected_mode] + push edx + + // Switch to our own temporary GDT. + lgdt [boot_gdtr] + retf + +protected_mode: + mov ax, 16 + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + +page_table_setup: + // Zero out the page table. + mov al, 0x00 + lea edi, [boot_page_table_start] + lea ecx, [boot_page_table_end] + sub ecx, edi + cld + rep stosb + +// PTE flags used in this file. +PTE_PRESENT = (1) +PTE_WRITE = (1 << 1) +PTE_HUGE = (1 << 7) +PTE_GLOBAL = (1 << 8) + + // PML4: 0x00000000_00000000 ~ 0x00000000_3fffffff + // 0x00000000_40000000 ~ 0x00000000_7fffffff + // 0x00000000_80000000 ~ 0x00000000_bfffffff + // 0x00000000_c0000000 ~ 0x00000000_ffffffff + lea edi, [boot_pml4] + lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PML4: 0xffff8000_00000000 ~ 0xffff8000_3fffffff + // 0xffff8000_40000000 ~ 0xffff8000_7fffffff + // 0xffff8000_80000000 ~ 0xffff8000_bfffffff + // 0xffff8000_c0000000 ~ 0xffff8000_ffffffff + lea edi, [boot_pml4 + 0x100 * 8] + lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PML4: 0xffffffff_80000000 ~ 0xffffffff_bfffffff + // 0xffffffff_c0000000 ~ 0xffffffff_ffffffff + lea edi, [boot_pml4 + 0x1ff * 8] + lea eax, [boot_pdpt + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0x00000000_00000000 ~ 0x00000000_3fffffff + lea edi, [boot_pdpt] + lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0x00000000_40000000 ~ 0x00000000_7fffffff + lea edi, [boot_pdpt + 0x1 * 8] + lea eax, [boot_pd_1g_2g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0x00000000_80000000 ~ 0x00000000_bfffffff + lea edi, [boot_pdpt + 0x2 * 8] + lea eax, [boot_pd_2g_3g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0x00000000_c0000000 ~ 0x00000000_ffffffff + lea edi, [boot_pdpt + 0x3 * 8] + lea eax, [boot_pd_3g_4g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0xffffffff_80000000 ~ 0xffffffff_bfffffff + lea edi, [boot_pdpt + 0x1fe * 8] + lea eax, [boot_pd_0g_1g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // PDPT: 0xffffffff_c0000000 ~ 0xffffffff_ffffffff + lea edi, [boot_pdpt + 0x1ff * 8] + lea eax, [boot_pd_1g_2g + (PTE_PRESENT | PTE_WRITE | PTE_GLOBAL)] + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + + // Page Directory: map to low 1 GiB * 4 space + lea edi, [boot_pd] + mov eax, PTE_PRESENT | PTE_WRITE | PTE_HUGE | PTE_GLOBAL + mov ecx, 512 * 4 // (of entries in PD) * (number of PD) + +write_pd_entry: + mov dword ptr [edi], eax + mov dword ptr [edi + 4], 0 + add eax, 0x200000 // 2 MiB + add edi, 8 + loop write_pd_entry + + jmp enable_long_mode + +enable_long_mode: + // Enable PAE and PGE. + mov eax, cr4 + or eax, 0xa0 + mov cr4, eax + + // Set the page table address. + lea eax, [boot_pml4] + mov cr3, eax + + // Enable long mode. + mov ecx, 0xc0000080 + rdmsr + or eax, 0x0100 + wrmsr + + // Prepare for far return. + mov eax, 8 + push eax + lea edx, [long_mode_in_low_address] + push edx + + // Enable paging. + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + + retf + +// Temporary GDTR/GDT entries. This must be located in the .boot section as its +// address (gdt) must be physical to load. +.align 16 +.global boot_gdtr +boot_gdtr: + .word gdt_end - gdt - 1 + .quad gdt + +.align 16 +gdt: + .quad 0x0000000000000000 // 0: null descriptor + .quad 0x00af9a000000ffff // 8: 64-bit code segment (kernel) + .quad 0x00cf92000000ffff // 16: 64-bit data segment (kernel) + .quad 0x00cf9a000000ffff // 24: 32-bit code segment (kernel) +gdt_end: + +// The page tables and the stack +.align 4096 + +boot_page_table_start: +boot_pml4: + .skip 4096 +boot_pdpt: + .skip 4096 +boot_pd: +boot_pd_0g_1g: + .skip 4096 +boot_pd_1g_2g: + .skip 4096 +boot_pd_2g_3g: + .skip 4096 +boot_pd_3g_4g: + .skip 4096 +boot_page_table_end: + +boot_stack_bottom: + .skip 0x40000 +boot_stack_top: + +.code64 +long_mode_in_low_address: + mov ax, 0 + mov ds, ax + mov ss, ax + mov es, ax + mov fs, ax + mov gs, ax + + // Update RSP/RIP to use the virtual address. + mov rbx, 0xffffffff80000000 + or rsp, rbx + lea rax, [long_mode - 0xffffffff80000000] + or rax, rbx + jmp rax + +// From here, we're in the .text section: we no longer use physical address. +.code64 +.text +long_mode: + // Clear .bss section. + mov al, 0x00 + lea rdi, [rip + __bss] + lea rcx, [rip + __bss_end] + sub rcx, rdi + cld + rep stosb + + pop rsi // the address of multiboot info + pop rdi // multiboot magic + + // Clear the frame pointer to stop backtracing here. + xor rbp, rbp + + lea rax, [rip + boot] // jump into Rust code + call rax + + // In case boot() returns. +halt: + cli + hlt + jmp halt diff --git a/framework/jinux-frame/src/arch/x86/boot/multiboot2/mod.rs b/framework/jinux-frame/src/arch/x86/boot/multiboot2/mod.rs new file mode 100644 index 000000000..9d1c8c1a2 --- /dev/null +++ b/framework/jinux-frame/src/arch/x86/boot/multiboot2/mod.rs @@ -0,0 +1,195 @@ +use alloc::{string::ToString, vec::Vec}; +use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType}; + +use super::{ + BootloaderAcpiArg, BootloaderFramebufferArg, MemoryRegion, MemoryRegionType, ACPI_RSDP, + BOOTLOADER_NAME, FRAMEBUFFER_INFO, INITRAMFS, KERNEL_COMMANDLINE, MEMORY_REGIONS, +}; +use core::{arch::global_asm, mem::swap}; +use spin::Once; + +use crate::{config::PHYS_OFFSET, vm::paddr_to_vaddr}; + +global_asm!(include_str!("boot.S")); + +static MB2_INFO: Once = Once::new(); + +pub fn init_bootloader_name() { + BOOTLOADER_NAME.call_once(|| { + MB2_INFO + .get() + .unwrap() + .boot_loader_name_tag() + .expect("Bootloader name not found from the Multiboot2 header!") + .name() + .expect("UTF-8 error: failed to parse bootloader name!") + .to_string() + }); +} + +pub fn init_kernel_commandline() { + KERNEL_COMMANDLINE.call_once(|| { + MB2_INFO + .get() + .unwrap() + .command_line_tag() + .expect("Kernel commandline not found from the Multiboot2 header!") + .cmdline() + .expect("UTF-8 error: failed to parse kernel commandline!") + .to_string() + }); +} + +pub fn init_initramfs() { + let mb2_module_tag = MB2_INFO + .get() + .unwrap() + .module_tags() + .next() + .expect("No Multiboot2 modules found!"); + let base_addr = mb2_module_tag.start_address() as usize; + // We must return a slice composed by VA since kernel should read every in VA. + let base_va = if base_addr < PHYS_OFFSET { + paddr_to_vaddr(base_addr) + } else { + base_addr + }; + let length = mb2_module_tag.module_size() as usize; + INITRAMFS.call_once(|| unsafe { core::slice::from_raw_parts(base_va as *const u8, length) }); +} + +pub fn init_acpi_rsdp() { + ACPI_RSDP.call_once(|| { + if let Some(v2_tag) = MB2_INFO.get().unwrap().rsdp_v2_tag() { + // check for rsdp v2 + BootloaderAcpiArg::Xsdt(v2_tag.xsdt_address()) + } else if let Some(v1_tag) = MB2_INFO.get().unwrap().rsdp_v1_tag() { + // fall back to rsdp v1 + BootloaderAcpiArg::Rsdt(v1_tag.rsdt_address()) + } else { + panic!("No ACPI RDSP information found!"); + } + }); +} + +pub fn init_framebuffer_info() { + let fb_tag = MB2_INFO.get().unwrap().framebuffer_tag().unwrap().unwrap(); + FRAMEBUFFER_INFO.call_once(|| BootloaderFramebufferArg { + address: fb_tag.address() as usize, + width: fb_tag.width() as usize, + height: fb_tag.height() as usize, + bpp: fb_tag.bpp() as usize, + }); +} + +impl From for MemoryRegionType { + fn from(value: MemoryAreaType) -> Self { + match value { + MemoryAreaType::Available => Self::Usable, + MemoryAreaType::Reserved => Self::Reserved, + MemoryAreaType::AcpiAvailable => Self::Reclaimable, + MemoryAreaType::ReservedHibernate => Self::NonVolatileSleep, + _ => Self::BadMemory, + } + } +} + +pub fn init_memory_regions() { + // We should later use regions in `regions_unusable` to truncate all + // regions in `regions_usable`. + // The difference is that regions in `regions_usable` could be used by + // the frame allocator. + let mut regions_usable = Vec::::new(); + let mut regions_unusable = Vec::::new(); + + // Add the regions returned by Grub. + let memory_regions_tag = MB2_INFO + .get() + .unwrap() + .memory_map_tag() + .expect("Memory region not found from the Multiboot2 header!"); + let num_memory_regions = memory_regions_tag.memory_areas().len(); + for i in 0..num_memory_regions { + let start = memory_regions_tag.memory_areas()[i].start_address(); + let end = memory_regions_tag.memory_areas()[i].end_address(); + let area_typ: MemoryRegionType = memory_regions_tag.memory_areas()[i].typ().into(); + let region = MemoryRegion::new( + start.try_into().unwrap(), + (end - start).try_into().unwrap(), + area_typ, + ); + match area_typ { + MemoryRegionType::Usable | MemoryRegionType::Reclaimable => { + regions_usable.push(region); + } + _ => { + regions_unusable.push(region); + } + } + } + // Add the framebuffer region since Grub does not specify it. + let fb_tag = MB2_INFO.get().unwrap().framebuffer_tag().unwrap().unwrap(); + let fb = BootloaderFramebufferArg { + address: fb_tag.address() as usize, + width: fb_tag.width() as usize, + height: fb_tag.height() as usize, + bpp: fb_tag.bpp() as usize, + }; + regions_unusable.push(MemoryRegion::new( + fb.address, + (fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte) + MemoryRegionType::Framebuffer, + )); + // Add the kernel region since Grub does not specify it. + // These are physical addresses provided by the linker script. + extern "C" { + fn __kernel_start(); + fn __kernel_end(); + } + regions_unusable.push(MemoryRegion::new( + __kernel_start as usize, + __kernel_end as usize - __kernel_start as usize, + MemoryRegionType::Kernel, + )); + // Add the boot module region since Grub does not specify it. + let mb2_module_tag = MB2_INFO.get().unwrap().module_tags(); + for m in mb2_module_tag { + regions_unusable.push(MemoryRegion::new( + m.start_address() as usize, + m.module_size() as usize, + MemoryRegionType::Module, + )); + } + + // `regions_*` are 2 rolling vectors since we are going to truncate + // the regions in a iterative manner. + let mut regions = Vec::::new(); + let regions_src = &mut regions_usable; + let regions_dst = &mut regions; + // Truncate the usable regions. + for &r_unusable in ®ions_unusable { + regions_dst.clear(); + for r_usable in &*regions_src { + regions_dst.append(&mut r_usable.truncate(r_unusable)); + } + swap(regions_src, regions_dst); + } + + // Initialize with regions_unusable + regions_src + regions_unusable.append(regions_src); + MEMORY_REGIONS.call_once(|| regions_unusable); +} + +extern "Rust" { + fn jinux_main() -> !; +} + +#[no_mangle] +/// The entry point of Rust code called by inline asm. +unsafe extern "C" fn boot(boot_magic: u32, boot_params: u64) -> ! { + assert_eq!(boot_magic, 0x36d76289_u32); + MB2_INFO.call_once(|| unsafe { + BootInformation::load(boot_params as *const BootInformationHeader).unwrap() + }); + jinux_main(); +} diff --git a/framework/jinux-frame/src/arch/x86/iommu/second_stage.rs b/framework/jinux-frame/src/arch/x86/iommu/second_stage.rs index 80ed20893..3d96c1507 100644 --- a/framework/jinux-frame/src/arch/x86/iommu/second_stage.rs +++ b/framework/jinux-frame/src/arch/x86/iommu/second_stage.rs @@ -87,6 +87,10 @@ impl PageTableFlagsTrait for PageTableFlags { self.contains(Self::ACCESSED) } + fn is_dirty(&self) -> bool { + self.contains(Self::DIRTY) + } + fn accessible_by_user(&self) -> bool { true } @@ -102,6 +106,16 @@ impl PageTableFlagsTrait for PageTableFlags { fn insert(&mut self, flags: &Self) { self.insert(*flags) } + + fn is_huge(&self) -> bool { + // FIXME: this is super bad + false + } + + fn set_huge(self, huge: bool) -> Self { + // FIXME: this is super bad + self + } } impl PageTableEntry { diff --git a/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs b/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs index 625da2e62..feffc7836 100644 --- a/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs +++ b/framework/jinux-frame/src/arch/x86/kernel/acpi/mod.rs @@ -6,9 +6,9 @@ use core::{ ptr::NonNull, }; -use crate::{config, vm::paddr_to_vaddr}; +use crate::arch::boot::{self, BootloaderAcpiArg}; +use crate::vm::paddr_to_vaddr; use acpi::{sdt::SdtHeader, AcpiHandler, AcpiTable, AcpiTables}; -use limine::LimineRsdpRequest; use log::info; use spin::{Mutex, Once}; @@ -89,17 +89,18 @@ impl AcpiHandler for AcpiMemoryHandler { fn unmap_physical_region(region: &acpi::PhysicalMapping) {} } -static RSDP_REQUEST: LimineRsdpRequest = LimineRsdpRequest::new(0); - 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; - // Safety: The RSDP is the value provided by bootloader. - let acpi_tables = - unsafe { AcpiTables::from_rsdp(AcpiMemoryHandler {}, rsdp as usize).unwrap() }; + let acpi_tables = match boot::get_acpi_rsdp() { + BootloaderAcpiArg::Rsdp(addr) => unsafe { + AcpiTables::from_rsdp(AcpiMemoryHandler {}, addr as usize).unwrap() + }, + BootloaderAcpiArg::Rsdt(addr) => unsafe { + AcpiTables::from_rsdt(AcpiMemoryHandler {}, 0, addr as usize).unwrap() + }, + BootloaderAcpiArg::Xsdt(addr) => unsafe { + AcpiTables::from_rsdt(AcpiMemoryHandler {}, 1, addr as usize).unwrap() + }, + }; for (signature, sdt) in acpi_tables.sdts.iter() { info!("ACPI found signature:{:?}", signature); diff --git a/framework/jinux-frame/src/arch/x86/mm/mod.rs b/framework/jinux-frame/src/arch/x86/mm/mod.rs index 11d13d851..cee04d1fa 100644 --- a/framework/jinux-frame/src/arch/x86/mm/mod.rs +++ b/framework/jinux-frame/src/arch/x86/mm/mod.rs @@ -1,6 +1,4 @@ -use alloc::{collections::BTreeMap, fmt, vec::Vec}; -use limine::{LimineMemmapEntry, LimineMemmapRequest, LimineMemoryMapEntryType}; -use log::debug; +use alloc::{collections::BTreeMap, fmt}; use pod::Pod; use spin::Mutex; use x86_64::structures::paging::PhysFrame; @@ -9,7 +7,7 @@ use crate::{ config::ENTRY_COUNT, vm::{ page_table::{table_of, PageTableEntryTrait, PageTableFlagsTrait}, - MemoryRegions, MemoryRegionsType, Paddr, + Paddr, }, }; @@ -31,6 +29,10 @@ bitflags::bitflags! { const NO_CACHE = 1 << 4; /// Whether this entry has been used for linear-address translation. const ACCESSED = 1 << 5; + /// Whether the memory area represented by this entry is modified. + const DIRTY = 1 << 6; + /// Only in the non-starting and non-ending levels, indication of huge page. + const HUGE = 1 << 7; /// Indicates that the mapping is present in all address spaces, so it isn't flushed from /// the TLB on an address space switch. const GLOBAL = 1 << 8; @@ -52,20 +54,6 @@ pub unsafe fn activate_page_table(root_paddr: Paddr, flags: x86_64::registers::c pub static ALL_MAPPED_PTE: Mutex> = Mutex::new(BTreeMap::new()); -/// Get memory regions, this function should call after the heap was initialized -pub fn get_memory_regions() -> Vec { - 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(MemoryRegions::from(&**i)); - } - memory_regions -} - pub fn init() { let (page_directory_base, _) = x86_64::registers::control::Cr3::read(); let page_directory_base = page_directory_base.start_address().as_u64() as usize; @@ -137,6 +125,10 @@ impl PageTableFlagsTrait for PageTableFlags { self.contains(Self::ACCESSED) } + fn is_dirty(&self) -> bool { + self.contains(Self::DIRTY) + } + fn union(&self, flags: &Self) -> Self { (*self).union(*flags) } @@ -148,6 +140,15 @@ impl PageTableFlagsTrait for PageTableFlags { fn insert(&mut self, flags: &Self) { self.insert(*flags) } + + fn is_huge(&self) -> bool { + self.contains(Self::HUGE) + } + + fn set_huge(mut self, huge: bool) -> Self { + self.set(Self::HUGE, huge); + self + } } impl PageTableEntry { @@ -193,30 +194,3 @@ impl fmt::Debug for PageTableEntry { .finish() } } - -static MEMMAP_REQUEST: LimineMemmapRequest = LimineMemmapRequest::new(0); - -impl From<&LimineMemmapEntry> for MemoryRegions { - fn from(value: &LimineMemmapEntry) -> Self { - Self { - base: value.base, - len: value.len, - typ: MemoryRegionsType::from(value.typ), - } - } -} - -impl From for MemoryRegionsType { - fn from(value: LimineMemoryMapEntryType) -> Self { - match value { - LimineMemoryMapEntryType::Usable => Self::Usable, - LimineMemoryMapEntryType::Reserved => Self::Reserved, - LimineMemoryMapEntryType::AcpiReclaimable => Self::AcpiReclaimable, - LimineMemoryMapEntryType::AcpiNvs => Self::AcpiNvs, - LimineMemoryMapEntryType::BadMemory => Self::BadMemory, - LimineMemoryMapEntryType::BootloaderReclaimable => Self::BootloaderReclaimable, - LimineMemoryMapEntryType::KernelAndModules => Self::KernelAndModules, - LimineMemoryMapEntryType::Framebuffer => Self::Framebuffer, - } - } -} diff --git a/framework/jinux-frame/src/arch/x86/mod.rs b/framework/jinux-frame/src/arch/x86/mod.rs index 5509a4f0d..217c173b3 100644 --- a/framework/jinux-frame/src/arch/x86/mod.rs +++ b/framework/jinux-frame/src/arch/x86/mod.rs @@ -1,4 +1,4 @@ -mod boot; +pub mod boot; pub(crate) mod cpu; pub mod device; pub mod iommu; diff --git a/framework/jinux-frame/src/vm/heap_allocator.rs b/framework/jinux-frame/src/heap_allocator.rs similarity index 100% rename from framework/jinux-frame/src/vm/heap_allocator.rs rename to framework/jinux-frame/src/heap_allocator.rs diff --git a/framework/jinux-frame/src/lib.rs b/framework/jinux-frame/src/lib.rs index f75aa45ee..5d5c0e642 100644 --- a/framework/jinux-frame/src/lib.rs +++ b/framework/jinux-frame/src/lib.rs @@ -8,8 +8,8 @@ #![feature(alloc_error_handler)] #![feature(core_intrinsics)] #![feature(new_uninit)] -#![feature(link_llvm_intrinsics)] #![feature(strict_provenance)] +#![feature(link_llvm_intrinsics)] #![feature(const_trait_impl)] #![feature(const_ops)] #![feature(generators)] @@ -23,6 +23,7 @@ pub mod bus; pub mod config; pub mod cpu; mod error; +mod heap_allocator; pub mod logger; pub mod io_mem; pub mod prelude; @@ -39,14 +40,13 @@ pub use self::error::Error; pub use self::prelude::Result; use alloc::vec::Vec; use core::{mem, panic::PanicInfo}; -#[cfg(target_arch = "x86_64")] -pub use limine::{LimineFramebufferRequest, LimineModuleRequest}; use trap::{IrqCallbackHandle, IrqLine}; use trapframe::TrapFrame; static mut IRQ_CALLBACK_LIST: Vec = Vec::new(); pub fn init() { + heap_allocator::init(); arch::before_all_init(); logger::init(); vm::init(); @@ -68,13 +68,13 @@ fn register_irq_common_callback() { fn invoke_c_init_funcs() { extern "C" { - fn sinit_array(); - fn einit_array(); + fn __sinit_array(); + fn __einit_array(); } - let call_len = (einit_array as u64 - sinit_array as u64) / 8; + let call_len = (__einit_array as u64 - __sinit_array as u64) / 8; for i in 0..call_len { unsafe { - let address = (sinit_array as u64 + 8 * i) as *const u64; + let address = (__sinit_array as u64 + 8 * i) as *const u64; let function = address as *const fn(); (*function)(); } diff --git a/framework/jinux-frame/src/vm/frame_allocator.rs b/framework/jinux-frame/src/vm/frame_allocator.rs index 4b74ccb3d..38487a24b 100644 --- a/framework/jinux-frame/src/vm/frame_allocator.rs +++ b/framework/jinux-frame/src/vm/frame_allocator.rs @@ -5,7 +5,7 @@ use spin::Once; use crate::{config::PAGE_SIZE, sync::SpinLock}; -use super::{frame::VmFrameFlags, MemoryRegions, MemoryRegionsType, VmFrame}; +use super::{frame::VmFrameFlags, MemoryRegion, MemoryRegionType, VmFrame}; pub(super) static FRAME_ALLOCATOR: Once> = Once::new(); @@ -55,19 +55,17 @@ pub(crate) unsafe fn dealloc(index: usize) { FRAME_ALLOCATOR.get().unwrap().lock().dealloc(index, 1); } -pub(crate) fn init(regions: &Vec) { +pub(crate) fn init(regions: &Vec) { let mut allocator = FrameAllocator::<32>::new(); for region in regions.iter() { - if region.typ == MemoryRegionsType::Usable { - assert_eq!(region.base % PAGE_SIZE as u64, 0); - assert_eq!(region.len % PAGE_SIZE as u64, 0); - let start = region.base as usize / PAGE_SIZE; - let end = start + region.len as usize / PAGE_SIZE; + if region.typ() == MemoryRegionType::Usable { + let start = region.base() / PAGE_SIZE; + let end = start + region.len() / PAGE_SIZE; allocator.add_frame(start, end); info!( "Found usable region, start:{:x}, end:{:x}", - region.base, - region.base + region.len + region.base(), + region.base() + region.len() ); } } diff --git a/framework/jinux-frame/src/vm/mod.rs b/framework/jinux-frame/src/vm/mod.rs index 7f59a7792..f284ab9f1 100644 --- a/framework/jinux-frame/src/vm/mod.rs +++ b/framework/jinux-frame/src/vm/mod.rs @@ -8,7 +8,6 @@ pub type Paddr = usize; mod frame; mod frame_allocator; -mod heap_allocator; mod io; mod memory_set; mod offset; @@ -29,33 +28,7 @@ pub use self::{ use alloc::vec::Vec; use spin::Once; -#[derive(Clone, Copy)] -pub struct MemoryRegions { - pub base: u64, - pub len: u64, - pub typ: MemoryRegionsType, -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -/// Copy from limine boot protocol -pub enum MemoryRegionsType { - Usable = 0, - Reserved = 1, - AcpiReclaimable = 2, - AcpiNvs = 3, - BadMemory = 4, - BootloaderReclaimable = 5, - /// The kernel and modules loaded are not marked as usable memory. They are - /// marked as Kernel/Modules. The entries are guaranteed to be sorted by base - /// address, lowest to highest. Usable and bootloader reclaimable entries are - /// guaranteed to be 4096 byte aligned for both base and length. Usable and - /// bootloader reclaimable entries are guaranteed not to overlap with any - /// other entry. To the contrary, all non-usable entries (including kernel/modules) - /// are not guaranteed any alignment, nor is it guaranteed that they do not - /// overlap other entries. - KernelAndModules = 6, - Framebuffer = 7, -} +use crate::arch::boot::{MemoryRegion, MemoryRegionType}; /// Convert physical address to virtual address using offset, only available inside jinux-frame pub(crate) fn paddr_to_vaddr(pa: usize) -> usize { @@ -76,23 +49,21 @@ pub const fn is_page_aligned(p: usize) -> bool { } /// Only available inside jinux-frame -pub(crate) static MEMORY_REGIONS: Once> = Once::new(); +pub(crate) static MEMORY_REGIONS: Once> = Once::new(); -pub static FRAMEBUFFER_REGIONS: Once> = Once::new(); +pub static FRAMEBUFFER_REGIONS: Once> = Once::new(); pub(crate) fn init() { - heap_allocator::init(); - let memory_regions = crate::arch::mm::get_memory_regions(); + let memory_regions = crate::arch::boot::get_memory_regions(); + frame_allocator::init(&memory_regions); let mut framebuffer_regions = Vec::new(); for i in memory_regions.iter() { - if i.typ == MemoryRegionsType::Framebuffer { + if i.typ() == MemoryRegionType::Framebuffer { framebuffer_regions.push(i.clone()); } } - - frame_allocator::init(&memory_regions); + FRAMEBUFFER_REGIONS.call_once(|| framebuffer_regions); MEMORY_REGIONS.call_once(|| memory_regions); - FRAMEBUFFER_REGIONS.call_once(|| framebuffer_regions); } diff --git a/framework/jinux-frame/src/vm/page_table.rs b/framework/jinux-frame/src/vm/page_table.rs index 1eabd8d2b..be8a509bf 100644 --- a/framework/jinux-frame/src/vm/page_table.rs +++ b/framework/jinux-frame/src/vm/page_table.rs @@ -25,6 +25,8 @@ pub trait PageTableFlagsTrait: Clone + Copy + Sized + Pod + Debug { fn set_executable(self, executable: bool) -> Self; + fn set_huge(self, huge: bool) -> Self; + fn is_present(&self) -> bool; fn writable(&self) -> bool; @@ -35,6 +37,10 @@ pub trait PageTableFlagsTrait: Clone + Copy + Sized + Pod + Debug { fn has_accessed(&self) -> bool; + fn is_dirty(&self) -> bool; + + fn is_huge(&self) -> bool; + fn accessible_by_user(&self) -> bool; /// Returns a new set of flags, containing any flags present in either self or other. It is similar to the OR operation. @@ -178,7 +184,7 @@ impl PageTable { }; while count > 1 { - if current.paddr() == 0 { + if !current.flags().is_present() { if !create { return None; } @@ -196,6 +202,9 @@ impl PageTable { current.update(frame.start_paddr(), flags); self.tables.push(frame); } + if current.flags().is_huge() { + break; + } count -= 1; debug_assert!(size_of::() * (T::page_index(vaddr, count) + 1) <= PAGE_SIZE); // Safety: The offset does not exceed the value of PAGE_SIZE. diff --git a/kernel/main.rs b/kernel/main.rs index 1d4807b32..55aea1cc3 100644 --- a/kernel/main.rs +++ b/kernel/main.rs @@ -10,31 +10,18 @@ extern crate jinux_frame; use core::panic::PanicInfo; use jinux_frame::println; -use limine::{LimineBootInfoRequest, LimineModuleRequest}; - -static BOOTLOADER_INFO: LimineBootInfoRequest = LimineBootInfoRequest::new(0); -static BOOTLOADER_MODULE: LimineModuleRequest = LimineModuleRequest::new(0); #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { #[cfg(test)] test_main(); jinux_frame::init(); println!("[kernel] finish init jinux_frame"); component::init_all(component::parse_metadata!()).unwrap(); - jinux_std::init(read_ramdisk_content()); + jinux_std::init(); jinux_std::run_first_process(); } -fn read_ramdisk_content() -> &'static [u8] { - let module_info = BOOTLOADER_MODULE.get_response().get().unwrap(); - assert!(module_info.module_count == 1); - let ramdisk_file = &module_info.modules()[0]; - let base_ptr = ramdisk_file.base.as_ptr().unwrap(); - let length = ramdisk_file.length as usize; - unsafe { core::slice::from_raw_parts(base_ptr, length) } -} - #[cfg(not(test))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { diff --git a/services/comps/framebuffer/src/lib.rs b/services/comps/framebuffer/src/lib.rs index 3d1234829..36b42dfbe 100644 --- a/services/comps/framebuffer/src/lib.rs +++ b/services/comps/framebuffer/src/lib.rs @@ -1,4 +1,4 @@ -//! The frambuffer of jinux +//! The framebuffer of jinux #![no_std] #![forbid(unsafe_code)] #![feature(strict_provenance)] @@ -13,7 +13,7 @@ use core::{ }; use font8x8::UnicodeFonts; use jinux_frame::{ - config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo, LimineFramebufferRequest, + config::PAGE_SIZE, io_mem::IoMem, sync::SpinLock, vm::VmIo, arch::boot, }; use spin::Once; @@ -24,44 +24,39 @@ fn framebuffer_init() -> Result<(), ComponentInitError> { } pub(crate) static WRITER: Once> = Once::new(); -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 framebuffer = boot::get_framebuffer_info(); let mut writer = None; let mut size = 0; for i in jinux_frame::vm::FRAMEBUFFER_REGIONS.get().unwrap().iter() { - size = i.len as usize; + size = i.len() as usize; } - for i in response.framebuffers() { - let page_size = size / PAGE_SIZE; - let start_paddr = i.address.as_ptr().unwrap().addr(); - let io_mem = - IoMem::new(start_paddr..(start_paddr + jinux_frame::config::PAGE_SIZE * page_size)) - .unwrap(); + let page_size = size / PAGE_SIZE; - let mut buffer: Vec = Vec::with_capacity(size); - for _ in 0..size { - buffer.push(0); - } - log::debug!("Found framebuffer:{:?}", *i); + let start_paddr = framebuffer.address.as_ptr().unwrap().addr(); + let io_mem = + IoMem::new(start_paddr..(start_paddr + jinux_frame::config::PAGE_SIZE * page_size)) + .unwrap(); - writer = Some(Writer { - io_mem, - x_pos: 0, - y_pos: 0, - bytes_per_pixel: (i.bpp / 8) as usize, - width: i.width as usize, - height: i.height as usize, - buffer: buffer.leak(), - }) + let mut buffer: Vec = Vec::with_capacity(size); + for _ in 0..size { + buffer.push(0); } + log::debug!("Found framebuffer:{:?}", framebuffer); + + writer = Some(Writer { + io_mem, + x_pos: 0, + y_pos: 0, + bytes_per_pixel: (framebuffer.bpp / 8) as usize, + width: framebuffer.width as usize, + height: framebuffer.height as usize, + buffer: buffer.leak(), + }) + writer.unwrap() }; writer.clear(); diff --git a/services/libs/jinux-std/src/lib.rs b/services/libs/jinux-std/src/lib.rs index bea7ab17a..072a69ba9 100644 --- a/services/libs/jinux-std/src/lib.rs +++ b/services/libs/jinux-std/src/lib.rs @@ -26,7 +26,7 @@ use crate::{ process::status::ProcessStatus, thread::{kernel_thread::KernelThreadExt, Thread}, }; -use jinux_frame::exit_qemu; +use jinux_frame::{arch::boot, exit_qemu}; use process::Process; extern crate alloc; @@ -48,11 +48,11 @@ pub mod time; mod util; pub mod vm; -pub fn init(ramdisk: &[u8]) { +pub fn init() { driver::init(); net::init(); process::fifo_scheduler::init(); - fs::initramfs::init(ramdisk).unwrap(); + fs::initramfs::init(boot::get_initramfs()).unwrap(); device::init().unwrap(); } diff --git a/tests/console_input.rs b/tests/console_input.rs index c18ba780c..ab5c8266f 100644 --- a/tests/console_input.rs +++ b/tests/console_input.rs @@ -10,7 +10,7 @@ use jinux_frame::println; static mut INPUT_VALUE: u8 = 0; #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { jinux_frame::init(); test_main(); loop {} diff --git a/tests/framebuffer.rs b/tests/framebuffer.rs index 7581a9873..2686fbeb9 100644 --- a/tests/framebuffer.rs +++ b/tests/framebuffer.rs @@ -7,7 +7,7 @@ extern crate alloc; use core::panic::PanicInfo; #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { jinux_frame::init(); component::init_all(component::parse_metadata!()).unwrap(); test_main(); diff --git a/tests/rtc.rs b/tests/rtc.rs index 88bc574c1..a353bc276 100644 --- a/tests/rtc.rs +++ b/tests/rtc.rs @@ -8,7 +8,7 @@ use core::panic::PanicInfo; use jinux_frame::println; #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { jinux_frame::init(); component::init_all(component::parse_metadata!()).unwrap(); test_main(); diff --git a/tests/test_example.rs b/tests/test_example.rs index 9d0b8896e..b1275ccde 100644 --- a/tests/test_example.rs +++ b/tests/test_example.rs @@ -6,7 +6,7 @@ use core::panic::PanicInfo; #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { jinux_frame::init(); test_main(); loop {} diff --git a/tests/timer_test.rs b/tests/timer_test.rs index bbe0c7f34..bad91118a 100644 --- a/tests/timer_test.rs +++ b/tests/timer_test.rs @@ -13,7 +13,7 @@ use jinux_frame::println; static mut TICK: usize = 0; #[no_mangle] -pub extern "C" fn _start() -> ! { +pub fn jinux_main() -> ! { jinux_frame::init(); test_main(); loop {} diff --git a/x86_64-custom.json b/x86_64-custom.json index d57f842fe..e4d6ee900 100644 --- a/x86_64-custom.json +++ b/x86_64-custom.json @@ -11,11 +11,6 @@ "executables": true, "linker-flavor": "ld.lld", "linker": "rust-lld", - "pre-link-args": { - "ld.lld": [ - "-Tboot/limine/conf/linker.ld" - ] - }, "panic-strategy": "abort", "disable-redzone": true, "features": "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"