kernel/src/main.rs

161 lines
5.5 KiB
Rust
Raw Normal View History

2022-11-01 07:24:50 -05:00
#![no_std]
#![no_main]
#![feature(abi_x86_interrupt)]
#![feature(alloc_error_handler)]
#![feature(allocator_api)]
#![feature(naked_functions)]
#![feature(int_roundings)]
#![feature(type_alias_impl_trait)]
#![deny(unsafe_op_in_unsafe_fn)]
extern crate alloc;
mod bootinfo;
mod gdt;
mod interrupts;
mod kernel_heap;
mod panic_handler;
mod physical_memory;
mod pit;
mod qemu_exit;
mod serial;
mod start;
mod tasking;
mod virtual_memory;
2024-06-06 22:02:00 -05:00
use core::{slice, usize};
use bootinfo::BOOTINFO;
2024-07-07 14:37:21 -05:00
use elf::{
abi::{
PT_DYNAMIC, PT_GNU_EH_FRAME, PT_GNU_RELRO, PT_GNU_STACK, PT_LOAD, PT_NULL, PT_PHDR,
R_X86_64_RELATIVE, SHT_REL, SHT_RELA,
},
endian::AnyEndian,
ElfBytes,
};
use serial::SECOND_PORT;
2022-11-01 07:24:50 -05:00
use tar_no_std::TarArchiveRef;
2023-09-29 15:44:53 -05:00
use tasking::TASKING;
2024-07-07 14:37:21 -05:00
use x86_64::{
registers::rflags::{self, RFlags},
structures::paging::{Page, PageTableFlags},
VirtAddr,
};
2024-06-06 22:02:00 -05:00
use crate::virtual_memory::AddressSpace;
2022-11-01 07:24:50 -05:00
2024-06-06 22:02:00 -05:00
// pub static INITRD: &[u8] = include_bytes!("../initrd.tar");
2023-09-29 15:44:53 -05:00
2022-11-01 07:24:50 -05:00
pub fn main() {
let mut rflags_data = rflags::read();
rflags_data |= RFlags::IOPL_HIGH | RFlags::IOPL_LOW;
unsafe {
rflags::write(rflags_data);
}
gdt::init();
interrupts::init();
pit::init(100);
2024-06-06 22:02:00 -05:00
let initrd = unsafe {
let ramdisk_start = BOOTINFO.ramdisk_addr.into_option().expect("ramdisk to be present");
let ramdisk_len = BOOTINFO.ramdisk_len;
slice::from_raw_parts(ramdisk_start as *const u8, ramdisk_len as usize)
};
let initrd = TarArchiveRef::new(initrd).unwrap();
let init_data = initrd
2023-09-29 15:44:53 -05:00
.entries()
2024-06-06 22:02:00 -05:00
.find(|x| x.filename().as_str().unwrap() == "bin/init")
2023-09-29 15:44:53 -05:00
.expect("Could not find init in initrd")
.data();
2024-06-06 22:02:00 -05:00
let init = ElfBytes::<AnyEndian>::minimal_parse(&init_data).unwrap();
2024-07-07 14:37:21 -05:00
let mut init_addr_space = AddressSpace::new().unwrap();
2024-06-06 22:02:00 -05:00
for mut pheader in init.segments().unwrap().iter() {
match pheader.p_type {
PT_NULL => (),
2024-07-07 14:37:21 -05:00
PT_LOAD => {
2024-06-06 22:02:00 -05:00
if pheader.p_vaddr < 0x1000 {
if pheader.p_memsz < 0x1000 {
continue;
}
2024-07-07 14:37:21 -05:00
pheader.p_offset += 0x1000 - pheader.p_vaddr;
pheader.p_memsz -= 0x1000 - pheader.p_vaddr;
pheader.p_filesz -= 0x1000 - pheader.p_vaddr;
2024-06-06 22:02:00 -05:00
pheader.p_vaddr = 0x1000;
}
let start_page = Page::containing_address(VirtAddr::new(pheader.p_vaddr));
let num_pages = (pheader.p_memsz.div_ceil(4096)
+ (pheader.p_vaddr & 0xFFF).div_ceil(4096))
as usize;
assert!(
(start_page.start_address().as_u64() + num_pages as u64 * 4096)
>= (pheader.p_vaddr + pheader.p_memsz)
);
#[allow(clippy::cast_possible_truncation)]
init_addr_space
.map_only_unused(start_page, num_pages, PageTableFlags::USER_ACCESSIBLE)
.expect("Unable to map region");
init_addr_space.run(|| unsafe {
2024-07-07 14:37:21 -05:00
let dst = slice::from_raw_parts_mut(
pheader.p_vaddr as *mut u8,
pheader.p_memsz as usize,
);
dst[0..pheader.p_filesz as usize].copy_from_slice(
&init_data[(pheader.p_offset as usize)
..((pheader.p_offset + pheader.p_filesz) as usize)],
);
2024-06-06 22:02:00 -05:00
dst[(pheader.p_filesz as usize)..(pheader.p_memsz as usize)].fill(0)
});
}
2024-07-07 14:37:21 -05:00
PT_GNU_RELRO => (),
2024-06-06 22:02:00 -05:00
PT_GNU_EH_FRAME => (),
PT_GNU_STACK => (),
PT_DYNAMIC => (),
PT_PHDR => (),
_ => println!("Warning: Unimplemented ELF program header type {:#x}", pheader.p_type),
}
}
for section in init.section_headers().unwrap().iter() {
if section.sh_type == SHT_REL {
for rel in init.section_data_as_rels(&section).unwrap() {
match rel.r_type {
_ => unimplemented!("ELF relocation type {}", rel.r_type),
}
}
}
if section.sh_type == SHT_RELA {
for rela in init.section_data_as_relas(&section).unwrap() {
match rela.r_type {
R_X86_64_RELATIVE => {
init_addr_space.run(|| unsafe {
let ptr = rela.r_offset as *mut u64;
ptr.write(rela.r_addend as u64);
});
}
_ => unimplemented!("ELF relocation type {}", rela.r_type),
}
}
}
}
// Before starting init, write the pcapng section header + interface description to the second serial port
SECOND_PORT.write_u32s(&[
0x0A0D0D0A, // SHB type
7 * 4, // Total block length
0x1A2B3C4D, // Byte order magic
0x0000_0001, // Version (1.0)
0xFFFFFFFF, // Length upper (-1) across both
0xFFFFFFFF, // Length lower
7 * 4, // Total block length
0x1, // IDB type
5 * 4, // Total block length
147, // Link type
4096 + 8, // Packet length limit,
5 * 4, // Total block length
]);
2022-11-01 07:24:50 -05:00
TASKING
.lock()
2024-07-07 14:37:21 -05:00
.new_process(init.ehdr.e_entry as _, init_addr_space)
2022-11-01 07:24:50 -05:00
.expect("Failed to create init process");
}