9f4ad484a4
Absorb P1-P4 bootloader patches into P5 carrier. Move absorbed patches to local/patches/bootloader/absorbed/ for reference. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
216 lines
7.3 KiB
Diff
216 lines
7.3 KiB
Diff
--- a/src/arch/x86/mod.rs
|
|
+++ b/src/arch/x86/mod.rs
|
|
@@ -3,10 +3,15 @@
|
|
pub(crate) mod x32;
|
|
pub(crate) mod x64;
|
|
|
|
-pub unsafe fn paging_create(os: &impl Os, kernel_phys: u64, kernel_size: u64) -> Option<usize> {
|
|
+pub unsafe fn paging_create(
|
|
+ os: &impl Os,
|
|
+ kernel_phys: u64,
|
|
+ kernel_size: u64,
|
|
+ identity_map_end: u64,
|
|
+) -> Option<usize> {
|
|
unsafe {
|
|
if crate::KERNEL_64BIT {
|
|
- x64::paging_create(os, kernel_phys, kernel_size)
|
|
+ x64::paging_create(os, kernel_phys, kernel_size, identity_map_end)
|
|
} else {
|
|
x32::paging_create(os, kernel_phys, kernel_size)
|
|
}
|
|
--- a/src/arch/x86/x64.rs
|
|
+++ b/src/arch/x86/x64.rs
|
|
@@ -29,7 +29,12 @@
|
|
const WRITABLE: u64 = 1 << 1;
|
|
const LARGE: u64 = 1 << 7;
|
|
|
|
-pub unsafe fn paging_create(os: &impl Os, kernel_phys: u64, kernel_size: u64) -> Option<usize> {
|
|
+pub unsafe fn paging_create(
|
|
+ os: &impl Os,
|
|
+ kernel_phys: u64,
|
|
+ kernel_size: u64,
|
|
+ identity_map_end: u64,
|
|
+) -> Option<usize> {
|
|
unsafe {
|
|
// Create PML4
|
|
let pml4 = paging_allocate(os)?;
|
|
@@ -42,8 +47,14 @@
|
|
pml4[0] = pdp.as_ptr() as u64 | WRITABLE | PRESENT;
|
|
pml4[256] = pdp.as_ptr() as u64 | WRITABLE | PRESENT;
|
|
|
|
- // Identity map 8 GiB using 2 MiB pages
|
|
- for pdp_i in 0..8 {
|
|
+ let mut needed_pdp = identity_map_end.div_ceil(0x4000_0000);
|
|
+ if needed_pdp == 0 {
|
|
+ needed_pdp = 1;
|
|
+ }
|
|
+ assert!(needed_pdp <= pdp.len() as u64, "identity map end exceeds paging span");
|
|
+
|
|
+ // Identity map required physical range using 2 MiB pages
|
|
+ for pdp_i in 0..needed_pdp as usize {
|
|
let pd = paging_allocate(os)?;
|
|
pdp[pdp_i] = pd.as_ptr() as u64 | WRITABLE | PRESENT;
|
|
for pd_i in 0..pd.len() {
|
|
--- a/src/main.rs
|
|
+++ b/src/main.rs
|
|
@@ -641,15 +641,34 @@
|
|
(memory.len() as u64, memory.as_mut_ptr() as u64)
|
|
};
|
|
|
|
- let page_phys = unsafe { paging_create(os, kernel.as_ptr() as u64, kernel.len() as u64) }
|
|
- .expect("Failed to set up paging");
|
|
-
|
|
let max_env_size = 64 * KIBI;
|
|
let mut env_size = max_env_size;
|
|
let env_base = os.alloc_zeroed_page_aligned(env_size);
|
|
if env_base.is_null() {
|
|
panic!("Failed to allocate memory for stack");
|
|
}
|
|
+
|
|
+ let mut identity_map_end = region_end(kernel.as_ptr() as u64, kernel.len() as u64)
|
|
+ .max(region_end(stack_base as u64, stack_size as u64))
|
|
+ .max(region_end(bootstrap_base, bootstrap_size))
|
|
+ .max(region_end(env_base as u64, max_env_size as u64));
|
|
+
|
|
+ if let Some(ref live) = live_opt {
|
|
+ identity_map_end = identity_map_end.max(region_end(
|
|
+ live.as_ptr() as u64,
|
|
+ live.len() as u64,
|
|
+ ));
|
|
+ }
|
|
+
|
|
+ let page_phys = unsafe {
|
|
+ paging_create(
|
|
+ os,
|
|
+ kernel.as_ptr() as u64,
|
|
+ kernel.len() as u64,
|
|
+ identity_map_end,
|
|
+ )
|
|
+ }
|
|
+ .expect("Failed to set up paging");
|
|
|
|
{
|
|
let mut w = SliceWriter {
|
|
--- a/src/os/uefi/device.rs
|
|
+++ b/src/os/uefi/device.rs
|
|
@@ -26,19 +26,10 @@
|
|
}
|
|
|
|
let mut header_buf = [0u8; 512];
|
|
- let lba1_block = block_size / redoxfs::BLOCK_SIZE;
|
|
- let header_read_len = if 512 <= redoxfs::BLOCK_SIZE as usize {
|
|
- redoxfs::BLOCK_SIZE as usize
|
|
- } else {
|
|
- 512
|
|
- };
|
|
- let mut read_buf = vec![0u8; header_read_len];
|
|
- if unsafe { disk.read_at(lba1_block, &mut read_buf) }.is_err() {
|
|
+ if disk.read_bytes(block_size, &mut header_buf).is_err() {
|
|
log::warn!("GPT: failed to read LBA 1");
|
|
return 2 * crate::MIBI as u64;
|
|
}
|
|
- let copy_len = 512.min(read_buf.len());
|
|
- header_buf[..copy_len].copy_from_slice(&read_buf[..copy_len]);
|
|
|
|
if &header_buf[0..8] != b"EFI PART" {
|
|
log::warn!("GPT: no valid signature at LBA 1");
|
|
@@ -64,19 +55,15 @@
|
|
}
|
|
|
|
let entries_byte_offset = partition_entry_start_lba * block_size;
|
|
- let entries_start_block = entries_byte_offset / redoxfs::BLOCK_SIZE;
|
|
|
|
let total_entries_bytes = num_entries as usize * entry_size as usize;
|
|
- let read_size = total_entries_bytes.min(4096);
|
|
- let mut entries_buf = vec![0u8; read_size + redoxfs::BLOCK_SIZE as usize];
|
|
- let entries_read_blocks = (read_size as u64).div_ceil(redoxfs::BLOCK_SIZE) as usize;
|
|
- if unsafe { disk.read_at(entries_start_block, &mut entries_buf[..entries_read_blocks * redoxfs::BLOCK_SIZE as usize]) }.is_err() {
|
|
+ let mut entries_buf = vec![0u8; total_entries_bytes];
|
|
+ if disk.read_bytes(entries_byte_offset, &mut entries_buf).is_err() {
|
|
log::warn!("GPT: failed to read partition entries");
|
|
return 2 * crate::MIBI as u64;
|
|
}
|
|
|
|
- let entries_per_chunk = read_size / entry_size as usize;
|
|
- for i in 0..entries_per_chunk.min(num_entries as usize) {
|
|
+ for i in 0..num_entries as usize {
|
|
let off = i * entry_size as usize;
|
|
if off + entry_size as usize > entries_buf.len() {
|
|
break;
|
|
--- a/src/os/uefi/disk.rs
|
|
+++ b/src/os/uefi/disk.rs
|
|
@@ -117,3 +117,43 @@
|
|
Err(Error::new(EIO))
|
|
}
|
|
}
|
|
+
|
|
+impl DiskEfi {
|
|
+ pub fn media_block_size(&self) -> usize {
|
|
+ self.0.Media.BlockSize as usize
|
|
+ }
|
|
+
|
|
+ pub fn read_bytes(&mut self, offset: u64, buffer: &mut [u8]) -> Result<()> {
|
|
+ let block_size = self.media_block_size();
|
|
+ if block_size == 0 || block_size > self.1.len() {
|
|
+ return Err(Error::new(EINVAL));
|
|
+ }
|
|
+
|
|
+ let scratch = &mut self.1[..block_size];
|
|
+ let mut copied = 0usize;
|
|
+
|
|
+ while copied < buffer.len() {
|
|
+ let absolute = offset as usize + copied;
|
|
+ let lba = (absolute / block_size) as u64;
|
|
+ let in_block = absolute % block_size;
|
|
+
|
|
+ match (self.0.ReadBlocks)(
|
|
+ self.0,
|
|
+ self.0.Media.MediaId,
|
|
+ lba,
|
|
+ block_size,
|
|
+ scratch.as_mut_ptr(),
|
|
+ ) {
|
|
+ status if status.is_success() => {
|
|
+ let chunk_len = core::cmp::min(block_size - in_block, buffer.len() - copied);
|
|
+ buffer[copied..copied + chunk_len]
|
|
+ .copy_from_slice(&scratch[in_block..in_block + chunk_len]);
|
|
+ copied += chunk_len;
|
|
+ }
|
|
+ _ => return Err(Error::new(EIO)),
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Ok(())
|
|
+ }
|
|
+}
|
|
--- a/src/os/uefi/mod.rs
|
|
+++ b/src/os/uefi/mod.rs
|
|
@@ -45,19 +45,18 @@
|
|
let pages = size.div_ceil(page_size);
|
|
|
|
let ptr = {
|
|
- // Max address mapped by src/arch paging code (8 GiB)
|
|
let mut ptr = 0x2_0000_0000;
|
|
- status_to_result((std::system_table().BootServices.AllocatePages)(
|
|
- 1, // AllocateMaxAddress
|
|
- MemoryType::EfiRuntimeServicesData, // Keeps this memory out of free space list
|
|
+ if status_to_result((std::system_table().BootServices.AllocatePages)(
|
|
+ 0,
|
|
+ MemoryType::EfiLoaderData,
|
|
pages,
|
|
&mut ptr,
|
|
))
|
|
- .unwrap_or_else(|_| {
|
|
- ptr = 0;
|
|
- 0
|
|
- });
|
|
- if ptr == 0 { ptr::null_mut() } else { ptr as *mut u8 }
|
|
+ .is_err()
|
|
+ {
|
|
+ return ptr::null_mut();
|
|
+ }
|
|
+ ptr as *mut u8
|
|
};
|
|
|
|
if !ptr.is_null() {
|