oh yeah we can decompress the kernel now
This commit is contained in:
parent
91d3d1b663
commit
8c6bfe0edf
@ -24,6 +24,7 @@ set_property(TARGET LindowsLinkerScript PROPERTY IMPORTED_LOCATION "${CMAKE_CURR
|
||||
# compiler stuff
|
||||
set(LW_CROSS_CC "${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/bin/gcc")
|
||||
set(LW_CROSS_CXX "${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/bin/g++")
|
||||
set(LW_CROSS_ASM "${LW_CROSS_CC}")
|
||||
set(LW_CROSS_LD "${LW_CROSS_CC}")
|
||||
set(LW_CROSS_INCFLAGS -isystem${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/include/c++/13.2.0 -isystem${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include -isystem${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include-fixed -isystem${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/include/c++/13.2.0/x86_64-pc-linux-gnu -isystem${CMAKE_CURRENT_BINARY_DIR}/glibc/prefix/include -isystem${CMAKE_CURRENT_BINARY_DIR}/linux/headers/include)
|
||||
set(LW_CROSS_CFLAGS -nostdinc ${LW_CROSS_INCFLAGS})
|
||||
@ -61,6 +62,7 @@ function(lw_project PROJECTNAME)
|
||||
elseif(${ARG_TARGET} STREQUAL "LINDOWS")
|
||||
set(CMAKE_C_COMPILER "${LW_CROSS_CC}" PARENT_SCOPE)
|
||||
set(CMAKE_CXX_COMPILER "${LW_CROSS_CXX}" PARENT_SCOPE)
|
||||
set(CMAKE_ASM_COMPILER "${LW_CROSS_ASM}" PARENT_SCOPE)
|
||||
set_property(DIRECTORY . PROPERTY INCLUDE_DIRECTORIES "")
|
||||
else()
|
||||
message(FATAL_ERROR "Unrecognized target type \"${ARG_TARGET}\"")
|
||||
|
@ -5,14 +5,72 @@ lw_project(lcrash
|
||||
TARGET LINDOWS
|
||||
)
|
||||
|
||||
lw_add_executable(lcrash
|
||||
SOURCES lcrash.c efi/memmap.c
|
||||
enable_language(ASM)
|
||||
|
||||
lw_add_executable(lcrashkern
|
||||
SOURCES lcrash.c util.c efi/guid.c efi/memmap.c gdb/gdb.c
|
||||
)
|
||||
add_executable(lcrashkernld IMPORTED)
|
||||
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
||||
set_property(TARGET lcrashkern PROPERTY LINK_DEPENDS
|
||||
$<TARGET_FILE:lcrashkernld>
|
||||
$<TARGET_FILE:LindowsCompilerSpec>
|
||||
)
|
||||
set_property(TARGET lcrashkern PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld )
|
||||
target_compile_options(lcrashkern PRIVATE -ggdb -fpic -pie)
|
||||
target_link_options(lcrashkern PRIVATE -fpic -pie)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz
|
||||
DEPENDS lcrashkern
|
||||
COMMAND gzip -fk $<TARGET_FILE:lcrashkern> > ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern_locs.h
|
||||
DEPENDS lcrashkern ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz
|
||||
COMMAND nm ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern | sed -E '"s/([0-9a-f]*) . (.*)/#define KK_\\2 0x\\1/g"' > lcrashkern_locs.h
|
||||
COMMAND echo -n "'#'define _KKCLEN " >> lcrashkern_locs.h
|
||||
COMMAND du -b lcrashkern.gz | cut -f 1 >> lcrashkern_locs.h
|
||||
)
|
||||
|
||||
# UnityOS cckernel stuffed into the bzImage
|
||||
lw_add_executable(cckernel
|
||||
SOURCES setup/compressed/cckernel.S
|
||||
setup/compressed/entry64.S
|
||||
setup/compressed/mem.S
|
||||
setup/compressed/main.c
|
||||
setup/compressed/gzip.c
|
||||
setup/compressed/elf.c
|
||||
)
|
||||
add_executable(cckernelld IMPORTED)
|
||||
set_property(TARGET cckernelld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/setup/compressed/compressed.ld)
|
||||
set_property(TARGET cckernel PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/setup/compressed/compressed.ld)
|
||||
target_compile_options(cckernel PRIVATE -ggdb -mno-sse -mno-avx) # disable generating SIMD code since we haven't configured it at this stage of the boot thing
|
||||
set_property(SOURCE setup/compressed/cckernel.S PROPERTY OBJECT_DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz
|
||||
)
|
||||
set_property(TARGET cckernel PROPERTY LINK_DEPENDS
|
||||
$<TARGET_FILE:cckernelld>
|
||||
)
|
||||
set(COMPRESSED_KERNEL_PATH ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz)
|
||||
configure_file(setup/compressed/cckernel.S.in setup/compressed/cckernel.S)
|
||||
|
||||
# This is the actual bzImage used by linux/grub
|
||||
lw_add_executable(lcrash
|
||||
SOURCES setup/header.S lcrashkern_locs.h
|
||||
)
|
||||
target_include_directories(lcrash PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
add_executable(lcrashld IMPORTED)
|
||||
set_property(TARGET lcrashld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
||||
set_property(TARGET lcrashld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/setup/setup.ld)
|
||||
set_property(TARGET lcrash PROPERTY LINK_DEPENDS
|
||||
$<TARGET_FILE:lcrashld>
|
||||
$<TARGET_FILE:LindowsCompilerSpec>
|
||||
$<TARGET_FILE:cckernel>
|
||||
)
|
||||
set_property(TARGET lcrash PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/setup/setup.ld)
|
||||
add_custom_command(TARGET lcrash POST_BUILD
|
||||
DEPENDS cckernel
|
||||
COMMAND bash -c "truncate \"$<TARGET_FILE:lcrash>\" -s \"$((0x$(nm \"$<TARGET_FILE:lcrash>\" | grep \" _end$\" | cut -d\" \" -f 1)))\""
|
||||
COMMAND dd "if=$<TARGET_FILE:cckernel>" "of=$<TARGET_FILE:lcrash>" conv=notrunc oflag=append
|
||||
VERBATIM
|
||||
)
|
||||
set_property(TARGET lcrash PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
||||
target_compile_options(lcrash PRIVATE -ggdb)
|
||||
|
22
lcrash/acpi/acpi.h
Normal file
22
lcrash/acpi/acpi.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
struct AcpiRSDP;
|
||||
struct AcpiXSDT;
|
||||
|
||||
/**
|
||||
* ACPI Root System Description Pointer
|
||||
*/
|
||||
struct [[gnu::packed]] AcpiRSDP {
|
||||
char Signature[8];
|
||||
u8 Checksum;
|
||||
char OEM[6];
|
||||
u8 Revision;
|
||||
[[gnu::deprecated]] // we dont care :>
|
||||
u32 RSDTAddress;
|
||||
u32 Length;
|
||||
struct AcpiXSDT* XSDTAddress;
|
||||
u8 ExtendedChecksum;
|
||||
u8 Reserved[3];
|
||||
};
|
3
lcrash/efi/guid.c
Normal file
3
lcrash/efi/guid.c
Normal file
@ -0,0 +1,3 @@
|
||||
#include "guid.h"
|
||||
|
||||
EfiGuid EFI_ACPI_20_TABLE_GUID = {0x8868e871, 0xe4f1, 0x11d3, {0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81}};
|
5
lcrash/efi/guid.h
Normal file
5
lcrash/efi/guid.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "./types.h"
|
||||
|
||||
extern EfiGuid EFI_ACPI_20_TABLE_GUID;
|
33
lcrash/efi/memmap.c
Normal file
33
lcrash/efi/memmap.c
Normal file
@ -0,0 +1,33 @@
|
||||
#include "memmap.h"
|
||||
|
||||
struct EfiMemoryDescription *StoredMemoryMap;
|
||||
u32 StoredMemoryMapEntryCount = 0;
|
||||
u32 StoredMemoryMapEntrySize = 0;
|
||||
|
||||
void EfiLoadStoredMemoryMap(
|
||||
struct EfiMemoryDescription* MemoryMap,
|
||||
u32 MemoryMapEntryCount,
|
||||
u32 MemoryMapEntrySize
|
||||
) {
|
||||
StoredMemoryMap = MemoryMap;
|
||||
StoredMemoryMapEntryCount = MemoryMapEntryCount;
|
||||
StoredMemoryMapEntrySize = MemoryMapEntrySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a pointer using what we can recover from the UEFI memory map, may return something invalid.
|
||||
*/
|
||||
void* EfiTranslatePointer(void* FirmwarePointer) {
|
||||
// Scan the memory map for where our thing is
|
||||
for (int i = 0; i < StoredMemoryMapEntryCount; i++) {
|
||||
struct EfiMemoryDescription* Entry = (struct EfiMemoryDescription*)((void*)StoredMemoryMap + i * StoredMemoryMapEntrySize);
|
||||
|
||||
if (FirmwarePointer >= Entry->VirtualStart &&
|
||||
FirmwarePointer < Entry->VirtualStart + 0x1000 * Entry->NumberOfPages) {
|
||||
return FirmwarePointer - Entry->VirtualStart + Entry->PhysicalStart;
|
||||
}
|
||||
}
|
||||
|
||||
// Well, we tried
|
||||
return -1;
|
||||
}
|
24
lcrash/efi/memmap.h
Normal file
24
lcrash/efi/memmap.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/// EFI Memory Descriptor
|
||||
struct EfiMemoryDescription {
|
||||
EfiUint32 Type;
|
||||
EfiVoid *PhysicalStart;
|
||||
EfiVoid *VirtualStart;
|
||||
EfiUint64 NumberOfPages;
|
||||
EfiUint64 Attribute;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a memory map to use for translating pointers recovered from EFI tables.
|
||||
*/
|
||||
void EfiLoadStoredMemoryMap(
|
||||
struct EfiMemoryDescription* StoredMemoryMap,
|
||||
u32 StoredMemoryMapEntryCount,
|
||||
u32 StoredMemoryMapEntrySize
|
||||
);
|
||||
|
||||
/// Translate a pointer to something we can use using the stored memory map.
|
||||
void* EfiTranslatePointer(void* FirmwarePointer);
|
54
lcrash/efi/types.h
Normal file
54
lcrash/efi/types.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
typedef void EfiVoid;
|
||||
|
||||
typedef u8 EfiUint8;
|
||||
typedef u16 EfiUint16;
|
||||
typedef u32 EfiUint32;
|
||||
typedef u64 EfiUint64;
|
||||
typedef uptr EfiUintN;
|
||||
|
||||
typedef c16 EfiChar16;
|
||||
|
||||
typedef EfiVoid* EfiHandle;
|
||||
|
||||
typedef struct _EfiGuid {
|
||||
u32 data1;
|
||||
u16 data2;
|
||||
u16 data3;
|
||||
u8 data4[8];
|
||||
} EfiGuid;
|
||||
|
||||
/// Generic EFI table header
|
||||
struct EfiTableHeader {
|
||||
EfiUint64 Signature;
|
||||
EfiUint32 Revision;
|
||||
EfiUint32 HeaderSize;
|
||||
EfiUint32 CRC32;
|
||||
EfiUint32 Reserved;
|
||||
};
|
||||
|
||||
/// EFI System Table
|
||||
struct EfiSystemTable {
|
||||
struct EfiTableHeader Hdr;
|
||||
EfiChar16 *FirmwareVendor;
|
||||
EfiUint32 FirmwareRevision;
|
||||
EfiHandle ConsoleInHandle;
|
||||
EfiVoid *ConIn;
|
||||
EfiHandle ConsoleOutHandle;
|
||||
EfiVoid *ConOut;
|
||||
EfiHandle StandardErrorHandle;
|
||||
EfiVoid *StdErr;
|
||||
struct EfiRuntimeServices *RuntimeServices;
|
||||
struct EfiBootServices *BootServices;
|
||||
EfiUintN NumberOfTableEntries;
|
||||
struct EfiConfigurationTable *ConfigurationTable;
|
||||
};
|
||||
|
||||
/// EFI Configuration Table
|
||||
struct EfiConfigurationTable {
|
||||
EfiGuid VendorGuid;
|
||||
EfiVoid *VendorTable;
|
||||
};
|
0
lcrash/empty.S
Normal file
0
lcrash/empty.S
Normal file
30
lcrash/gdb/autorun.py
Normal file
30
lcrash/gdb/autorun.py
Normal file
@ -0,0 +1,30 @@
|
||||
import functools;
|
||||
|
||||
# --- printers for stuff and yeah ---
|
||||
class EfiGuidPrinter(gdb.ValuePrinter):
|
||||
"Print an EfiGuid"
|
||||
|
||||
def __init__(self, val):
|
||||
self.__val = val;
|
||||
|
||||
def to_string(self):
|
||||
# it's really disappointing that you cant iterate these silly arrays
|
||||
d4 = self.__val["data4"];
|
||||
last = functools.reduce(lambda s, bit: f'{s}{int(bit):0>2X}', [d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]], "");
|
||||
|
||||
return f'{int(self.__val["data1"]):0>8X}-{int(self.__val["data2"]):0>4X}-{int(self.__val["data3"]):0>4X}-{last}';
|
||||
|
||||
def add_pretty_printer(name, printer, custom_lookup = None):
|
||||
def lookup(val):
|
||||
if val.type.tag == name:
|
||||
return printer(val);
|
||||
|
||||
return None;
|
||||
|
||||
gdb.current_objfile().pretty_printers.append(lookup if custom_lookup is None else custom_lookup);
|
||||
|
||||
return;
|
||||
|
||||
add_pretty_printer("_EfiGuid", EfiGuidPrinter, lambda val: EfiGuidPrinter(val) if val.type.strip_typedefs().tag == "_EfiGuid" else None);
|
||||
|
||||
# --- ---
|
3
lcrash/gdb/gdb.c
Normal file
3
lcrash/gdb/gdb.c
Normal file
@ -0,0 +1,3 @@
|
||||
#include "gdb.h"
|
||||
|
||||
DEFINE_GDB_PY_SCRIPT("lcrash/gdb/autorun.py")
|
9
lcrash/gdb/gdb.h
Normal file
9
lcrash/gdb/gdb.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define DEFINE_GDB_PY_SCRIPT(name) \
|
||||
asm("\
|
||||
.pushsection \".debug_gdb_scripts\", \"MS\", @progbits, 1\n\
|
||||
.byte 1\n\
|
||||
.asciz \""name"\"\n\
|
||||
.popsection \n\
|
||||
");
|
@ -1,31 +1,8 @@
|
||||
#include "lnxboot.h"
|
||||
#include "util.h"
|
||||
#include "efi/types.h"
|
||||
#include "efi/memmap.h"
|
||||
|
||||
extern void _start();
|
||||
|
||||
[[gnu::section(".lnxhead")]]
|
||||
[[gnu::used]]
|
||||
[[gnu::aligned(1)]]
|
||||
[[gnu::unavailable("not present at runtime. use setup_info instead")]]
|
||||
struct setup_info bzhead = {
|
||||
.setup_sects = 2, // 1 512-byte sector
|
||||
.boot_flag = 0xAA55,
|
||||
.syssize = 16,
|
||||
.jump_instruction = 0xEB,
|
||||
.jump_offset = sizeof(struct setup_info) - __builtin_offsetof(struct setup_info, signature),
|
||||
.signature = 0x53726448,
|
||||
.version = 0x020F,
|
||||
.loadflags = 0x01, // LOADED_HIGH,
|
||||
.kernel_alignment = 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
|
||||
};
|
||||
|
||||
struct setup_info* setup_info;
|
||||
struct boot_params* boot_params;
|
||||
#include "efi/guid.h"
|
||||
|
||||
unsigned short serial_port;
|
||||
|
||||
@ -84,28 +61,12 @@ void Panic(const char* message) {
|
||||
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"
|
||||
"addq $0x1f1, %0"
|
||||
: "=m" (setup_info),
|
||||
"=m" (boot_params)
|
||||
);
|
||||
asm ("jmp entry");
|
||||
}
|
||||
void entry64() {
|
||||
while (1) {};
|
||||
|
||||
c16* FirmwareVendor = 0;
|
||||
Panic("HELLO WORLD.");
|
||||
|
||||
/**
|
||||
* 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 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));
|
||||
|
||||
@ -125,11 +86,6 @@ void entry() {
|
||||
boot_params->efi_info.EfiMemoryMapSize / boot_params->efi_info.EfiMemoryDescriptionSize,
|
||||
boot_params->efi_info.EfiMemoryDescriptionSize
|
||||
);
|
||||
|
||||
FirmwareVendor = EfiTranslatePointer(systab_ptr->FirmwareVendor);
|
||||
while (1) {
|
||||
volatile char* a = FirmwareVendor;
|
||||
}
|
||||
}
|
||||
|
||||
// -- find acpi --
|
||||
@ -138,9 +94,22 @@ void entry() {
|
||||
// check bootparams
|
||||
if (boot_params->acpi_rsdp_addr) AcpiRSDP = boot_params->acpi_rsdp_addr;
|
||||
|
||||
while (true) {
|
||||
volatile void* a = &EFI_ACPI_20_TABLE_GUID;
|
||||
}
|
||||
|
||||
// check efi
|
||||
if (!AcpiRSDP && systab_ptr && systab_ptr->NumberOfTableEntries) {
|
||||
volatile void* ConfigurationTable = EfiTranslatePointer(systab_ptr->ConfigurationTable);
|
||||
struct EfiConfigurationTable* ConfigurationTable = EfiTranslatePointer(systab_ptr->ConfigurationTable);
|
||||
for (int i = 0; i < systab_ptr->NumberOfTableEntries; i++) {
|
||||
if (CompareMemory(&ConfigurationTable[i].VendorGuid, &EFI_ACPI_20_TABLE_GUID, sizeof(EfiGuid))) {
|
||||
AcpiRSDP = ConfigurationTable[i].VendorTable;
|
||||
while (true) {
|
||||
volatile void* a = AcpiRSDP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we're playing where's waldo with this stupid fucking tableS
|
||||
@ -159,7 +128,9 @@ void entry() {
|
||||
if (!AcpiRSDP) Panic("Failed to find ACPI RSDP");
|
||||
|
||||
// do we have acpi?
|
||||
asm volatile ("ljmp 0");
|
||||
while (1) {
|
||||
volatile void* p = AcpiRSDP;
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -191,6 +162,6 @@ void entry() {
|
||||
// serial_puts("test\n");
|
||||
// serial_puts(bzhead.cmd_line_ptr);
|
||||
|
||||
// Die.
|
||||
// Die.*/
|
||||
Panic("Nothing left to do.");
|
||||
}
|
||||
|
@ -1,28 +1,33 @@
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
code (rx) : ORIGIN = 0x0dfe8000, LENGTH = 0x00001000
|
||||
data (rw) : ORIGIN = 0x0dff0000, LENGTH = 0x00001000
|
||||
}
|
||||
ENTRY(entry64)
|
||||
|
||||
SECTIONS {
|
||||
.lnxhead 0x01f1 : ALIGN(1) {
|
||||
*(.lnxhead);
|
||||
. = 0;
|
||||
|
||||
.text : {
|
||||
_text = .;
|
||||
*(.text);
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.rodata : ALIGN(1) {
|
||||
.rodata : {
|
||||
_rodata = .;
|
||||
*(.rodata);
|
||||
} > data
|
||||
_erodata = .;
|
||||
}
|
||||
|
||||
/* this section helps us to coerce the linker into not breaking down because of big addresses */
|
||||
.text._start 0xdfe8000 : ALIGN(1) {
|
||||
*(.text._start);
|
||||
} > code
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data);
|
||||
_edata = .;
|
||||
}
|
||||
|
||||
.text : ALIGN(512) { *(.text); } > code
|
||||
.bss : { *(.bss); }
|
||||
.bss : {
|
||||
_bss = .;
|
||||
*(.bss);
|
||||
_ebss = .;
|
||||
}
|
||||
|
||||
.debug_info 0 : { *(.debug_info); }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev); }
|
||||
@ -31,6 +36,7 @@ SECTIONS {
|
||||
.debug_line 0 : { *(.debug_line); }
|
||||
.debug_str 0 : { *(.debug_str); }
|
||||
.debug_line_str 0 : { *(.debug_line_str); }
|
||||
.debug_gdb_scripts 0 : { *(.debug_gdb_scripts); }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(*);
|
||||
|
6
lcrash/setup/compressed/cckernel.S.in
Normal file
6
lcrash/setup/compressed/cckernel.S.in
Normal file
@ -0,0 +1,6 @@
|
||||
.section ".cckernel", "a"
|
||||
.globl _CC_cckernel
|
||||
_CC_cckernel:
|
||||
.incbin "@COMPRESSED_KERNEL_PATH@"
|
||||
.globl _CC_ecckernel
|
||||
_CC_ecckernel:
|
35
lcrash/setup/compressed/compressed.ld
Normal file
35
lcrash/setup/compressed/compressed.ld
Normal file
@ -0,0 +1,35 @@
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
|
||||
SECTIONS {
|
||||
_CC_start = .;
|
||||
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.cckernel : {
|
||||
*(.cckernel)
|
||||
}
|
||||
|
||||
_CC_end = .;
|
||||
|
||||
.bss : {
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
.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); }
|
||||
.debug_gdb_scripts 0 : { *(.debug_gdb_scripts); }
|
||||
|
||||
/DISCARD/ : {
|
||||
*(*);
|
||||
}
|
||||
|
||||
/* ASSERT(entry64 != 0x200, "entry64 is not the entry point, this should never happen.") */
|
||||
}
|
7
lcrash/setup/compressed/elf.c
Normal file
7
lcrash/setup/compressed/elf.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "elf.h"
|
||||
|
||||
int ElfExecute(void* Binary, void* LoadAddr) {
|
||||
|
||||
|
||||
while (1) {}
|
||||
}
|
36
lcrash/setup/compressed/elf.h
Normal file
36
lcrash/setup/compressed/elf.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
[[packed]]
|
||||
struct Elf64_Ehdr {
|
||||
c8 e_ident[16];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u64 e_entry;
|
||||
u64 e_phoff;
|
||||
u64 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shentnum;
|
||||
u16 e_shstrndx;
|
||||
};
|
||||
|
||||
[[packed]]
|
||||
struct Elf64_Phdr {
|
||||
u32 p_type;
|
||||
u32 p_flags;
|
||||
u64 p_offset;
|
||||
u64 p_vaddr;
|
||||
u64 p_paddr;
|
||||
u64 p_filesz;
|
||||
u64 p_memsz;
|
||||
u64 p_align;
|
||||
};
|
||||
|
||||
/// We don't have space to allocate memory, so we have no idea where we can pass back ELF state, we'll have to do this all at once
|
||||
int ElfExecute(void* Binary, void* LoadAddr);
|
32
lcrash/setup/compressed/entry64.S
Normal file
32
lcrash/setup/compressed/entry64.S
Normal file
@ -0,0 +1,32 @@
|
||||
.section ".text", "ax"
|
||||
.org 0x200
|
||||
.global entry64
|
||||
entry64: // 64-bit entry point for kernel decompression
|
||||
// get the cckernel image base. if the opcode generated by the assembler changes, this will break
|
||||
lea -0x207(%rip), %rdi
|
||||
|
||||
// we might get some stack space from the previous kernel, but we have no idea how much
|
||||
// it could just be a few bytes for all we know. it's far safer to just use our own
|
||||
mov $einit_stack, %rsp
|
||||
mov %rsp, %rbp
|
||||
|
||||
// lets get out of here -- ccmain(rdi: IMGBASE, rsi: BOOTPARAMS)
|
||||
call ccmain
|
||||
|
||||
// what the fuck is going on, why have you returned here, was my work not enough for you
|
||||
// ungrateful fucking machine. away with you, you do not deserve the privilege of my
|
||||
// loving grace.
|
||||
int3
|
||||
int3
|
||||
int3
|
||||
int3
|
||||
|
||||
// begone
|
||||
cli
|
||||
1: hlt
|
||||
jmp 1b
|
||||
|
||||
.section ".bss"
|
||||
init_stack: // this should be sufficient for kernel decompression
|
||||
.skip 0x8000, 0
|
||||
einit_stack:
|
304
lcrash/setup/compressed/gzip.c
Normal file
304
lcrash/setup/compressed/gzip.c
Normal file
@ -0,0 +1,304 @@
|
||||
#include "gzip.h"
|
||||
|
||||
// we build a table of uh everything. this uses a lot of stack space,
|
||||
void GzipPopulateTable(
|
||||
u8* InputLengths, // Lengths of symbol bits
|
||||
uptr InputCount, // Number of symbols
|
||||
u8* OutputLengths, // Output bit lengths
|
||||
u32* OutputSymbols, // Output symbols
|
||||
uptr OutputCount, // Number of outputs
|
||||
uptr OutputBits // Highest bit length
|
||||
) {
|
||||
u32 NextSym[15]; /// Next symbol for a specific bit length
|
||||
for (int i = 0; i < 15; i++) NextSym[i] = -1;
|
||||
|
||||
// Count the symbols in each bit length
|
||||
u32 CodeCounts[15] = {};
|
||||
for (int i = 0; i < InputCount; i++) {
|
||||
CodeCounts[InputLengths[i]]++;
|
||||
if (NextSym[InputLengths[i]] == -1) NextSym[InputLengths[i]] = i;
|
||||
}
|
||||
|
||||
// Ignore null symbols
|
||||
CodeCounts[0] = 0;
|
||||
|
||||
// Find lowest code for each bit length
|
||||
u32 Code = 0;
|
||||
u32 NextCode[15] = {}; // Next code to add to the table
|
||||
for (u32 Bits = 1; Bits < 15; Bits++) {
|
||||
Code = (Code + CodeCounts[Bits - 1]) << 1;
|
||||
NextCode[Bits] = Code;
|
||||
}
|
||||
|
||||
// Fill in the table in a horribly inefficient manner
|
||||
Code = 0;
|
||||
for (u32 Bits = 0; Bits < 15; Bits++) {
|
||||
const uptr OutputMask = ~(-1 << Bits);
|
||||
for (int i = 0; i < CodeCounts[Bits]; i++) {
|
||||
// Take the next symbol
|
||||
Code = NextSym[Bits];
|
||||
|
||||
// Set the next next symbol
|
||||
for (int j = Code + 1; j < InputCount; j++) {
|
||||
if (InputLengths[j] == Bits) {
|
||||
NextSym[Bits] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reverse the bits i dont fucking know it doesn't work if i dont
|
||||
u32 Reversed = 0;
|
||||
for (int j = 0; j < Bits; j++) {
|
||||
Reversed |= ((NextCode[Bits] >> j) & 1) << (Bits - j - 1);
|
||||
}
|
||||
|
||||
// this is horrible
|
||||
for (int j = 0; j < OutputCount; j++) {
|
||||
if ((j & OutputMask) == Reversed) {
|
||||
OutputLengths[j] = Bits;
|
||||
OutputSymbols[j] = Code;
|
||||
}
|
||||
}
|
||||
|
||||
// Next
|
||||
NextCode[Bits]++;
|
||||
Code++;
|
||||
}
|
||||
}
|
||||
|
||||
// "Good Practice" insists that i inform you that this is in fact, a return statement.
|
||||
return;
|
||||
}
|
||||
|
||||
u64 GzipFetchBits(u8* Stream, u64* Location, uptr Length) {
|
||||
u64 Output = 0;
|
||||
for (uptr i = 0; i < Length; i++) {
|
||||
Output |= ((Stream[*Location / 8] >> (*Location % 8)) & 1) << i;
|
||||
*Location += 1;
|
||||
}
|
||||
return Output;
|
||||
}
|
||||
|
||||
uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output) {
|
||||
#define TAKE_(_TYPE) (\
|
||||
(Location += sizeof(_TYPE)), \
|
||||
*(_TYPE*)(Location - sizeof(_TYPE)) \
|
||||
)
|
||||
|
||||
const u32 LengthAddends[29] = {
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
|
||||
15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
|
||||
67, 83, 99, 115, 131, 163, 195, 227, 258
|
||||
};
|
||||
|
||||
const u32 DistanceAddends[30] = {
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025,
|
||||
1537, 2049, 3073, 40097, 6145, 8193, 12289, 15385, 24577
|
||||
};
|
||||
|
||||
void* Location = (void*)Input;
|
||||
void* End = Location + InputSize;
|
||||
void* BinaryStart = (void*)Output;
|
||||
|
||||
// each member hopefully. any bug will result in complete failure c:
|
||||
// we dont even bother making sure it's valid, we have no way to tell
|
||||
// the user there's something wrong
|
||||
while (Location < End) {
|
||||
c8 Id1 = TAKE_(c8);
|
||||
c8 Id2 = TAKE_(c8);
|
||||
|
||||
u8 Method = TAKE_(u8);
|
||||
u8 Flags = TAKE_(u8);
|
||||
u32 LastModified = TAKE_(u32);
|
||||
u8 ExtraFlags = TAKE_(u8);
|
||||
u8 OperatingSystem = TAKE_(u8);
|
||||
|
||||
// for the magic extra field
|
||||
u16 XLen = 0;
|
||||
void* XBuf = 0;
|
||||
if (Flags & 0x04) { // FLG.FEXTRA
|
||||
XLen = TAKE_(u16);
|
||||
XBuf = Location;
|
||||
Location += XLen;
|
||||
}
|
||||
|
||||
// filename
|
||||
c8* FileName = 0;
|
||||
if (Flags & 0x08) { // FLG.FNAME
|
||||
FileName = Location;
|
||||
while (TAKE_(c8) != 0) {}
|
||||
}
|
||||
|
||||
// comment
|
||||
c8* FileComment = 0;
|
||||
if (Flags & 0x10) { // FLG.FCOMMENT
|
||||
FileComment = Location;
|
||||
while (TAKE_(c8) != 0) {}
|
||||
}
|
||||
|
||||
// hash
|
||||
u16 CRC16 = 0;
|
||||
if (Flags & 0x02) { // FLG.FHCRC
|
||||
CRC16 = TAKE_(u16);
|
||||
}
|
||||
|
||||
u8* Stream = Location;
|
||||
u64 BitLocation = 0;
|
||||
while (true) {
|
||||
u8 head = GzipFetchBits(Stream, &BitLocation, 3);
|
||||
switch ((head & 0x06) >> 1) {
|
||||
case 0: { // NO COMPRESSION
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// FIXED HUFFMAN
|
||||
break;
|
||||
}
|
||||
case 2: { // DYNAMIC HUFFMAN
|
||||
// Get huffman code counts
|
||||
u64 OperationCount = GzipFetchBits(Stream, &BitLocation, 5) + 257;
|
||||
u64 DistanceCount = GzipFetchBits(Stream, &BitLocation, 5) + 1;
|
||||
u64 CodeCount = GzipFetchBits(Stream, &BitLocation, 4) + 4;
|
||||
|
||||
const u8 CodeLengthLengthOffset[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
|
||||
u8 CodeLengthLengthProto[19] = {};
|
||||
for (int i = 0; i < CodeCount; i++) {
|
||||
CodeLengthLengthProto[CodeLengthLengthOffset[i]] = GzipFetchBits(Stream, &BitLocation, 3);
|
||||
}
|
||||
|
||||
// Build our decoding tables
|
||||
u8 CodeLengthLengths[0x80] = {};
|
||||
u32 CodeLengthSymbols[0x80] = {};
|
||||
GzipPopulateTable(CodeLengthLengthProto, 19, CodeLengthLengths, CodeLengthSymbols, 0x80, 7);
|
||||
|
||||
// Collect lengths
|
||||
u8 Lengths[OperationCount + DistanceCount] = {};
|
||||
uptr CurrentLen = 0;
|
||||
while (CurrentLen < OperationCount + DistanceCount) {
|
||||
// Fetch the next op
|
||||
u64 Code = GzipFetchBits(Stream, &BitLocation, 7);
|
||||
u64 Error = 7 - CodeLengthLengths[Code];
|
||||
BitLocation -= Error;
|
||||
Code = CodeLengthSymbols[Code];
|
||||
|
||||
if (Code < 16) { // Literal
|
||||
Lengths[CurrentLen++] = Code;
|
||||
} else { // Repeat
|
||||
u64 RepeatCount = 0;
|
||||
u64 RepeatedLen = 0;
|
||||
|
||||
if (Code == 16) {
|
||||
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 2);
|
||||
RepeatedLen = Lengths[CurrentLen - 1];
|
||||
} else if (Code == 17) {
|
||||
RepeatCount = 3 + GzipFetchBits(Stream, &BitLocation, 3);
|
||||
} else if (Code == 18) {
|
||||
RepeatCount =11 + GzipFetchBits(Stream, &BitLocation, 7);
|
||||
} else {} // Should be unreachable
|
||||
|
||||
for (int i = 0; i < RepeatCount; i++) {
|
||||
Lengths[CurrentLen++] = RepeatedLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build operation table
|
||||
u32 OperationMaxBits = 0;
|
||||
for (int i = 0; i < OperationCount; i++) {
|
||||
if (Lengths[i] > OperationMaxBits) OperationMaxBits = Lengths[i];
|
||||
}
|
||||
|
||||
// We have no standard library
|
||||
u32 OperationTableLength = 1;
|
||||
for (int i = 0; i < OperationMaxBits; i++) OperationTableLength *= 2;
|
||||
|
||||
// Tables
|
||||
u32 OperationSymbols[OperationTableLength + 0x10];
|
||||
u8 OperationLengths[OperationTableLength + 0x10];
|
||||
GzipPopulateTable(Lengths, OperationCount,
|
||||
OperationLengths, OperationSymbols, OperationTableLength,
|
||||
OperationMaxBits);
|
||||
|
||||
// Build distance tables
|
||||
u32 DistanceMaxBits = 0;
|
||||
for (int i = 0; i < DistanceCount; i++) {
|
||||
if (Lengths[OperationCount + i] > DistanceMaxBits) {
|
||||
DistanceMaxBits = Lengths[OperationCount + i];
|
||||
}
|
||||
}
|
||||
|
||||
// Power
|
||||
u32 DistanceTableLength = 1;
|
||||
for (int i = 0; i < DistanceMaxBits; i++) DistanceTableLength *= 2;
|
||||
|
||||
// More tables
|
||||
u32 DistanceSymbols[DistanceTableLength + 0x10]; // ad dsome padding theres some bugs i cant see
|
||||
u8 DistanceLengths[DistanceTableLength + 0x10];
|
||||
GzipPopulateTable(Lengths + OperationCount, DistanceCount,
|
||||
DistanceLengths, DistanceSymbols, DistanceTableLength,
|
||||
DistanceMaxBits);
|
||||
|
||||
// Inflate
|
||||
while (Location + BitLocation / 8 < End) {
|
||||
// Fetch
|
||||
u32 Code = GzipFetchBits(Stream, &BitLocation, OperationMaxBits);
|
||||
u64 Error = OperationMaxBits - OperationLengths[Code];
|
||||
BitLocation -= Error;
|
||||
Code = OperationSymbols[Code];
|
||||
|
||||
if (Code < 256) { // Literal
|
||||
*Output++ = Code;
|
||||
} else if (Code == 256) { // End block
|
||||
break;
|
||||
} else if (Code < OperationCount) { // Copy
|
||||
// You'd need to look at the spec yourself to understand this
|
||||
u32 CopyLength = GzipFetchBits(Stream, &BitLocation,
|
||||
Code <= 284 && Code > 264
|
||||
? (Code - 1) / 4 - 65
|
||||
: 0)
|
||||
+ LengthAddends[Code - 257];
|
||||
|
||||
// More bitstream shit! I'm done formatting this stuff nicely.
|
||||
Code = GzipFetchBits(Stream, &BitLocation, DistanceMaxBits);
|
||||
Error = DistanceMaxBits - DistanceLengths[Code];
|
||||
BitLocation -= Error;
|
||||
Code = DistanceSymbols[Code];
|
||||
|
||||
// make this a s32 because address and offset awaaa
|
||||
s32 Distance = GzipFetchBits(Stream, &BitLocation,
|
||||
Code > 3 && Code <= 29
|
||||
? (Code - 2) / 2
|
||||
: 0)
|
||||
+ DistanceAddends[Code];
|
||||
|
||||
// Finally copy the thing
|
||||
for (int i = 0; i < CopyLength; i++) {
|
||||
Output[i] = Output[i - Distance];
|
||||
}
|
||||
|
||||
Output += CopyLength;
|
||||
} else { while (1) {} } // Unreachable unless invalid
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// THIS SHOULD NEVER HAPPEN
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (head & 0x01) break; // BFINAL
|
||||
}
|
||||
|
||||
// I think this is necessary but im not completely sure
|
||||
Location += BitLocation / 8 + 1;
|
||||
|
||||
// trailer..? hey siri, what's the opposite of a header?
|
||||
u32 CRC32 = TAKE_(u32);
|
||||
u32 InputSize = TAKE_(u32);
|
||||
}
|
||||
|
||||
return (void*)Output - BinaryStart;
|
||||
|
||||
#undef TAKE_
|
||||
}
|
5
lcrash/setup/compressed/gzip.h
Normal file
5
lcrash/setup/compressed/gzip.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output);
|
30
lcrash/setup/compressed/main.c
Normal file
30
lcrash/setup/compressed/main.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "../../lnxboot.h"
|
||||
|
||||
#include "gzip.h"
|
||||
#include "elf.h"
|
||||
|
||||
extern void* _CC_cckernel;
|
||||
extern void* _CC_ecckernel;
|
||||
|
||||
/// C entry point for cckernel
|
||||
[[noreturn]]
|
||||
void ccmain(void* imgbase, struct boot_params* boot_params) {
|
||||
struct setup_info* setup_info = (struct setup_info*)((void*)boot_params + 0x1f1);
|
||||
|
||||
char* kernel_load_addr = (char*)setup_info->code32_start;
|
||||
if (kernel_load_addr == 0) kernel_load_addr = (char*)0x100000;
|
||||
|
||||
char* cckernel = imgbase + (uptr)&_CC_cckernel;
|
||||
//for (long i = 0; i < setup_info->payload_length; i++) {
|
||||
// kernel_load_addr[i] = cckernel[i];
|
||||
//}
|
||||
|
||||
// decompress the kernel
|
||||
uptr BinaryLength = GzipDecompress(cckernel, (u8*)&_CC_ecckernel - (u8*)&_CC_cckernel, kernel_load_addr);
|
||||
|
||||
// start the kernel
|
||||
ElfExecute(kernel_load_addr, kernel_load_addr + BinaryLength + 0x1000 - BinaryLength % 0x1000);
|
||||
|
||||
// we fucked up
|
||||
while (1) {}
|
||||
}
|
9
lcrash/setup/compressed/mem.S
Normal file
9
lcrash/setup/compressed/mem.S
Normal file
@ -0,0 +1,9 @@
|
||||
/// File with support code for gcc memory stuff
|
||||
.section ".text", "ax"
|
||||
.globl memset
|
||||
memset:
|
||||
mov %rdx, %rcx
|
||||
mov %sil, %al
|
||||
rep stosb (%rdi)
|
||||
mov %rdi, %rax
|
||||
ret
|
64
lcrash/setup/header.S
Normal file
64
lcrash/setup/header.S
Normal file
@ -0,0 +1,64 @@
|
||||
#include <lcrashkern_locs.h>
|
||||
|
||||
.extern _end
|
||||
.extern cckernel_size
|
||||
.extern cckernel_start
|
||||
|
||||
.section ".header", "ax"
|
||||
.globl setup_info
|
||||
setup_sects: .byte setup_sectors - 1
|
||||
root_flags: .word 0
|
||||
syssize: .long KK__ebss / 16
|
||||
ram_size: .word 0
|
||||
vid_mode: .word 0
|
||||
root_dev: .word 0
|
||||
boot_flag: .word 0xAA55
|
||||
.globl _start
|
||||
_start:
|
||||
jump: .byte 0xeb
|
||||
.byte -2 // entrylow - 1f
|
||||
1:
|
||||
signature: .ascii "HdrS"
|
||||
version: .word 0x020f
|
||||
realmode_switch: .word 0, 0
|
||||
start_sys_seg: .word 0
|
||||
.word 0 //kernel_version - 512
|
||||
type_of_loader: .byte 0
|
||||
loadflags: .byte 0x81
|
||||
setup_move_size: .word 0x8000
|
||||
code32_start: .long 0 # .long 0x100000
|
||||
ramdisk_image: .long 0
|
||||
ramdisk_size: .long 0
|
||||
bootsect_kludge: .long 0
|
||||
heap_end_ptr: .word 0 # _end + 512
|
||||
ext_loader_ver: .byte 0
|
||||
ext_loader_type: .byte 0
|
||||
cmd_line_ptr: .long 0
|
||||
initrd_addr_max: .long 0x7fffffff
|
||||
kernel_alignment: .long 1
|
||||
relocatable_kernel: .byte 1
|
||||
min_alignment: .byte 1
|
||||
xloadflags: .word 0x13
|
||||
cmdline_size: .long 512
|
||||
hardware_subarch: .long 0
|
||||
hardware_subarch_data: .quad 0
|
||||
payload_offset: .long _end // cckernel_start
|
||||
payload_length: .long _KKCLEN // cckernel_size
|
||||
setup_data: .quad 0
|
||||
pref_address: .quad 0
|
||||
init_size: .long 0x20000 // a bit of space
|
||||
handover_offset: .long 0 // TODO
|
||||
kernel_info_offset: .long 0 // TODO
|
||||
/* .globl entrylow
|
||||
.section ".entrytext", "ax"
|
||||
entrylow:
|
||||
1: jmp 1b
|
||||
2: jmp 2b
|
||||
3: jmp 3b
|
||||
4: jmp 4b
|
||||
5: jmp 5b
|
||||
6: jmp 6b
|
||||
7: jmp 7b
|
||||
|
||||
.section ".initdata", "a"
|
||||
kernel_version: .asciz "lcrash 0.1.0"*/
|
37
lcrash/setup/setup.ld
Normal file
37
lcrash/setup/setup.ld
Normal file
@ -0,0 +1,37 @@
|
||||
/* linker script shamelessly ripped from the linux kernel */
|
||||
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0;
|
||||
|
||||
. = 0x1F1;
|
||||
.header : { *(.header); }
|
||||
.entrytext : { *(.entrytext); }
|
||||
.inittext : { *(.inittext); }
|
||||
.initdata : { *(.initdata); }
|
||||
|
||||
/* i dont actually know what this does, but it seems important */
|
||||
.signature : {
|
||||
setup_sig = .;
|
||||
LONG(0x5a5aaa55);
|
||||
|
||||
setup_size = ALIGN(ABSOLUTE(.), 4096);
|
||||
setup_sectors = ABSOLUTE(setup_size / 512);
|
||||
}
|
||||
|
||||
. = ALIGN(16);
|
||||
.bss : {
|
||||
__bss_start = .;
|
||||
*(.bss);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
_end = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note.*);
|
||||
}
|
||||
}
|
29
lcrash/types.h
Normal file
29
lcrash/types.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
|
||||
typedef char c8;
|
||||
typedef short c16;
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
typedef u8 bool;
|
||||
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
typedef u32 uptr;
|
||||
typedef s32 sptr;
|
||||
#elif __SIZEOF_POINTER__ == 8
|
||||
typedef u64 uptr;
|
||||
typedef s64 sptr;
|
||||
#else
|
||||
#error What the fuck? [pointers are not 4 or 8 bytes long]
|
||||
#endif
|
13
lcrash/util.c
Normal file
13
lcrash/util.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "util.h"
|
||||
#include "types.h"
|
||||
|
||||
bool CompareMemory(void* Addr1, void* Addr2, uptr Length) {
|
||||
u8* Data1 = Addr1;
|
||||
u8* Data2 = Addr2;
|
||||
|
||||
for (uptr i = 0; i < Length; i++) {
|
||||
if (Data1[i] != Data2[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
8
lcrash/util.h
Normal file
8
lcrash/util.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/**
|
||||
* Compare the data at two memory addresses
|
||||
*/
|
||||
bool CompareMemory(void* Addr1, void* Addr2, uptr Length);
|
16
scripts/gdb/lcrash.gdb
Normal file
16
scripts/gdb/lcrash.gdb
Normal file
@ -0,0 +1,16 @@
|
||||
define info bootparams
|
||||
set $f_info_bootparams_boot_params = (struct boot_params*)$arg0
|
||||
set $f_info_bootparams_efi_system_table = (struct EfiSystemTable*)(((long)$f_info_bootparams_boot_params->efi_info.EfiSystemTable) | ((long)$f_info_bootparams_boot_params->efi_info.EfiSystemTableHigh << 32))
|
||||
set $f_info_bootparams_efi_memory_map = (struct EfiMemoryDescription*)(((long)$f_info_bootparams_boot_params->efi_info.EfiMemoryMap) | ((long)$f_info_bootparams_boot_params->efi_info.EfiMemoryMapHigh << 32))
|
||||
|
||||
printf "Boot Params: *0x%llx\n", $f_info_bootparams_boot_params
|
||||
printf " EFI info:\n"
|
||||
printf " System Table: *0x%llx\n", $f_info_bootparams_efi_system_table
|
||||
printf " Memory map: *0x%llx\n", $f_info_bootparams_efi_memory_map
|
||||
set $f_info_bootparams_i = 0
|
||||
while $f_info_bootparams_i < $f_info_bootparams_boot_params->efi_info.EfiMemoryMapSize
|
||||
set $f_info_bootparams_mmcurrentdesc = (struct EfiMemoryDescription*)((void*)$f_info_bootparams_efi_memory_map + $f_info_bootparams_i)
|
||||
printf " Entry 0x%016llx-0x%016llx -> 0x%016llx T:%016llx A:%016llx\n", $f_info_bootparams_mmcurrentdesc->VirtualStart, $f_info_bootparams_mmcurrentdesc->VirtualStart + 0x1000 * $f_info_bootparams_mmcurrentdesc->NumberOfPages, $f_info_bootparams_mmcurrentdesc->PhysicalStart, $f_info_bootparams_mmcurrentdesc->Type, $f_info_bootparams_mmcurrentdesc->Attribute
|
||||
set $f_info_bootparams_i += $f_info_bootparams_boot_params->efi_info.EfiMemoryDescriptionSize
|
||||
end
|
||||
end
|
@ -2,5 +2,5 @@
|
||||
clear
|
||||
|
||||
# boot
|
||||
linux /Windows/vmlinux.exe console=tty0 console=ttyS0 root=PARTUUID=48d29da8-2ff8-4f23-ba1a-0e8ccfc329e2 rootflags=force rw init=/Windows/System32/lexecutive.exe loglevel=8 crashkernel=16M
|
||||
linux /Windows/vmlinux.exe console=tty0 console=ttyS0 root=PARTUUID=48d29da8-2ff8-4f23-ba1a-0e8ccfc329e2 rootflags=force rw init=/Windows/System32/lexecutive.exe loglevel=8 crashkernel=48M dyndbg nokaslr
|
||||
boot
|
||||
|
@ -5074,14 +5074,23 @@ CONFIG_DEBUG_MISC=y
|
||||
#
|
||||
# Compile-time checks and compiler options
|
||||
#
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_AS_HAS_NON_CONST_LEB128=y
|
||||
CONFIG_DEBUG_INFO_NONE=y
|
||||
# CONFIG_DEBUG_INFO_NONE is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
CONFIG_DEBUG_INFO_DWARF5=y
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_NONE is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_ZLIB=y
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZSTD is not set
|
||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
||||
CONFIG_PAHOLE_HAS_SPLIT_BTF=y
|
||||
CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y
|
||||
CONFIG_GDB_SCRIPTS=y
|
||||
CONFIG_FRAME_WARN=2048
|
||||
# CONFIG_STRIP_ASM_SYMS is not set
|
||||
# CONFIG_READABLE_ASM is not set
|
||||
CONFIG_READABLE_ASM=y
|
||||
# CONFIG_HEADERS_INSTALL is not set
|
||||
# CONFIG_DEBUG_SECTION_MISMATCH is not set
|
||||
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
|
||||
|
Loading…
x
Reference in New Issue
Block a user