Do not require unreal mode, load stage 2 in conventional memory
This commit is contained in:
@@ -7,8 +7,15 @@ stage2:
|
||||
align 512, db 0
|
||||
stage2.end:
|
||||
|
||||
; the maximum size of stage1 + stage2 is 5 KiB
|
||||
; this places stage3 at 0x9000
|
||||
times 5120-($-$$) db 0
|
||||
|
||||
stage3:
|
||||
%defstr STAGE3_STR %[STAGE3]
|
||||
incbin STAGE3_STR
|
||||
align 512, db 0
|
||||
.end:
|
||||
|
||||
; the maximum size of the boot loader portion is 128 KiB
|
||||
times 131072-($-$$) db 0
|
||||
|
||||
@@ -3,7 +3,7 @@ USE16
|
||||
|
||||
cpuid_required_features:
|
||||
.edx equ cpuid_edx.fpu | cpuid_edx.sse | cpuid_edx.pae | cpuid_edx.pse | cpuid_edx.pge | cpuid_edx.fxsr
|
||||
.ecx equ cpuid_ecx.xsave
|
||||
.ecx equ 0
|
||||
|
||||
cpuid_check:
|
||||
mov eax, 1
|
||||
@@ -20,8 +20,8 @@ cpuid_check:
|
||||
ret
|
||||
|
||||
.error:
|
||||
push edx
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
mov si, .msg_features
|
||||
call print
|
||||
@@ -29,6 +29,30 @@ cpuid_check:
|
||||
mov si, .msg_line
|
||||
call print
|
||||
|
||||
mov si, .msg_edx
|
||||
call print
|
||||
|
||||
pop ebx
|
||||
push ebx
|
||||
shr ebx, 16
|
||||
call print_hex
|
||||
|
||||
pop ebx
|
||||
call print_hex
|
||||
|
||||
mov si, .msg_must_contain
|
||||
call print
|
||||
|
||||
mov ebx, cpuid_required_features.edx
|
||||
shr ebx, 16
|
||||
call print_hex
|
||||
|
||||
mov ebx, cpuid_required_features.edx
|
||||
call print_hex
|
||||
|
||||
mov si, .msg_line
|
||||
call print
|
||||
|
||||
mov si, .msg_ecx
|
||||
call print
|
||||
|
||||
@@ -53,30 +77,6 @@ cpuid_check:
|
||||
mov si, .msg_line
|
||||
call print
|
||||
|
||||
mov si, .msg_edx
|
||||
call print
|
||||
|
||||
pop ebx
|
||||
push ebx
|
||||
rol ebx, 16
|
||||
call print_hex
|
||||
|
||||
pop ebx
|
||||
call print_hex
|
||||
|
||||
mov si, .msg_must_contain
|
||||
call print
|
||||
|
||||
mov ebx, cpuid_required_features.edx
|
||||
shr ebx, 16
|
||||
call print_hex
|
||||
|
||||
mov ebx, cpuid_required_features.edx
|
||||
call print_hex
|
||||
|
||||
mov si, .msg_line
|
||||
call print
|
||||
|
||||
.halt:
|
||||
cli
|
||||
hlt
|
||||
@@ -84,8 +84,8 @@ cpuid_check:
|
||||
|
||||
.msg_features: db "Required CPU features are not present",0
|
||||
.msg_line: db 13,10,0
|
||||
.msg_ecx: db "ECX ",0
|
||||
.msg_edx: db "EDX ",0
|
||||
.msg_ecx: db "ECX ",0
|
||||
.msg_must_contain: db " must contain ",0
|
||||
|
||||
cpuid_edx:
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
SECTION .text
|
||||
USE16
|
||||
|
||||
;Generate a memory map at 0x500 to 0x5000 (available memory not used for kernel or bootloader)
|
||||
memory_map:
|
||||
.start equ 0x0500
|
||||
.end equ 0x5000
|
||||
.length equ .end - .start
|
||||
|
||||
xor eax, eax
|
||||
mov di, .start
|
||||
mov ecx, .length / 4 ; moving 4 Bytes at once
|
||||
cld
|
||||
rep stosd
|
||||
|
||||
mov di, .start
|
||||
mov edx, 0x534D4150
|
||||
xor ebx, ebx
|
||||
.lp:
|
||||
mov eax, 0xE820
|
||||
mov ecx, 24
|
||||
|
||||
int 0x15
|
||||
jc .done ; Error or finished
|
||||
|
||||
cmp ebx, 0
|
||||
je .done ; Finished
|
||||
|
||||
add di, 24
|
||||
cmp di, .end
|
||||
jb .lp ; Still have buffer space
|
||||
.done:
|
||||
ret
|
||||
@@ -28,11 +28,10 @@ stage1: ; dl comes with disk
|
||||
|
||||
mov eax, (stage2 - stage1) / 512
|
||||
mov bx, stage2
|
||||
mov cx, (stage2.end - stage2) / 512
|
||||
xor dx, dx
|
||||
mov cx, (stage3.end - stage2) / 512
|
||||
mov dx, 0
|
||||
call load
|
||||
|
||||
call print_line
|
||||
mov si, finished
|
||||
call print
|
||||
call print_line
|
||||
@@ -79,9 +78,6 @@ load:
|
||||
ret
|
||||
|
||||
print_dapack:
|
||||
mov al, 13
|
||||
call print_char
|
||||
|
||||
mov bx, [DAPACK.addr + 2]
|
||||
call print_hex
|
||||
|
||||
@@ -106,6 +102,8 @@ print_dapack:
|
||||
mov bx, [DAPACK.buf]
|
||||
call print_hex
|
||||
|
||||
call print_line
|
||||
|
||||
ret
|
||||
|
||||
error:
|
||||
|
||||
@@ -10,112 +10,22 @@ stage2.entry:
|
||||
or al, 2
|
||||
out 0x92, al
|
||||
|
||||
; load memory map
|
||||
;TODO: rewrite this in Rust
|
||||
call memory_map
|
||||
|
||||
mov edi, [args.stage3_base]
|
||||
mov ecx, (stage3.end - stage3)
|
||||
mov [args.stage3_size], ecx
|
||||
|
||||
mov eax, (stage3 - stage1)/512
|
||||
add ecx, 511
|
||||
shr ecx, 9
|
||||
call load_extent
|
||||
|
||||
mov dword [protected_mode.func], stage3.entry
|
||||
jmp protected_mode.entry
|
||||
|
||||
args:
|
||||
.stage3_base dq 0x100000
|
||||
.stage3_size dq 0
|
||||
|
||||
; load a disk extent into high memory
|
||||
; eax - sector address
|
||||
; ecx - sector count
|
||||
; edi - destination
|
||||
load_extent:
|
||||
; loading stage3 to 1MiB
|
||||
; move part of stage3 to stage2.end via bootsector#load and then copy it up
|
||||
; repeat until all of the stage3 is loaded
|
||||
buffer_size_sectors equ 127
|
||||
|
||||
.lp:
|
||||
cmp ecx, buffer_size_sectors
|
||||
jb .break
|
||||
|
||||
; saving counter
|
||||
push eax
|
||||
push ecx
|
||||
|
||||
push edi
|
||||
|
||||
; populating buffer
|
||||
mov ecx, buffer_size_sectors
|
||||
mov bx, stage2.end
|
||||
mov dx, 0x0
|
||||
|
||||
; load sectors
|
||||
call load
|
||||
|
||||
; set up unreal mode
|
||||
call unreal
|
||||
|
||||
pop edi
|
||||
|
||||
; move data
|
||||
mov esi, stage2.end
|
||||
mov ecx, buffer_size_sectors * 512 / 4
|
||||
cld
|
||||
a32 rep movsd
|
||||
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
add eax, buffer_size_sectors
|
||||
sub ecx, buffer_size_sectors
|
||||
jmp .lp
|
||||
|
||||
.break:
|
||||
; load the part of the stage3 that does not fill the buffer completely
|
||||
test ecx, ecx
|
||||
jz .finish ; if cx = 0 => skip
|
||||
|
||||
push ecx
|
||||
push edi
|
||||
|
||||
mov bx, stage2.end
|
||||
mov dx, 0x0
|
||||
call load
|
||||
|
||||
; moving remnants of stage3
|
||||
call unreal
|
||||
|
||||
pop edi
|
||||
pop ecx
|
||||
|
||||
mov esi, stage2.end
|
||||
shl ecx, 7 ; * 512 / 4
|
||||
cld
|
||||
a32 rep movsd
|
||||
|
||||
.finish:
|
||||
call print_line
|
||||
ret
|
||||
|
||||
%include "cpuid.asm"
|
||||
%include "gdt.asm"
|
||||
%include "long_mode.asm"
|
||||
%include "memory_map.asm"
|
||||
%include "protected_mode.asm"
|
||||
%include "thunk.asm"
|
||||
%include "unreal.asm"
|
||||
|
||||
USE32
|
||||
stage3.entry:
|
||||
mov esp, 0x800000 - 128
|
||||
|
||||
; entry point
|
||||
stage3.entry:
|
||||
; stage3 stack at 256 KiB
|
||||
mov esp, 0x40000
|
||||
|
||||
; push arguments
|
||||
mov eax, thunk.int16
|
||||
push eax
|
||||
mov eax, thunk.int15
|
||||
@@ -127,8 +37,8 @@ stage3.entry:
|
||||
xor eax, eax
|
||||
mov al, [disk]
|
||||
push eax
|
||||
mov eax, [args.stage3_base]
|
||||
call [eax + 0x18]
|
||||
mov eax, [stage3 + 0x18]
|
||||
call eax
|
||||
.halt:
|
||||
cli
|
||||
hlt
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
SECTION .text
|
||||
USE16
|
||||
|
||||
; switch to unreal mode; ds and es can address up to 4GiB
|
||||
unreal:
|
||||
cli
|
||||
|
||||
lgdt [gdtr]
|
||||
|
||||
push es
|
||||
push ds
|
||||
|
||||
mov eax, cr0 ; switch to pmode by
|
||||
or al,1 ; set pmode bit
|
||||
mov cr0, eax
|
||||
|
||||
jmp $+2
|
||||
|
||||
; http://wiki.osdev.org/Babystep7
|
||||
; When this register given a "selector", a "segment descriptor cache register"
|
||||
; is filled with the descriptor values, including the size (or limit). After
|
||||
; the switch back to real mode, these values are not modified, regardless of
|
||||
; what value is in the 16-bit segment register. So the 64k limit is no longer
|
||||
; valid and 32-bit offsets can be used with the real-mode addressing rules
|
||||
mov bx, gdt.pm32_data
|
||||
mov es, bx
|
||||
mov ds, bx
|
||||
|
||||
and al,0xFE ; back to realmode
|
||||
mov cr0, eax ; by toggling bit again
|
||||
|
||||
pop ds
|
||||
pop es
|
||||
sti
|
||||
ret
|
||||
@@ -2,7 +2,8 @@ ENTRY(kstart)
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x100000;
|
||||
/* The start address must match bootloader.asm */
|
||||
. = 0x9000;
|
||||
|
||||
. += SIZEOF_HEADERS;
|
||||
. = ALIGN(4096);
|
||||
|
||||
+71
-50
@@ -8,22 +8,28 @@ extern crate alloc;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::{
|
||||
alloc::{GlobalAlloc, Layout},
|
||||
cmp,
|
||||
fmt::{self, Write},
|
||||
ptr,
|
||||
slice,
|
||||
};
|
||||
use linked_list_allocator::LockedHeap;
|
||||
use log::{error, info};
|
||||
use spin::Mutex;
|
||||
|
||||
use self::disk::DiskBios;
|
||||
use self::logger::LOGGER;
|
||||
use self::memory_map::memory_map;
|
||||
use self::thunk::ThunkData;
|
||||
use self::vbe::{VbeCardInfo, VbeModeInfo};
|
||||
use self::vga::{VgaTextBlock, VgaTextColor, Vga};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod disk;
|
||||
mod logger;
|
||||
mod memory_map;
|
||||
mod paging;
|
||||
mod panic;
|
||||
mod thunk;
|
||||
@@ -34,6 +40,7 @@ mod vga;
|
||||
// 0x500 to 0x7BFF is free
|
||||
const VBE_CARD_INFO_ADDR: usize = 0x500; // 512 bytes, ends at 0x6FF
|
||||
const VBE_MODE_INFO_ADDR: usize = 0x700; // 256 bytes, ends at 0x7FF
|
||||
const MEMORY_MAP_ADDR: usize = 0x800; // 24 bytes, ends at 0x817
|
||||
const DISK_ADDRESS_PACKET_ADDR: usize = 0x0FF0; // 16 bytes, ends at 0x0FFF
|
||||
const DISK_BIOS_ADDR: usize = 0x1000; // 4096 bytes, ends at 0x1FFF
|
||||
const THUNK_STACK_ADDR: usize = 0x7C00; // Grows downwards
|
||||
@@ -42,7 +49,9 @@ const VGA_ADDR: usize = 0xB8000;
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||
|
||||
static mut VGA: Vga = unsafe { Vga::new(VGA_ADDR as *mut VgaTextBlock, 80, 25) };
|
||||
static VGA: Mutex<Vga> = Mutex::new(
|
||||
unsafe { Vga::new(VGA_ADDR, 80, 25) }
|
||||
);
|
||||
|
||||
static mut KERNEL_PHYS: u64 = 0;
|
||||
|
||||
@@ -71,59 +80,71 @@ pub unsafe extern "C" fn kstart(
|
||||
|
||||
{
|
||||
// Clear VGA console
|
||||
let blocks = VGA.blocks();
|
||||
let mut vga = VGA.lock();
|
||||
let blocks = vga.blocks();
|
||||
for i in 0..blocks.len() {
|
||||
blocks[i] = VgaTextBlock {
|
||||
char: 0,
|
||||
color: ((VGA.bg as u8) << 4) | (VGA.fg as u8),
|
||||
color: ((vga.bg as u8) << 4) | (vga.fg as u8),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize allocator at the end of stage 3 with a meager 1 MiB, which we can be pretty
|
||||
// sure will be available.
|
||||
extern "C" {
|
||||
static mut __end: u8;
|
||||
}
|
||||
let heap_start = &__end as *const _ as usize;
|
||||
let heap_size = 1024 * 1024;
|
||||
ALLOCATOR.lock().init(heap_start, heap_size);
|
||||
|
||||
// Set logger
|
||||
LOGGER.init();
|
||||
|
||||
// Locate RedoxFS
|
||||
{
|
||||
let (heap_start, heap_size) = memory_map(thunk15).expect("no memory for heap");
|
||||
|
||||
println!("HEAP: {:X}:{:X}", heap_start, heap_size);
|
||||
ALLOCATOR.lock().init(heap_start, heap_size);
|
||||
|
||||
// Locate kernel on RedoxFS
|
||||
let kernel = {
|
||||
//TODO: ensure boot_disk is 8-bit
|
||||
info!("DISK {:02X}", boot_disk);
|
||||
println!("BIOS Disk: {:02X}", boot_disk);
|
||||
let disk = DiskBios::new(boot_disk as u8, thunk13);
|
||||
|
||||
//TODO: get block from partition table
|
||||
let block = 1024 * 1024 / redoxfs::BLOCK_SIZE;
|
||||
match redoxfs::FileSystem::open(disk, Some(block)) {
|
||||
Ok(mut fs) => {
|
||||
info!("RedoxFS {} MiB", fs.header.1.size / 1024 / 1024);
|
||||
let mut fs = redoxfs::FileSystem::open(disk, Some(block))
|
||||
.expect("Failed to open RedoxFS");
|
||||
|
||||
match fs.find_node("kernel", fs.header.1.root) {
|
||||
Ok(node) => match fs.node_len(node.0) {
|
||||
Ok(len) => {
|
||||
info!("Kernel {} MiB", len / 1024 / 1024);
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Failed to read kernel file length: {:?}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Failed to find kernel file: {:?}", err);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Failed to open RedoxFS: {:?}", err);
|
||||
}
|
||||
println!("RedoxFS Size: {} MiB", fs.header.1.size / 1024 / 1024);
|
||||
|
||||
let node = fs.find_node("kernel", fs.header.1.root)
|
||||
.expect("failed to find kernel file");
|
||||
|
||||
let size = fs.node_len(node.0)
|
||||
.expect("failed to read kernel size");
|
||||
|
||||
println!("Kernel Size: {} MiB", size / 1024 / 1024);
|
||||
|
||||
let ptr = ALLOCATOR.alloc_zeroed(
|
||||
Layout::from_size_align(size as usize, 4096).unwrap()
|
||||
);
|
||||
if ptr.is_null() {
|
||||
panic!("Failed to allocate memory for kernel");
|
||||
}
|
||||
}
|
||||
|
||||
//let page_phys = paging::paging_create(KERNEL_PHYS);
|
||||
let kernel = slice::from_raw_parts_mut(
|
||||
ptr,
|
||||
size as usize
|
||||
);
|
||||
|
||||
let mut i = 0;
|
||||
for chunk in kernel.chunks_mut(1024 * 1024) {
|
||||
print!("\rKernel Loading: {}%", i * 100 / size);
|
||||
i += fs.read_node(node.0, i, chunk, 0, 0)
|
||||
.expect("Failed to read kernel file") as u64;
|
||||
}
|
||||
println!("\rKernel Loading: 100%");
|
||||
|
||||
kernel
|
||||
};
|
||||
|
||||
println!("Kernel Phys: 0x{:X}", kernel.as_ptr() as u64);
|
||||
let page_phys = paging::paging_create(kernel.as_ptr() as u64);
|
||||
panic!("kernel entry not implemented");
|
||||
|
||||
let mut modes = Vec::new();
|
||||
{
|
||||
@@ -182,22 +203,22 @@ pub unsafe extern "C" fn kstart(
|
||||
format!("{:>4}x{:<4} {:>3}:{:<3}", w, h, aspect_w, aspect_h)
|
||||
));
|
||||
} else {
|
||||
error!("Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.eax);
|
||||
panic!("Failed to read VBE mode 0x{:04X} info: 0x{:04X}", mode, data.eax);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Failed to read VBE card info: 0x{:04X}", data.eax);
|
||||
panic!("Failed to read VBE card info: 0x{:04X}", data.eax);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort modes by pixel area, reversed
|
||||
modes.sort_by(|a, b| (b.1 * b.2).cmp(&(a.1 * a.2)));
|
||||
|
||||
writeln!(VGA, "Arrow keys and enter select mode").unwrap();
|
||||
println!("Arrow keys and enter select mode");
|
||||
|
||||
//TODO 0x4F03 VBE function to get current mode
|
||||
let off_x = VGA.x;
|
||||
let off_y = VGA.y;
|
||||
let off_x = VGA.lock().x;
|
||||
let off_y = VGA.lock().y;
|
||||
let rows = 12;
|
||||
let mut selected = modes.get(0).map_or(0, |x| x.0);
|
||||
loop {
|
||||
@@ -209,18 +230,18 @@ pub unsafe extern "C" fn kstart(
|
||||
row = 0;
|
||||
}
|
||||
|
||||
VGA.x = off_x + col * 20;
|
||||
VGA.y = off_y + row;
|
||||
VGA.lock().x = off_x + col * 20;
|
||||
VGA.lock().y = off_y + row;
|
||||
|
||||
if *mode == selected {
|
||||
VGA.bg = VgaTextColor::White;
|
||||
VGA.fg = VgaTextColor::Black;
|
||||
VGA.lock().bg = VgaTextColor::White;
|
||||
VGA.lock().fg = VgaTextColor::Black;
|
||||
} else {
|
||||
VGA.bg = VgaTextColor::DarkGray;
|
||||
VGA.fg = VgaTextColor::White;
|
||||
VGA.lock().bg = VgaTextColor::DarkGray;
|
||||
VGA.lock().fg = VgaTextColor::White;
|
||||
}
|
||||
|
||||
write!(VGA, "{}", text).unwrap();
|
||||
print!("{}", text);
|
||||
|
||||
row += 1;
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,8 +1,6 @@
|
||||
use core::fmt::Write;
|
||||
use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
|
||||
|
||||
use crate::VGA;
|
||||
|
||||
pub static LOGGER: Logger = Logger;
|
||||
|
||||
pub struct Logger;
|
||||
@@ -21,9 +19,7 @@ impl Log for Logger {
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
unsafe {
|
||||
writeln!(VGA, "{} - {}", record.level(), record.args()).unwrap();
|
||||
}
|
||||
println!("{} - {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/// Print to console
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ({
|
||||
use core::fmt::Write;
|
||||
write!($crate::VGA.lock(), $($arg)*).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
/// Print with new line to console
|
||||
#[macro_export]
|
||||
macro_rules! println {
|
||||
() => (print!("\n"));
|
||||
($fmt:expr) => (print!(concat!($fmt, "\n")));
|
||||
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use core::{cmp, mem, ptr};
|
||||
|
||||
use crate::thunk::ThunkData;
|
||||
|
||||
#[repr(packed)]
|
||||
struct MemoryMapEntry {
|
||||
pub base: u64,
|
||||
pub length: u64,
|
||||
pub kind: u32,
|
||||
}
|
||||
|
||||
pub unsafe fn memory_map(thunk15: extern "C" fn()) -> Option<(usize, usize)> {
|
||||
let mut heap_limits = None;
|
||||
let mut data = ThunkData::new();
|
||||
loop {
|
||||
let index = data.ebx;
|
||||
|
||||
data.eax = 0xE820;
|
||||
data.ecx = mem::size_of::<MemoryMapEntry>() as u32;
|
||||
data.edx = 0x534D4150;
|
||||
data.edi = crate::MEMORY_MAP_ADDR as u32;
|
||||
|
||||
data.with(thunk15);
|
||||
|
||||
assert_eq!(data.eax, 0x534D4150);
|
||||
assert_eq!(data.ecx, mem::size_of::<MemoryMapEntry>() as u32);
|
||||
let entry = ptr::read(crate::MEMORY_MAP_ADDR as *const MemoryMapEntry);
|
||||
|
||||
println!("MEM {}: 0x{:016X} 0x{:016X} 0x{:08X}", index, entry.base, entry.length, entry.kind);
|
||||
|
||||
//TODO: There is a problem with QEMU crashing if we write at about 8 MiB, so skip to 16
|
||||
let heap_start = 16 * 1024 * 1024;
|
||||
if (
|
||||
entry.kind == 1 &&
|
||||
entry.base <= heap_start as u64 &&
|
||||
(entry.base + entry.length) >= heap_start as u64
|
||||
) {
|
||||
let heap_end = cmp::min(
|
||||
entry.base + entry.length,
|
||||
usize::MAX as u64
|
||||
) as usize;
|
||||
if heap_end >= heap_start {
|
||||
heap_limits = Some((
|
||||
heap_start,
|
||||
heap_end - heap_start
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if data.ebx == 0 {
|
||||
return heap_limits;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
//! Intrinsics for panic handling
|
||||
|
||||
use core::alloc::Layout;
|
||||
use core::fmt::Write;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
@@ -11,9 +12,9 @@ pub extern "C" fn rust_eh_personality() {}
|
||||
#[panic_handler]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_begin_unwind(info: &PanicInfo) -> ! {
|
||||
log::error!("BOOTLOADER PANIC: {}", info);
|
||||
loop {
|
||||
unsafe {
|
||||
unsafe {
|
||||
let _ = writeln!(crate::VGA.lock(), "BOOTLOADER PANIC:\n{}", info);
|
||||
loop {
|
||||
llvm_asm!("hlt" : : : : "intel", "volatile");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -29,7 +29,7 @@ pub enum VgaTextColor {
|
||||
}
|
||||
|
||||
pub struct Vga {
|
||||
pub ptr: *mut VgaTextBlock,
|
||||
pub base: usize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub x: usize,
|
||||
@@ -39,9 +39,9 @@ pub struct Vga {
|
||||
}
|
||||
|
||||
impl Vga {
|
||||
pub const unsafe fn new(ptr: *mut VgaTextBlock, width: usize, height: usize) -> Self {
|
||||
pub const unsafe fn new(base: usize, width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
ptr,
|
||||
base,
|
||||
width,
|
||||
height,
|
||||
x: 0,
|
||||
@@ -53,7 +53,7 @@ impl Vga {
|
||||
|
||||
pub unsafe fn blocks(&mut self) -> &'static mut [VgaTextBlock] {
|
||||
slice::from_raw_parts_mut(
|
||||
self.ptr,
|
||||
self.base as *mut VgaTextBlock,
|
||||
self.width * self.height,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user