worked on stuff
This commit is contained in:
parent
ded4ea603e
commit
d5f31ecce7
10 changed files with 250 additions and 127 deletions
|
@ -15,7 +15,6 @@ use core::fmt::Debug;
|
|||
use core::panic::PanicInfo;
|
||||
|
||||
use aphrodite::arch::egatext;
|
||||
use aphrodite::arch::enable_a20;
|
||||
use aphrodite::arch::output::*;
|
||||
use aphrodite::boot::{BootInfo, MemoryMapping};
|
||||
use aphrodite::display::COLOR_DEFAULT;
|
||||
|
@ -27,11 +26,20 @@ use aphrodite::output::*;
|
|||
#[cfg(not(CONFIG_DISABLE_MULTIBOOT2_SUPPORT))]
|
||||
#[unsafe(link_section = ".bootheader")]
|
||||
#[unsafe(no_mangle)]
|
||||
static MULTIBOOT2_HEADER: [u8; 24] = [
|
||||
static MULTIBOOT2_HEADER: [u8; 48] = [
|
||||
0xd6, 0x50, 0x52, 0xe8, // Magic number
|
||||
0x00, 0x00, 0x00, 0x00, // Architecture
|
||||
0x18, 0x00, 0x00, 0x00, // Size
|
||||
0x12, 0xaf, 0xad, 0x17, // Checksum
|
||||
|
||||
0x0A, 0x00, // Relocatable tag
|
||||
0x00, 0x00, // Flags,
|
||||
0x18, 0x00, 0x00, 0x00, // Size of tag
|
||||
0x00, 0x00, 0x00, 0xB0, // Starting minimum location
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // Ending maximum location: End of 32-bit address space
|
||||
0x00, 0x00, 0x00, 0x00, // Image alignment
|
||||
0x01, 0x00, 0x00, 0x00, // Loading preference: lowest possible
|
||||
|
||||
0x00, 0x00, // End tag
|
||||
0x00, 0x00, // Flags
|
||||
0x08, 0x00, 0x00, 0x00, // Size
|
||||
|
@ -85,6 +93,7 @@ extern "C" fn _start() -> ! {
|
|||
memory_map: None,
|
||||
bootloader_name: None,
|
||||
output: None,
|
||||
load_base: None,
|
||||
};
|
||||
unsafe {
|
||||
match MAGIC {
|
||||
|
@ -135,7 +144,7 @@ extern "C" fn _start() -> ! {
|
|||
break;
|
||||
},
|
||||
4 => {
|
||||
// Basic memory information
|
||||
// Basic memory information, ignore
|
||||
if current_tag.tag_len != 16 {
|
||||
// Unexpected size, something is probably up
|
||||
panic!("size of basic memory information tag != 16");
|
||||
|
@ -177,7 +186,7 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
let memorysections: &'static mut [aphrodite::multiboot2::MemorySection] = &mut *core::ptr::from_raw_parts_mut((&mut (*rawmemorymap).sections[0]) as &mut MemorySection, (*rawmemorymap).sections.len());
|
||||
// Above is a bit hard to understand, but what it does is transmute
|
||||
// rawmemorymap's sections into a pointer to those sections.
|
||||
// rawmemorymap's sections into a pointer to those sections
|
||||
|
||||
for ele in &mut *memorysections {
|
||||
(*ele) = core::mem::transmute::<
|
||||
|
@ -252,6 +261,20 @@ extern "C" fn _start() -> ! {
|
|||
};
|
||||
BI.output = Some(&FBI)
|
||||
},
|
||||
21 => {
|
||||
// Image load base physical address
|
||||
if current_tag.tag_len != 12 {
|
||||
panic!("size of image load base physical address tag != 12");
|
||||
}
|
||||
let ptr = (ptr + size_of::<Tag>()) as *const u32;
|
||||
|
||||
sdebugs("ptr: ");
|
||||
sdebugbnp(&aphrodite::usize_as_u8_slice(ptr as usize));
|
||||
sdebugsnp(" value: ");
|
||||
sdebugbnpln(&aphrodite::u32_as_u8_slice(*ptr));
|
||||
|
||||
BI.load_base = Some(*ptr);
|
||||
},
|
||||
_ => {
|
||||
// Unknown/unimplemented tag type, ignore
|
||||
swarnings("Unknown tag type ");
|
||||
|
@ -292,10 +315,7 @@ extern "C" fn _start() -> ! {
|
|||
sdebugsln("Bootloader information has been successfully loaded");
|
||||
sdebugunp(b'\n');
|
||||
|
||||
if !enable_a20() {
|
||||
panic!("failed to enable a20 gate");
|
||||
}
|
||||
initalize_rtc();
|
||||
aphrodite::arch::initalize_rtc();
|
||||
|
||||
unsafe {
|
||||
if BI.output.clone().is_some() {
|
||||
|
@ -318,7 +338,7 @@ extern "C" fn _start() -> ! {
|
|||
|
||||
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
|
||||
framebuffer_info.disable_cursor();
|
||||
ega.clear_screen(COLOR_DEFAULT);
|
||||
ega.clear_screen(COLOR_DEFAULT).unwrap();
|
||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||
toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
|
||||
|
|
|
@ -2,9 +2,25 @@
|
|||
#![cfg(target_arch = "x86")]
|
||||
|
||||
use core::alloc::Layout;
|
||||
use core::arch::asm;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// The GDTR. Used internally in [activate_gdt].
|
||||
#[repr(C, packed)]
|
||||
struct Gdtr {
|
||||
base: *const u8,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
pub unsafe fn activate_gdt(ptr: *const [u8]) {
|
||||
let gdtr = Gdtr {
|
||||
base: ptr as *const u8,
|
||||
size: ptr.len(),
|
||||
};
|
||||
unsafe { asm!("lgdt {}", in(reg) (&gdtr) as *const Gdtr as usize) }
|
||||
}
|
||||
|
||||
/// Writes a series of GDT entries to an allocated section of memory and returns
|
||||
/// a pointer.
|
||||
pub unsafe fn write_gdt_entries(
|
||||
|
@ -34,6 +50,13 @@ pub struct GDTEntry {
|
|||
pub flags: u8,
|
||||
}
|
||||
|
||||
pub const GDT_NULL_ENTRY: GDTEntry = GDTEntry {
|
||||
limit: 0,
|
||||
base: 0,
|
||||
access: 0,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
/// An error returned by [GDTEntry::write_to_addr] when the limit is greater
|
||||
/// than 0xFFFFF.
|
||||
const GDT_WRITE_ADDR_INVALID_LIMIT: i16 = -1;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#![cfg(target_arch = "x86")]
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
use core::alloc::{Allocator, Layout};
|
||||
use core::arch::asm;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
|
@ -70,29 +69,125 @@ struct Idtr {
|
|||
size: usize,
|
||||
}
|
||||
|
||||
unsafe impl Send for Idtr {}
|
||||
unsafe impl Sync for Idtr {}
|
||||
|
||||
/// Loads an interrupt descriptor table.
|
||||
fn load_idt(base: *const u8, size: usize) {
|
||||
static mut IDTR: MaybeUninit<Idtr> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
IDTR.write(Idtr { base, size });
|
||||
}
|
||||
unsafe { asm!("lidt {}", in(reg) IDTR.as_ptr() as usize) }
|
||||
unsafe fn load_idt(base: *const u8, size: usize) {
|
||||
let idtr = Idtr { base, size };
|
||||
unsafe { asm!("lidt {}", in(reg) (&idtr) as *const Idtr as usize) }
|
||||
}
|
||||
|
||||
/// Activate an IDT.
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct IdtEntry {
|
||||
pub offset_high: u16,
|
||||
pub data: u16,
|
||||
pub segment: u16,
|
||||
pub offset_low: u16,
|
||||
pub vector: u16,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct RawIdtEntry {
|
||||
pub offset_high: u16,
|
||||
pub data: u16,
|
||||
pub segment: u16,
|
||||
pub offset_low: u16,
|
||||
}
|
||||
|
||||
impl From<IdtEntry> for RawIdtEntry {
|
||||
fn from(value: IdtEntry) -> Self {
|
||||
RawIdtEntry {
|
||||
offset_high: value.offset_high,
|
||||
data: value.data,
|
||||
segment: value.segment,
|
||||
offset_low: value.offset_low,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Activate an IDT. Requires that all handlers can properly handle the calling
|
||||
/// convention and are in GDT segment 1.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if the global allocator has not been setup
|
||||
#[aphrodite_proc_macros::kernel_item(ActivateIDT)]
|
||||
fn activate_idt(idt: Idt, alloc: crate::mem::MemoryMapAlloc) {
|
||||
let mem = alloc
|
||||
.allocate(unsafe { Layout::from_size_align_unchecked(8 * idt.len, 1) })
|
||||
.unwrap()
|
||||
.as_mut_ptr();
|
||||
fn activate_idt(idt: Idt) {
|
||||
let mut entries = alloc::vec::Vec::new();
|
||||
for i in 0..idt.len {
|
||||
let _vector = idt.vectors[i];
|
||||
let _func = unsafe { idt.funcs[i].assume_init() } as usize as u64;
|
||||
let _user_callable = idt.user_callable[i];
|
||||
if idt.using_raw[i] {
|
||||
entries.push(idt.raw_entries[i]);
|
||||
continue;
|
||||
}
|
||||
let vector = idt.vectors[i];
|
||||
let func = unsafe { idt.funcs[i].assume_init() } as usize as u32;
|
||||
let user_callable = idt.user_callable[i];
|
||||
let exception = idt.exception[i];
|
||||
|
||||
let mut entry = IdtEntry {
|
||||
offset_high: (func & 0xFFFF0000) as u16,
|
||||
data: 0b1000000000000000,
|
||||
segment: 1,
|
||||
offset_low: (func & 0xFFFF) as u16,
|
||||
vector,
|
||||
};
|
||||
if user_callable {
|
||||
entry.data |= 0b110000000000000;
|
||||
}
|
||||
if exception {
|
||||
entry.data |= 0b111100000000;
|
||||
} else {
|
||||
entry.data |= 0b111000000000;
|
||||
}
|
||||
entries.push(entry);
|
||||
}
|
||||
entries.sort_by(|ele1: &IdtEntry, ele2: &IdtEntry| ele1.vector.cmp(&ele2.vector));
|
||||
let mut last_vector = 0u16;
|
||||
let mut start = true;
|
||||
|
||||
let mut entries2 = alloc::vec::Vec::new();
|
||||
|
||||
for entry in &entries {
|
||||
if start {
|
||||
let mut vector = entry.vector;
|
||||
while vector > 0 {
|
||||
entries2.push(IdtEntry {
|
||||
offset_high: 0,
|
||||
data: 0,
|
||||
segment: 0,
|
||||
offset_low: 0,
|
||||
vector: 0,
|
||||
});
|
||||
vector -= 1;
|
||||
}
|
||||
last_vector = entry.vector;
|
||||
entries2.push(*entry);
|
||||
start = false;
|
||||
continue;
|
||||
}
|
||||
if entry.vector - last_vector > 0 {
|
||||
let mut vector = entry.vector - last_vector;
|
||||
while vector > 0 {
|
||||
entries2.push(IdtEntry {
|
||||
offset_high: 0,
|
||||
data: 0,
|
||||
segment: 0,
|
||||
offset_low: 0,
|
||||
vector: 0,
|
||||
});
|
||||
vector -= 1;
|
||||
}
|
||||
}
|
||||
last_vector = entry.vector;
|
||||
entries2.push(*entry);
|
||||
}
|
||||
|
||||
let mut raw_entries: alloc::vec::Vec<RawIdtEntry, _> = alloc::vec::Vec::new();
|
||||
for entry in &entries2 {
|
||||
raw_entries.push(RawIdtEntry::from(*entry));
|
||||
}
|
||||
|
||||
let raw_entries = raw_entries.into_raw_parts();
|
||||
|
||||
unsafe {
|
||||
load_idt(raw_entries.0 as *const u8, (idt.len * 8) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +197,9 @@ pub struct Idt {
|
|||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
user_callable: [bool; 256],
|
||||
exception: [bool; 256],
|
||||
raw_entries: [IdtEntry; 256],
|
||||
using_raw: [bool; 256],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
|
@ -111,6 +209,9 @@ pub struct IdtBuilder {
|
|||
vectors: [u16; 256],
|
||||
funcs: [MaybeUninit<fn()>; 256],
|
||||
user_callable: [bool; 256],
|
||||
exception: [bool; 256],
|
||||
raw_entries: [IdtEntry; 256],
|
||||
using_raw: [bool; 256],
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
|
@ -121,14 +222,38 @@ impl IdtBuilder {
|
|||
vectors: [0; 256],
|
||||
funcs: [MaybeUninit::uninit(); 256],
|
||||
user_callable: [false; 256],
|
||||
exception: [false; 256],
|
||||
raw_entries: [IdtEntry {
|
||||
offset_high: 0,
|
||||
data: 0,
|
||||
segment: 0,
|
||||
offset_low: 0,
|
||||
vector: 0,
|
||||
}; 256],
|
||||
using_raw: [false; 256],
|
||||
idx: 0,
|
||||
}
|
||||
}
|
||||
/// Add a function to this IdtBuilder.
|
||||
pub fn add_fn(&mut self, vector: u16, func: fn(), user_callable: bool) -> &mut Self {
|
||||
pub fn add_fn(
|
||||
&mut self,
|
||||
vector: u16,
|
||||
func: fn(),
|
||||
user_callable: bool,
|
||||
exception: bool,
|
||||
) -> &mut Self {
|
||||
self.vectors[self.idx] = vector;
|
||||
self.funcs[self.idx].write(func);
|
||||
self.user_callable[self.idx] = user_callable;
|
||||
self.exception[self.idx] = exception;
|
||||
self.using_raw[self.idx] = false;
|
||||
self.idx += 1;
|
||||
self
|
||||
}
|
||||
pub fn add_raw(&mut self, vector: u16, raw_entry: IdtEntry) -> &mut Self {
|
||||
self.vectors[self.idx] = vector;
|
||||
self.raw_entries[self.idx] = raw_entry;
|
||||
self.using_raw[self.idx] = true;
|
||||
self.idx += 1;
|
||||
self
|
||||
}
|
||||
|
@ -138,18 +263,14 @@ impl IdtBuilder {
|
|||
vectors: self.vectors,
|
||||
funcs: self.funcs,
|
||||
user_callable: self.user_callable,
|
||||
raw_entries: self.raw_entries,
|
||||
using_raw: self.using_raw,
|
||||
exception: self.exception,
|
||||
len: self.idx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for IdtBuilder {
|
||||
fn default() -> Self {
|
||||
IdtBuilder {
|
||||
vectors: [0; 256],
|
||||
funcs: [MaybeUninit::uninit(); 256],
|
||||
user_callable: [false; 256],
|
||||
idx: 0,
|
||||
}
|
||||
}
|
||||
fn default() -> Self { Self::new() }
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ pub mod ports;
|
|||
|
||||
mod constants;
|
||||
|
||||
use alloc::vec;
|
||||
use constants::*;
|
||||
use gdt::GDTEntry;
|
||||
use interrupts::{pop_irq, restore_irq};
|
||||
use ports::{inb, outb};
|
||||
|
||||
|
@ -77,83 +79,6 @@ pub fn get_keyboard_data() -> u8 { inb(0x60) }
|
|||
/// Sends data to the keyboard.
|
||||
pub fn send_keyboard_data(data: u8) { outb(0x60, data); }
|
||||
|
||||
/// Tries to enable the a20 gate via the keyboard controller method.
|
||||
pub fn enable_a20_keyboard() {
|
||||
let irq = pop_irq();
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_cmd(0xAD); // disable keyboard
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_cmd(0xD0); // read from input
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
wait_for_keyboard_data();
|
||||
let a = get_keyboard_data();
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_cmd(0xD1); // write to output
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_data(a | 2);
|
||||
|
||||
wait_for_keyboard_cmd();
|
||||
send_keyboard_cmd(0xAE); // enable keyboard
|
||||
|
||||
restore_irq(irq);
|
||||
}
|
||||
|
||||
/// Tries to enable the a20 gate via fast a20.
|
||||
/// Note that this may not work or do something unexpected.
|
||||
pub fn enable_a20_fasta20() {
|
||||
let mut a = inb(0x92);
|
||||
if a & 0b10 > 0 {
|
||||
return;
|
||||
}
|
||||
a |= 0b10;
|
||||
a &= 0xFE;
|
||||
outb(0x92, a);
|
||||
}
|
||||
|
||||
/// Tries to enable the a20 gate by reading from port 0xee.
|
||||
pub fn enable_a20_ee_port() { inb(0xee); }
|
||||
|
||||
/// Tries to enable the a20 gate by trying many different methods
|
||||
/// and seeing what sticks.
|
||||
pub fn enable_a20() -> bool {
|
||||
if test_a20() {
|
||||
return true;
|
||||
}
|
||||
|
||||
enable_a20_keyboard();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if test_a20() {
|
||||
return true;
|
||||
}
|
||||
|
||||
enable_a20_ee_port();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if test_a20() {
|
||||
return true;
|
||||
}
|
||||
|
||||
enable_a20_fasta20();
|
||||
let mut i = 0u32;
|
||||
while (!test_a20()) && i < 10000 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return test_a20();
|
||||
}
|
||||
|
||||
static mut RTC_INITALIZED: bool = false;
|
||||
|
||||
pub fn initalize_rtc() {
|
||||
|
@ -167,10 +92,27 @@ pub fn initalize_rtc() {
|
|||
unsafe { RTC_INITALIZED = true }
|
||||
}
|
||||
|
||||
pub fn sleep(seconds: u32) {
|
||||
initalize_rtc();
|
||||
}
|
||||
pub fn sleep(seconds: u32) { initalize_rtc(); }
|
||||
|
||||
pub fn alloc_available_boot() {
|
||||
|
||||
let irq = pop_irq();
|
||||
let mut entries = vec![];
|
||||
entries.push(gdt::GDT_NULL_ENTRY);
|
||||
entries.push(GDTEntry {
|
||||
limit: 0,
|
||||
base: 0,
|
||||
access: 0b10011011,
|
||||
flags: 0b1100,
|
||||
}); // kernel code segment
|
||||
entries.push(GDTEntry {
|
||||
limit: 0,
|
||||
base: 0,
|
||||
access: 0b10010011,
|
||||
flags: 0b1100,
|
||||
}); //
|
||||
|
||||
unsafe {
|
||||
gdt::activate_gdt(gdt::write_gdt_entries(entries).unwrap());
|
||||
}
|
||||
restore_irq(irq);
|
||||
}
|
||||
|
|
|
@ -135,7 +135,6 @@ impl core::iter::Iterator for MemoryMap {
|
|||
#[derive(Clone)]
|
||||
pub struct BootInfo<'a> {
|
||||
/// The commandline of the kernel.
|
||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
||||
pub cmdline: Option<&'static str>,
|
||||
|
||||
/// The memory map provided by the bootloader. If None, the kernel will
|
||||
|
@ -147,4 +146,7 @@ pub struct BootInfo<'a> {
|
|||
|
||||
/// Provides a way to display text.
|
||||
pub output: Option<&'a dyn crate::display::TextDisplay>,
|
||||
|
||||
/// The base address of the kernel
|
||||
pub load_base: Option<u32>,
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#![allow(unexpected_cfgs)]
|
||||
#![allow(static_mut_refs)]
|
||||
|
||||
use crate::arch::output::*;
|
||||
use crate::display::{COLOR_DEFAULT, NoneTextDisplay};
|
||||
use crate::output::*;
|
||||
|
||||
|
@ -37,5 +38,14 @@ fn indep_boot_entry(
|
|||
tinfosln("Successfully ran all configured power on tests", display).unwrap();
|
||||
}
|
||||
|
||||
if cfg!(CONFIG_PREUSER_OUTPUT_DEBUG = "true") {
|
||||
if let Some(load_base) = BI.load_base {
|
||||
sdebugs("Image load base address is ");
|
||||
sdebugbnpln(&crate::u32_as_u8_slice(load_base));
|
||||
} else {
|
||||
sdebugsln("Image load base address was not provided");
|
||||
}
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
|
|
@ -69,9 +69,9 @@ static mut ALLOCATOR_INITALIZED: bool = false;
|
|||
pub fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
|
||||
if unsafe { ALLOCATOR_INITALIZED } {
|
||||
#[allow(static_mut_refs)]
|
||||
return Some(unsafe { ALLOCATOR.assume_init_ref() });
|
||||
Some(unsafe { ALLOCATOR.assume_init_ref() })
|
||||
} else {
|
||||
return None;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#![feature(ptr_as_uninit)]
|
||||
#![allow(internal_features)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(vec_into_raw_parts)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
|
|
@ -197,7 +197,6 @@ pub struct Multiboot2BootInfo {
|
|||
// If you need it, good luck.
|
||||
/// We're provided with a C-style UTF-8(null-terminated UTF-8) string. This
|
||||
/// should contain the original pointer provided by the bootloader.
|
||||
/// See <https://aphrodite-os.github.io/book/command-line.html> for the format.
|
||||
pub cmdline: Option<&'static core::ffi::CStr>,
|
||||
|
||||
// Due to the way modules work, it's not easily possible to make a struct that contains all the
|
||||
|
@ -220,14 +219,16 @@ pub struct Multiboot2BootInfo {
|
|||
// it.
|
||||
/// Provides information on the framebuffer.
|
||||
pub framebuffer_info: Option<FramebufferInfo>,
|
||||
|
||||
/// Color info, stored separately from [FramebufferInfo] because rust
|
||||
pub color_info: Option<ColorInfo>,
|
||||
|
||||
// Even though SMBIOS is documented for Multiboot2, we're not using it and will instead search
|
||||
// for it ourselves. This is because right now I cannot figure out what format it provides
|
||||
// the SMBIOS table in.
|
||||
|
||||
// EFI memory map and image handle pointers are not included for portability.
|
||||
|
||||
// "Image load base physical address" is not included as at the moment the kernel is not
|
||||
// relocatable.
|
||||
// EFI memory map and image handle pointers are not included for portability. Yeah, that's what
|
||||
// I'm calling it.
|
||||
/// Base address of the kernel
|
||||
pub load_base: Option<u32>,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#![cfg(all(not(CONFIG_POWERON_TESTS = "false"), not(CONFIG_POWERON_TEST_ALLOC = "false")))]
|
||||
#![cfg(all(
|
||||
not(CONFIG_POWERON_TESTS = "false"),
|
||||
not(CONFIG_POWERON_TEST_ALLOC = "false")
|
||||
))]
|
||||
|
||||
use crate::display::TextDisplay;
|
||||
use crate::output::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue