add KePanic instead of splattering _disable __halt everywhere, implement a DMA + interrupts path to the IDE driver, move the dynamic arrays from kmain.c to ke_utils.h, remove weird unicode chars
This commit is contained in:
1 parent
83d48e09bb
commit
4b57738fe3
15 files changed
+673
-219
No files matched your search
+26
-4
@@ -14,6 +14,12 @@ void kernel_putchar(char c) {
|
||||
PrintChar(c, 0x00FF00, 0x000000);
|
||||
}
|
||||
|
||||
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v) {
|
||||
gDebugEnabled = v;
|
||||
PrintChar = PrintPtr;
|
||||
printf_set_putchar(kernel_putchar);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void DbgPrint(const char* fmt, ...) {
|
||||
if (!gDebugEnabled) return;
|
||||
|
||||
@@ -26,8 +32,24 @@ __declspec(dllexport) void DbgPrint(const char* fmt, ...) {
|
||||
KeReleaseSpinlock(&sl, flags);
|
||||
}
|
||||
|
||||
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v) {
|
||||
gDebugEnabled = v;
|
||||
PrintChar = PrintPtr;
|
||||
printf_set_putchar(kernel_putchar);
|
||||
// KePanic - Forces output even if debug was compiled out, then the macro halts.
|
||||
__declspec(dllexport) _Noreturn void KePanic(const char *fmt, ...) {
|
||||
// We are done, go away
|
||||
_disable();
|
||||
|
||||
// Print a bright-red banner so the framebuffer is unmistakable.
|
||||
// We call PrintChar directly so we can set a red foreground.
|
||||
// (DbgPrint uses green; we want this visually distinct.)
|
||||
static const char banner[] = "\n*** KERNEL PANIC ***\n";
|
||||
for (const char *p = banner; *p; p++)
|
||||
PrintChar(*p, 0xFF2222, 0x000000);
|
||||
|
||||
// Now print the caller's message through the normal vprintf path.
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vprintf(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
// Halt it!
|
||||
while (true) __halt();
|
||||
}
|
||||
@@ -5,5 +5,6 @@
|
||||
|
||||
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v);
|
||||
__declspec(dllexport) void DbgPrint(const char* fmt, ...);
|
||||
__declspec(dllexport) void KePanic(const char *fmt, ...);
|
||||
|
||||
#endif // KE_DEBUG_H
|
||||
#endif // KE_DEBUG_H
|
||||
@@ -39,7 +39,7 @@ __declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) {
|
||||
else
|
||||
ListInsertTail(&q->Head, &irp->Link);
|
||||
KeReleaseSpinlock(&q->Lock, flags);
|
||||
// Signal outside the spinlock — safe, and avoids priority-inversion risk.
|
||||
// Signal outside the spinlock - safe, and avoids priority-inversion risk.
|
||||
KeSignalSemaphore((SEMAPHORE *)q->Semaphore);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ __declspec(dllexport) KSTATUS IoSubmitIrp(IRP *irp) {
|
||||
|
||||
if (st == STATUS_SUCCESS) {
|
||||
// Sync fallback ran; irp->Status is already written.
|
||||
// Fire completion hooks now — we are in kernel context so this is safe.
|
||||
// Fire completion hooks now - we are in kernel context so this is safe.
|
||||
if (irp->CompletionEvent)
|
||||
KeSignalEvent((EVENT *)irp->CompletionEvent);
|
||||
if (irp->CompletionFn)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// ke_irp.h - I/O Request Packet
|
||||
//
|
||||
// This header intentionally includes only ke_list.h, ke_spinlock.h, and
|
||||
// ke_status.h — all of which are pure-inline / macro headers with no
|
||||
// ke_status.h - all of which are pure-inline / macro headers with no
|
||||
// external symbol references. ke_event.h and ke_semaphore.h are forward-
|
||||
// declared here so the HAL layer (hal_disk.c, io_driver.h) can include this
|
||||
// header without dragging in kernel sync-object link dependencies.
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <ke_spinlock.h>
|
||||
#include <ke_status.h>
|
||||
|
||||
// Forward declarations — full types live in ke_event.h / ke_semaphore.h.
|
||||
// Forward declarations - full types live in ke_event.h / ke_semaphore.h.
|
||||
// We only ever hold pointers in IRP and IRP_QUEUE, so a forward decl suffices.
|
||||
struct EVENT;
|
||||
struct SEMAPHORE;
|
||||
@@ -42,7 +42,7 @@ typedef void (*IRP_COMPLETION_FN)(IRP *irp, void *ctx);
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
typedef struct IRP {
|
||||
// Embedded list node — driver-internal; do not touch after submit.
|
||||
// Embedded list node - driver-internal; do not touch after submit.
|
||||
LIST_ENTRY Link;
|
||||
|
||||
// ---- Request parameters (caller fills before IoSubmitIrp) ------------
|
||||
@@ -85,7 +85,7 @@ __declspec(dllexport) void IrpQueueEnqueue (IRP_QUEUE *q, IRP *irp);
|
||||
__declspec(dllexport) IRP *IrpQueueDequeue (IRP_QUEUE *q);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public dispatch API — implemented in kernel/ke_irp.c
|
||||
// Public dispatch API - implemented in kernel/ke_irp.c
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// Submit asynchronously. Returns STATUS_PENDING on success.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ke_irq.c — IRQ dispatch, kernel-side
|
||||
// ke_irq.c - IRQ dispatch, kernel-side
|
||||
#include <ke_irq.h>
|
||||
#include <hal_api.h>
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ __declspec(dllexport) void KeYield(void) {
|
||||
|
||||
// Only re-queue the outgoing thread if it is still in the running state.
|
||||
// If KeBlockThread set State = ThreadWaiting, SchedulerLink was already
|
||||
// inserted into the sync object's wait list — inserting it here too would
|
||||
// inserted into the sync object's wait list - inserting it here too would
|
||||
// corrupt both lists simultaneously (same intrusive node in two lists).
|
||||
// If KeExitThread set State = ThreadDead, the thread must not be re-queued.
|
||||
if (cur != gIdleThread && cur->State == ThreadRunning) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// ke_util.h - kernel utility macros (dynamic arrays, etc.)
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
#include <mm_virt.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dynamic array (stretchy-buffer style)
|
||||
//
|
||||
// T *buf = NULL;
|
||||
// arr_push(buf, value); // appends; grows automatically
|
||||
// arr_push_front(buf, value); // prepends
|
||||
// arr_remove(buf, i); // removes index i, shifts tail left
|
||||
// size_t n = arr_len(buf); // element count (0 if buf == NULL)
|
||||
// arr_free(buf); // frees header + data
|
||||
//
|
||||
// The allocation layout is:
|
||||
// [ Header (count, capacity) ][ T[0] ][ T[1] ] ...
|
||||
// buf always points at T[0]; the Header lives one slot before it.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} _ArrHeader;
|
||||
|
||||
#define _ARR_INIT_CAPACITY 2
|
||||
|
||||
#define _arr_header(arr) ((_ArrHeader *)(arr) - 1)
|
||||
|
||||
#define arr_len(arr) ((arr) ? _arr_header(arr)->count : 0u)
|
||||
|
||||
#define _arr_maybe_grow(arr) \
|
||||
do { \
|
||||
if (!(arr)) { \
|
||||
_ArrHeader *_h = MmAllocatePool(sizeof(_ArrHeader) + \
|
||||
sizeof(*(arr)) * _ARR_INIT_CAPACITY); \
|
||||
_h->count = 0; \
|
||||
_h->capacity = _ARR_INIT_CAPACITY; \
|
||||
(arr) = (void *)(_h + 1); \
|
||||
} \
|
||||
_ArrHeader *_h = _arr_header(arr); \
|
||||
if (_h->count >= _h->capacity) { \
|
||||
_h->capacity *= 2; \
|
||||
_h = MmReallocatePool(_h, sizeof(_ArrHeader) + \
|
||||
sizeof(*(arr)) * _h->capacity); \
|
||||
(arr) = (void *)(_h + 1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define arr_push(arr, x) \
|
||||
do { \
|
||||
_arr_maybe_grow(arr); \
|
||||
(arr)[_arr_header(arr)->count++] = (x); \
|
||||
} while (0)
|
||||
|
||||
#define arr_push_front(arr, x) \
|
||||
do { \
|
||||
_arr_maybe_grow(arr); \
|
||||
_ArrHeader *_h = _arr_header(arr); \
|
||||
memmove(&(arr)[1], &(arr)[0], sizeof(*(arr)) * _h->count); \
|
||||
(arr)[0] = (x); \
|
||||
_h->count++; \
|
||||
} while (0)
|
||||
|
||||
#define arr_remove(arr, index) \
|
||||
do { \
|
||||
if ((arr) && (size_t)(index) < arr_len(arr)) { \
|
||||
_ArrHeader *_h = _arr_header(arr); \
|
||||
memmove(&(arr)[index], &(arr)[(index) + 1], \
|
||||
sizeof(*(arr)) * (_h->count - (size_t)(index) - 1)); \
|
||||
_h->count--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define arr_free(arr) MmFreePool(_arr_header(arr))
|
||||
+20
-76
@@ -13,65 +13,12 @@
|
||||
#include <ke_irq.h>
|
||||
#include <ke_syscall.h>
|
||||
#include <ke_debug.h>
|
||||
#include <ke_util.h>
|
||||
#include <ldr_image.h>
|
||||
#include <hal_api.h>
|
||||
#include <io_file.h>
|
||||
#include <ini_parser.h>
|
||||
|
||||
// dynamic arrays bitch
|
||||
typedef struct {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} Header;
|
||||
|
||||
#define ARR_INIT_CAPACITY 2
|
||||
|
||||
#define _arr_header(arr) ((Header*)(arr) - 1)
|
||||
|
||||
#define _arr_maybe_grow(arr) \
|
||||
do { \
|
||||
if (!(arr)) { \
|
||||
Header* h = MmAllocatePool(sizeof(Header) + sizeof(*(arr)) * ARR_INIT_CAPACITY); \
|
||||
h->count = 0; \
|
||||
h->capacity = ARR_INIT_CAPACITY; \
|
||||
(arr) = (void*)(h + 1); \
|
||||
} \
|
||||
Header* h = _arr_header(arr); \
|
||||
if (h->count >= h->capacity) { \
|
||||
h->capacity *= 2; \
|
||||
h = MmReallocatePool(h, sizeof(Header) + sizeof(*(arr)) * h->capacity); \
|
||||
(arr) = (void*)(h + 1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define arr_push(arr, x) \
|
||||
do { \
|
||||
_arr_maybe_grow(arr); \
|
||||
(arr)[_arr_header(arr)->count++] = (x); \
|
||||
} while (0)
|
||||
|
||||
#define arr_push_front(arr, x) \
|
||||
do { \
|
||||
_arr_maybe_grow(arr); \
|
||||
Header* h = _arr_header(arr); \
|
||||
memmove(&(arr)[1], &(arr)[0], sizeof(*(arr)) * h->count); \
|
||||
(arr)[0] = (x); \
|
||||
h->count++; \
|
||||
} while (0)
|
||||
|
||||
#define arr_remove(arr, index) \
|
||||
do { \
|
||||
if ((arr) && (index) < arr_len(arr)) { \
|
||||
Header* h = _arr_header(arr); \
|
||||
memmove(&(arr)[index], &(arr)[index + 1], sizeof(*(arr)) * (h->count - (index) - 1)); \
|
||||
h->count--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define arr_len(arr) ((Header*)(arr) - 1)->count
|
||||
|
||||
#define arr_free(arr) MmFreePool((Header*)(arr) - 1)
|
||||
|
||||
typedef struct {
|
||||
BOOT_INFO* bootInfo;
|
||||
const HAL_API* hal;
|
||||
@@ -138,17 +85,15 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
|
||||
s = IoOpenFile("drivers\\drivers.ini", &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("InitializeDrivers: Failed to open drivers.ini\n");
|
||||
_disable(); while(true) __halt();
|
||||
KePanic("InitializeDrivers: Failed to open drivers.ini (status %d)\n", s);
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f) + 1;
|
||||
char* mem = MmAllocatePool(size);
|
||||
size_t got;
|
||||
if (!KSUCCESS(IoReadFile(f, mem, size, &got))) {
|
||||
DbgPrint("InitializeDrivers: Failed to read drivers.ini\n");
|
||||
IoCloseFile(f);
|
||||
_disable(); while(true) __halt();
|
||||
KePanic("InitializeDrivers: Failed to read drivers.ini\n");
|
||||
}
|
||||
mem[got] = '\0';
|
||||
|
||||
@@ -162,16 +107,17 @@ static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) {
|
||||
|
||||
// Load the driver
|
||||
size_t len = strlen(runtimeKeys[i]);
|
||||
char* path = MmAllocatePool(len + 10);
|
||||
if (!path) {
|
||||
DbgPrint("InitializeDrivers: Failed to allocate memory for driver path. How?\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assemble the path
|
||||
strncpy(path, "drivers\\", sizeof(path) - 1);
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
strncat(path, runtimeKeys[i], sizeof(path) - strlen(path) - 1);
|
||||
// "drivers\" is 8 chars; +1 for the NUL terminator already in len.
|
||||
size_t pathLen = 8 + len + 1; // len already includes the NUL from strlen+1 above
|
||||
char *path = MmAllocatePool(pathLen);
|
||||
if (!path) {
|
||||
DbgPrint("InitializeDrivers: OOM building driver path\n");
|
||||
continue;
|
||||
}
|
||||
memcpy(path, "drivers\\", 8);
|
||||
memcpy(path + 8, runtimeKeys[i], len); // len includes the NUL
|
||||
|
||||
s = IoOpenFile(path, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
@@ -229,17 +175,15 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
// Read the DLL from disk
|
||||
s = IoOpenFile(filename, &f);
|
||||
if (s != STATUS_SUCCESS) {
|
||||
DbgPrint("LoadAndRegisterDll: Failed to open DLL: %s\n", filename);
|
||||
return;
|
||||
KePanic("LoadAndRegisterDll: Failed to open DLL: %s\n", filename);
|
||||
}
|
||||
|
||||
uint64_t size = IoGetFileSize(f);
|
||||
void* mem = MmAllocatePool(size); // Temporary pool for the raw file
|
||||
size_t got;
|
||||
if (!KSUCCESS(IoReadFile(f, mem, size, &got))) {
|
||||
DbgPrint("LoadAndRegisterDll: Failed to read %s\n", filename);
|
||||
KePanic("LoadAndRegisterDll: Failed to read %s\n", filename);
|
||||
IoCloseFile(f);
|
||||
return;
|
||||
}
|
||||
IoCloseFile(f);
|
||||
|
||||
@@ -248,8 +192,7 @@ static void LoadAndRegisterDll(const char* filename) {
|
||||
uintptr_t mappedBase = 0;
|
||||
s = LdrLoadImage(mem, size, &mappedBase, true);
|
||||
if (!KSUCCESS(s)) {
|
||||
DbgPrint("LoadAndRegisterDll: Failed to map %s\n", filename);
|
||||
return;
|
||||
KePanic("LoadAndRegisterDll: Failed to map %s\n", filename);
|
||||
}
|
||||
|
||||
MmFreePool(mem); // Free the raw file buffer, we only need the mapped image now
|
||||
@@ -428,7 +371,10 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
.DebugEnabled = bootInfo->DebugEnabled
|
||||
};
|
||||
KSTATUS s = HalInitialize(&halParams);
|
||||
if (!KSUCCESS(s)) while (true) __halt(); // there's nothing we can do.
|
||||
if (!KSUCCESS(s)) {
|
||||
_disable();
|
||||
while (true) __halt(); // there's nothing we can do.
|
||||
}
|
||||
const HAL_API* hal = HalGetApi();
|
||||
gKmainHal = hal;
|
||||
|
||||
@@ -466,9 +412,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
PriorityNormal, &initThread);
|
||||
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("KernelMain: PANIC - Failed to create SystemInitThread! (0x%x)\n", st);
|
||||
_disable();
|
||||
for(;;) __halt();
|
||||
KePanic("KernelMain: Failed to create SystemInitThread (status 0x%x)\n", st);
|
||||
}
|
||||
|
||||
DbgPrint("KernelMain: Handing over to scheduler...\n");
|
||||
|
||||
@@ -120,7 +120,7 @@ void MmFreeFrame(PHYSICAL_ADDRESS frame) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
if (gFrameStack.Top < gFrameStack.Capacity)
|
||||
gFrameStack.Stack[gFrameStack.Top++] = frame;
|
||||
// else: stack full — leak rather than corrupt
|
||||
// else: stack full - leak rather than corrupt
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user