Move protocol struct details outside of main crate
This commit is contained in:
Generated
+6
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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<u32> for PixelFormat {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(f: u32) -> Result<Self, Self::Error> {
|
||||
match f {
|
||||
0 => Ok(PixelFormat::PixelRedGreenBlueReserved8BitPerColor),
|
||||
1 => Ok(PixelFormat::PixelBlueGreenRedReserved8BitPerColor),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+3
-2
@@ -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)?;
|
||||
|
||||
+39
-80
@@ -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()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+25
-3
@@ -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<efi::gop::PixelFormat> {
|
||||
use efi::gop::PixelFormat::*;
|
||||
match from {
|
||||
PixelFormat::LfbRgb32 => Some(PixelRedGreenBlueReserved8BitPerColor),
|
||||
PixelFormat::LfbBgr32 => Some(PixelBlueGreenRedReserved8BitPerColor),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn pixel_from_efi(from: efi::gop::PixelFormat) -> Option<PixelFormat> {
|
||||
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<T: LoadProtocol>(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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user