Start parsing kernel
This commit is contained in:
parent
5a86c41d07
commit
0f2fa36333
169
notes.md
169
notes.md
|
@ -40,3 +40,172 @@ Tons of arch-specific restrictions
|
|||
* Pointers are passed as 32-bit, must be within the first 4G
|
||||
* First 4G of virtual memory must be identity mapped
|
||||
* Kernel virtual address must also be mapped to kernel (normally `0xffff_ffff_8000_0000`)
|
||||
|
||||
## Sample kernel
|
||||
modinfo:
|
||||
```
|
||||
0xffffffff8282b000:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 20
|
||||
value: /boot/kernel/kernel
|
||||
0xffffffff8282b020:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 11
|
||||
value: elf kernel
|
||||
0xffffffff8282b038:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff80200000
|
||||
0xffffffff8282b048:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 32731368
|
||||
0xffffffff8282b058:
|
||||
type: (0x9004) MODINFO_METADATA | MODINFOMD_EFI_MAP
|
||||
len: 6080
|
||||
value: buffer contents omitted
|
||||
0xffffffff8282c820:
|
||||
type: (0x9005) MODINFO_METADATA | MODINFOMD_EFI_FB
|
||||
len: 48
|
||||
value: 0x0000000084000000
|
||||
0xffffffff8282c858:
|
||||
type: (0x800d) MODINFO_METADATA | MODINFOMD_KEYBUF
|
||||
len: 33028
|
||||
value: buffer contents omitted
|
||||
0xffffffff82834968:
|
||||
type: (0x800c) MODINFO_METADATA | MODINFOMD_FW_HANDLE
|
||||
len: 8
|
||||
value: buffer contents omitted
|
||||
0xffffffff82834978:
|
||||
type: (0x9006) MODINFO_METADATA | MODINFOMD_MODULEP
|
||||
len: 8
|
||||
value:
|
||||
0xffffffff82834988:
|
||||
type: (0x8008) MODINFO_METADATA | MODINFOMD_KERNEND
|
||||
len: 8
|
||||
value: 0x0000000002837000
|
||||
0xffffffff82834998:
|
||||
type: (0x8006) MODINFO_METADATA | MODINFOMD_ENVP
|
||||
len: 8
|
||||
value: 0x000000000282a000
|
||||
0xffffffff828349a8:
|
||||
type: (0x8007) MODINFO_METADATA | MODINFOMD_HOWTO
|
||||
len: 4
|
||||
value: 0x20000000
|
||||
0xffffffff828349b8:
|
||||
type: (0x8002) MODINFO_METADATA | MODINFOMD_ELFHDR
|
||||
len: 64
|
||||
value: buffer contents omitted
|
||||
0xffffffff82834a00:
|
||||
type: (0x8005) MODINFO_METADATA | MODINFOMD_DYNAMIC
|
||||
len: 8
|
||||
value: 0xffffffff81600000
|
||||
0xffffffff82834a10:
|
||||
type: (0x8004) MODINFO_METADATA | MODINFOMD_ESYM
|
||||
len: 8
|
||||
value: 0xffffffff821370e8
|
||||
0xffffffff82834a20:
|
||||
type: (0x8003) MODINFO_METADATA | MODINFOMD_SSYM
|
||||
len: 8
|
||||
value: 0xffffffff81e00000
|
||||
0xffffffff82834a30:
|
||||
type: (0x8009) MODINFO_METADATA | MODINFOMD_SHDR
|
||||
len: 3904
|
||||
value: buffer contents omitted
|
||||
0xffffffff82835978:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 20
|
||||
value: /boot/kernel/zfs.ko
|
||||
0xffffffff82835998:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 15
|
||||
value: elf obj module
|
||||
0xffffffff828359b0:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff82138000
|
||||
0xffffffff828359c0:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 6084104
|
||||
0xffffffff828359d0:
|
||||
type: (0x8002) MODINFO_METADATA | MODINFOMD_ELFHDR
|
||||
len: 64
|
||||
value: buffer contents omitted
|
||||
0xffffffff82835a18:
|
||||
type: (0x8009) MODINFO_METADATA | MODINFOMD_SHDR
|
||||
len: 1984
|
||||
value: buffer contents omitted
|
||||
0xffffffff828361e0:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 26
|
||||
value: /boot/kernel/cryptodev.ko
|
||||
0xffffffff82836208:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 15
|
||||
value: elf obj module
|
||||
0xffffffff82836220:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff82706000
|
||||
0xffffffff82836230:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 30680
|
||||
0xffffffff82836240:
|
||||
type: (0x8002) MODINFO_METADATA | MODINFOMD_ELFHDR
|
||||
len: 64
|
||||
value: buffer contents omitted
|
||||
0xffffffff82836288:
|
||||
type: (0x8009) MODINFO_METADATA | MODINFOMD_SHDR
|
||||
len: 1856
|
||||
value: buffer contents omitted
|
||||
0xffffffff828369d0:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 12
|
||||
value: /etc/hostid
|
||||
0xffffffff828369e8:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 9
|
||||
value: hostuuid
|
||||
0xffffffff82836a00:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff8270d7d8
|
||||
0xffffffff82836a10:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 37
|
||||
0xffffffff82836a20:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 14
|
||||
value: /boot/entropy
|
||||
0xffffffff82836a38:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 19
|
||||
value: boot_entropy_cache
|
||||
0xffffffff82836a58:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff8270d7fd
|
||||
0xffffffff82836a68:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 4096
|
||||
0xffffffff82836a78:
|
||||
type: (0x01) MODINFO_NAME
|
||||
len: 6
|
||||
value: TSLOG
|
||||
0xffffffff82836a88:
|
||||
type: (0x02) MODINFO_TYPE
|
||||
len: 11
|
||||
value: TSLOG data
|
||||
0xffffffff82836aa0:
|
||||
type: (0x03) MODINFO_ADDR
|
||||
len: 8
|
||||
value: 0xffffffff8270e7fd
|
||||
0xffffffff82836ab0:
|
||||
type: (0x04) MODINFO_SIZE
|
||||
len: 8
|
||||
value: 1159497
|
||||
```
|
||||
|
|
|
@ -181,8 +181,8 @@ impl Serialize for ModuleInfoValue {
|
|||
/// TODO: figure out how to make this properly typesafe
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleInfoItem {
|
||||
tag: ModuleInfoType,
|
||||
value: ModuleInfoValue,
|
||||
pub tag: ModuleInfoType,
|
||||
pub value: ModuleInfoValue,
|
||||
}
|
||||
|
||||
impl Serialize for ModuleInfoItem {
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -2,10 +2,11 @@
|
|||
#![no_std]
|
||||
|
||||
mod abi;
|
||||
mod object;
|
||||
mod staging;
|
||||
|
||||
use elf::endian::NativeEndian;
|
||||
use log::info;
|
||||
use object::{Kernel, Module};
|
||||
use uefi::{fs::FileSystem, prelude::*};
|
||||
|
||||
#[entry]
|
||||
|
@ -14,8 +15,6 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|||
|
||||
info!("Starting freeloader");
|
||||
|
||||
let staging_buf = staging::allocate_staging(system_table.boot_services());
|
||||
|
||||
let mut esp = FileSystem::new(
|
||||
system_table
|
||||
.boot_services()
|
||||
|
@ -23,18 +22,18 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|||
.expect("Failed to get ESP handle"),
|
||||
);
|
||||
|
||||
let kernel = esp
|
||||
let kernel_data = esp
|
||||
.read(cstr16!("efi\\freebsd\\kernel"))
|
||||
.expect("Failed to read kernel");
|
||||
|
||||
info!("Loaded kernel");
|
||||
info!("Read kernel");
|
||||
|
||||
staging_buf[..kernel.len()].copy_from_slice(&kernel);
|
||||
let kernel = Kernel::from_elf_bytes(&kernel_data);
|
||||
|
||||
let header =
|
||||
elf::ElfBytes::<NativeEndian>::minimal_parse(staging_buf).expect("Failed to parse kernel");
|
||||
|
||||
info!("Kernel is {:?}", header.ehdr.class);
|
||||
info!(
|
||||
"Kernel metadata is {:#?}",
|
||||
kernel.metadata(core::ptr::null::<u8>())
|
||||
);
|
||||
|
||||
loop {
|
||||
system_table.boot_services().stall(10_000_000);
|
||||
|
|
80
src/object.rs
Normal file
80
src/object.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
extern crate alloc;
|
||||
|
||||
use crate::abi::{ModuleInfoItem, ModuleInfoType, ModuleInfoValue, Serialize};
|
||||
use alloc::vec::Vec;
|
||||
use elf::{endian::NativeEndian, ElfBytes};
|
||||
use log::info;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const NATIVE_ELF_MACHINE: u16 = elf::abi::EM_X86_64;
|
||||
|
||||
pub trait Module {
|
||||
/// Associated metadata for this module, including name and type
|
||||
fn metadata(&self, load_address: *const u8) -> Vec<ModuleInfoItem>;
|
||||
}
|
||||
|
||||
pub struct Kernel<'a> {
|
||||
/// Full ELF
|
||||
elf: &'a [u8],
|
||||
/// Parsed ELF
|
||||
parsed: ElfBytes<'a, NativeEndian>,
|
||||
/// Raw ELF header bytes
|
||||
elf_header: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> Kernel<'a> {
|
||||
pub fn from_elf_bytes(elf: &'a [u8]) -> Self {
|
||||
let parsed =
|
||||
elf::ElfBytes::<NativeEndian>::minimal_parse(elf).expect("Failed to parse kernel");
|
||||
info!("Kernel is {:?}", parsed.ehdr.class);
|
||||
if parsed.ehdr.e_machine != NATIVE_ELF_MACHINE {
|
||||
panic!("Kernel has wrong ELF machine");
|
||||
}
|
||||
|
||||
let header_size = match parsed.ehdr.class {
|
||||
elf::file::Class::ELF32 => 0x34,
|
||||
elf::file::Class::ELF64 => 0x40,
|
||||
};
|
||||
let elf_header = &elf[..header_size];
|
||||
|
||||
Self {
|
||||
elf,
|
||||
parsed,
|
||||
elf_header,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Serialize for Kernel<'a> {
|
||||
fn alignment() -> usize {
|
||||
// On some platforms we need to be aligned to a level 2 page
|
||||
2 * 1024 * 1024
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn serialize(&self, out: &mut [u8]) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Module for Kernel<'a> {
|
||||
fn metadata(&self, load_address: *const u8) -> Vec<ModuleInfoItem> {
|
||||
alloc::vec![
|
||||
ModuleInfoItem {
|
||||
tag: ModuleInfoType::Name,
|
||||
value: ModuleInfoValue::StaticString("/boot/kernel/kernel")
|
||||
},
|
||||
ModuleInfoItem {
|
||||
tag: ModuleInfoType::Type,
|
||||
value: ModuleInfoValue::StaticString("elf kernel")
|
||||
},
|
||||
ModuleInfoItem {
|
||||
tag: ModuleInfoType::ElfHeader,
|
||||
value: ModuleInfoValue::Buffer(self.elf_header.to_vec())
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue