Move load protocol impl outside
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
[build]
|
[build]
|
||||||
target = "x86_64-unknown-uefi"
|
target = "x86_64-unknown-uefi"
|
||||||
|
|
||||||
|
[unstable]
|
||||||
|
build-std = ["core"]
|
||||||
|
|
||||||
[target.x86_64-unknown-uefi]
|
[target.x86_64-unknown-uefi]
|
||||||
rustflags = ["-Ccode-model=small", "-Clink-arg=/debug:none"]
|
rustflags = ["-Ccode-model=small", "-Clink-arg=/debug:none"]
|
||||||
|
|||||||
Generated
+1
-1
@@ -25,4 +25,4 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "yboot2-proto"
|
name = "yboot2-proto"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://git.alnyan.me/yggdrasil/yboot2-proto.git#fa586d7d0d7664826e344e830554486ba9cec933"
|
source = "git+https://git.alnyan.me/yggdrasil/yboot2-proto.git#e125ef89d686e6fc1f539d643b24cf54e5f96ea9"
|
||||||
|
|||||||
+4
-1
@@ -10,4 +10,7 @@ edition = "2018"
|
|||||||
efi = { path = "crates/efi" }
|
efi = { path = "crates/efi" }
|
||||||
char16-literal = { path = "crates/char16-literal" }
|
char16-literal = { path = "crates/char16-literal" }
|
||||||
core-rt = { path = "crates/core-rt" }
|
core-rt = { path = "crates/core-rt" }
|
||||||
yboot2-proto = { git = "https://git.alnyan.me/yggdrasil/yboot2-proto.git" }
|
|
||||||
|
[dependencies.yboot2-proto]
|
||||||
|
git = "https://git.alnyan.me/yggdrasil/yboot2-proto.git"
|
||||||
|
features = ["kernel-protocol", "load-protocol"]
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
use efi::{File, Status, CStr16, MemoryMap};
|
use efi::{File, Status, CStr16, MemoryMap};
|
||||||
use core::mem::{MaybeUninit, size_of};
|
use core::mem::{MaybeUninit, size_of};
|
||||||
use yboot2_proto::LoadProtocol;
|
use yboot2_proto::{LoadProtocol, KernelProtocol};
|
||||||
|
|
||||||
type Off = u64;
|
type Off = u64;
|
||||||
type Addr = u64;
|
type Addr = u64;
|
||||||
@@ -121,7 +121,7 @@ impl Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called after load()
|
// Called after load()
|
||||||
pub fn locate_protocol_data<T: LoadProtocol>(&mut self)
|
pub fn locate_protocol_data<T: KernelProtocol + LoadProtocol>(&mut self)
|
||||||
-> Result<&'static mut T, Status>
|
-> Result<&'static mut T, Status>
|
||||||
{
|
{
|
||||||
let mut shdr = unsafe { MaybeUninit::<Shdr>::uninit().assume_init() };
|
let mut shdr = unsafe { MaybeUninit::<Shdr>::uninit().assume_init() };
|
||||||
|
|||||||
+27
-11
@@ -17,15 +17,26 @@ use efi::{
|
|||||||
system_table,
|
system_table,
|
||||||
image_handle,
|
image_handle,
|
||||||
};
|
};
|
||||||
use yboot2_proto::LoadProtocol;
|
use yboot2_proto::{LoadProtocol, ProtoV1, MemoryMapInfo};
|
||||||
|
use core::convert::TryInto;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod println;
|
mod println;
|
||||||
mod initrd;
|
mod initrd;
|
||||||
mod proto;
|
|
||||||
mod video;
|
mod video;
|
||||||
mod elf;
|
mod elf;
|
||||||
|
|
||||||
|
fn set_efi_mmap<T: LoadProtocol>(data: &mut T, mmap: &efi::MemoryMap) -> efi::Result<()> {
|
||||||
|
match data.set_mmap(&MemoryMapInfo {
|
||||||
|
address: mmap.storage_ref.as_ptr() as u64,
|
||||||
|
entsize: mmap.descriptor_size.try_into().unwrap(),
|
||||||
|
size: mmap.size.try_into().unwrap()
|
||||||
|
}) {
|
||||||
|
Err(_) => Err(Status::Err),
|
||||||
|
Ok(()) => Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> efi::Result<()> {
|
fn main() -> efi::Result<()> {
|
||||||
let mut desc_array = [0u8; 16384];
|
let mut desc_array = [0u8; 16384];
|
||||||
let mut mmap = efi::MemoryMap::new(&mut desc_array);
|
let mut mmap = efi::MemoryMap::new(&mut desc_array);
|
||||||
@@ -48,22 +59,27 @@ fn main() -> efi::Result<()> {
|
|||||||
// Load kernel
|
// Load kernel
|
||||||
let mut obj = elf::Object::open(&mut root, CStr16::from_literal(cstr16!(r"\kernel.elf")))?;
|
let mut obj = elf::Object::open(&mut root, CStr16::from_literal(cstr16!(r"\kernel.elf")))?;
|
||||||
let entry = obj.load(&mmap)?;
|
let entry = obj.load(&mmap)?;
|
||||||
let data = obj.locate_protocol_data::<proto::V1>()?;
|
let data = obj.locate_protocol_data::<ProtoV1>()?;
|
||||||
|
|
||||||
// Load initrd
|
if (data.get_flags() & yboot2_proto::FLAG_INITRD) != 0 {
|
||||||
let (initrd_base, initrd_size) = initrd::load_somewhere(&mut root,
|
// Load initrd
|
||||||
CStr16::from_literal(cstr16!(r"\initrd.img")),
|
let (initrd_base, initrd_size) = initrd::load_somewhere(&mut root,
|
||||||
&mmap,
|
CStr16::from_literal(cstr16!(r"\initrd.img")),
|
||||||
&obj)?;
|
&mmap,
|
||||||
|
&obj)?;
|
||||||
|
|
||||||
|
// Set video mode
|
||||||
|
data.set_initrd(initrd_base, initrd_size);
|
||||||
|
} else {
|
||||||
|
data.set_initrd(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Set video mode
|
|
||||||
data.set_initrd(initrd_base, initrd_size);
|
|
||||||
data.set_acpi_rsdp(rsdp.unwrap_or(core::ptr::null_mut()) as usize);
|
data.set_acpi_rsdp(rsdp.unwrap_or(core::ptr::null_mut()) as usize);
|
||||||
data.set_loader_magic();
|
data.set_loader_magic();
|
||||||
|
|
||||||
// Get the new memory map and terminate boot services
|
// Get the new memory map and terminate boot services
|
||||||
bs.get_memory_map(&mut mmap)?;
|
bs.get_memory_map(&mut mmap)?;
|
||||||
data.set_efi_mmap(&mmap);
|
set_efi_mmap(data, &mmap)?;
|
||||||
video::set_mode(bs, data)?;
|
video::set_mode(bs, data)?;
|
||||||
|
|
||||||
bs.exit_boot_services(mmap.key)?;
|
bs.exit_boot_services(mmap.key)?;
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
use core::convert::TryInto;
|
|
||||||
use yboot2_proto::{
|
|
||||||
ProtoV1,
|
|
||||||
LoadProtocol,
|
|
||||||
PixelFormat,
|
|
||||||
MemoryMapInfo,
|
|
||||||
VideoInfo,
|
|
||||||
VideoRequest
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct V1 {
|
|
||||||
proto: ProtoV1
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LoadProtocol for V1 {
|
|
||||||
const KERNEL_MAGIC: [u8; 8] = [
|
|
||||||
0x07, 0xB0, 0x07, 0xB0, 0xA9, 0x97, 0xA1, 0x00
|
|
||||||
];
|
|
||||||
|
|
||||||
fn set_loader_magic(&mut self) {
|
|
||||||
const LOADER_MAGIC: [u8; 8] = [
|
|
||||||
0x1A, 0x79, 0x9A, 0x0B, 0x70, 0x0B, 0x70, 0x00
|
|
||||||
];
|
|
||||||
self.proto.hdr.loader_magic = LOADER_MAGIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.proto.memory_map_size {
|
|
||||||
panic!("Can't fit memory map");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
extern "C" {
|
|
||||||
fn memcpy(dst: *mut u8, src: *const u8, count: usize) -> *mut u8;
|
|
||||||
}
|
|
||||||
memcpy(self.proto.memory_map_data as *mut _, ptr, map.size as usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.proto.initrd_base + self.proto.initrd_size >= 0x100000000 {
|
|
||||||
panic!("Initrd crosses 4GiB");
|
|
||||||
}
|
|
||||||
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.proto.rsdp = rsdp.try_into().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_video_request(&self) -> VideoRequest {
|
|
||||||
use core::convert::TryFrom;
|
|
||||||
VideoRequest {
|
|
||||||
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 info.framebuffer >= 0x100000000 {
|
|
||||||
panic!("Video framebuffer address is above 4GiB");
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+5
-7
@@ -1,4 +1,4 @@
|
|||||||
use yboot2_proto::{LoadProtocol, VideoRequest, VideoInfo, PixelFormat};
|
use yboot2_proto::{LoadProtocol, VideoInfo, video::PixelFormat};
|
||||||
use efi::{BootServices, Status, GraphicsOutputProtocol, gop::ModeInformation};
|
use efi::{BootServices, Status, GraphicsOutputProtocol, gop::ModeInformation};
|
||||||
|
|
||||||
// TODO: "Any" format
|
// TODO: "Any" format
|
||||||
@@ -18,12 +18,11 @@ fn pixel_from_efi(from: efi::gop::PixelFormat) -> Option<PixelFormat> {
|
|||||||
match from {
|
match from {
|
||||||
PixelRedGreenBlueReserved8BitPerColor => Some(PixelFormat::LfbRgb32),
|
PixelRedGreenBlueReserved8BitPerColor => Some(PixelFormat::LfbRgb32),
|
||||||
PixelBlueGreenRedReserved8BitPerColor => Some(PixelFormat::LfbBgr32),
|
PixelBlueGreenRedReserved8BitPerColor => Some(PixelFormat::LfbBgr32),
|
||||||
_ => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_mode(proto: &GraphicsOutputProtocol,
|
fn find_mode(proto: &GraphicsOutputProtocol,
|
||||||
req: &VideoRequest) -> Result<(u32, &'static ModeInformation), Status> {
|
req: &VideoInfo) -> Result<(u32, &'static ModeInformation), Status> {
|
||||||
let req_format = pixel_to_efi(req.format).unwrap();
|
let req_format = pixel_to_efi(req.format).unwrap();
|
||||||
for (num, info) in proto.mode_iter() {
|
for (num, info) in proto.mode_iter() {
|
||||||
if info.horizontal_resolution == req.width &&
|
if info.horizontal_resolution == req.width &&
|
||||||
@@ -36,10 +35,9 @@ fn find_mode(proto: &GraphicsOutputProtocol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mode<T: LoadProtocol>(bs: &BootServices, data: &mut T) -> Result<(), Status> {
|
pub fn set_mode<T: LoadProtocol>(bs: &BootServices, data: &mut T) -> Result<(), Status> {
|
||||||
let req = data.get_video_request();
|
|
||||||
let gop = bs.locate_protocol::<GraphicsOutputProtocol>()?;
|
let gop = bs.locate_protocol::<GraphicsOutputProtocol>()?;
|
||||||
|
|
||||||
match find_mode(gop, &req) {
|
match find_mode(gop, data.get_video_info()) {
|
||||||
Ok((num, info)) => {
|
Ok((num, info)) => {
|
||||||
let mode = gop.set_mode(num)?;
|
let mode = gop.set_mode(num)?;
|
||||||
|
|
||||||
@@ -47,8 +45,8 @@ pub fn set_mode<T: LoadProtocol>(bs: &BootServices, data: &mut T) -> Result<(),
|
|||||||
width: info.horizontal_resolution,
|
width: info.horizontal_resolution,
|
||||||
height: info.vertical_resolution,
|
height: info.vertical_resolution,
|
||||||
format: pixel_from_efi(info.pixel_format).unwrap(),
|
format: pixel_from_efi(info.pixel_format).unwrap(),
|
||||||
framebuffer: mode.framebuffer_addr(),
|
framebuffer: mode.framebuffer_addr() as u64,
|
||||||
pitch: 4 * info.horizontal_resolution as usize
|
pitch: 4 * info.horizontal_resolution as u64
|
||||||
};
|
};
|
||||||
|
|
||||||
data.set_video_info(&info);
|
data.set_video_info(&info);
|
||||||
|
|||||||
Reference in New Issue
Block a user