fix: consolidate bootloader patches
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>
This commit is contained in:
@@ -1,564 +0,0 @@
|
||||
diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs
|
||||
index 55c68f5..765ae41 100644
|
||||
--- a/src/arch/aarch64.rs
|
||||
+++ b/src/arch/aarch64.rs
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::area_add;
|
||||
-use crate::os::{Os, OsMemoryEntry, OsMemoryKind, dtb::is_in_dev_mem_region};
|
||||
+use crate::os::{dtb::is_in_dev_mem_region, Os, OsMemoryEntry, OsMemoryKind};
|
||||
use core::slice;
|
||||
|
||||
pub(crate) const PF_PRESENT: u64 = 1 << 0;
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 542b059..78dabb0 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -10,6 +10,7 @@ extern crate uefi_std as std;
|
||||
use alloc::{format, string::String, vec::Vec};
|
||||
use core::{
|
||||
cmp,
|
||||
+ convert::TryFrom,
|
||||
fmt::{self, Write},
|
||||
mem, ptr, slice, str,
|
||||
};
|
||||
@@ -114,6 +115,10 @@ fn select_mode(
|
||||
live: &mut bool,
|
||||
edit_env: &mut bool,
|
||||
) -> Option<OsVideoMode> {
|
||||
+ const DEFAULT_WIDTH: u32 = 1280;
|
||||
+ const DEFAULT_HEIGHT: u32 = 720;
|
||||
+ const AUTOBOOT_SECONDS: usize = 5;
|
||||
+
|
||||
let mut modes = Vec::new();
|
||||
for mode in os.video_modes(output_i) {
|
||||
let mut aspect_w = mode.width;
|
||||
@@ -141,15 +146,26 @@ fn select_mode(
|
||||
// Sort modes by pixel area, reversed
|
||||
modes.sort_by(|a, b| (b.0.width * b.0.height).cmp(&(a.0.width * a.0.height)));
|
||||
|
||||
- // Set selected based on best resolution
|
||||
+ // Set selected based on Red Bear default resolution first, then best resolution fallback
|
||||
print!("Output {}", output_i);
|
||||
let mut selected = modes.first().map_or(0, |x| x.0.id);
|
||||
- if let Some((best_width, best_height)) = os.best_resolution(output_i) {
|
||||
- print!(", best resolution: {}x{}", best_width, best_height);
|
||||
- for (mode, _text) in modes.iter() {
|
||||
- if mode.width == best_width && mode.height == best_height {
|
||||
- selected = mode.id;
|
||||
- break;
|
||||
+ let mut selected_from_default = false;
|
||||
+ for (mode, _text) in modes.iter() {
|
||||
+ if mode.width == DEFAULT_WIDTH && mode.height == DEFAULT_HEIGHT {
|
||||
+ selected = mode.id;
|
||||
+ selected_from_default = true;
|
||||
+ print!(", default resolution: {}x{}", DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if !selected_from_default {
|
||||
+ if let Some((best_width, best_height)) = os.best_resolution(output_i) {
|
||||
+ print!(", best resolution: {}x{}", best_width, best_height);
|
||||
+ for (mode, _text) in modes.iter() {
|
||||
+ if mode.width == best_width && mode.height == best_height {
|
||||
+ selected = mode.id;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,12 +179,19 @@ fn select_mode(
|
||||
println!("Press l to enable live mode");
|
||||
}
|
||||
println!("Press e to edit boot environment");
|
||||
+ println!(
|
||||
+ "Autobooting default mode in {} seconds (press any key to cancel countdown)",
|
||||
+ AUTOBOOT_SECONDS
|
||||
+ );
|
||||
println!();
|
||||
print!(" ");
|
||||
|
||||
let (off_x, off_y) = os.get_text_position();
|
||||
let rows = 12;
|
||||
let mut mode_opt = None;
|
||||
+ let countdown_y = off_y.saturating_sub(2);
|
||||
+ let mut countdown = AUTOBOOT_SECONDS;
|
||||
+ let mut countdown_active = true;
|
||||
while !modes.is_empty() {
|
||||
let mut row = 0;
|
||||
let mut col = 0;
|
||||
@@ -186,9 +209,38 @@ fn select_mode(
|
||||
row += 1;
|
||||
}
|
||||
|
||||
+ os.set_text_position(0, countdown_y);
|
||||
+ os.set_text_highlight(false);
|
||||
+ if countdown_active {
|
||||
+ println!(
|
||||
+ "Autobooting default mode in {} seconds (press any key to cancel countdown)",
|
||||
+ countdown
|
||||
+ );
|
||||
+ } else {
|
||||
+ println!("Manual mode selection active. Press Enter to boot selected mode. ");
|
||||
+ }
|
||||
+
|
||||
// Read keypress
|
||||
- match os.get_key() {
|
||||
+ match if countdown_active {
|
||||
+ os.get_key_timeout(1000)
|
||||
+ } else {
|
||||
+ os.get_key()
|
||||
+ } {
|
||||
+ OsKey::Timeout => {
|
||||
+ if countdown_active {
|
||||
+ if countdown == 0 {
|
||||
+ if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
+ if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
+ mode_opt = Some(*mode);
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ countdown = countdown.saturating_sub(1);
|
||||
+ }
|
||||
+ }
|
||||
OsKey::Left => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if mode_i < rows {
|
||||
while mode_i < modes.len() {
|
||||
@@ -202,6 +254,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Right => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
mode_i += rows;
|
||||
if mode_i >= modes.len() {
|
||||
@@ -213,6 +266,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Up => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if mode_i % rows == 0 {
|
||||
mode_i += rows;
|
||||
@@ -227,6 +281,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Down => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
mode_i += 1;
|
||||
if mode_i % rows == 0 {
|
||||
@@ -241,6 +296,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Enter => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
mode_opt = Some(*mode);
|
||||
@@ -249,6 +305,7 @@ fn select_mode(
|
||||
break;
|
||||
}
|
||||
OsKey::Char('l') => {
|
||||
+ countdown_active = false;
|
||||
*live = !*live;
|
||||
os.set_text_position(live_mode.0, live_mode.1);
|
||||
if *live {
|
||||
@@ -258,6 +315,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Char('e') => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
*edit_env = true;
|
||||
@@ -266,7 +324,9 @@ fn select_mode(
|
||||
}
|
||||
break;
|
||||
}
|
||||
- _ => (),
|
||||
+ OsKey::Other | OsKey::Backspace | OsKey::Delete | OsKey::Char(_) => {
|
||||
+ countdown_active = false;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,36 +558,62 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
|
||||
print!("live: 0/{} MiB", size / MIBI as u64);
|
||||
|
||||
- let ptr = os.alloc_zeroed_page_aligned(size as usize);
|
||||
- if ptr.is_null() {
|
||||
- panic!("Failed to allocate memory for live");
|
||||
+ let live_size = match usize::try_from(size) {
|
||||
+ Ok(live_size) => live_size,
|
||||
+ Err(_) => {
|
||||
+ println!("\rlive: disabled (image too large for bootloader address space)");
|
||||
+ live = false;
|
||||
+ 0
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ let ptr = if live {
|
||||
+ os.alloc_zeroed_page_aligned(live_size)
|
||||
+ } else {
|
||||
+ ptr::null_mut()
|
||||
+ };
|
||||
+ if live && ptr.is_null() {
|
||||
+ println!(
|
||||
+ "\rlive: disabled (unable to allocate {} MiB upfront)",
|
||||
+ size / MIBI as u64
|
||||
+ );
|
||||
+ live = false;
|
||||
}
|
||||
|
||||
- let live = unsafe { slice::from_raw_parts_mut(ptr, size as usize) };
|
||||
+ let live = if live {
|
||||
+ Some(unsafe { slice::from_raw_parts_mut(ptr, live_size) })
|
||||
+ } else {
|
||||
+ println!("Continuing without live preload");
|
||||
+ None
|
||||
+ };
|
||||
|
||||
- let mut i = 0;
|
||||
- for chunk in live.chunks_mut(MIBI) {
|
||||
- print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
- i += unsafe {
|
||||
- fs.disk
|
||||
- .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
- .expect("Failed to read live disk") as u64
|
||||
- };
|
||||
- }
|
||||
- println!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
+ if let Some(live) = live {
|
||||
+ let mut i = 0;
|
||||
+ for chunk in live.chunks_mut(MIBI) {
|
||||
+ print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
+ i += unsafe {
|
||||
+ fs.disk
|
||||
+ .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
+ .expect("Failed to read live disk") as u64
|
||||
+ };
|
||||
+ }
|
||||
+ 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)));
|
||||
- }
|
||||
+ println!("Switching to live disk");
|
||||
+ unsafe {
|
||||
+ LIVE_OPT = Some((fs.block, slice::from_raw_parts_mut(ptr, live_size)));
|
||||
+ }
|
||||
|
||||
- area_add(OsMemoryEntry {
|
||||
- base: live.as_ptr() as u64,
|
||||
- size: live.len() as u64,
|
||||
- kind: OsMemoryKind::Reserved,
|
||||
- });
|
||||
+ area_add(OsMemoryEntry {
|
||||
+ base: live.as_ptr() as u64,
|
||||
+ size: live.len() as u64,
|
||||
+ kind: OsMemoryKind::Reserved,
|
||||
+ });
|
||||
|
||||
- Some(live)
|
||||
+ Some(live)
|
||||
+ } else {
|
||||
+ None
|
||||
+ }
|
||||
} else {
|
||||
None
|
||||
};
|
||||
diff --git a/src/os/bios/disk.rs b/src/os/bios/disk.rs
|
||||
index 4570292..aeee85d 100644
|
||||
--- a/src/os/bios/disk.rs
|
||||
+++ b/src/os/bios/disk.rs
|
||||
@@ -1,8 +1,8 @@
|
||||
use core::{mem, ptr};
|
||||
-use redoxfs::{BLOCK_SIZE, Disk};
|
||||
-use syscall::error::{EIO, Error, Result};
|
||||
+use redoxfs::{Disk, BLOCK_SIZE};
|
||||
+use syscall::error::{Error, Result, EIO};
|
||||
|
||||
-use super::{DISK_ADDRESS_PACKET_ADDR, DISK_BIOS_ADDR, ThunkData};
|
||||
+use super::{ThunkData, DISK_ADDRESS_PACKET_ADDR, DISK_BIOS_ADDR};
|
||||
|
||||
const SECTOR_SIZE: u64 = 512;
|
||||
const BLOCKS_PER_SECTOR: u64 = BLOCK_SIZE / SECTOR_SIZE;
|
||||
diff --git a/src/os/bios/memory_map.rs b/src/os/bios/memory_map.rs
|
||||
index d47f6b2..78677ec 100644
|
||||
--- a/src/os/bios/memory_map.rs
|
||||
+++ b/src/os/bios/memory_map.rs
|
||||
@@ -3,7 +3,7 @@ use core::{cmp, mem, ptr};
|
||||
use crate::area_add;
|
||||
use crate::os::{OsMemoryEntry, OsMemoryKind};
|
||||
|
||||
-use super::{MEMORY_MAP_ADDR, thunk::ThunkData};
|
||||
+use super::{thunk::ThunkData, MEMORY_MAP_ADDR};
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct MemoryMapEntry {
|
||||
diff --git a/src/os/bios/mod.rs b/src/os/bios/mod.rs
|
||||
index a9873d7..c016688 100644
|
||||
--- a/src/os/bios/mod.rs
|
||||
+++ b/src/os/bios/mod.rs
|
||||
@@ -1,11 +1,11 @@
|
||||
-use alloc::alloc::{Layout, alloc_zeroed};
|
||||
+use alloc::alloc::{alloc_zeroed, Layout};
|
||||
use core::{convert::TryFrom, mem, ptr, slice};
|
||||
use linked_list_allocator::LockedHeap;
|
||||
use spin::Mutex;
|
||||
|
||||
-use crate::KernelArgs;
|
||||
use crate::logger::LOGGER;
|
||||
use crate::os::{Os, OsHwDesc, OsKey, OsVideoMode};
|
||||
+use crate::KernelArgs;
|
||||
|
||||
use self::disk::DiskBios;
|
||||
use self::memory_map::memory_map;
|
||||
@@ -109,9 +109,14 @@ impl Os for OsBios {
|
||||
|
||||
let page_size = self.page_size();
|
||||
let pages = size.div_ceil(page_size);
|
||||
+ let Some(total_size) = pages.checked_mul(page_size) else {
|
||||
+ return ptr::null_mut();
|
||||
+ };
|
||||
+ let Ok(layout) = Layout::from_size_align(total_size, page_size) else {
|
||||
+ return ptr::null_mut();
|
||||
+ };
|
||||
|
||||
- let ptr =
|
||||
- unsafe { alloc_zeroed(Layout::from_size_align(pages * page_size, page_size).unwrap()) };
|
||||
+ let ptr = unsafe { alloc_zeroed(layout) };
|
||||
|
||||
assert!(!ptr.is_null());
|
||||
ptr
|
||||
diff --git a/src/os/mod.rs b/src/os/mod.rs
|
||||
index 92c00c9..f01c222 100644
|
||||
--- a/src/os/mod.rs
|
||||
+++ b/src/os/mod.rs
|
||||
@@ -32,6 +32,7 @@ pub enum OsKey {
|
||||
Delete,
|
||||
Enter,
|
||||
Char(char),
|
||||
+ Timeout,
|
||||
Other,
|
||||
}
|
||||
|
||||
@@ -87,6 +88,9 @@ pub trait Os {
|
||||
fn best_resolution(&self, output_i: usize) -> Option<(u32, u32)>;
|
||||
|
||||
fn get_key(&self) -> OsKey;
|
||||
+ fn get_key_timeout(&self, _milliseconds: usize) -> OsKey {
|
||||
+ self.get_key()
|
||||
+ }
|
||||
|
||||
fn clear_text(&self);
|
||||
fn get_text_position(&self) -> (usize, usize);
|
||||
diff --git a/src/os/uefi/arch/aarch64.rs b/src/os/uefi/arch/aarch64.rs
|
||||
index 3e36beb..bede418 100644
|
||||
--- a/src/os/uefi/arch/aarch64.rs
|
||||
+++ b/src/os/uefi/arch/aarch64.rs
|
||||
@@ -2,12 +2,12 @@ use core::{arch::asm, fmt::Write, mem, slice};
|
||||
use uefi::status::Result;
|
||||
|
||||
use crate::{
|
||||
- KernelArgs,
|
||||
arch::{ENTRY_ADDRESS_MASK, PAGE_ENTRIES, PF_PRESENT, PF_TABLE, PHYS_OFFSET},
|
||||
logger::LOGGER,
|
||||
+ KernelArgs,
|
||||
};
|
||||
|
||||
-use super::super::{OsEfi, memory_map::memory_map};
|
||||
+use super::super::{memory_map::memory_map, OsEfi};
|
||||
|
||||
unsafe fn dump_page_tables(table_phys: u64, table_virt: u64, table_level: u64) {
|
||||
unsafe {
|
||||
diff --git a/src/os/uefi/arch/riscv64/mod.rs b/src/os/uefi/arch/riscv64/mod.rs
|
||||
index ac3bc49..92dc280 100644
|
||||
--- a/src/os/uefi/arch/riscv64/mod.rs
|
||||
+++ b/src/os/uefi/arch/riscv64/mod.rs
|
||||
@@ -1,8 +1,8 @@
|
||||
-use crate::KernelArgs;
|
||||
use crate::arch::PHYS_OFFSET;
|
||||
use crate::logger::LOGGER;
|
||||
-use crate::os::OsEfi;
|
||||
use crate::os::uefi::memory_map::memory_map;
|
||||
+use crate::os::OsEfi;
|
||||
+use crate::KernelArgs;
|
||||
use core::arch::asm;
|
||||
use core::mem;
|
||||
use uefi::status::Result;
|
||||
diff --git a/src/os/uefi/arch/x86_64.rs b/src/os/uefi/arch/x86_64.rs
|
||||
index e1ecaa5..52cef13 100644
|
||||
--- a/src/os/uefi/arch/x86_64.rs
|
||||
+++ b/src/os/uefi/arch/x86_64.rs
|
||||
@@ -5,9 +5,9 @@ use x86::{
|
||||
msr,
|
||||
};
|
||||
|
||||
-use crate::{KernelArgs, logger::LOGGER};
|
||||
+use crate::{logger::LOGGER, KernelArgs};
|
||||
|
||||
-use super::super::{OsEfi, memory_map::memory_map};
|
||||
+use super::super::{memory_map::memory_map, OsEfi};
|
||||
|
||||
unsafe extern "C" fn kernel_entry(
|
||||
page_phys: usize,
|
||||
diff --git a/src/os/uefi/device.rs b/src/os/uefi/device.rs
|
||||
index 36b48dc..0b7991f 100644
|
||||
--- a/src/os/uefi/device.rs
|
||||
+++ b/src/os/uefi/device.rs
|
||||
@@ -1,13 +1,13 @@
|
||||
use alloc::{string::String, vec, vec::Vec};
|
||||
use core::{fmt::Write, mem, ptr, slice};
|
||||
use uefi::{
|
||||
- Handle,
|
||||
device::{
|
||||
DevicePath, DevicePathAcpiType, DevicePathBbsType, DevicePathEndType,
|
||||
DevicePathHardwareType, DevicePathMediaType, DevicePathMessagingType, DevicePathType,
|
||||
},
|
||||
guid::Guid,
|
||||
status::Status,
|
||||
+ Handle,
|
||||
};
|
||||
use uefi_std::{fs::FileSystem, loaded_image::LoadedImage, proto::Protocol};
|
||||
|
||||
diff --git a/src/os/uefi/disk.rs b/src/os/uefi/disk.rs
|
||||
index 31e02db..3f920bb 100644
|
||||
--- a/src/os/uefi/disk.rs
|
||||
+++ b/src/os/uefi/disk.rs
|
||||
@@ -1,10 +1,10 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::slice;
|
||||
-use redoxfs::{BLOCK_SIZE, Disk, RECORD_SIZE};
|
||||
+use redoxfs::{Disk, BLOCK_SIZE, RECORD_SIZE};
|
||||
use std::proto::Protocol;
|
||||
-use syscall::{EINVAL, EIO, Error, Result};
|
||||
+use syscall::{Error, Result, EINVAL, EIO};
|
||||
use uefi::block_io::BlockIo as UefiBlockIo;
|
||||
-use uefi::guid::{BLOCK_IO_GUID, Guid};
|
||||
+use uefi::guid::{Guid, BLOCK_IO_GUID};
|
||||
|
||||
pub enum DiskOrFileEfi {
|
||||
Disk(DiskEfi),
|
||||
diff --git a/src/os/uefi/display.rs b/src/os/uefi/display.rs
|
||||
index 95b7c2f..8bbe6e3 100644
|
||||
--- a/src/os/uefi/display.rs
|
||||
+++ b/src/os/uefi/display.rs
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::proto::Protocol;
|
||||
use uefi::graphics::GraphicsOutput;
|
||||
-use uefi::guid::{GRAPHICS_OUTPUT_PROTOCOL_GUID, Guid};
|
||||
+use uefi::guid::{Guid, GRAPHICS_OUTPUT_PROTOCOL_GUID};
|
||||
|
||||
pub struct Output(pub &'static mut GraphicsOutput);
|
||||
|
||||
diff --git a/src/os/uefi/dtb.rs b/src/os/uefi/dtb.rs
|
||||
index 812c752..975c983 100644
|
||||
--- a/src/os/uefi/dtb.rs
|
||||
+++ b/src/os/uefi/dtb.rs
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::Os;
|
||||
use alloc::vec::Vec;
|
||||
-use byteorder::BE;
|
||||
use byteorder::ByteOrder;
|
||||
+use byteorder::BE;
|
||||
use core::slice;
|
||||
use fdt::Fdt;
|
||||
use uefi::guid::DEVICE_TREE_GUID;
|
||||
diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs
|
||||
index bbd034b..c79266e 100644
|
||||
--- a/src/os/uefi/mod.rs
|
||||
+++ b/src/os/uefi/mod.rs
|
||||
@@ -2,13 +2,13 @@ use alloc::vec::Vec;
|
||||
use core::{cell::RefCell, mem, ptr, slice};
|
||||
use std::proto::Protocol;
|
||||
use uefi::{
|
||||
- Handle,
|
||||
boot::LocateSearchType,
|
||||
memory::MemoryType,
|
||||
reset::ResetType,
|
||||
status::{Result, Status},
|
||||
system::SystemTable,
|
||||
text::TextInputKey,
|
||||
+ Handle,
|
||||
};
|
||||
|
||||
use crate::os::{Os, OsHwDesc, OsKey, OsVideoMode};
|
||||
@@ -103,7 +103,7 @@ impl OsEfi {
|
||||
|
||||
for other_output in outputs.iter() {
|
||||
if output.0.Mode.FrameBufferBase
|
||||
- == other_output.0.0.Mode.FrameBufferBase
|
||||
+ == other_output.0 .0.Mode.FrameBufferBase
|
||||
{
|
||||
log::debug!(
|
||||
"Skipping output with frame buffer base matching another output"
|
||||
@@ -236,7 +236,7 @@ impl Os for OsEfi {
|
||||
let output_opt = match self.outputs.borrow_mut().get_mut(output_i) {
|
||||
Some(output) => unsafe {
|
||||
// Hack to enable clone
|
||||
- let ptr = output.0.0 as *mut _;
|
||||
+ let ptr = output.0 .0 as *mut _;
|
||||
Some(Output::new(&mut *ptr))
|
||||
},
|
||||
None => None,
|
||||
@@ -320,6 +320,40 @@ impl Os for OsEfi {
|
||||
}
|
||||
}
|
||||
|
||||
+ fn get_key_timeout(&self, milliseconds: usize) -> OsKey {
|
||||
+ let slices = milliseconds.div_ceil(100);
|
||||
+ for _ in 0..slices {
|
||||
+ let mut key = TextInputKey {
|
||||
+ ScanCode: 0,
|
||||
+ UnicodeChar: 0,
|
||||
+ };
|
||||
+
|
||||
+ let status = (self.st.ConsoleIn.ReadKeyStroke)(self.st.ConsoleIn, &mut key);
|
||||
+ if status.is_success() {
|
||||
+ return match key.ScanCode {
|
||||
+ 0 => match key.UnicodeChar {
|
||||
+ 8 => OsKey::Backspace,
|
||||
+ 13 => OsKey::Enter,
|
||||
+ w => match char::from_u32(w as u32) {
|
||||
+ Some(c) => OsKey::Char(c),
|
||||
+ None => OsKey::Other,
|
||||
+ },
|
||||
+ },
|
||||
+ 1 => OsKey::Up,
|
||||
+ 2 => OsKey::Down,
|
||||
+ 3 => OsKey::Right,
|
||||
+ 4 => OsKey::Left,
|
||||
+ 8 => OsKey::Delete,
|
||||
+ _ => OsKey::Other,
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ let _ = status_to_result((self.st.BootServices.Stall)(100_000));
|
||||
+ }
|
||||
+
|
||||
+ OsKey::Timeout
|
||||
+ }
|
||||
+
|
||||
fn clear_text(&self) {
|
||||
//TODO: why does this sometimes return InvalidParameter, but otherwise appear to work?
|
||||
let _ = status_to_result((self.st.ConsoleOut.ClearScreen)(self.st.ConsoleOut));
|
||||
diff --git a/src/os/uefi/video_mode.rs b/src/os/uefi/video_mode.rs
|
||||
index b6e020a..364dfbc 100644
|
||||
--- a/src/os/uefi/video_mode.rs
|
||||
+++ b/src/os/uefi/video_mode.rs
|
||||
@@ -2,8 +2,8 @@ use core::ptr;
|
||||
use log::error;
|
||||
use uefi::status::Status;
|
||||
|
||||
-use crate::os::OsVideoMode;
|
||||
use crate::os::uefi::display::Output;
|
||||
+use crate::os::OsVideoMode;
|
||||
|
||||
pub struct VideoModeIter {
|
||||
output_opt: Option<Output>,
|
||||
@@ -1,97 +0,0 @@
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index b2e2736..a6a9474 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -500,36 +500,63 @@ pub extern "C" fn main() -> ! {
|
||||
|
||||
print!("live: 0/{} MiB", size / MIBI as u64);
|
||||
|
||||
- let ptr = os.alloc_zeroed_page_aligned(size as usize);
|
||||
- if ptr.is_null() {
|
||||
- panic!("Failed to allocate memory for live");
|
||||
- }
|
||||
-
|
||||
- let live = unsafe { slice::from_raw_parts_mut(ptr, size as usize) };
|
||||
-
|
||||
- let mut i = 0;
|
||||
- for chunk in live.chunks_mut(MIBI) {
|
||||
- print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
- i += unsafe {
|
||||
- fs.disk
|
||||
- .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
- .expect("Failed to read live disk") as u64
|
||||
- };
|
||||
- }
|
||||
- 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)));
|
||||
- }
|
||||
+ let live_size = match usize::try_from(size) {
|
||||
+ Ok(live_size) => live_size,
|
||||
+ Err(_) => {
|
||||
+ println!("\rlive: disabled (image too large for bootloader address space)");
|
||||
+ live = false;
|
||||
+ 0
|
||||
+ }
|
||||
+ };
|
||||
|
||||
- area_add(OsMemoryEntry {
|
||||
- base: live.as_ptr() as u64,
|
||||
- size: live.len() as u64,
|
||||
- kind: OsMemoryKind::Reserved,
|
||||
- });
|
||||
+ let ptr = if live {
|
||||
+ os.alloc_zeroed_page_aligned(live_size)
|
||||
+ } else {
|
||||
+ ptr::null_mut()
|
||||
+ };
|
||||
+
|
||||
+ if live && ptr.is_null() {
|
||||
+ println!(
|
||||
+ "\rlive: disabled (unable to allocate {} MiB upfront)",
|
||||
+ size / MIBI as u64
|
||||
+ );
|
||||
+ live = false;
|
||||
+ }
|
||||
+
|
||||
+ let live = if live {
|
||||
+ Some(unsafe { slice::from_raw_parts_mut(ptr, live_size) })
|
||||
+ } else {
|
||||
+ println!("Continuing without live preload");
|
||||
+ None
|
||||
+ };
|
||||
+
|
||||
+ if let Some(live) = live {
|
||||
+ let mut i = 0;
|
||||
+ for chunk in live.chunks_mut(MIBI) {
|
||||
+ print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
+ i += unsafe {
|
||||
+ fs.disk
|
||||
+ .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
+ .expect("Failed to read live disk") as u64
|
||||
+ };
|
||||
+ }
|
||||
+ 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, live_size)));
|
||||
+ }
|
||||
+
|
||||
+ area_add(OsMemoryEntry {
|
||||
+ base: live.as_ptr() as u64,
|
||||
+ size: live.len() as u64,
|
||||
+ kind: OsMemoryKind::Reserved,
|
||||
+ });
|
||||
+
|
||||
+ Some(live)
|
||||
+ } else {
|
||||
+ None
|
||||
+ }
|
||||
-
|
||||
- Some(live)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -1,392 +0,0 @@
|
||||
diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs
|
||||
index bda3f5d..55889df 100644
|
||||
--- a/src/arch/x86/mod.rs
|
||||
+++ b/src/arch/x86/mod.rs
|
||||
@@ -3,10 +3,15 @@ use crate::os::Os;
|
||||
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)
|
||||
}
|
||||
diff --git a/src/arch/x86/x64.rs b/src/arch/x86/x64.rs
|
||||
index a0a275a..fcf309d 100644
|
||||
--- a/src/arch/x86/x64.rs
|
||||
+++ b/src/arch/x86/x64.rs
|
||||
@@ -29,7 +29,12 @@ const PRESENT: u64 = 1;
|
||||
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 @@ pub unsafe fn paging_create(os: &impl Os, kernel_phys: u64, kernel_size: u64) -
|
||||
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() {
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 78dabb0..fd8eb81 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -62,6 +62,10 @@ pub static mut KERNEL_64BIT: bool = false;
|
||||
|
||||
pub static mut LIVE_OPT: Option<(u64, &'static [u8])> = None;
|
||||
|
||||
+fn region_end(base: u64, size: u64) -> u64 {
|
||||
+ base.saturating_add(size).next_multiple_of(0x1000)
|
||||
+}
|
||||
+
|
||||
struct SliceWriter<'a> {
|
||||
slice: &'a mut [u8],
|
||||
i: usize,
|
||||
@@ -645,9 +649,6 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
(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);
|
||||
@@ -655,6 +656,28 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
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 {
|
||||
slice: unsafe { slice::from_raw_parts_mut(env_base, max_env_size) },
|
||||
diff --git a/src/os/uefi/device.rs b/src/os/uefi/device.rs
|
||||
index 0b7991f..554d88e 100644
|
||||
--- a/src/os/uefi/device.rs
|
||||
+++ b/src/os/uefi/device.rs
|
||||
@@ -13,6 +13,154 @@ use uefi_std::{fs::FileSystem, loaded_image::LoadedImage, proto::Protocol};
|
||||
|
||||
use super::disk::{DiskEfi, DiskOrFileEfi};
|
||||
|
||||
+#[derive(Clone, Copy)]
|
||||
+struct GptPartitionInfo {
|
||||
+ first_lba: u64,
|
||||
+ last_lba: u64,
|
||||
+}
|
||||
+
|
||||
+fn read_u32_le(bytes: &[u8]) -> Option<u32> {
|
||||
+ Some(u32::from_le_bytes(bytes.get(..4)?.try_into().ok()?))
|
||||
+}
|
||||
+
|
||||
+fn read_u64_le(bytes: &[u8]) -> Option<u64> {
|
||||
+ Some(u64::from_le_bytes(bytes.get(..8)?.try_into().ok()?))
|
||||
+}
|
||||
+
|
||||
+fn decode_utf16_name(bytes: &[u8]) -> Option<String> {
|
||||
+ let mut units = Vec::new();
|
||||
+ for chunk in bytes.chunks_exact(2) {
|
||||
+ let unit = u16::from_le_bytes([chunk[0], chunk[1]]);
|
||||
+ if unit == 0 {
|
||||
+ break;
|
||||
+ }
|
||||
+ units.push(unit);
|
||||
+ }
|
||||
+ String::from_utf16(&units).ok()
|
||||
+}
|
||||
+
|
||||
+fn select_partition(best: &mut Option<GptPartitionInfo>, candidate: GptPartitionInfo) {
|
||||
+ match best {
|
||||
+ Some(current) if current.last_lba.saturating_sub(current.first_lba) >= candidate.last_lba.saturating_sub(candidate.first_lba) => {}
|
||||
+ _ => *best = Some(candidate),
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+fn parse_gpt_partition_offset_from_bytes(data: &[u8], block_size: usize) -> Option<u64> {
|
||||
+ let header_offset = block_size;
|
||||
+ let header = data.get(header_offset..header_offset + 92)?;
|
||||
+ if header.get(..8)? != b"EFI PART" {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let entries_lba = read_u64_le(header.get(72..80)?)?;
|
||||
+ let entry_count = read_u32_le(header.get(80..84)?)? as usize;
|
||||
+ let entry_size = read_u32_le(header.get(84..88)?)? as usize;
|
||||
+ if entry_size < 128 {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let entries_offset = entries_lba.checked_mul(block_size as u64)? as usize;
|
||||
+ let mut redox_partition = None;
|
||||
+ let mut fallback_partition = None;
|
||||
+
|
||||
+ for index in 0..entry_count {
|
||||
+ let entry_offset = entries_offset.checked_add(index.checked_mul(entry_size)?)?;
|
||||
+ let entry = data.get(entry_offset..entry_offset + entry_size)?;
|
||||
+ if entry.get(..16)?.iter().all(|byte| *byte == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ let first_lba = read_u64_le(entry.get(32..40)?)?;
|
||||
+ let last_lba = read_u64_le(entry.get(40..48)?)?;
|
||||
+ if first_lba == 0 || last_lba < first_lba {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ let partition = GptPartitionInfo { first_lba, last_lba };
|
||||
+ let name = decode_utf16_name(entry.get(56..128)?).unwrap_or_default();
|
||||
+ if name == "REDOX" {
|
||||
+ redox_partition = Some(partition);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ select_partition(&mut fallback_partition, partition);
|
||||
+ }
|
||||
+
|
||||
+ redox_partition
|
||||
+ .or(fallback_partition)
|
||||
+ .map(|partition| partition.first_lba * block_size as u64)
|
||||
+}
|
||||
+
|
||||
+fn parse_gpt_partition_offset_from_parts(
|
||||
+ entries: &[u8],
|
||||
+ entry_count: usize,
|
||||
+ entry_size: usize,
|
||||
+ block_size: usize,
|
||||
+) -> Option<u64> {
|
||||
+ let mut redox_partition = None;
|
||||
+ let mut fallback_partition = None;
|
||||
+
|
||||
+ for index in 0..entry_count {
|
||||
+ let entry_offset = index.checked_mul(entry_size)?;
|
||||
+ let entry = entries.get(entry_offset..entry_offset + entry_size)?;
|
||||
+ if entry.get(..16)?.iter().all(|byte| *byte == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ let first_lba = read_u64_le(entry.get(32..40)?)?;
|
||||
+ let last_lba = read_u64_le(entry.get(40..48)?)?;
|
||||
+ if first_lba == 0 || last_lba < first_lba {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ let partition = GptPartitionInfo { first_lba, last_lba };
|
||||
+ let name = decode_utf16_name(entry.get(56..128)?).unwrap_or_default();
|
||||
+ if name == "REDOX" {
|
||||
+ redox_partition = Some(partition);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ select_partition(&mut fallback_partition, partition);
|
||||
+ }
|
||||
+ redox_partition
|
||||
+ .or(fallback_partition)
|
||||
+ .map(|partition| partition.first_lba * block_size as u64)
|
||||
+}
|
||||
+
|
||||
+fn gpt_partition_offset_from_buffer(data: &[u8]) -> Option<u64> {
|
||||
+ parse_gpt_partition_offset_from_bytes(data, 512)
|
||||
+}
|
||||
+
|
||||
+fn gpt_partition_offset_from_disk(disk: &mut DiskEfi) -> Option<u64> {
|
||||
+ const GPT_SECTOR_SIZE: usize = 512;
|
||||
+
|
||||
+ if disk.media_block_size() == 0 {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let mut boot_region = vec![0_u8; 2048];
|
||||
+ disk.read_bytes(0, &mut boot_region).ok()?;
|
||||
+ let header = boot_region.get(GPT_SECTOR_SIZE..GPT_SECTOR_SIZE + 92)?;
|
||||
+ if header.get(..8)? != b"EFI PART" {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let entries_lba = read_u64_le(header.get(72..80)?)?;
|
||||
+ let entry_count = read_u32_le(header.get(80..84)?)? as usize;
|
||||
+ let entry_size = read_u32_le(header.get(84..88)?)? as usize;
|
||||
+ if entry_size < 128 {
|
||||
+ return None;
|
||||
+ }
|
||||
+
|
||||
+ let entries_bytes = entry_count.checked_mul(entry_size)?;
|
||||
+ let entries_offset = entries_lba.checked_mul(GPT_SECTOR_SIZE as u64)?;
|
||||
+ let mut entries = vec![0_u8; entries_bytes];
|
||||
+ disk.read_bytes(entries_offset, &mut entries).ok()?;
|
||||
+
|
||||
+ parse_gpt_partition_offset_from_parts(&entries, entry_count, entry_size, GPT_SECTOR_SIZE)
|
||||
+}
|
||||
+
|
||||
#[derive(Debug)]
|
||||
enum DevicePathRelation {
|
||||
This,
|
||||
@@ -131,12 +285,7 @@ pub fn disk_device_priority() -> Vec<DiskDevice> {
|
||||
return vec![DiskDevice {
|
||||
handle: esp_handle,
|
||||
// Support both a copy of livedisk.iso and a standalone redoxfs partition
|
||||
- partition_offset: if &buffer[512..520] == b"EFI PART" {
|
||||
- //TODO: get block from partition table
|
||||
- 2 * crate::MIBI as u64
|
||||
- } else {
|
||||
- 0
|
||||
- },
|
||||
+ partition_offset: gpt_partition_offset_from_buffer(&buffer).unwrap_or(0),
|
||||
disk: DiskOrFileEfi::File(buffer),
|
||||
device_path: esp_device_path,
|
||||
file_path: Some("redox-live.iso"),
|
||||
@@ -154,7 +303,7 @@ pub fn disk_device_priority() -> Vec<DiskDevice> {
|
||||
};
|
||||
let mut devices = Vec::with_capacity(handles.len());
|
||||
for handle in handles {
|
||||
- let disk = match DiskEfi::handle_protocol(handle) {
|
||||
+ let mut disk = match DiskEfi::handle_protocol(handle) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
log::warn!(
|
||||
@@ -182,14 +331,15 @@ pub fn disk_device_priority() -> Vec<DiskDevice> {
|
||||
}
|
||||
};
|
||||
|
||||
+ let partition_offset = if disk.0.Media.LogicalPartition {
|
||||
+ 0
|
||||
+ } else {
|
||||
+ gpt_partition_offset_from_disk(&mut disk).unwrap_or(2 * crate::MIBI as u64)
|
||||
+ };
|
||||
+
|
||||
devices.push(DiskDevice {
|
||||
handle,
|
||||
- partition_offset: if disk.0.Media.LogicalPartition {
|
||||
- 0
|
||||
- } else {
|
||||
- //TODO: get block from partition table
|
||||
- 2 * crate::MIBI as u64
|
||||
- },
|
||||
+ partition_offset,
|
||||
disk: DiskOrFileEfi::Disk(disk),
|
||||
device_path,
|
||||
file_path: None,
|
||||
diff --git a/src/os/uefi/disk.rs b/src/os/uefi/disk.rs
|
||||
index 3f920bb..4d109f8 100644
|
||||
--- a/src/os/uefi/disk.rs
|
||||
+++ b/src/os/uefi/disk.rs
|
||||
@@ -117,3 +117,43 @@ impl Disk for DiskEfi {
|
||||
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(())
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs
|
||||
index c79266e..86235a4 100644
|
||||
--- a/src/os/uefi/mod.rs
|
||||
+++ b/src/os/uefi/mod.rs
|
||||
@@ -47,17 +47,19 @@ pub(crate) fn alloc_zeroed_page_aligned(size: usize) -> *mut u8 {
|
||||
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, // AllocateAnyPages
|
||||
+ MemoryType::EfiLoaderData,
|
||||
pages,
|
||||
&mut ptr,
|
||||
))
|
||||
- .unwrap();
|
||||
+ .is_err()
|
||||
+ {
|
||||
+ return ptr::null_mut();
|
||||
+ }
|
||||
ptr as *mut u8
|
||||
};
|
||||
|
||||
- assert!(!ptr.is_null());
|
||||
unsafe { ptr::write_bytes(ptr, 0, pages * page_size) };
|
||||
ptr
|
||||
}
|
||||
@@ -1,196 +1,13 @@
|
||||
diff --git a/src/main.rs b/src/main.rs
|
||||
index 542b059..adc8da3 100644
|
||||
--- a/src/main.rs
|
||||
+++ b/src/main.rs
|
||||
@@ -10,6 +10,7 @@ extern crate uefi_std as std;
|
||||
use alloc::{format, string::String, vec::Vec};
|
||||
use core::{
|
||||
cmp,
|
||||
+ convert::TryFrom,
|
||||
fmt::{self, Write},
|
||||
mem, ptr, slice, str,
|
||||
};
|
||||
@@ -62,6 +63,10 @@ pub static mut KERNEL_64BIT: bool = false;
|
||||
|
||||
pub static mut LIVE_OPT: Option<(u64, &'static [u8])> = None;
|
||||
|
||||
+fn region_end(base: u64, size: u64) -> u64 {
|
||||
+ base.saturating_add(size).next_multiple_of(0x1000)
|
||||
+}
|
||||
+
|
||||
struct SliceWriter<'a> {
|
||||
slice: &'a mut [u8],
|
||||
i: usize,
|
||||
@@ -114,6 +119,10 @@ fn select_mode(
|
||||
live: &mut bool,
|
||||
edit_env: &mut bool,
|
||||
) -> Option<OsVideoMode> {
|
||||
+ const DEFAULT_WIDTH: u32 = 1280;
|
||||
+ const DEFAULT_HEIGHT: u32 = 720;
|
||||
+ const AUTOBOOT_SECONDS: usize = 5;
|
||||
+
|
||||
let mut modes = Vec::new();
|
||||
for mode in os.video_modes(output_i) {
|
||||
let mut aspect_w = mode.width;
|
||||
@@ -141,15 +150,26 @@ fn select_mode(
|
||||
// Sort modes by pixel area, reversed
|
||||
modes.sort_by(|a, b| (b.0.width * b.0.height).cmp(&(a.0.width * a.0.height)));
|
||||
|
||||
- // Set selected based on best resolution
|
||||
+ // Set selected based on Red Bear default resolution first, then best resolution fallback
|
||||
print!("Output {}", output_i);
|
||||
let mut selected = modes.first().map_or(0, |x| x.0.id);
|
||||
- if let Some((best_width, best_height)) = os.best_resolution(output_i) {
|
||||
- print!(", best resolution: {}x{}", best_width, best_height);
|
||||
- for (mode, _text) in modes.iter() {
|
||||
- if mode.width == best_width && mode.height == best_height {
|
||||
- selected = mode.id;
|
||||
- break;
|
||||
+ let mut selected_from_default = false;
|
||||
+ for (mode, _text) in modes.iter() {
|
||||
+ if mode.width == DEFAULT_WIDTH && mode.height == DEFAULT_HEIGHT {
|
||||
+ selected = mode.id;
|
||||
+ selected_from_default = true;
|
||||
+ print!(", default resolution: {}x{}", DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if !selected_from_default {
|
||||
+ if let Some((best_width, best_height)) = os.best_resolution(output_i) {
|
||||
+ print!(", best resolution: {}x{}", best_width, best_height);
|
||||
+ for (mode, _text) in modes.iter() {
|
||||
+ if mode.width == best_width && mode.height == best_height {
|
||||
+ selected = mode.id;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,12 +183,19 @@ fn select_mode(
|
||||
println!("Press l to enable live mode");
|
||||
}
|
||||
println!("Press e to edit boot environment");
|
||||
+ println!(
|
||||
+ "Autobooting default mode in {} seconds (press any key to cancel countdown)",
|
||||
+ AUTOBOOT_SECONDS
|
||||
+ );
|
||||
println!();
|
||||
print!(" ");
|
||||
|
||||
let (off_x, off_y) = os.get_text_position();
|
||||
let rows = 12;
|
||||
let mut mode_opt = None;
|
||||
+ let countdown_y = off_y.saturating_sub(2);
|
||||
+ let mut countdown = AUTOBOOT_SECONDS;
|
||||
+ let mut countdown_active = true;
|
||||
while !modes.is_empty() {
|
||||
let mut row = 0;
|
||||
let mut col = 0;
|
||||
@@ -186,9 +213,38 @@ fn select_mode(
|
||||
row += 1;
|
||||
}
|
||||
|
||||
+ os.set_text_position(0, countdown_y);
|
||||
+ os.set_text_highlight(false);
|
||||
+ if countdown_active {
|
||||
+ println!(
|
||||
+ "Autobooting default mode in {} seconds (press any key to cancel countdown)",
|
||||
+ countdown
|
||||
+ );
|
||||
+ } else {
|
||||
+ println!("Manual mode selection active. Press Enter to boot selected mode. ");
|
||||
+ }
|
||||
+
|
||||
// Read keypress
|
||||
- match os.get_key() {
|
||||
+ match if countdown_active {
|
||||
+ os.get_key_timeout(1000)
|
||||
+ } else {
|
||||
+ os.get_key()
|
||||
+ } {
|
||||
+ OsKey::Timeout => {
|
||||
+ if countdown_active {
|
||||
+ if countdown == 0 {
|
||||
+ if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
+ if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
+ mode_opt = Some(*mode);
|
||||
+ }
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ countdown = countdown.saturating_sub(1);
|
||||
+ }
|
||||
+ }
|
||||
OsKey::Left => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if mode_i < rows {
|
||||
while mode_i < modes.len() {
|
||||
@@ -202,6 +258,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Right => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
mode_i += rows;
|
||||
if mode_i >= modes.len() {
|
||||
@@ -213,6 +270,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Up => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if mode_i % rows == 0 {
|
||||
mode_i += rows;
|
||||
@@ -227,6 +285,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Down => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mut mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
mode_i += 1;
|
||||
if mode_i % rows == 0 {
|
||||
@@ -241,6 +300,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Enter => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
mode_opt = Some(*mode);
|
||||
@@ -249,6 +309,7 @@ fn select_mode(
|
||||
break;
|
||||
}
|
||||
OsKey::Char('l') => {
|
||||
+ countdown_active = false;
|
||||
*live = !*live;
|
||||
os.set_text_position(live_mode.0, live_mode.1);
|
||||
if *live {
|
||||
@@ -258,6 +319,7 @@ fn select_mode(
|
||||
}
|
||||
}
|
||||
OsKey::Char('e') => {
|
||||
+ countdown_active = false;
|
||||
if let Some(mode_i) = modes.iter().position(|x| x.0.id == selected) {
|
||||
if let Some((mode, _text)) = modes.get(mode_i) {
|
||||
*edit_env = true;
|
||||
@@ -266,7 +328,9 @@ fn select_mode(
|
||||
}
|
||||
break;
|
||||
}
|
||||
- _ => (),
|
||||
+ OsKey::Other | OsKey::Backspace | OsKey::Delete | OsKey::Char(_) => {
|
||||
+ countdown_active = false;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,38 +560,84 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
@@ -556,9 +556,21 @@
|
||||
let live_opt = if live {
|
||||
let size = fs.header.size();
|
||||
|
||||
- print!("live: 0/{} MiB", size / MIBI as u64);
|
||||
+ let max_preload: u64 = 1024 * MIBI as u64; // Cap live preload at 1 GiB
|
||||
-
|
||||
- let live_size = match usize::try_from(size) {
|
||||
+ let max_preload: u64 = 1024 * MIBI as u64;
|
||||
+ let preload_size = if size > max_preload {
|
||||
+ println!(
|
||||
+ "live: filesystem is {} MiB, capping preload at {} MiB",
|
||||
@@ -201,71 +18,26 @@ index 542b059..adc8da3 100644
|
||||
+ } else {
|
||||
+ size
|
||||
+ };
|
||||
|
||||
- let ptr = os.alloc_zeroed_page_aligned(size as usize);
|
||||
- if ptr.is_null() {
|
||||
- panic!("Failed to allocate memory for live");
|
||||
- }
|
||||
+
|
||||
+ print!("live: 0/{} MiB", preload_size / MIBI as u64);
|
||||
|
||||
- let live = unsafe { slice::from_raw_parts_mut(ptr, size as usize) };
|
||||
+
|
||||
+ let live_size = match usize::try_from(preload_size) {
|
||||
+ Ok(live_size) => live_size,
|
||||
+ Err(_) => {
|
||||
+ println!("\rlive: disabled (image too large for bootloader address space)");
|
||||
+ live = false;
|
||||
+ 0
|
||||
+ }
|
||||
+ };
|
||||
|
||||
- let mut i = 0;
|
||||
- for chunk in live.chunks_mut(MIBI) {
|
||||
- print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
- i += unsafe {
|
||||
- fs.disk
|
||||
- .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
- .expect("Failed to read live disk") as u64
|
||||
- };
|
||||
+ let ptr = if live {
|
||||
+ os.alloc_zeroed_page_aligned(live_size)
|
||||
+ } else {
|
||||
+ ptr::null_mut()
|
||||
+ };
|
||||
+ if live && ptr.is_null() {
|
||||
+ println!(
|
||||
+ "\rlive: disabled (unable to allocate {} MiB upfront)",
|
||||
+ size / MIBI as u64
|
||||
+ );
|
||||
+ live = false;
|
||||
}
|
||||
- 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)));
|
||||
- }
|
||||
+ let live = if live {
|
||||
+ Some(unsafe { slice::from_raw_parts_mut(ptr, live_size) })
|
||||
+ } else {
|
||||
+ println!("Continuing without live preload");
|
||||
+ None
|
||||
+ };
|
||||
|
||||
- area_add(OsMemoryEntry {
|
||||
- base: live.as_ptr() as u64,
|
||||
- size: live.len() as u64,
|
||||
- kind: OsMemoryKind::Reserved,
|
||||
- });
|
||||
+ if let Some(live) = live {
|
||||
+ let mut i = 0;
|
||||
+ for chunk in live.chunks_mut(MIBI) {
|
||||
Ok(live_size) => live_size,
|
||||
Err(_) => {
|
||||
println!("\rlive: disabled (image too large for bootloader address space)");
|
||||
@@ -590,14 +602,23 @@
|
||||
if let Some(live) = live {
|
||||
let mut i = 0;
|
||||
for chunk in live.chunks_mut(MIBI) {
|
||||
- print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
+ print!("\rlive: {}/{} MiB", i / MIBI as u64, preload_size / MIBI as u64);
|
||||
+ i += unsafe {
|
||||
+ fs.disk
|
||||
+ .read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
+ .expect("Failed to read live disk") as u64
|
||||
+ };
|
||||
+ }
|
||||
i += unsafe {
|
||||
fs.disk
|
||||
.read_at(fs.block + i / redoxfs::BLOCK_SIZE, chunk)
|
||||
.expect("Failed to read live disk") as u64
|
||||
};
|
||||
}
|
||||
- println!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||
+ println!("\rlive: {}/{} MiB", i / MIBI as u64, preload_size / MIBI as u64);
|
||||
+
|
||||
+ if preload_size < size {
|
||||
@@ -276,61 +48,6 @@ index 542b059..adc8da3 100644
|
||||
+ (size - preload_size) / MIBI as u64
|
||||
+ );
|
||||
+ }
|
||||
+ println!("Switching to live disk");
|
||||
+ unsafe {
|
||||
+ LIVE_OPT = Some((fs.block, slice::from_raw_parts_mut(ptr, live_size)));
|
||||
+ }
|
||||
+
|
||||
+ area_add(OsMemoryEntry {
|
||||
+ base: live.as_ptr() as u64,
|
||||
+ size: live.len() as u64,
|
||||
+ kind: OsMemoryKind::Reserved,
|
||||
+ });
|
||||
|
||||
- Some(live)
|
||||
+ Some(live)
|
||||
+ } else {
|
||||
+ None
|
||||
+ }
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -555,9 +665,6 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
(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);
|
||||
@@ -565,6 +672,28 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||
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 {
|
||||
slice: unsafe { slice::from_raw_parts_mut(env_base, max_env_size) },
|
||||
println!("Switching to live disk");
|
||||
unsafe {
|
||||
|
||||
+15
-23
@@ -1,22 +1,15 @@
|
||||
diff --git a/src/os/uefi/device.rs b/src/os/uefi/device.rs
|
||||
index 4b0bf31..90a97b8 100644
|
||||
--- a/src/os/uefi/device.rs
|
||||
+++ b/src/os/uefi/device.rs
|
||||
@@ -46,6 +46,8 @@ fn device_path_relation(a_path: &DevicePath, b_path: &DevicePath) -> DevicePath
|
||||
}
|
||||
|
||||
fn esp_live_image(esp_handle: Handle, esp_device_path: &DevicePath) -> Option<Vec<u8>> {
|
||||
+ const MAX_LIVE_IMAGE_PRELOAD: usize = 128 * 1024 * 1024;
|
||||
+
|
||||
let mut esp_fs = match FileSystem::handle_protocol(esp_handle) {
|
||||
Ok(esp_fs) => esp_fs,
|
||||
Err(err) => {
|
||||
@@ -87,8 +89,36 @@ fn esp_live_image(esp_handle: Handle, esp_device_path: &DevicePath) -> Option<V
|
||||
@@ -228,8 +228,38 @@
|
||||
};
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
-
|
||||
- live_image.read_to_end(&mut buffer).unwrap();
|
||||
+ let mut chunk = [0_u8; 64 * 1024];
|
||||
+
|
||||
+ const MAX_LIVE_IMAGE_PRELOAD: usize = 128 * 1024 * 1024;
|
||||
+
|
||||
+ loop {
|
||||
+ let read = match live_image.read(&mut chunk) {
|
||||
+ Ok(read) => read,
|
||||
@@ -33,8 +26,7 @@ index 4b0bf31..90a97b8 100644
|
||||
+ if read == 0 {
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- live_image.read_to_end(&mut buffer).unwrap();
|
||||
+
|
||||
+ if buffer.len().saturating_add(read) > MAX_LIVE_IMAGE_PRELOAD {
|
||||
+ log::warn!(
|
||||
+ "Skipping {}\\redox-live.iso preload: file exceeds {} MiB safety limit",
|
||||
@@ -49,12 +41,12 @@ index 4b0bf31..90a97b8 100644
|
||||
|
||||
Some(buffer)
|
||||
}
|
||||
@@ -130,7 +160,7 @@ pub fn disk_device_priority() -> Vec<DiskDevice> {
|
||||
return vec![DiskDevice {
|
||||
handle: esp_handle,
|
||||
// Support both a copy of livedisk.iso and a standalone redoxfs partition
|
||||
- partition_offset: if &buffer[512..520] == b"EFI PART" {
|
||||
+ partition_offset: if buffer.len() >= 520 && &buffer[512..520] == b"EFI PART" {
|
||||
//TODO: get block from partition table
|
||||
2 * crate::MIBI as u64
|
||||
} else {
|
||||
@@ -267,7 +297,7 @@
|
||||
|
||||
if cfg!(feature = "live") {
|
||||
if let Some(buffer) = esp_live_image(esp_handle, esp_device_path.0) {
|
||||
- let partition_offset = if buffer.len() > 520 && &buffer[512..520] == b"EFI PART" {
|
||||
+ let partition_offset = if buffer.len() >= 520 && &buffer[512..520] == b"EFI PART" {
|
||||
gpt_find_redoxfs_offset_from_slice(&buffer)
|
||||
} else {
|
||||
0
|
||||
@@ -0,0 +1,215 @@
|
||||
--- 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() {
|
||||
@@ -1 +1 @@
|
||||
../../../local/patches/bootloader/P3-uefi-live-image-safe-read.patch
|
||||
../../../local/patches/bootloader/absorbed/P3-uefi-live-image-safe-read.patch
|
||||
@@ -1 +1 @@
|
||||
../../../local/patches/bootloader/P4-live-large-iso-boot.patch
|
||||
../../../local/patches/bootloader/absorbed/P4-live-large-iso-boot.patch
|
||||
@@ -1,6 +1,6 @@
|
||||
[source]
|
||||
git = "https://gitlab.redox-os.org/redox-os/bootloader.git"
|
||||
patches = ["redox.patch", "fix-uefi-alloc-panic.patch", "P0-gpt-partition-offset.patch"]
|
||||
patches = ["redox.patch", "fix-uefi-alloc-panic.patch", "P0-gpt-partition-offset.patch", "P5-live-preload-cap-1gib.patch"]
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
|
||||
Reference in New Issue
Block a user