This commit is contained in:
xwashere 2024-03-19 08:44:57 -04:00
parent f0ec001801
commit 91d3d1b663
Signed by: XWasHere
GPG Key ID: 042F8BFA1B0EF93B
4 changed files with 131 additions and 43 deletions

View File

@ -6,7 +6,7 @@ lw_project(lcrash
)
lw_add_executable(lcrash
SOURCES lcrash.c
SOURCES lcrash.c efi/memmap.c
)
add_executable(lcrashld IMPORTED)
set_property(TARGET lcrashld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
@ -15,3 +15,4 @@ set_property(TARGET lcrash PROPERTY LINK_DEPENDS
$<TARGET_FILE:LindowsCompilerSpec>
)
set_property(TARGET lcrash PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
target_compile_options(lcrash PRIVATE -ggdb)

View File

@ -1,4 +1,6 @@
#include "lnxboot.h"
#include "efi/types.h"
#include "efi/memmap.h"
extern void _start();
@ -7,7 +9,7 @@ extern void _start();
[[gnu::aligned(1)]]
[[gnu::unavailable("not present at runtime. use setup_info instead")]]
struct setup_info bzhead = {
.setup_sects = 1, // 1 512-byte sector
.setup_sects = 2, // 1 512-byte sector
.boot_flag = 0xAA55,
.syssize = 16,
.jump_instruction = 0xEB,
@ -16,7 +18,7 @@ struct setup_info bzhead = {
.version = 0x020F,
.loadflags = 0x01, // LOADED_HIGH,
.kernel_alignment = 1,
.relocatable_kernel = 1,
.relocatable_kernel = 0,
.xloadflags = 0x13, // XLF_KERNEL_64 | XLF_CAN_BE_LOADED_ABOVE_4G | XLF_5LEVEL
.cmdline_size = 255, // max command line size
.init_size = 0x10000 // we dont need THAT much memory
@ -60,8 +62,31 @@ void serial_put_formatted_u64(u64 v) {
}
}
[[gnu::section(".text._start"), gnu::naked]]
/**
* We can't do anything, just hang.
*/
[[noreturn, gnu::naked]]
void Hang() {
// This should make us hang
asm volatile (
" cli\n"
"1: hlt\n"
" jmp 1b"
);
}
/**
* Congratulations, you panicked twice!
*/
[[noreturn]]
void Panic(const char* message) {
// We don't even do anything with the message, but it's nice to have just in case.
Hang();
}
[[gnu::section(".text._start"), gnu::naked, gnu::no_reorder]]
extern void _start() {
asm ("jmp _start");
asm ( // grab the setup_info and boot_params locations
"mov %%rsi, %1\n"
"mov %%rsi, %0\n"
@ -72,27 +97,70 @@ extern void _start() {
asm ("jmp entry");
}
[[gnu::section(".text._start")]]
c16* FirmwareVendor = 0;
/**
* we're in some kind of purgatory between booted and not booted, a lot of devices are currently initialized from the previous
* kernel, but we have no idea where they are, what they are, or how to use them. all we have is the stuff in setup_info and
* boot_params, and whatever we can salvage from the crashed kernel.
*/
[[gnu::section(".text._start"), gnu::no_reorder]]
void entry() {
// get the zero page
//boot_params = (struct boot_params*)(
// 0x202 - 0x1f1
// + setup_info->jump_offset
// + (u64)setup_info);
// get command line from kernel. we likely won't use it, but its nice to have.
u8* cmdline_ptr = (u8*)((u64)setup_info->cmd_line_ptr | ((u64)boot_params->ext_cmd_line_ptr << 32));
// do we have efi?
struct EfiSystemTable* systab_ptr = 0;
if (boot_params) {
systab_ptr = (struct EfiSystemTable*)(
(u64)boot_params->efi_info.EfiSystemTable |
((u64)boot_params->efi_info.EfiSystemTableHigh << 32)
);
// orignally we would try to import the serial port from the kernel (see kexec tools)
// as you can see, we gave up!
// serial_port = (unsigned short)*(long*)&serial_base;
serial_port = 0x3f8;
EfiLoadStoredMemoryMap(
(struct EfiMemoryDescription*)(
(u64)boot_params->efi_info.EfiMemoryMap |
((u64)boot_params->efi_info.EfiMemoryMapHigh << 32)
), // this might be 0, we should probably check ---------------V
boot_params->efi_info.EfiMemoryMapSize / boot_params->efi_info.EfiMemoryDescriptionSize,
boot_params->efi_info.EfiMemoryDescriptionSize
);
// construct pointers
u8* cmdline_ptr = (u8*)((u64)setup_info->cmd_line_ptr | ((u64)boot_params->ext_cmd_line_ptr << 32));
FirmwareVendor = EfiTranslatePointer(systab_ptr->FirmwareVendor);
while (1) {
volatile char* a = FirmwareVendor;
}
}
// check out command line
serial_puts(cmdline_ptr);
serial_putc('\r');
serial_putc('\n');
// -- find acpi --
struct AcpiRSDP* AcpiRSDP = 0;
// check bootparams
if (boot_params->acpi_rsdp_addr) AcpiRSDP = boot_params->acpi_rsdp_addr;
// check efi
if (!AcpiRSDP && systab_ptr && systab_ptr->NumberOfTableEntries) {
volatile void* ConfigurationTable = EfiTranslatePointer(systab_ptr->ConfigurationTable);
}
// we're playing where's waldo with this stupid fucking tableS
if (!AcpiRSDP) {
for (struct AcpiRSDP* addr = 0x00000000; addr < 0x000FFFFF; addr = (void*)addr + 16) {
if (addr->Signature[0] == 'R' && addr->Signature[1] == 'S'
&& addr->Signature[2] == 'D' && addr->Signature[3] == ' '
&& addr->Signature[4] == 'P' && addr->Signature[5] == 'T'
&& addr->Signature[6] == 'R' && addr->Signature[7] == ' ') {
AcpiRSDP = addr;
break;
}
}
}
if (!AcpiRSDP) Panic("Failed to find ACPI RSDP");
// do we have acpi?
asm volatile ("ljmp 0");
// we dont have the privilege of getting a rodata segment. any reads off our stack cause a triple fault
// for some fucking reason. allocate our strings and shit on the stack.
//char s_you_fucked_up[] = "!!! YOU FUCKED UP !!!\n";
@ -124,6 +192,5 @@ void entry() {
// serial_puts(bzhead.cmd_line_ptr);
// Die.
asm ("cli");
asm ("hlt");
Panic("Nothing left to do.");
}

View File

@ -1,24 +1,36 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start)
MEMORY {
code (rx) : ORIGIN = 0x0dfe8000, LENGTH = 0x00001000
data (rw) : ORIGIN = 0x0dff0000, LENGTH = 0x00001000
}
SECTIONS {
.lnxhead 0x01f1 : ALIGN(1) {
*(.lnxhead);
}
.rodata 0x900000 : ALIGN(1) {
.rodata : ALIGN(1) {
*(.rodata);
}
} > data
.text._start 0x80000000 : ALIGN(1) {
/* this section helps us to coerce the linker into not breaking down because of big addresses */
.text._start 0xdfe8000 : ALIGN(1) {
*(.text._start);
}
} > code
.text : ALIGN(512) { *(.text); }
.text : ALIGN(512) { *(.text); } > code
.bss : { *(.bss); }
.kernel_imports 0xFFFFFFFF : {
*(.kernel_imports);
}
.debug_info 0 : { *(.debug_info); }
.debug_abbrev 0 : { *(.debug_abbrev); }
.debug_aranges 0 : { *(.debug_aranges); }
.debug_rnglists 0 : { *(.debug_rnglists); }
.debug_line 0 : { *(.debug_line); }
.debug_str 0 : { *(.debug_str); }
.debug_line_str 0 : { *(.debug_line_str); }
/DISCARD/ : {
*(*);

View File

@ -1,9 +1,7 @@
#pragma once
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#include "types.h"
#include "acpi/acpi.h"
struct [[gnu::packed]] setup_info {
u8 setup_sects;
@ -61,13 +59,14 @@ struct [[gnu::packed]] screen_info {
u16 reserved2;
u8 orig_video_lines;
u8 orig_video_isVGA;
u8 orig_video_points;
u16 orig_video_points;
// linear frame buffer
u16 lfb_width;
u16 lfb_height;
u16 lfb_depth;
u32 lfb_base;
u32 lfb_size;
u16 cl_magic;
u16 cl_offset;
u16 lfb_linelength;
@ -79,8 +78,8 @@ struct [[gnu::packed]] screen_info {
u8 blue_pos;
u8 reserved_size;
u8 reserved_pos;
u8 vesapm_seg;
u8 vesapm_off;
u16 vesapm_seg;
u16 vesapm_off;
u16 pages;
u16 vesa_attributes;
u32 capabilities;
@ -106,11 +105,20 @@ struct [[gnu::packed]] edid_info {
};
struct [[gnu::packed]] efi_info {
u8 pad[0x20];
u32 EfiLoaderSignature;
u32 EfiSystemTable;
u32 EfiMemoryDescriptionSize;
u32 EfiMemoryDescriptionVersion;
u32 EfiMemoryMap;
u32 EfiMemoryMapSize;
u32 EfiSystemTableHigh;
u32 EfiMemoryMapHigh;
};
struct [[gnu::packed]] e820_entry {
u8 pad;
u64 base;
u64 length;
u32 type;
};
struct [[gnu::packed]] edd_info {
@ -123,8 +131,8 @@ struct [[gnu::packed]] boot_params {
u8 reserved0[0x4];
void* tboot_addr;
struct ist_info ist_info;
void* acpi_rsdp_addr;
u8 reserved1[0x2];
struct acpi_rsdp* acpi_rsdp_addr;
u8 reserved1[0x8];
u8 hd0_info[0x10];
u8 hd1_info[0x10];
struct sys_desc_table sys_desc_table;
@ -136,7 +144,7 @@ struct [[gnu::packed]] boot_params {
/// cmd_line_ptr high 32 bits
u32 ext_cmd_line_ptr;
u8 reserved2[0x70];
void* cc_blob_address;
u32 cc_blob_address;
struct edid_info edid_info;
struct efi_info efi_info;
u32 alt_mem_k;
@ -150,7 +158,7 @@ struct [[gnu::packed]] boot_params {
u8 sentinel;
u8 reserved4[0xa0]; // setup_info lives here!
u8 edd_mbr_sig_buffer[0x40];
u8 e20_table[0xa00];
struct e820_entry e820_table[128];
u8 reserved5[0x30];
u8 eddbuf[0x1ec];
};