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,
|
|
|
|
};
|
2024-07-07 07:59:27 -05:00
|
|
|
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(§ion).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(§ion).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),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-07 07:59:27 -05:00
|
|
|
|
|
|
|
// 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");
|
|
|
|
}
|