fix the return value of LdrLoadImage, make use of __declspec(dllexport), speed up blitting, add dummy TEB, redesign the syscall interface, fix stack alignent so movaps doesn't crash, implement a shitload of win32, implement a simple shell, add bink as video.exe 😎, minor kmain.c cleanup, HAL now supports power-off events, implemented \b in hal_screen.c, fix many deadlocks, add wait for exit event for processes, completely new error codes, small readme changes.
This commit is contained in:
1 parent
c13dd99150
commit
7f4052f41c
33 files changed
+6396
-735
No files matched your search
@@ -60,6 +60,12 @@ typedef struct HAL_INTC {
|
||||
void (*SendEoi)(void);
|
||||
} HAL_INTC;
|
||||
|
||||
typedef struct HAL_POWER {
|
||||
// ACPI S5 soft-off. Disables interrupts, writes SLP_EN to PM1a/b_CNT,
|
||||
// and halts if firmware doesn't respond. Does not return.
|
||||
void (*Shutdown)(void);
|
||||
} HAL_POWER;
|
||||
|
||||
typedef struct HAL_API {
|
||||
uint32_t Version;
|
||||
void *(*PhysToVirt)(uint64_t physAddr);
|
||||
@@ -69,6 +75,7 @@ typedef struct HAL_API {
|
||||
HAL_TIMER Timer;
|
||||
HAL_PCI Pci;
|
||||
HAL_INTC Intc;
|
||||
HAL_POWER Power;
|
||||
} HAL_API;
|
||||
|
||||
typedef struct HAL_INIT_PARAMS {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer
|
||||
#include "hal_api.h"
|
||||
#include "hal_apic.h"
|
||||
#include "hal_debug.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <intrin.h>
|
||||
@@ -48,7 +49,6 @@ static uint8_t KbdReadScancode(void) {
|
||||
}
|
||||
|
||||
static char KbdReadChar(void) {
|
||||
if (gHead == gTail) return 0;
|
||||
uint8_t sc = KbdReadScancode();
|
||||
if (sc < 128) return gScanToAscii[sc];
|
||||
return 0;
|
||||
|
||||
+127
-10
@@ -81,6 +81,12 @@ static uintptr_t gLapicPhys = 0xFEE00000;
|
||||
static uintptr_t gIoapicPhys = 0xFEC00000;
|
||||
static uintptr_t gHpetPhys = 0xFED00000;
|
||||
|
||||
// ACPI power-off state (filled in by ParseFadt / ScanDsdtForS5)
|
||||
static uint16_t gPm1aCntBlk = 0;
|
||||
static uint16_t gPm1bCntBlk = 0;
|
||||
static uint8_t gSlpTypA = 5; // S5 SLP_TYP for PM1a; 5 is correct for QEMU/most VMs
|
||||
static uint8_t gSlpTypB = 5; // S5 SLP_TYP for PM1b
|
||||
|
||||
int debugEnabled = 0;
|
||||
int _fltused; // fuckass
|
||||
static void hal_putchar(char c) {
|
||||
@@ -99,6 +105,101 @@ static void *HalPhysToVirt(uint64_t phys) {
|
||||
return (void *)(phys + gPhysBase);
|
||||
}
|
||||
|
||||
// FADT (Fixed ACPI Description Table) - partial layout up to PM1b_CNT_BLK.
|
||||
// We only need offsets 40 (DSDT ptr), 64 (PM1a_CNT_BLK), 68 (PM1b_CNT_BLK).
|
||||
// The full table is ~276 bytes (ACPI 2.0+); we never access beyond offset 68.
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
ACPISDTHeader Header; // 0 (36 bytes)
|
||||
uint32_t FirmwareCtrl; // 36
|
||||
uint32_t Dsdt; // 40 - physical addr of DSDT
|
||||
uint8_t Reserved1; // 44
|
||||
uint8_t PreferredPmProfile; // 45
|
||||
uint16_t SciInt; // 46
|
||||
uint32_t SmiCmd; // 48
|
||||
uint8_t AcpiEnable; // 52
|
||||
uint8_t AcpiDisable; // 53
|
||||
uint8_t S4BiosReq; // 54
|
||||
uint8_t PstateCnt; // 55
|
||||
uint32_t Pm1aEvtBlk; // 56
|
||||
uint32_t Pm1bEvtBlk; // 60
|
||||
uint32_t Pm1aCntBlk; // 64 - I/O port for PM1a control register
|
||||
uint32_t Pm1bCntBlk; // 68 - I/O port for PM1b control register
|
||||
} FADT;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Scan DSDT AML for the _S5_ Name object and extract SLP_TYP values.
|
||||
// The encoding looks like:
|
||||
// 0x08 '_' 'S' '5' '_' ; NameOp + "_S5_"
|
||||
// 0x12 <PkgLen> ; PackageOp + encoded length
|
||||
// <NumElements> ; usually 0x04
|
||||
// 0x0A <slp_typ_a> ; BytePrefix + value (or 0x00 for zero)
|
||||
// 0x0A <slp_typ_b>
|
||||
static void ScanDsdtForS5(const uint8_t* aml, uint32_t len) {
|
||||
for (uint32_t i = 0; i + 9 < len; i++) {
|
||||
// Match NameOp + "_S5_" + PackageOp
|
||||
if (aml[i] != 0x08) continue;
|
||||
if (aml[i+1] != 0x5F || aml[i+2] != 0x53 ||
|
||||
aml[i+3] != 0x35 || aml[i+4] != 0x5F) continue;
|
||||
if (aml[i+5] != 0x12) continue;
|
||||
|
||||
// PkgLength encoding: low 6 bits = byte count (0 → only this byte);
|
||||
// bits [7:6] = number of following bytes in the length field.
|
||||
uint8_t pkgByte = aml[i+6];
|
||||
uint32_t pkgExtra = pkgByte >> 6; // 0..3 extra bytes
|
||||
uint32_t j = i + 7 + pkgExtra; // skip PkgLen field
|
||||
if (j + 2 >= len) break;
|
||||
j++; // skip NumElements byte
|
||||
|
||||
// SLP_TYP_A
|
||||
if (aml[j] == 0x0A && j + 1 < len) {
|
||||
gSlpTypA = aml[j + 1]; j += 2;
|
||||
} else if (aml[j] == 0x00) {
|
||||
gSlpTypA = 0; j++;
|
||||
} else {
|
||||
break; // unexpected encoding - keep defaults
|
||||
}
|
||||
|
||||
// SLP_TYP_B
|
||||
if (j < len && aml[j] == 0x0A && j + 1 < len)
|
||||
gSlpTypB = aml[j + 1];
|
||||
else if (j < len && aml[j] == 0x00)
|
||||
gSlpTypB = 0;
|
||||
|
||||
HalDbgPrint("HAL: _S5_ SLP_TYP_A=0x%02x SLP_TYP_B=0x%02x\n",
|
||||
gSlpTypA, gSlpTypB);
|
||||
return;
|
||||
}
|
||||
HalDbgPrint("HAL: _S5_ not found in DSDT, using defaults (A=0x%02x B=0x%02x)\n",
|
||||
gSlpTypA, gSlpTypB);
|
||||
}
|
||||
|
||||
static int validate_checksum(void* table, uint32_t length) {
|
||||
uint8_t sum = 0;
|
||||
uint8_t* bytes = (uint8_t*)table;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
sum += bytes[i];
|
||||
}
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
static void ParseFadt(const FADT* fadt) {
|
||||
gPm1aCntBlk = (uint16_t)fadt->Pm1aCntBlk;
|
||||
gPm1bCntBlk = (uint16_t)fadt->Pm1bCntBlk;
|
||||
HalDbgPrint("HAL: FADT PM1a_CNT=0x%04x PM1b_CNT=0x%04x DSDT=0x%08x\n",
|
||||
gPm1aCntBlk, gPm1bCntBlk, fadt->Dsdt);
|
||||
|
||||
if (fadt->Dsdt) {
|
||||
const ACPISDTHeader* dsdt =
|
||||
(const ACPISDTHeader*)((uintptr_t)fadt->Dsdt + gPhysBase);
|
||||
if (memcmp(dsdt->Signature, "DSDT", 4) == 0 &&
|
||||
validate_checksum((void*)dsdt, dsdt->Length)) {
|
||||
const uint8_t* aml = (const uint8_t*)(dsdt + 1);
|
||||
ScanDsdtForS5(aml, dsdt->Length - (uint32_t)sizeof(ACPISDTHeader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ParseMadt(MADT* madt) {
|
||||
gLapicPhys = madt->LocalAPICAddress;
|
||||
uint8_t* p = (uint8_t *)(madt + 1);
|
||||
@@ -112,15 +213,6 @@ static void ParseMadt(MADT* madt) {
|
||||
}
|
||||
}
|
||||
|
||||
static int validate_checksum(void* table, uint32_t length) {
|
||||
uint8_t sum = 0;
|
||||
uint8_t* bytes = (uint8_t*)table;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
sum += bytes[i];
|
||||
}
|
||||
return sum == 0;
|
||||
}
|
||||
|
||||
static void WalkAcpi(uintptr_t rsdpPhys) {
|
||||
if (!rsdpPhys) return;
|
||||
|
||||
@@ -188,7 +280,11 @@ static void WalkAcpi(uintptr_t rsdpPhys) {
|
||||
// Parse MADT
|
||||
if (memcmp(header->Signature, "APIC", 4) == 0) {
|
||||
ParseMadt((MADT*)header);
|
||||
}
|
||||
}
|
||||
// Parse FADT (signature "FACP") for PM1 control ports and DSDT pointer
|
||||
else if (memcmp(header->Signature, "FACP", 4) == 0) {
|
||||
ParseFadt((const FADT*)header);
|
||||
}
|
||||
// Parse HPET
|
||||
else if (memcmp(header->Signature, "HPET", 4) == 0) {
|
||||
// HPET base address block is located at offset 44
|
||||
@@ -198,6 +294,25 @@ static void WalkAcpi(uintptr_t rsdpPhys) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// HalShutdown - ACPI S5 soft power-off. Does not return.
|
||||
// ---------------------------------------------------------------------------
|
||||
#include <intrin.h>
|
||||
|
||||
static void HalShutdown(void) {
|
||||
_disable();
|
||||
|
||||
// SLP_EN (bit 13) | SLP_TYPx (bits 12:10)
|
||||
uint16_t valA = (uint16_t)((gSlpTypA << 10) | (1 << 13));
|
||||
uint16_t valB = (uint16_t)((gSlpTypB << 10) | (1 << 13));
|
||||
|
||||
if (gPm1aCntBlk) __outword(gPm1aCntBlk, valA);
|
||||
if (gPm1bCntBlk) __outword(gPm1bCntBlk, valB);
|
||||
|
||||
// Firmware should have powered off by now. If it didn't, halt.
|
||||
for (;;) __halt();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
if (gInitialised) return STATUS_ALREADY_EXISTS;
|
||||
@@ -236,6 +351,8 @@ KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) {
|
||||
gApi.Intc.UnmaskIrq = HalApicUnmaskIrq;
|
||||
gApi.Intc.SendEoi = HalApicSendEoi;
|
||||
|
||||
gApi.Power.Shutdown = HalShutdown;
|
||||
|
||||
gApi.Version = HAL_API_VERSION;
|
||||
gInitialised = 1;
|
||||
|
||||
|
||||
+50
-4
@@ -45,9 +45,47 @@ static void ScreenPutPixel(int x, int y, uint32_t color) {
|
||||
}
|
||||
|
||||
static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||
for (int row = 0; row < h; row++)
|
||||
for (int col = 0; col < w; col++)
|
||||
PutPixelRaw(x + col, y + row, pixels[row * w + col]);
|
||||
// Calculate clipping bounds
|
||||
int startX = (x < 0) ? 0 : x;
|
||||
int startY = (y < 0) ? 0 : y;
|
||||
int endX = (x + w > gWidth) ? gWidth : (x + w);
|
||||
int endY = (y + h > gHeight) ? gHeight : (y + h);
|
||||
|
||||
int drawW = endX - startX;
|
||||
int drawH = endY - startY;
|
||||
|
||||
// If the image is entirely off-screen, do nothing
|
||||
if (drawW <= 0 || drawH <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust the source pointer if the image was clipped on the top or left
|
||||
int srcOffsetX = startX - x;
|
||||
int srcOffsetY = startY - y;
|
||||
|
||||
// Calculate bytes to copy per row
|
||||
size_t bytesPerRow = (size_t)drawW * sizeof(uint32_t);
|
||||
|
||||
// If the width we are drawing exactly matches the physical screen stride,
|
||||
// AND it matches the original source image width, memory is perfectly contiguous.
|
||||
if (drawW == gStride && drawW == w) {
|
||||
uint32_t* dst = gFb + (startY * gStride) + startX;
|
||||
const uint32_t* src = pixels + (srcOffsetY * w) + srcOffsetX;
|
||||
|
||||
memcpy(dst, src, bytesPerRow * drawH);
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy row-by-row
|
||||
for (int row = 0; row < drawH; row++) {
|
||||
// Destination in the actual framebuffer (accounting for stride)
|
||||
uint32_t* dst = gFb + ((startY + row) * gStride) + startX;
|
||||
|
||||
// Source from the provided pixel buffer
|
||||
const uint32_t* src = pixels + ((srcOffsetY + row) * w) + srcOffsetX;
|
||||
|
||||
memcpy(dst, src, bytesPerRow);
|
||||
}
|
||||
}
|
||||
|
||||
static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; }
|
||||
@@ -68,7 +106,8 @@ static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) {
|
||||
for (int row = 0; row < 16; row++) {
|
||||
uint8_t bits = glyph[row];
|
||||
for (int col = 0; col < 8; col++) {
|
||||
uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why, i shouldn't have to wonder why but the font is backwards unless we do this terriblness
|
||||
uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why
|
||||
// i shouldn't have to wonder why but the font is backwards unless we do this terriblness
|
||||
PutPixelRaw(x + col, y + row, color);
|
||||
}
|
||||
}
|
||||
@@ -88,6 +127,13 @@ static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) {
|
||||
gCursorY++;
|
||||
} else if (c == '\r') {
|
||||
gCursorX = 0;
|
||||
} else if (c == '\b') {
|
||||
if (gCursorX > 0) {
|
||||
gCursorX--;
|
||||
} else if (gCursorY > 0) {
|
||||
gCursorY--;
|
||||
gCursorX = cols - 1;
|
||||
}
|
||||
} else {
|
||||
ScreenPutChar(c, gCursorX * FONT_W, gCursorY * FONT_H, fg, bg);
|
||||
if (++gCursorX >= cols) { gCursorX = 0; gCursorY++; }
|
||||
|
||||
Reference in new issue
Block a user