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
|
# compiler stuff
|
||||||
set(LW_CROSS_CC "${CMAKE_CURRENT_BINARY_DIR}/gcc/prefix/bin/gcc")
|
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_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_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_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})
|
set(LW_CROSS_CFLAGS -nostdinc ${LW_CROSS_INCFLAGS})
|
||||||
@ -61,6 +62,7 @@ function(lw_project PROJECTNAME)
|
|||||||
elseif(${ARG_TARGET} STREQUAL "LINDOWS")
|
elseif(${ARG_TARGET} STREQUAL "LINDOWS")
|
||||||
set(CMAKE_C_COMPILER "${LW_CROSS_CC}" PARENT_SCOPE)
|
set(CMAKE_C_COMPILER "${LW_CROSS_CC}" PARENT_SCOPE)
|
||||||
set(CMAKE_CXX_COMPILER "${LW_CROSS_CXX}" 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 "")
|
set_property(DIRECTORY . PROPERTY INCLUDE_DIRECTORIES "")
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Unrecognized target type \"${ARG_TARGET}\"")
|
message(FATAL_ERROR "Unrecognized target type \"${ARG_TARGET}\"")
|
||||||
|
@ -5,14 +5,72 @@ lw_project(lcrash
|
|||||||
TARGET LINDOWS
|
TARGET LINDOWS
|
||||||
)
|
)
|
||||||
|
|
||||||
lw_add_executable(lcrash
|
enable_language(ASM)
|
||||||
SOURCES lcrash.c efi/memmap.c
|
|
||||||
|
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)
|
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
|
set_property(TARGET lcrash PROPERTY LINK_DEPENDS
|
||||||
$<TARGET_FILE:lcrashld>
|
$<TARGET_FILE:lcrashld>
|
||||||
$<TARGET_FILE:LindowsCompilerSpec>
|
$<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 "lnxboot.h"
|
||||||
|
#include "util.h"
|
||||||
#include "efi/types.h"
|
#include "efi/types.h"
|
||||||
#include "efi/memmap.h"
|
#include "efi/memmap.h"
|
||||||
|
#include "efi/guid.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;
|
|
||||||
|
|
||||||
unsigned short serial_port;
|
unsigned short serial_port;
|
||||||
|
|
||||||
@ -84,28 +61,12 @@ void Panic(const char* message) {
|
|||||||
Hang();
|
Hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[gnu::section(".text._start"), gnu::naked, gnu::no_reorder]]
|
void entry64() {
|
||||||
extern void _start() {
|
while (1) {};
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// 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));
|
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.EfiMemoryMapSize / boot_params->efi_info.EfiMemoryDescriptionSize,
|
||||||
boot_params->efi_info.EfiMemoryDescriptionSize
|
boot_params->efi_info.EfiMemoryDescriptionSize
|
||||||
);
|
);
|
||||||
|
|
||||||
FirmwareVendor = EfiTranslatePointer(systab_ptr->FirmwareVendor);
|
|
||||||
while (1) {
|
|
||||||
volatile char* a = FirmwareVendor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- find acpi --
|
// -- find acpi --
|
||||||
@ -138,9 +94,22 @@ void entry() {
|
|||||||
// check bootparams
|
// check bootparams
|
||||||
if (boot_params->acpi_rsdp_addr) AcpiRSDP = boot_params->acpi_rsdp_addr;
|
if (boot_params->acpi_rsdp_addr) AcpiRSDP = boot_params->acpi_rsdp_addr;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
volatile void* a = &EFI_ACPI_20_TABLE_GUID;
|
||||||
|
}
|
||||||
|
|
||||||
// check efi
|
// check efi
|
||||||
if (!AcpiRSDP && systab_ptr && systab_ptr->NumberOfTableEntries) {
|
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
|
// 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");
|
if (!AcpiRSDP) Panic("Failed to find ACPI RSDP");
|
||||||
|
|
||||||
// do we have acpi?
|
// 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
|
// 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.
|
// for some fucking reason. allocate our strings and shit on the stack.
|
||||||
@ -191,6 +162,6 @@ void entry() {
|
|||||||
// serial_puts("test\n");
|
// serial_puts("test\n");
|
||||||
// serial_puts(bzhead.cmd_line_ptr);
|
// serial_puts(bzhead.cmd_line_ptr);
|
||||||
|
|
||||||
// Die.
|
// Die.*/
|
||||||
Panic("Nothing left to do.");
|
Panic("Nothing left to do.");
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,33 @@
|
|||||||
OUTPUT_FORMAT(elf64-x86-64)
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(entry64)
|
||||||
|
|
||||||
MEMORY {
|
|
||||||
code (rx) : ORIGIN = 0x0dfe8000, LENGTH = 0x00001000
|
|
||||||
data (rw) : ORIGIN = 0x0dff0000, LENGTH = 0x00001000
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.lnxhead 0x01f1 : ALIGN(1) {
|
. = 0;
|
||||||
*(.lnxhead);
|
|
||||||
|
.text : {
|
||||||
|
_text = .;
|
||||||
|
*(.text);
|
||||||
|
_etext = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rodata : ALIGN(1) {
|
.rodata : {
|
||||||
|
_rodata = .;
|
||||||
*(.rodata);
|
*(.rodata);
|
||||||
} > data
|
_erodata = .;
|
||||||
|
}
|
||||||
|
|
||||||
/* this section helps us to coerce the linker into not breaking down because of big addresses */
|
.data : {
|
||||||
.text._start 0xdfe8000 : ALIGN(1) {
|
_data = .;
|
||||||
*(.text._start);
|
*(.data);
|
||||||
} > code
|
_edata = .;
|
||||||
|
}
|
||||||
|
|
||||||
.text : ALIGN(512) { *(.text); } > code
|
.bss : {
|
||||||
.bss : { *(.bss); }
|
_bss = .;
|
||||||
|
*(.bss);
|
||||||
|
_ebss = .;
|
||||||
|
}
|
||||||
|
|
||||||
.debug_info 0 : { *(.debug_info); }
|
.debug_info 0 : { *(.debug_info); }
|
||||||
.debug_abbrev 0 : { *(.debug_abbrev); }
|
.debug_abbrev 0 : { *(.debug_abbrev); }
|
||||||
@ -31,6 +36,7 @@ SECTIONS {
|
|||||||
.debug_line 0 : { *(.debug_line); }
|
.debug_line 0 : { *(.debug_line); }
|
||||||
.debug_str 0 : { *(.debug_str); }
|
.debug_str 0 : { *(.debug_str); }
|
||||||
.debug_line_str 0 : { *(.debug_line_str); }
|
.debug_line_str 0 : { *(.debug_line_str); }
|
||||||
|
.debug_gdb_scripts 0 : { *(.debug_gdb_scripts); }
|
||||||
|
|
||||||
/DISCARD/ : {
|
/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
|
clear
|
||||||
|
|
||||||
# boot
|
# 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
|
boot
|
||||||
|
@ -5074,14 +5074,23 @@ CONFIG_DEBUG_MISC=y
|
|||||||
#
|
#
|
||||||
# Compile-time checks and compiler options
|
# Compile-time checks and compiler options
|
||||||
#
|
#
|
||||||
|
CONFIG_DEBUG_INFO=y
|
||||||
CONFIG_AS_HAS_NON_CONST_LEB128=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_DWARF_TOOLCHAIN_DEFAULT is not set
|
||||||
# CONFIG_DEBUG_INFO_DWARF4 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_FRAME_WARN=2048
|
||||||
# CONFIG_STRIP_ASM_SYMS is not set
|
# CONFIG_STRIP_ASM_SYMS is not set
|
||||||
# CONFIG_READABLE_ASM is not set
|
CONFIG_READABLE_ASM=y
|
||||||
# CONFIG_HEADERS_INSTALL is not set
|
# CONFIG_HEADERS_INSTALL is not set
|
||||||
# CONFIG_DEBUG_SECTION_MISMATCH is not set
|
# CONFIG_DEBUG_SECTION_MISMATCH is not set
|
||||||
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
|
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
|
||||||
|
Loading…
x
Reference in New Issue
Block a user