diff --git a/src/main.rs b/src/main.rs index 963823f32746c10e8418c6bacee0f77ae737ad14..01d1fb6632ffcd69a0307217d5e49f306eac2c56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,8 @@ pub static mut AREAS: [OsMemoryEntry; 512] = [OsMemoryEntry { pub static mut KERNEL_64BIT: bool = false; +pub static mut LIVE_OPT: Option<(u64, &'static [u8])> = None; + struct SliceWriter<'a> { slice: &'a mut [u8], i: usize, @@ -383,38 +385,6 @@ fn main< panic!("Failed to allocate memory for stack"); } - let (kernel, kernel_entry) = { - let kernel = load_to_memory(os, &mut fs, "boot", "kernel", Filetype::Elf); - let (kernel_entry, kernel_64bit) = elf_entry(kernel); - unsafe { KERNEL_64BIT = kernel_64bit; } - (kernel, kernel_entry) - }; - - let (bootstrap_size, bootstrap_base, bootstrap_entry, initfs_offset, initfs_len) = { - let initfs_slice = load_to_memory(os, &mut fs, "boot", "initfs", Filetype::Other); - let bootstrap_slice = load_to_memory(os, &mut fs, "boot", "bootstrap", Filetype::Elf); - let bootstrap_len = (bootstrap_slice.len()+4095)/4096*4096; - let initfs_len = (initfs_slice.len()+4095)/4096*4096; - let (bootstrap_entry, bootstrap_64bit) = elf_entry(bootstrap_slice); - unsafe { assert_eq!(KERNEL_64BIT, bootstrap_64bit); } - - let memory = unsafe { - let total_size = initfs_len + bootstrap_len; - let ptr = os.alloc_zeroed_page_aligned(total_size); - assert!(!ptr.is_null(), "failed to allocate bootstrap+initfs memory"); - core::slice::from_raw_parts_mut(ptr, total_size) - }; - memory[..bootstrap_slice.len()].copy_from_slice(bootstrap_slice); - memory[bootstrap_len..bootstrap_len + initfs_slice.len()].copy_from_slice(initfs_slice); - - (memory.len() as u64, memory.as_mut_ptr() as u64, bootstrap_entry, bootstrap_len, initfs_len) - }; - - let page_phys = unsafe { - paging_create(os, kernel.as_ptr() as u64, kernel.len() as u64) - }.expect("Failed to set up paging"); - //TODO: properly reserve page table allocations so kernel does not re-use them - let live_opt = if cfg!(feature = "live") { let size = fs.header.size(); @@ -439,12 +409,53 @@ fn main< } println!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64); + println!("Switching to live disk"); + unsafe { + LIVE_OPT = Some(( + fs.block, + slice::from_raw_parts_mut(ptr, size as usize) + )); + } + Some(live) } else { None }; //TODO: properly reserve live disk so kernel does not re-use it + let (kernel, kernel_entry) = { + let kernel = load_to_memory(os, &mut fs, "boot", "kernel", Filetype::Elf); + let (kernel_entry, kernel_64bit) = elf_entry(kernel); + unsafe { KERNEL_64BIT = kernel_64bit; } + (kernel, kernel_entry) + }; + + let (bootstrap_size, bootstrap_base, bootstrap_entry, initfs_offset, initfs_len) = { + let bootstrap_slice = load_to_memory(os, &mut fs, "boot", "bootstrap", Filetype::Elf); + let bootstrap_len = (bootstrap_slice.len()+4095)/4096*4096; + let (bootstrap_entry, bootstrap_64bit) = elf_entry(bootstrap_slice); + unsafe { assert_eq!(KERNEL_64BIT, bootstrap_64bit); } + + let initfs_slice = load_to_memory(os, &mut fs, "boot", "initfs", Filetype::Other); + let initfs_len = (initfs_slice.len()+4095)/4096*4096; + + let memory = unsafe { + let total_size = initfs_len + bootstrap_len; + let ptr = os.alloc_zeroed_page_aligned(total_size); + assert!(!ptr.is_null(), "failed to allocate bootstrap+initfs memory"); + core::slice::from_raw_parts_mut(ptr, total_size) + }; + memory[..bootstrap_slice.len()].copy_from_slice(bootstrap_slice); + memory[bootstrap_len..bootstrap_len + initfs_slice.len()].copy_from_slice(initfs_slice); + + (memory.len() as u64, memory.as_mut_ptr() as u64, bootstrap_entry, bootstrap_len, initfs_len) + }; + + let page_phys = unsafe { + paging_create(os, kernel.as_ptr() as u64, kernel.len() as u64) + }.expect("Failed to set up paging"); + //TODO: properly reserve page table allocations so kernel does not re-use them + let mut env_size = 4 * KIBI; let env_base = os.alloc_zeroed_page_aligned(env_size); if env_base.is_null() { diff --git a/src/os/bios/disk.rs b/src/os/bios/disk.rs index 1eb4c96af70095efe0556bd0e78a9db63896918a..0551ef10bcdce8c4382d7d716a4bd68558038497 100644 --- a/src/os/bios/disk.rs +++ b/src/os/bios/disk.rs @@ -52,6 +52,18 @@ impl DiskBios { impl Disk for DiskBios { unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { + // Optimization for live disks + if let Some(live) = crate::LIVE_OPT { + if block >= live.0 { + let start = ((block - live.0) * BLOCK_SIZE) as usize; + let end = start + buffer.len(); + if end <= live.1.len() { + buffer.copy_from_slice(&live.1[start..end]); + return Ok(buffer.len()); + } + } + } + for (i, chunk) in buffer.chunks_mut((MAX_BLOCKS * BLOCK_SIZE) as usize).enumerate() { let mut dap = DiskAddressPacket::from_block( block + i as u64 * MAX_BLOCKS, diff --git a/src/os/uefi/disk.rs b/src/os/uefi/disk.rs index 5a52355d45f4831e087077527f8e8cb52a857bf6..25b9aa01bb1fa1e0cb5e78d308f07f8ebc19167d 100644 --- a/src/os/uefi/disk.rs +++ b/src/os/uefi/disk.rs @@ -19,6 +19,18 @@ impl Protocol<UefiBlockIo> for DiskEfi { impl Disk for DiskEfi { unsafe fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { + // Optimization for live disks + if let Some(live) = crate::LIVE_OPT { + if block >= live.0 { + let start = ((block - live.0) * BLOCK_SIZE) as usize; + let end = start + buffer.len(); + if end <= live.1.len() { + buffer.copy_from_slice(&live.1[start..end]); + return Ok(buffer.len()); + } + } + } + let block_size = self.0.Media.BlockSize as u64; let lba = block * BLOCK_SIZE / block_size;