mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Replace bootloader with limine
This commit is contained in:
parent
78e72fd94a
commit
0435902579
@ -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"
|
||||
|
@ -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"
|
||||
anyhow = "1.0.32"
|
||||
|
||||
[features]
|
||||
default = ["limine"]
|
||||
limine= []
|
18
src/boot/limine/conf/limine.cfg
Normal file
18
src/boot/limine/conf/limine.cfg
Normal file
@ -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
|
81
src/boot/limine/conf/linker.ld
Normal file
81
src/boot/limine/conf/linker.ld
Normal file
@ -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) }
|
||||
}
|
37
src/boot/limine/scripts/limine-build.sh
Executable file
37
src/boot/limine/scripts/limine-build.sh
Executable file
@ -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
|
@ -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<String> {
|
||||
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<String> {
|
||||
))
|
||||
}
|
||||
|
||||
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<ExitStatus> {
|
||||
let status = runner_utils::run_with_timeout(&mut cmd, Duration::from_secs(TEST_TIMEOUT_SECS))?;
|
||||
Ok(status)
|
20
src/build.rs
Normal file
20
src/build.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use std::{env, error::Error};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
limine_build_script()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn limine_build_script() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
// 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(())
|
||||
}
|
@ -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 = []
|
||||
|
||||
|
26
src/framework/jinux-frame/src/boot/limine.rs
Normal file
26
src/framework/jinux-frame/src/boot/limine.rs
Normal file
@ -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)
|
||||
};
|
9
src/framework/jinux-frame/src/boot/mod.rs
Normal file
9
src/framework/jinux-frame/src/boot/mod.rs
Normal file
@ -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();
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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<Option<Writer>> = 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<Option<Writer>> = 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))
|
||||
|
@ -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| {});
|
||||
}
|
||||
|
@ -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<T>(region: &acpi::PhysicalMapping<Self, T>) {}
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -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<u64>) {
|
||||
acpi::init(rsdp.unwrap());
|
||||
pub(crate) fn init() {
|
||||
acpi::init();
|
||||
timer::init();
|
||||
if apic::has_apic() {
|
||||
ioapic::init();
|
||||
|
@ -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<IrqCallbackHandle> = 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() {
|
||||
|
@ -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.*)
|
||||
}
|
||||
}
|
@ -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<Vec<&limine::LimineMemmapEntry>> = 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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user