diff --git a/nel_os_kernel/bzImage b/nel_os_bootloader/bzImage similarity index 100% rename from nel_os_kernel/bzImage rename to nel_os_bootloader/bzImage diff --git a/nel_os_bootloader/create-iso.sh b/nel_os_bootloader/create-iso.sh index d74dd1e..f416c36 100755 --- a/nel_os_bootloader/create-iso.sh +++ b/nel_os_bootloader/create-iso.sh @@ -6,12 +6,14 @@ cd ../nel_os_kernel cargo build --release -q cd ../nel_os_bootloader -dd if=/dev/zero of=fat.img bs=1k count=1440 -mformat -i fat.img -f 1440 :: +dd if=/dev/zero of=fat.img bs=1k count=32768 +mformat -i fat.img -C -h 16 -t 128 -s 32 :: mmd -i fat.img ::/EFI mmd -i fat.img ::/EFI/BOOT mcopy -i fat.img "$EFI_BINARY" ::/EFI/BOOT/BOOTX64.EFI mcopy -i fat.img ../nel_os_kernel/target/x86_64-nel_os/release/nel_os_kernel.elf ::/nel_os_kernel.elf +mcopy -i fat.img bzImage ::/bzImage +mcopy -i fat.img rootfs-n.cpio.gz ::/rootfs-n.cpio.gz mkdir iso cp fat.img iso diff --git a/nel_os_kernel/rootfs-n.cpio.gz b/nel_os_bootloader/rootfs-n.cpio.gz similarity index 100% rename from nel_os_kernel/rootfs-n.cpio.gz rename to nel_os_bootloader/rootfs-n.cpio.gz diff --git a/nel_os_bootloader/src/main.rs b/nel_os_bootloader/src/main.rs index 059bbcb..24e35b5 100644 --- a/nel_os_bootloader/src/main.rs +++ b/nel_os_bootloader/src/main.rs @@ -42,25 +42,53 @@ fn get_fs() -> Directory { fs.open_volume().unwrap() } -fn read_kernel(name: &CStr16) -> Box<[u8]> { +fn read_file(name: &CStr16) -> Box<[u8]> { let mut root = get_fs(); - let kernel_file_info = root + let file_info = root .open(name, FileMode::Read, FileAttribute::empty()) .unwrap(); - let mut kernel_file = kernel_file_info.into_regular_file().unwrap(); + let mut file = file_info.into_regular_file().unwrap(); - let file_size = kernel_file - .get_boxed_info::() - .unwrap() - .file_size(); + let file_size = file.get_boxed_info::().unwrap().file_size(); let mut buf = vec![0; file_size as usize]; - let read_size = kernel_file.read(&mut buf).unwrap(); - println!("kernel size: {}", read_size); + let read_size = file.read(&mut buf).unwrap(); + println!("file {} size: {}", name, read_size); buf.into_boxed_slice() } +fn load_file_to_laoder_data(name: &CStr16) -> (u64, u64) { + let mut root = get_fs(); + let file_info = root + .open(name, FileMode::Read, FileAttribute::empty()) + .expect("Failed to open file"); + let mut file = file_info + .into_regular_file() + .expect("Failed to convert to regular file"); + + let file_size = file + .get_boxed_info::() + .expect("Failed to get file info") + .file_size(); + + let page_ptr = unsafe { + uefi::boot::allocate_pages( + AllocateType::AnyPages, + MemoryType::LOADER_DATA, + file_size.div_ceil(4096) as usize, + ) + .expect("Failed to allocate pages") + .as_mut() + }; + + let buf = unsafe { slice::from_raw_parts_mut(page_ptr, file_size as usize) }; + let read_size = file.read(buf).expect("Failed to read file"); + println!("file {} size: {}", name, read_size); + + (page_ptr as *mut u8 as u64, file_size) +} + fn load_elf(bin: Box<[u8]>) -> u64 { let elf = elf::Elf::parse(&bin).expect("Failed to parse elf"); let mut dest_start = u64::MAX; @@ -143,7 +171,10 @@ fn main() -> Status { println!("{} v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); - let kernel = read_kernel(cstr16!("nel_os_kernel.elf")); + let kernel = read_file(cstr16!("nel_os_kernel.elf")); + + let (bzimage_addr, bzimage_size) = load_file_to_laoder_data(cstr16!("bzImage")); + let (rootfs_addr, rootfs_size) = load_file_to_laoder_data(cstr16!("rootfs-n.cpio.gz")); let entry_point = load_elf(kernel); @@ -195,6 +226,10 @@ fn main() -> Status { usable_memory, frame_buffer, rsdp, + bzimage_addr, + bzimage_size, + rootfs_addr, + rootfs_size, }); hlt_loop(); diff --git a/nel_os_common/src/lib.rs b/nel_os_common/src/lib.rs index 9373912..3fbbfac 100644 --- a/nel_os_common/src/lib.rs +++ b/nel_os_common/src/lib.rs @@ -9,4 +9,8 @@ pub struct BootInfo { pub usable_memory: UsableMemory, pub frame_buffer: FrameBuffer, pub rsdp: u64, + pub bzimage_addr: u64, + pub bzimage_size: u64, + pub rootfs_addr: u64, + pub rootfs_size: u64, } diff --git a/nel_os_kernel/src/main.rs b/nel_os_kernel/src/main.rs index e556399..2d482e8 100644 --- a/nel_os_kernel/src/main.rs +++ b/nel_os_kernel/src/main.rs @@ -22,6 +22,7 @@ use core::panic::PanicInfo; use core::ptr::addr_of; use ::acpi::AcpiTables; +use spin::Once; use x86_64::{registers::control::Cr3, structures::paging::OffsetPageTable, VirtAddr}; use crate::{ @@ -32,6 +33,11 @@ use crate::{ memory::{allocator, memory::BitmapMemoryTable, paging}, }; +pub static BZIMAGE_ADDR: Once = Once::new(); +pub static BZIMAGE_SIZE: Once = Once::new(); +pub static ROOTFS_ADDR: Once = Once::new(); +pub static ROOTFS_SIZE: Once = Once::new(); + #[repr(C, align(16))] struct AlignedStack { stack: [u8; KERNEL_STACK_SIZE], @@ -159,7 +165,14 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) { serial::disable_screen_output(); + BZIMAGE_ADDR.call_once(|| boot_info.bzimage_addr); + BZIMAGE_SIZE.call_once(|| boot_info.bzimage_size); + ROOTFS_ADDR.call_once(|| boot_info.rootfs_addr); + ROOTFS_SIZE.call_once(|| boot_info.rootfs_size); + let mut vcpu = vmm::get_vcpu(&mut bitmap_table).unwrap(); + + info!("Running guest VM..."); loop { let result = vcpu.run(&mut bitmap_table); if let Err(e) = result { diff --git a/nel_os_kernel/src/vmm/x86_64/common/linux.rs b/nel_os_kernel/src/vmm/x86_64/common/linux.rs index 52daf1c..097a25a 100644 --- a/nel_os_kernel/src/vmm/x86_64/common/linux.rs +++ b/nel_os_kernel/src/vmm/x86_64/common/linux.rs @@ -1,12 +1,16 @@ use core::ptr::read_unaligned; -use crate::vmm::VCpu; +use crate::{vmm::VCpu, BZIMAGE_ADDR, BZIMAGE_SIZE}; pub fn load_kernel(vcpu: &mut dyn VCpu) -> Result<(), &'static str> { - let kernel = BZIMAGE; + let kernel_addr = BZIMAGE_ADDR.get().unwrap(); + let kernel_size = BZIMAGE_SIZE.get().unwrap(); + + let kernel = + unsafe { core::slice::from_raw_parts(*kernel_addr as *const u8, *kernel_size as usize) }; let guest_mem_size = vcpu.get_guest_memory_size(); - let mut bp = BootParams::from_bytes(kernel).unwrap(); + let mut bp = BootParams::from_bytes(kernel)?; bp.e820_entries = 0; bp.hdr.type_of_loader = 0xFF; @@ -68,9 +72,6 @@ fn load_image(vcpu: &mut dyn VCpu, image: &[u8], addr: usize) -> Result<(), &'st Ok(()) } -pub const BZIMAGE: &[u8] = include_bytes!("../../../../bzImage"); -pub const INITRD: &[u8] = include_bytes!("../../../../rootfs-n.cpio.gz"); - pub const LAYOUT_BOOTPARAM: u64 = 0x0001_0000; pub const LAYOUT_CMDLINE: u64 = 0x0002_0000; pub const LAYOUT_KERNEL_BASE: u64 = 0x0010_0000; @@ -209,7 +210,7 @@ impl SetupHeader { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() < Self::HEADER_OFFSET + size_of::() { - return Err("バイト配列が小さすぎます"); + return Err("Binary data is too short to contain a valid SetupHeader"); } let mut hdr = unsafe { @@ -335,7 +336,7 @@ impl E820Entry { 3 => Ok(E820Type::Acpi), 4 => Ok(E820Type::Nvs), 5 => Ok(E820Type::Unusable), - _ => Err("不明なE820タイプ"), + _ => Err("Invalid E820 type"), } } diff --git a/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs b/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs index bb2b7b4..bbbf31b 100644 --- a/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs +++ b/nel_os_kernel/src/vmm/x86_64/intel/vcpu.rs @@ -124,10 +124,12 @@ impl IntelVCpu { controls::setup_entry_controls()?; controls::setup_exit_controls()?; Self::setup_host_state()?; - Self::setup_guest_state()?; + self.setup_guest_state()?; self.init_guest_memory(frame_allocator)?; + common::linux::load_kernel(self)?; + Ok(()) } @@ -135,7 +137,7 @@ impl IntelVCpu { &mut self, frame_allocator: &mut dyn FrameAllocator, ) -> Result<(), &'static str> { - let mut pages = 1000; + let mut pages = self.guest_memory_size / 0x1000; let mut gpa = 0; while pages > 0 { @@ -147,22 +149,9 @@ impl IntelVCpu { pages -= 1; } - let guest_ptr = Self::test_guest_code as u64; - let guest_addr = self.ept.get_phys_addr(0).unwrap(); - unsafe { - core::ptr::copy_nonoverlapping(guest_ptr as *const u8, guest_addr as *mut u8, 200); - } - let eptp = ept::EPTP::init(&self.ept.root_table); vmwrite(x86::vmx::vmcs::control::EPTP_FULL, u64::from(eptp))?; - info!( - "GPA 0x0 -> HPA {:#x}", - self.ept - .get_phys_addr(0) - .ok_or("Failed to get physical address")? - ); - Ok(()) } @@ -213,7 +202,7 @@ impl IntelVCpu { Ok(()) } - fn setup_guest_state() -> Result<(), &'static str> { + fn setup_guest_state(&mut self) -> Result<(), &'static str> { use x86::{controlregs::*, vmx::vmcs}; let cr0 = Cr0::empty() | Cr0::CR0_PROTECTED_MODE @@ -316,8 +305,8 @@ impl IntelVCpu { vmwrite(vmcs::guest::RFLAGS, 0x2)?; vmwrite(vmcs::guest::LINK_PTR_FULL, u64::MAX)?; - vmwrite(vmcs::guest::RIP, 0)?; // TODO: Set linux kernel base - // TODO: RSI + vmwrite(vmcs::guest::RIP, common::linux::LAYOUT_KERNEL_BASE as u64)?; + self.guest_registers.rsi = common::linux::LAYOUT_BOOTPARAM as u64; //vmwrite(vmcs::control::CR0_READ_SHADOW, vmread(vmcs::guest::CR0)?)?; //vmwrite(vmcs::control::CR4_READ_SHADOW, vmread(vmcs::guest::CR4)?)?;