Verified Commit 426fc818 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Select mode based on EDID

parent c7eeb9f2
......@@ -86,7 +86,7 @@ fn main<
M: Iterator<Item=OsMemoryEntry>,
V: Iterator<Item=OsVideoMode>
>(os: &mut dyn Os<D, M, V>) -> (usize, KernelArgs) {
println!("Redox OS Bootloader {}", env!("CARGO_PKG_VERSION"));
println!("Redox OS Bootloader {} on {}", env!("CARGO_PKG_VERSION"), os.name());
let mut fs = os.filesystem();
......@@ -120,6 +120,18 @@ fn main<
// 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
let mut selected = modes.get(0).map_or(0, |x| x.0.id);
if let Some((best_width, best_height)) = os.best_resolution() {
println!("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;
}
}
}
println!();
println!("Arrow keys and enter select mode");
println!();
......@@ -127,8 +139,6 @@ fn main<
let (off_x, off_y) = os.get_text_position();
let rows = 12;
//TODO 0x4F03 VBE function to get current mode
let mut selected = modes.get(0).map_or(0, |x| x.0.id);
let mut mode_opt = None;
while ! modes.is_empty() {
let mut row = 0;
......
......@@ -2,6 +2,7 @@ use alloc::alloc::{alloc_zeroed, Layout};
use core::{
convert::TryFrom,
ptr,
slice,
};
use linked_list_allocator::LockedHeap;
use spin::Mutex;
......@@ -31,8 +32,9 @@ mod vga;
const DISK_BIOS_ADDR: usize = 0x1000; // 4096 bytes, ends at 0x1FFF
const VBE_CARD_INFO_ADDR: usize = 0x2000; // 512 bytes, ends at 0x21FF
const VBE_MODE_INFO_ADDR: usize = 0x2200; // 256 bytes, ends at 0x22FF
const MEMORY_MAP_ADDR: usize = 0x2300; // 24 bytes, ends at 0x2317
const DISK_ADDRESS_PACKET_ADDR: usize = 0x2318; // 16 bytes, ends at 0x2327
const VBE_EDID_ADDR: usize = 0x2300; // 128 bytes, ends at 0x237F
const MEMORY_MAP_ADDR: usize = 0x2380; // 24 bytes, ends at 0x2397
const DISK_ADDRESS_PACKET_ADDR: usize = 0x2398; // 16 bytes, ends at 0x23A7
const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards
const VGA_ADDR: usize = 0xB8000;
......@@ -58,6 +60,10 @@ impl Os<
MemoryMapIter,
VideoModeIter
> for OsBios {
fn name(&self) -> &str {
"x86/BIOS"
}
fn alloc_zeroed_page_aligned(&self, size: usize) -> *mut u8 {
assert!(size != 0);
......@@ -105,6 +111,30 @@ impl Os<
//TODO: check result
}
fn best_resolution(&self) -> Option<(u32, u32)> {
let mut data = ThunkData::new();
data.eax = 0x4F15;
data.ebx = 0x01;
data.ecx = 0;
data.edx = 0;
data.edi = VBE_EDID_ADDR as u32;
unsafe { data.with(self.thunk10); }
if data.eax == 0x4F {
let edid = unsafe {
slice::from_raw_parts(VBE_EDID_ADDR as *const u8, 128)
};
Some((
(edid[0x38] as u32) | (((edid[0x3A] as u32) & 0xF0) << 4),
(edid[0x3B] as u32) | (((edid[0x3D] as u32) & 0xF0) << 4),
))
} else {
log::warn!("Failed to get VBE EDID: 0x{:X}", data.eax);
None
}
}
fn get_key(&self) -> OsKey {
// Read keypress
let mut data = ThunkData::new();
......
......@@ -51,6 +51,8 @@ pub trait Os<
M: Iterator<Item=OsMemoryEntry>,
V: Iterator<Item=OsVideoMode>
> {
fn name(&self) -> &str;
fn alloc_zeroed_page_aligned(&self, size: usize) -> *mut u8;
fn page_size(&self) -> usize;
......@@ -61,6 +63,7 @@ pub trait Os<
fn video_modes(&self) -> V;
fn set_video_mode(&self, mode: &mut OsVideoMode);
fn best_resolution(&self) -> Option<(u32, u32)>;
fn get_key(&self) -> OsKey;
......
use core::{mem, ops::{ControlFlow, Try}, ptr};
use core::{mem, ops::{ControlFlow, Try}, ptr, slice};
use std::proto::Protocol;
use std::vec::Vec;
use uefi::status::{Result, Status};
......@@ -17,7 +17,7 @@ use crate::{
use super::super::{
disk::DiskEfi,
display::Output,
display::{EdidDiscovered, Output},
};
use self::memory_map::{MemoryMapIter, memory_map};
......@@ -135,6 +135,10 @@ impl Os<
MemoryMapIter,
VideoModeIter
> for OsEfi {
fn name(&self) -> &str {
"x86_64/UEFI"
}
fn alloc_zeroed_page_aligned(&self, size: usize) -> *mut u8 {
assert!(size != 0);
......@@ -200,6 +204,26 @@ impl Os<
mode.base = output.0.Mode.FrameBufferBase as u64;
}
fn best_resolution(&self) -> Option<(u32, u32)> {
//TODO: get this per output
match EdidDiscovered::one() {
Ok(efi_edid) => {
let edid = unsafe {
slice::from_raw_parts(efi_edid.0.Edid, efi_edid.0.SizeOfEdid as usize)
};
Some((
(edid[0x38] as u32) | (((edid[0x3A] as u32) & 0xF0) << 4),
(edid[0x3B] as u32) | (((edid[0x3D] as u32) & 0xF0) << 4),
))
},
Err(err) => {
log::warn!("Failed to get EFI EDID: {:?}", err);
None
}
}
}
fn get_key(&self) -> OsKey {
//TODO: do not unwrap
......
......@@ -13,3 +13,25 @@ impl Protocol<GraphicsOutput> for Output {
Output(inner)
}
}
const EDID_DISCOVERED_PROTOCOL_GUID: Guid = Guid(
0x1c0c34f6, 0xd380, 0x41fa, [0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa]
);
#[repr(C)]
pub struct EdidDiscoveredProtocol {
pub SizeOfEdid: u32,
pub Edid: *const u8,
}
pub struct EdidDiscovered(pub &'static mut EdidDiscoveredProtocol);
impl Protocol<EdidDiscoveredProtocol> for EdidDiscovered {
fn guid() -> Guid {
EDID_DISCOVERED_PROTOCOL_GUID
}
fn new(inner: &'static mut EdidDiscoveredProtocol) -> Self {
EdidDiscovered(inner)
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment