diff --git a/Cargo.lock b/Cargo.lock index 2a00644..a4e3c81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,4 +19,10 @@ dependencies = [ "char16-literal", "core-rt", "efi", + "yboot2-proto", ] + +[[package]] +name = "yboot2-proto" +version = "0.1.0" +source = "git+https://git.alnyan.me/yggdrasil/yboot2-proto.git#fa586d7d0d7664826e344e830554486ba9cec933" diff --git a/Cargo.toml b/Cargo.toml index 9f42997..bfd5383 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ edition = "2018" efi = { path = "crates/efi" } char16-literal = { path = "crates/char16-literal" } core-rt = { path = "crates/core-rt" } +yboot2-proto = { git = "https://git.alnyan.me/yggdrasil/yboot2-proto.git" } diff --git a/crates/efi/src/proto/gop.rs b/crates/efi/src/proto/gop.rs index a949cf2..0b10605 100644 --- a/crates/efi/src/proto/gop.rs +++ b/crates/efi/src/proto/gop.rs @@ -1,6 +1,5 @@ use crate::{Status, Guid}; use crate::proto::Protocol; -use core::convert::TryFrom; use core::ffi::c_void; #[repr(C)] @@ -132,15 +131,3 @@ impl Mode { self.framebuffer_base } } - -impl TryFrom for PixelFormat { - type Error = (); - - fn try_from(f: u32) -> Result { - match f { - 0 => Ok(PixelFormat::PixelRedGreenBlueReserved8BitPerColor), - 1 => Ok(PixelFormat::PixelBlueGreenRedReserved8BitPerColor), - _ => Err(()) - } - } -} diff --git a/src/elf.rs b/src/elf.rs index cb0006b..6f998ea 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1,6 +1,6 @@ use efi::{File, Status, CStr16, MemoryMap}; use core::mem::{MaybeUninit, size_of}; -use crate::proto::LoadProtocol; +use yboot2_proto::LoadProtocol; type Off = u64; type Addr = u64; diff --git a/src/main.rs b/src/main.rs index f870ba5..2584502 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ extern crate efi; extern crate core_rt; extern crate char16_literal; +extern crate yboot2_proto; pub (crate) use char16_literal::cstr16; use efi::{ @@ -16,6 +17,7 @@ use efi::{ system_table, image_handle, }; +use yboot2_proto::LoadProtocol; #[macro_use] mod println; @@ -55,14 +57,13 @@ fn main() -> efi::Result<()> { &obj)?; // Set video mode - use proto::LoadProtocol; data.set_initrd(initrd_base, initrd_size); data.set_acpi_rsdp(rsdp.unwrap_or(core::ptr::null_mut()) as usize); data.set_loader_magic(); // Get the new memory map and terminate boot services bs.get_memory_map(&mut mmap)?; - data.set_mmap(&mmap); + data.set_efi_mmap(&mmap); video::set_mode(bs, data)?; bs.exit_boot_services(mmap.key)?; diff --git a/src/proto.rs b/src/proto.rs index 12b343a..a87601c 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -1,65 +1,15 @@ use core::convert::TryInto; -use efi::{MemoryMap, gop::PixelFormat}; +use yboot2_proto::{ + ProtoV1, + LoadProtocol, + PixelFormat, + MemoryMapInfo, + VideoInfo, + VideoRequest +}; -const CMDLINE_SIZE: usize = 256; - -pub trait LoadProtocol: Sized { - const KERNEL_MAGIC: [u8; 8]; - - fn set_loader_magic(&mut self); - fn set_mmap(&mut self, map: &MemoryMap); - fn set_initrd(&mut self, base: usize, size: usize); - fn set_acpi_rsdp(&mut self, rsdp: usize); - fn set_video_info(&mut self, info: &VideoInfo); - fn get_video_request(&self) -> VideoRequest; -} - -pub struct VideoRequest { - pub width: u32, - pub height: u32, - pub format: PixelFormat -} - -pub struct VideoInfo { - pub width: u32, - pub height: u32, - pub format: PixelFormat, - pub framebuffer: usize, - pub pitch: usize -} - -#[repr(C)] -pub struct Header { - kernel_magic: [u8; 8], - loader_magic: [u8; 8] -} - -#[repr(C)] pub struct V1 { - hdr: Header, - - memory_map_data: u64, - memory_map_size: u32, - memory_map_entsize: u32, - - video_width: u32, - video_height: u32, - video_format: u32, - _pad0: u32, - video_framebuffer: u64, - video_pitch: u64, - - elf_symtab_hdr: u64, - elf_symtab_data: u64, - elf_strtab_hdr: u64, - elf_strtab_data: u64, - - initrd_base: u64, - initrd_size: u64, - - rsdp: u64, - - cmdline: [u8; CMDLINE_SIZE] + proto: ProtoV1 } impl LoadProtocol for V1 { @@ -71,15 +21,15 @@ impl LoadProtocol for V1 { const LOADER_MAGIC: [u8; 8] = [ 0x1A, 0x79, 0x9A, 0x0B, 0x70, 0x0B, 0x70, 0x00 ]; - self.hdr.loader_magic = LOADER_MAGIC; + self.proto.hdr.loader_magic = LOADER_MAGIC; } - fn set_mmap(&mut self, map: &MemoryMap) { - let ptr = map.storage_ref.as_ptr(); + fn set_mmap(&mut self, map: &MemoryMapInfo) { + let ptr = map.address as *const u8; if ptr >= 0x100000000 as *const _ { panic!("Memory map pointer crosses 4GiB"); } - if map.size > self.memory_map_size as usize { + if map.size > self.proto.memory_map_size { panic!("Can't fit memory map"); } @@ -87,44 +37,53 @@ impl LoadProtocol for V1 { extern "C" { fn memcpy(dst: *mut u8, src: *const u8, count: usize) -> *mut u8; } - memcpy(self.memory_map_data as *mut _, ptr, map.size); + memcpy(self.proto.memory_map_data as *mut _, ptr, map.size as usize); } - //self.memory_map_data = (map.storage_ref.as_ptr() as usize).try_into().unwrap(); - self.memory_map_size = map.size.try_into().unwrap(); - self.memory_map_entsize = map.descriptor_size.try_into().unwrap(); + self.proto.memory_map_size = map.size; + self.proto.memory_map_entsize = map.entsize; } fn set_initrd(&mut self, base: usize, size: usize) { - if self.initrd_base + self.initrd_size >= 0x100000000 { + if self.proto.initrd_base + self.proto.initrd_size >= 0x100000000 { panic!("Initrd crosses 4GiB"); } - self.initrd_base = base.try_into().unwrap(); - self.initrd_size = size.try_into().unwrap(); + self.proto.initrd_base = base.try_into().unwrap(); + self.proto.initrd_size = size.try_into().unwrap(); } fn set_acpi_rsdp(&mut self, rsdp: usize) { - self.rsdp = rsdp.try_into().unwrap(); + self.proto.rsdp = rsdp.try_into().unwrap(); } fn get_video_request(&self) -> VideoRequest { use core::convert::TryFrom; VideoRequest { - width: self.video_width, - height: self.video_height, - format: PixelFormat::try_from(self.video_format).unwrap() + width: self.proto.video_width, + height: self.proto.video_height, + format: PixelFormat::try_from(self.proto.video_format).unwrap() } } fn set_video_info(&mut self, info: &VideoInfo) { - if self.video_framebuffer >= 0x100000000 { + if info.framebuffer >= 0x100000000 { panic!("Video framebuffer address is above 4GiB"); } - self.video_width = info.width; - self.video_height = info.height; - self.video_format = info.format as u32; - self.video_framebuffer = info.framebuffer as u64; - self.video_pitch = info.pitch as u64; + self.proto.video_width = info.width; + self.proto.video_height = info.height; + self.proto.video_format = info.format as u32; + self.proto.video_framebuffer = info.framebuffer as u64; + self.proto.video_pitch = info.pitch as u64; + } +} + +impl V1 { + pub fn set_efi_mmap(&mut self, mmap: &efi::MemoryMap) { + self.set_mmap(&MemoryMapInfo { + address: mmap.storage_ref.as_ptr() as u64, + entsize: mmap.descriptor_size.try_into().unwrap(), + size: mmap.size.try_into().unwrap() + }); } } diff --git a/src/video.rs b/src/video.rs index 028dca6..9130290 100644 --- a/src/video.rs +++ b/src/video.rs @@ -1,12 +1,34 @@ -use crate::proto::{LoadProtocol, VideoRequest, VideoInfo}; +use yboot2_proto::{LoadProtocol, VideoRequest, VideoInfo, PixelFormat}; use efi::{BootServices, Status, GraphicsOutputProtocol, gop::ModeInformation}; +// TODO: "Any" format +// TODO: "Text" format + +fn pixel_to_efi(from: PixelFormat) -> Option { + use efi::gop::PixelFormat::*; + match from { + PixelFormat::LfbRgb32 => Some(PixelRedGreenBlueReserved8BitPerColor), + PixelFormat::LfbBgr32 => Some(PixelBlueGreenRedReserved8BitPerColor), + _ => None + } +} + +fn pixel_from_efi(from: efi::gop::PixelFormat) -> Option { + use efi::gop::PixelFormat::*; + match from { + PixelRedGreenBlueReserved8BitPerColor => Some(PixelFormat::LfbRgb32), + PixelBlueGreenRedReserved8BitPerColor => Some(PixelFormat::LfbBgr32), + _ => None + } +} + fn find_mode(proto: &GraphicsOutputProtocol, req: &VideoRequest) -> Result<(u32, &'static ModeInformation), Status> { + let req_format = pixel_to_efi(req.format).unwrap(); for (num, info) in proto.mode_iter() { if info.horizontal_resolution == req.width && info.vertical_resolution == req.height && - info.pixel_format == req.format { + info.pixel_format == req_format { return Ok((num, info)); } } @@ -24,7 +46,7 @@ pub fn set_mode(bs: &BootServices, data: &mut T) -> Result<(), let info = VideoInfo { width: info.horizontal_resolution, height: info.vertical_resolution, - format: info.pixel_format, + format: pixel_from_efi(info.pixel_format).unwrap(), framebuffer: mode.framebuffer_addr(), pitch: 4 * info.horizontal_resolution as usize };