completely redesign how user mode memory is allocated, fix a few smp and scheduler bugs, terminating a process now terminates the process, telemetry, optimize text editor, new font, new color scheme
This commit is contained in:
1 parent
27b31f62b6
commit
325149006c
45 files changed
+2091
-760
No files matched your search
Binary file not shown.
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
[kernel]
|
||||
; bitmask: 1 = debug prints, 2 = self check, 4 = write debug prints to file
|
||||
debug = 4
|
||||
debug = 1
|
||||
[init]
|
||||
commandline = apps/shell_native.exe
|
||||
+16
-14
@@ -36,7 +36,7 @@ static const Driver_Target STANDALONE_DRIVERS[] = {
|
||||
void create_layout() {
|
||||
const char *dirs[] = {
|
||||
"obj", "bin", "obj\\boot", "obj\\kernel", "obj\\lwip", "obj\\hal",
|
||||
"obj\\syscall", "obj\\win32", "obj\\posix", "obj\\drivers", "obj\\init",
|
||||
"obj\\syscall", "obj\\runtime", "obj\\win32", "obj\\posix", "obj\\drivers", "obj\\init",
|
||||
"obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native",
|
||||
"obj\\async_apc", "obj\\async_cancel", "obj\\edit", "obj\\httpget",
|
||||
"obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping", "obj\\doom", "obj\\video"
|
||||
@@ -86,6 +86,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
nob_temp_sprintf("cl %s /MP /c /Foobj\\ code\\common\\printf.c code\\common\\ini_parser.c", CFLAGS),
|
||||
"cl /nologo /c /Foobj\\libc.obj code\\common\\libc.c",
|
||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap.obj code\\user\\runtime\\heap.c", CFLAGS),
|
||||
nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap_exports.obj code\\user\\runtime\\heap_exports.c", CFLAGS),
|
||||
|
||||
// Bootloader
|
||||
nob_temp_sprintf("cl %s /MP /c /Icode\\boot\\uefi\\include /Foobj\\boot\\ code\\boot\\uefi\\*.c && link %s /FORCE:MULTIPLE /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:bin\\bootx64.efi obj\\libc.obj obj\\ini_parser.obj code\\boot\\uefi\\efilib.lib obj\\boot\\*.obj", CFLAGS, LFLAGS),
|
||||
@@ -98,8 +100,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Subsystem DLLs
|
||||
"link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\syscall.dll obj\\syscall\\stubs.obj",
|
||||
nob_temp_sprintf("cl %s /MP /c /Foobj\\win32\\ code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", CFLAGS),
|
||||
nob_temp_sprintf("cl %s /MP /c /Foobj\\posix\\ code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", CFLAGS)
|
||||
nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /MP /c /Foobj\\win32\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", CFLAGS),
|
||||
nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /MP /c /Foobj\\posix\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", CFLAGS)
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < NOB_ARRAY_LEN(core_tasks); i++) {
|
||||
@@ -140,19 +142,19 @@ int main(int argc, char **argv) {
|
||||
// Queue Subsystem Applications
|
||||
const char *apps[][4] = {
|
||||
// Folder, Libs, Name, Optional Extra Link Args
|
||||
{"system\\init", "bin\\syscall.lib obj\\libc.obj", "init", "/ENTRY:_start"},
|
||||
{"system\\init", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "init", "/ENTRY:_start"},
|
||||
{"apps\\shell_win32", "bin\\win32.lib obj\\libc.obj", "shell_win32", "/ENTRY:main"},
|
||||
{"apps\\shell_posix", "bin\\posix.lib obj\\libc.obj", "shell_posix", "/ENTRY:main"},
|
||||
{"apps\\shell_native", "bin\\syscall.lib obj\\libc.obj", "shell_native", "/ENTRY:main"},
|
||||
{"tests\\async_apc", "bin\\syscall.lib obj\\libc.obj", "async_apc", "/ENTRY:main"},
|
||||
{"tests\\async_cancel", "bin\\syscall.lib obj\\libc.obj", "async_cancel", "/ENTRY:main"},
|
||||
{"apps\\edit", "bin\\syscall.lib obj\\libc.obj", "edit", "/ENTRY:main"},
|
||||
{"apps\\httpget", "bin\\syscall.lib obj\\libc.obj", "httpget", "/ENTRY:main"},
|
||||
{"apps\\tcpserve", "bin\\syscall.lib obj\\libc.obj", "tcpserve", "/ENTRY:main"},
|
||||
{"apps\\udp", "bin\\syscall.lib obj\\libc.obj", "udp", "/ENTRY:main"},
|
||||
{"apps\\resolve", "bin\\syscall.lib obj\\libc.obj", "resolve", "/ENTRY:main"},
|
||||
{"apps\\ping", "bin\\syscall.lib obj\\libc.obj", "ping", "/ENTRY:main"},
|
||||
{"apps\\doom", "bin\\syscall.lib obj\\libc.obj", "doom", "/ENTRY:main"},
|
||||
{"apps\\shell_native", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "shell_native", "/ENTRY:main"},
|
||||
{"tests\\async_apc", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "async_apc", "/ENTRY:main"},
|
||||
{"tests\\async_cancel", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "async_cancel", "/ENTRY:main"},
|
||||
{"apps\\edit", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "edit", "/ENTRY:main"},
|
||||
{"apps\\httpget", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "httpget", "/ENTRY:main"},
|
||||
{"apps\\tcpserve", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "tcpserve", "/ENTRY:main"},
|
||||
{"apps\\udp", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "udp", "/ENTRY:main"},
|
||||
{"apps\\resolve", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "resolve", "/ENTRY:main"},
|
||||
{"apps\\ping", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "ping", "/ENTRY:main"},
|
||||
{"apps\\doom", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "doom", "/ENTRY:main"},
|
||||
{"apps\\video", "bin\\win32.lib obj\\libc.obj code\\user\\apps\\video\\bink2w64.lib", "video", "/ENTRY:main"}
|
||||
};
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ KSTATUS UsbMapMmio(const HAL_API* hal, uint64_t physBase,
|
||||
for (uint32_t i = 0; i < pages; i++) {
|
||||
PHYSICAL_ADDRESS phys = pageBase + (uint64_t)i * PAGE_SIZE;
|
||||
uintptr_t virt = (uintptr_t)hal->PhysToVirt(phys);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE, MmMapFailIfPresent);
|
||||
if (st == STATUS_ALREADY_EXISTS)
|
||||
st = MmSetPageProtect(virt, PAGE_SIZE, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
if (!KSUCCESS(st)) {
|
||||
|
||||
@@ -41,7 +41,7 @@ KSTATUS Rtl8139MapMmio(uint64_t physBase, volatile uint8_t** outMmio) {
|
||||
for (uint32_t i = 0; i < RTL8139_MMIO_PAGES; i++) {
|
||||
PHYSICAL_ADDRESS phys = pageBase + (uint64_t)i * PAGE_SIZE;
|
||||
uintptr_t virt = (uintptr_t)gHal->PhysToVirt(phys);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE, MmMapFailIfPresent);
|
||||
if (st == STATUS_ALREADY_EXISTS)
|
||||
st = MmSetPageProtect(virt, PAGE_SIZE, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
if (!KSUCCESS(st))
|
||||
|
||||
@@ -54,7 +54,7 @@ KSTATUS RtlMapMmio(uint64_t physBase, volatile uint8_t** outMmio) {
|
||||
for (uint32_t i = 0; i < RTL_MMIO_PAGES; i++) {
|
||||
PHYSICAL_ADDRESS phys = pageBase + (uint64_t)i * PAGE_SIZE;
|
||||
uintptr_t virt = (uintptr_t)gHal->PhysToVirt(phys);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE, MmMapFailIfPresent);
|
||||
if (st == STATUS_ALREADY_EXISTS)
|
||||
st = MmSetPageProtect(virt, PAGE_SIZE, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
if (!KSUCCESS(st))
|
||||
|
||||
@@ -6,7 +6,7 @@ KSTATUS ahci_map_mmio(uint64_t physBase) {
|
||||
uint64_t phys = physBase + (uint64_t)i * 4096;
|
||||
uintptr_t virt = (uintptr_t)g_hal->PhysToVirt(phys);
|
||||
uint64_t flags = PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE;
|
||||
KSTATUS st = MmMapPage(virt, phys, flags);
|
||||
KSTATUS st = MmMapPage(virt, phys, flags, MmMapFailIfPresent);
|
||||
// Ignore STATUS_ALREADY_EXISTS - a prior mapping with different flags
|
||||
// is possible for the first page if the bootloader was overly generous.
|
||||
// Use MmSetPageProtect to force NOCACHE in that case.
|
||||
|
||||
@@ -93,7 +93,7 @@ static int gS5Found = 0;
|
||||
int debugEnabled = 0;
|
||||
int _fltused; // MSVC floating-point helper anchor
|
||||
static void hal_putchar(char c) {
|
||||
gApi.Screen.PrintChar(c, 0x00FF00, 0x000000);
|
||||
gApi.Screen.PrintChar(c, 0xCCCCCC, 0x012456);
|
||||
}
|
||||
void HalDbgPrint(const char* fmt, ...) {
|
||||
if (!debugEnabled) return;
|
||||
|
||||
@@ -19,6 +19,9 @@ static int gCursorX = 0, gCursorY = 0;
|
||||
#define FONT_W 8
|
||||
#define FONT_H 16
|
||||
|
||||
#define SCREEN_DEFAULT_FG 0xCCCCCCu
|
||||
#define SCREEN_DEFAULT_BG 0x012456u
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 8x16 VGA font - printable ASCII only (glyph 0 = space = 0x20)
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -113,28 +116,36 @@ static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) {
|
||||
static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; }
|
||||
|
||||
static void ScreenScroll(int lines) {
|
||||
if (lines <= 0 || lines >= gHeight) { ScreenClear(0); return; }
|
||||
if (lines <= 0)
|
||||
return;
|
||||
if (lines >= gHeight) {
|
||||
ScreenClear(SCREEN_DEFAULT_BG);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t rowBytes = (size_t)gStride * sizeof(uint32_t);
|
||||
uint32_t* shadow = gBackbuffer ? gBackbuffer : gFb;
|
||||
|
||||
memmove(shadow, shadow + lines * gStride,
|
||||
(size_t)(gHeight - lines) * rowBytes);
|
||||
// Clear the revealed rows at the bottom.
|
||||
memset(shadow + (gHeight - lines) * gStride, 0,
|
||||
(size_t)lines * rowBytes);
|
||||
|
||||
// Fill the revealed rows with the console background. Do not memset here:
|
||||
// the background color is not zero.
|
||||
uint32_t* fill = shadow + (gHeight - lines) * gStride;
|
||||
for (int y = 0; y < lines; y++) {
|
||||
for (int x = 0; x < gWidth; x++)
|
||||
fill[y * gStride + x] = SCREEN_DEFAULT_BG;
|
||||
}
|
||||
|
||||
ScreenFlushRows(0, gHeight);
|
||||
}
|
||||
|
||||
static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) {
|
||||
if ((unsigned char)c < 0x20 || (unsigned char)c > 0x7E) c = '?';
|
||||
const uint8_t* glyph = Font8x16 + ((unsigned char)c - 0x20) * 16;
|
||||
const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16);
|
||||
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 & (0x80u >> col)) ? fg : bg;
|
||||
PutPixelRaw(x + col, y + row, color);
|
||||
}
|
||||
}
|
||||
@@ -321,5 +332,5 @@ void HalScreenInitialize(void* (*AllocatePool)(size_t size), uintptr_t fb, int w
|
||||
out->PrintChar = ScreenPrintChar;
|
||||
out->DrawCursor = HalScreenDrawCursor;
|
||||
out->EraseCursor = HalScreenEraseCursor;
|
||||
ScreenClear(0x000000);
|
||||
ScreenClear(SCREEN_DEFAULT_BG);
|
||||
}
|
||||
@@ -175,6 +175,13 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) {
|
||||
return elapsed / 10; // APIC ticks per ms
|
||||
}
|
||||
|
||||
__declspec(dllexport) void HalTimerConfigureCurrentCpu(void) {
|
||||
if (!gLapic || !gApicTicksPerQuantum) return;
|
||||
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
|
||||
LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR;
|
||||
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
|
||||
}
|
||||
|
||||
KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *out) {
|
||||
gLapic = (volatile uint32_t *)gApi.PhysToVirt(lapicPhys);
|
||||
HalDbgPrint("HAL: lapicPhys=0x%016llX, lapicVirt=0x%016llX, hpetPhys=0x%016llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys);
|
||||
@@ -205,10 +212,9 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *o
|
||||
|
||||
HalDbgPrint("HAL: APIC timer: %u ticks/ms\n", ticksPerMs);
|
||||
|
||||
// Configure LAPIC timer in periodic mode
|
||||
LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16;
|
||||
LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR;
|
||||
LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum;
|
||||
// Configure this CPU's LAPIC timer; APs call HalTimerConfigureCurrentCpu()
|
||||
// after enabling their local APIC.
|
||||
HalTimerConfigureCurrentCpu();
|
||||
|
||||
out->QueryTicks = QueryTicks;
|
||||
out->Stall = Stall;
|
||||
|
||||
@@ -1,199 +1,521 @@
|
||||
#pragma once
|
||||
// font8x16.h - embedded 8x16 VGA bitmap font, printable ASCII (0x20-0x7E)
|
||||
// 95 glyphs × 16 bytes = 1520 bytes total.
|
||||
// Each byte is one scanline; bit 7 = leftmost pixel.
|
||||
// font8x16.h - embedded 8x16 CP437 bitmap font.
|
||||
// Source: PC Face oldschool-vga-8x16 fontlist.js.
|
||||
// Converted from: oldschool-vga-8x16-fontlist.js
|
||||
// Layout: 256 glyphs * 16 scanlines. Bit 7 is the leftmost pixel.
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t Font8x16[95 * 16] = {
|
||||
// 0x20 ' '
|
||||
static const uint8_t Font8x16[256 * 16] = {
|
||||
// 0x00
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x21 '!'
|
||||
0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x22 '"'
|
||||
0x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x23 '#'
|
||||
0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x24 '$'
|
||||
0x18,0x18,0x3E,0x63,0x03,0x03,0x1E,0x30,0x30,0x63,0x3E,0x18,0x18,0x00,0x00,0x00,
|
||||
// 0x25 '%'
|
||||
0x00,0x00,0x63,0x33,0x18,0x0C,0x06,0x31,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x26 '&'
|
||||
0x00,0x1C,0x36,0x1C,0x0E,0x3B,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x27 '\''
|
||||
0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x28 '('
|
||||
0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x29 ')'
|
||||
0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2A '*'
|
||||
0x00,0x00,0x00,0x33,0x1E,0xFF,0x1E,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2B '+'
|
||||
0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2C ','
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2D '-'
|
||||
0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2E '.'
|
||||
// 0x01
|
||||
0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0x02
|
||||
0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0x03
|
||||
0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,
|
||||
// 0x04
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x05
|
||||
0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x06
|
||||
0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x07
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x08
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
// 0x09
|
||||
0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x0A
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
// 0x0B
|
||||
0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
|
||||
// 0x0C
|
||||
0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x0D
|
||||
0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,
|
||||
// 0x0E
|
||||
0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,
|
||||
// 0x0F
|
||||
0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x10
|
||||
0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
|
||||
// 0x11
|
||||
0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
// 0x12
|
||||
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x13
|
||||
0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
// 0x14
|
||||
0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,
|
||||
// 0x15
|
||||
0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,
|
||||
// 0x16
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x17
|
||||
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0x18
|
||||
0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x19
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x1A
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x1B
|
||||
0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x1C
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x1D
|
||||
0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x1E
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x1F
|
||||
0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x20
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x21
|
||||
0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x22
|
||||
0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x23
|
||||
0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,
|
||||
// 0x24
|
||||
0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,
|
||||
// 0x25
|
||||
0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,
|
||||
// 0x26
|
||||
0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x27
|
||||
0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x28
|
||||
0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,
|
||||
// 0x29
|
||||
0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
// 0x2A
|
||||
0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2B
|
||||
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2C
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,
|
||||
// 0x2D
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2E
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x2F
|
||||
0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,
|
||||
// 0x30
|
||||
0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
|
||||
// 0x31
|
||||
0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0x32
|
||||
0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x33
|
||||
0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x34
|
||||
0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,
|
||||
// 0x35
|
||||
0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x36
|
||||
0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x37
|
||||
0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,
|
||||
// 0x38
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x39
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,
|
||||
// 0x3A
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3B
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,
|
||||
// 0x3C
|
||||
0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,
|
||||
// 0x3D
|
||||
0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3E
|
||||
0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,
|
||||
// 0x3F
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x40
|
||||
0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x41
|
||||
0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x42
|
||||
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,
|
||||
// 0x43
|
||||
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x44
|
||||
0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,
|
||||
// 0x45
|
||||
0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x46
|
||||
0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
|
||||
// 0x47
|
||||
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,
|
||||
// 0x48
|
||||
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x49
|
||||
0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x4A
|
||||
0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,
|
||||
// 0x4B
|
||||
0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
|
||||
// 0x4C
|
||||
0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x4D
|
||||
0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x4E
|
||||
0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x4F
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x50
|
||||
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
|
||||
// 0x51
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,
|
||||
// 0x52
|
||||
0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
|
||||
// 0x53
|
||||
0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x54
|
||||
0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x55
|
||||
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x56
|
||||
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,
|
||||
// 0x57
|
||||
0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,
|
||||
// 0x58
|
||||
0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x59
|
||||
0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x5A
|
||||
0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x5B
|
||||
0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x5C
|
||||
0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,
|
||||
// 0x5D
|
||||
0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x5E
|
||||
0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5F
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,
|
||||
// 0x60
|
||||
0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x61
|
||||
0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x62
|
||||
0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x63
|
||||
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x64
|
||||
0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x65
|
||||
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x66
|
||||
0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
|
||||
// 0x67
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00,
|
||||
// 0x68
|
||||
0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,
|
||||
// 0x69
|
||||
0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x6A
|
||||
0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,
|
||||
// 0x6B
|
||||
0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,
|
||||
// 0x6C
|
||||
0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x6D
|
||||
0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x6E
|
||||
0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
// 0x6F
|
||||
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x70
|
||||
0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,
|
||||
// 0x71
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,
|
||||
// 0x72
|
||||
0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,
|
||||
// 0x73
|
||||
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x74
|
||||
0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,
|
||||
// 0x75
|
||||
0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x76
|
||||
0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x77
|
||||
0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,
|
||||
// 0x78
|
||||
0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x79
|
||||
0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,
|
||||
// 0x7A
|
||||
0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x7B
|
||||
0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,
|
||||
// 0x7C
|
||||
0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x7D
|
||||
0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
|
||||
// 0x7E
|
||||
0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7F
|
||||
0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x80
|
||||
0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,
|
||||
// 0x81
|
||||
0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x82
|
||||
0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x83
|
||||
0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x84
|
||||
0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x85
|
||||
0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x86
|
||||
0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x87
|
||||
0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,
|
||||
// 0x88
|
||||
0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x89
|
||||
0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x8A
|
||||
0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x8B
|
||||
0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x8C
|
||||
0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x8D
|
||||
0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0x8E
|
||||
0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x8F
|
||||
0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x90
|
||||
0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0x91
|
||||
0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,
|
||||
// 0x92
|
||||
0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,
|
||||
// 0x93
|
||||
0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x94
|
||||
0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x95
|
||||
0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x96
|
||||
0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x97
|
||||
0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0x98
|
||||
0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,
|
||||
// 0x99
|
||||
0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x9A
|
||||
0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0x9B
|
||||
0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x9C
|
||||
0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,
|
||||
// 0x9D
|
||||
0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0x9E
|
||||
0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0x9F
|
||||
0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,
|
||||
// 0xA0
|
||||
0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0xA1
|
||||
0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0xA2
|
||||
0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0xA3
|
||||
0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0xA4
|
||||
0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,
|
||||
// 0xA5
|
||||
0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0xA6
|
||||
0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xA7
|
||||
0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xA8
|
||||
0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,
|
||||
// 0xA9
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xAA
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xAB
|
||||
0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,
|
||||
// 0xAC
|
||||
0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,
|
||||
// 0xAD
|
||||
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0xAE
|
||||
0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xAF
|
||||
0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xB0
|
||||
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
|
||||
// 0xB1
|
||||
0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
|
||||
// 0xB2
|
||||
0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,
|
||||
// 0xB3
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xB4
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xB5
|
||||
0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xB6
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xB7
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xB8
|
||||
0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xB9
|
||||
0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xBA
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xBB
|
||||
0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xBC
|
||||
0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xBD
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xBE
|
||||
0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xBF
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xC0
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xC1
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xC2
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xC3
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xC4
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xC5
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xC6
|
||||
0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xC7
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xC8
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xC9
|
||||
0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xCA
|
||||
0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xCB
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xCC
|
||||
0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xCD
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xCE
|
||||
0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xCF
|
||||
0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xD0
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xD1
|
||||
0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xD2
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xD3
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xD4
|
||||
0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xD5
|
||||
0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xD6
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xD7
|
||||
0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
|
||||
// 0xD8
|
||||
0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xD9
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xDA
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xDB
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
// 0xDC
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
// 0xDD
|
||||
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
|
||||
// 0xDE
|
||||
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
|
||||
// 0xDF
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xE0
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,
|
||||
// 0xE1
|
||||
0x00,0x00,0x78,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00,
|
||||
// 0xE2
|
||||
0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,
|
||||
// 0xE3
|
||||
0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,
|
||||
// 0xE4
|
||||
0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,
|
||||
// 0xE5
|
||||
0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
|
||||
// 0xE6
|
||||
0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00,
|
||||
// 0xE7
|
||||
0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
|
||||
// 0xE8
|
||||
0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0xE9
|
||||
0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,
|
||||
// 0xEA
|
||||
0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,
|
||||
// 0xEB
|
||||
0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,
|
||||
// 0xEC
|
||||
0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xED
|
||||
0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,
|
||||
// 0xEE
|
||||
0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,
|
||||
// 0xEF
|
||||
0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,
|
||||
// 0xF0
|
||||
0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xF1
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
|
||||
// 0xF2
|
||||
0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0xF3
|
||||
0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,
|
||||
// 0xF4
|
||||
0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
||||
// 0xF5
|
||||
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,
|
||||
// 0xF6
|
||||
0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xF7
|
||||
0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xF8
|
||||
0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xF9
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x2F '/'
|
||||
0x00,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x30 '0'
|
||||
0x00,0x3C,0x66,0x66,0x76,0x6E,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x31 '1'
|
||||
0x00,0x18,0x1C,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x32 '2'
|
||||
0x00,0x3C,0x66,0x60,0x30,0x18,0x0C,0x66,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x33 '3'
|
||||
0x00,0x3C,0x66,0x60,0x38,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x34 '4'
|
||||
0x00,0x30,0x38,0x3C,0x36,0x33,0x7F,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x35 '5'
|
||||
0x00,0x7E,0x06,0x06,0x3E,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x36 '6'
|
||||
0x00,0x38,0x0C,0x06,0x3E,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x37 '7'
|
||||
0x00,0x7E,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x38 '8'
|
||||
0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x39 '9'
|
||||
0x00,0x3C,0x66,0x66,0x7C,0x60,0x30,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3A ':'
|
||||
0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3B ';'
|
||||
0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3C '<'
|
||||
0x00,0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3D '='
|
||||
0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3E '>'
|
||||
0x00,0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x3F '?'
|
||||
0x00,0x3C,0x66,0x60,0x30,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x40 '@'
|
||||
0x00,0x3E,0x63,0x7B,0x7B,0x7B,0x3B,0x03,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x41 'A'
|
||||
0x00,0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x42 'B'
|
||||
0x00,0x3E,0x66,0x66,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x43 'C'
|
||||
0x00,0x3C,0x66,0x06,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x44 'D'
|
||||
0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x36,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x45 'E'
|
||||
0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x46 'F'
|
||||
0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x47 'G'
|
||||
0x00,0x3C,0x66,0x06,0x06,0x76,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x48 'H'
|
||||
0x00,0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x49 'I'
|
||||
0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4A 'J'
|
||||
0x00,0x78,0x30,0x30,0x30,0x30,0x36,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4B 'K'
|
||||
0x00,0x66,0x36,0x1E,0x0E,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4C 'L'
|
||||
0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4D 'M'
|
||||
0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4E 'N'
|
||||
0x00,0x63,0x67,0x6F,0x7B,0x73,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x4F 'O'
|
||||
0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x50 'P'
|
||||
0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x51 'Q'
|
||||
0x00,0x3C,0x66,0x66,0x66,0x66,0x6E,0x3C,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x52 'R'
|
||||
0x00,0x3E,0x66,0x66,0x3E,0x36,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x53 'S'
|
||||
0x00,0x3C,0x66,0x06,0x1C,0x30,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x54 'T'
|
||||
0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x55 'U'
|
||||
0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x56 'V'
|
||||
0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x57 'W'
|
||||
0x00,0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x58 'X'
|
||||
0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x59 'Y'
|
||||
0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5A 'Z'
|
||||
0x00,0x7E,0x60,0x30,0x18,0x0C,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5B '['
|
||||
0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5C '\'
|
||||
0x00,0x03,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5D ']'
|
||||
0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5E '^'
|
||||
0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x5F '_'
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x60 '`'
|
||||
0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x61-0x7A lowercase - condensed to save space, using same shapes as upper offset by 32
|
||||
// 0x61 'a'
|
||||
0x00,0x00,0x00,0x1C,0x30,0x3C,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x62 'b'
|
||||
0x00,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x63 'c'
|
||||
0x00,0x00,0x00,0x3C,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x64 'd'
|
||||
0x00,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x65 'e'
|
||||
0x00,0x00,0x00,0x3C,0x66,0x7E,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x66 'f'
|
||||
0x00,0x38,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x67 'g'
|
||||
0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x68 'h'
|
||||
0x00,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x69 'i'
|
||||
0x00,0x18,0x00,0x1C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6A 'j'
|
||||
0x00,0x30,0x00,0x38,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6B 'k'
|
||||
0x00,0x06,0x06,0x66,0x36,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6C 'l'
|
||||
0x00,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6D 'm'
|
||||
0x00,0x00,0x00,0x37,0x7F,0x6B,0x6B,0x6B,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6E 'n'
|
||||
0x00,0x00,0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x6F 'o'
|
||||
0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x70 'p'
|
||||
0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x71 'q'
|
||||
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x72 'r'
|
||||
0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x73 's'
|
||||
0x00,0x00,0x00,0x3C,0x06,0x1C,0x30,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x74 't'
|
||||
0x00,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x75 'u'
|
||||
0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x76 'v'
|
||||
0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x77 'w'
|
||||
0x00,0x00,0x00,0x63,0x6B,0x6B,0x7F,0x77,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x78 'x'
|
||||
0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x79 'y'
|
||||
0x00,0x00,0x66,0x66,0x66,0x7C,0x60,0x30,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7A 'z'
|
||||
0x00,0x00,0x00,0x7E,0x30,0x18,0x0C,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7B '{'
|
||||
0x00,0x30,0x18,0x18,0x0C,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7C '|'
|
||||
0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7D '}'
|
||||
0x00,0x0C,0x18,0x18,0x30,0x18,0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0x7E '~'
|
||||
0x00,0x6E,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xFA
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xFB
|
||||
0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,
|
||||
// 0xFC
|
||||
0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xFD
|
||||
0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xFE
|
||||
0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,
|
||||
// 0xFF
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
@@ -34,4 +34,5 @@ __declspec(dllexport) void HalApicEnableCurrentCpu(void);
|
||||
__declspec(dllexport) void HalApicSendPanicIpi(void);
|
||||
__declspec(dllexport) void HalApicSendRescheduleIpi(uint32_t lapicId);
|
||||
__declspec(dllexport) void HalApicSendTlbShootdownIpi(uint32_t lapicId);
|
||||
__declspec(dllexport) void HalTimerConfigureCurrentCpu(void);
|
||||
__declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uint8_t startupVector);
|
||||
@@ -31,7 +31,6 @@ KSTATUS LdrResolveImports(uintptr_t imageBase);
|
||||
KSTATUS LdrResolveImportsForProcess(struct PROCESS* process, uintptr_t imageBase);
|
||||
|
||||
// Apply final page permissions for a loaded image after relocations/imports.
|
||||
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user);
|
||||
KSTATUS LdrProtectImageForProcess(struct PROCESS* process, uintptr_t imageBase, bool user);
|
||||
|
||||
// Load a DLL for a specific process, resolve it against that process's
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
// mm_phys.h - physical memory manager (PMM)
|
||||
// Stack allocator over 4 KB frames, seeded from MEMORY_MAP.
|
||||
// Bitmap allocator over 4 KB frames, seeded from MEMORY_MAP.
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
@@ -11,6 +11,15 @@
|
||||
|
||||
typedef uint64_t PHYSICAL_ADDRESS;
|
||||
|
||||
typedef struct MM_PHYSICAL_STATS {
|
||||
uint64_t TotalFrames;
|
||||
uint64_t FreeFrames;
|
||||
uint64_t UsedFrames;
|
||||
uint64_t LargestFreeRun;
|
||||
uint64_t FreeRunCount;
|
||||
uint64_t FreeRunHistogram[8];
|
||||
} MM_PHYSICAL_STATS;
|
||||
|
||||
// Called once by KernelMain with the MEMORY_MAP from BOOT_INFO.
|
||||
bool MmInitializePhysical(const MEMORY_MAP* map,
|
||||
uint64_t physicalWindowBase);
|
||||
@@ -29,3 +38,4 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count);
|
||||
|
||||
size_t MmFreeFrameCount(void);
|
||||
size_t MmTotalFrameCount(void);
|
||||
void MmQueryPhysicalStats(MM_PHYSICAL_STATS* out);
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
// mm_virt.h - virtual memory manager (VMM)
|
||||
// Manages the single shared PML4, kernel pool, and user heap.
|
||||
// Manages the single shared PML4, kernel pool, and page-granular user VM regions.
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <kernel/mm_phys.h>
|
||||
@@ -9,6 +9,11 @@
|
||||
struct PROCESS;
|
||||
typedef struct PROCESS PROCESS;
|
||||
|
||||
typedef enum MM_MAP_MODE {
|
||||
MmMapFailIfPresent = 0,
|
||||
MmMapReplaceExisting = 1,
|
||||
} MM_MAP_MODE;
|
||||
|
||||
typedef enum USER_REGION_TYPE {
|
||||
UserRegionGeneric = 0,
|
||||
UserRegionHeap,
|
||||
@@ -59,7 +64,7 @@ void MmActivate(void);
|
||||
// ---------------------------------------------------------------------------
|
||||
// Page mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags);
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode);
|
||||
__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt);
|
||||
|
||||
// Modify protection flags on an already-mapped virtual range.
|
||||
@@ -120,6 +125,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
|
||||
KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t pageFlags);
|
||||
KSTATUS MmDestroyUserRegion(PROCESS* process, void* base);
|
||||
void MmDestroyAllUserRegions(PROCESS* process);
|
||||
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut, uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut);
|
||||
size_t MmGetUserRegionSize(PROCESS* process, const void* base);
|
||||
size_t MmGetUserRegionSizeByBase(const void* base);
|
||||
|
||||
|
||||
@@ -6,95 +6,97 @@
|
||||
// R10, R11 = args 4-5 (loaded by SYSCALL_STUB6)
|
||||
// RAX = return value
|
||||
|
||||
#define SYS_EXIT_PROCESS 0
|
||||
#define SYS_EXIT_THREAD 1
|
||||
#define SYS_CREATE_PROCESS 2
|
||||
#define SYS_WAIT_FOR_PROCESS 3
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 4
|
||||
#define SYS_KILL_PROCESS 5
|
||||
#define SYS_GET_PROCESS_LIST 6
|
||||
#define SYS_GET_PROCESS_PID 7
|
||||
#define SYS_CREATE_THREAD 8
|
||||
#define SYS_WAIT_THREAD 9
|
||||
#define SYS_GET_CURRENT_TID 10
|
||||
#define SYS_GET_CURRENT_PID 11
|
||||
#define SYS_SET_THREAD_PRIORITY 12
|
||||
#define SYS_YIELD 13
|
||||
#define SYS_SLEEP 14
|
||||
#define SYS_SET_USER_APC_DISPATCHER 15
|
||||
#define SYS_APC_RETURN 16
|
||||
#define SYS_ALLOC 17
|
||||
#define SYS_FREE 18
|
||||
#define SYS_REALLOC 19
|
||||
#define SYS_CLOSE_HANDLE 20
|
||||
#define SYS_MUTEX_CREATE 21
|
||||
#define SYS_MUTEX_ACQUIRE 22
|
||||
#define SYS_MUTEX_TRY_ACQUIRE 23
|
||||
#define SYS_MUTEX_RELEASE 24
|
||||
#define SYS_SEM_CREATE 25
|
||||
#define SYS_SEM_WAIT 26
|
||||
#define SYS_SEM_TRY_WAIT 27
|
||||
#define SYS_SEM_SIGNAL 28
|
||||
#define SYS_EVENT_CREATE 29
|
||||
#define SYS_EVENT_SIGNAL 30
|
||||
#define SYS_EVENT_CLEAR 31
|
||||
#define SYS_EVENT_WAIT 32
|
||||
#define SYS_QUEUE_CREATE 33
|
||||
#define SYS_QUEUE_SEND 34
|
||||
#define SYS_QUEUE_RECV 35
|
||||
#define SYS_PUBLISH_QUEUE 36
|
||||
#define SYS_OPEN_NAMED_QUEUE 37
|
||||
#define SYS_QUEUE_DUPLICATE 38
|
||||
#define SYS_NAMED_QUEUE_OWNER_PID 39
|
||||
#define SYS_OPEN_FILE 40
|
||||
#define SYS_CREATE_FILE 41
|
||||
#define SYS_READ_FILE 42
|
||||
#define SYS_WRITE_FILE 43
|
||||
#define SYS_READ_FILE_ASYNC 44
|
||||
#define SYS_WRITE_FILE_ASYNC 45
|
||||
#define SYS_CANCEL_IO 46
|
||||
#define SYS_SEEK_FILE 47
|
||||
#define SYS_GET_FILE_POS 48
|
||||
#define SYS_GET_FILE_SIZE 49
|
||||
#define SYS_TRUNCATE_FILE 50
|
||||
#define SYS_DELETE_FILE 51
|
||||
#define SYS_RENAME_FILE 52
|
||||
#define SYS_OPEN_DIR 53
|
||||
#define SYS_READ_DIR 54
|
||||
#define SYS_CREATE_DIR 55
|
||||
#define SYS_REMOVE_DIR 56
|
||||
#define SYS_SET_CWD 57
|
||||
#define SYS_GET_CWD 58
|
||||
#define SYS_WRITE_CONSOLE 59
|
||||
#define SYS_SCREEN_BLIT 60
|
||||
#define SYS_SCREEN_CLEAR 61
|
||||
#define SYS_SCREEN_GET_SIZE 62
|
||||
#define SYS_SCREEN_PUT_CHAR 63
|
||||
#define SYS_KB_POLL 64
|
||||
#define SYS_KB_IS_KEY_DOWN 65
|
||||
#define SYS_KB_READ_CHAR 66
|
||||
#define SYS_KB_READ_KEY 67
|
||||
#define SYS_KB_GET_MODIFIERS 68
|
||||
#define SYS_MOUSE_POLL 69
|
||||
#define SYS_MOUSE_READ 70
|
||||
#define SYS_MOUSE_GET_POS 71
|
||||
#define SYS_GET_TICK 72
|
||||
#define SYS_DEBUG_PRINT 73
|
||||
#define SYS_QUERY_TRAP_FRAME 74
|
||||
#define SYS_SOCKET 75
|
||||
#define SYS_BIND 76
|
||||
#define SYS_LISTEN 77
|
||||
#define SYS_ACCEPT 78
|
||||
#define SYS_CONNECT 79
|
||||
#define SYS_SEND 80
|
||||
#define SYS_RECV 81
|
||||
#define SYS_SHUTDOWN 82
|
||||
#define SYS_SEND_TO 83
|
||||
#define SYS_RECV_FROM 84
|
||||
#define SYS_RESOLVE_HOST 85
|
||||
#define SYS_SET_SOCKET_OPTION 86
|
||||
#define SYS_GET_SOCKET_OPTION 87
|
||||
#define SYS_POLL 88
|
||||
#define SYS_GET_MEMORY_STATUS 89
|
||||
#define SYS_EXIT_PROCESS 0
|
||||
#define SYS_EXIT_THREAD 1
|
||||
#define SYS_CREATE_PROCESS 2
|
||||
#define SYS_WAIT_FOR_PROCESS 3
|
||||
#define SYS_GET_PROCESS_EXIT_CODE 4
|
||||
#define SYS_KILL_PROCESS 5
|
||||
#define SYS_GET_PROCESS_LIST 6
|
||||
#define SYS_GET_PROCESS_PID 7
|
||||
#define SYS_CREATE_THREAD 8
|
||||
#define SYS_WAIT_THREAD 9
|
||||
#define SYS_GET_CURRENT_TID 10
|
||||
#define SYS_GET_CURRENT_PID 11
|
||||
#define SYS_SET_THREAD_PRIORITY 12
|
||||
#define SYS_YIELD 13
|
||||
#define SYS_SLEEP 14
|
||||
#define SYS_SET_USER_APC_DISPATCHER 15
|
||||
#define SYS_APC_RETURN 16
|
||||
#define SYS_VM_ALLOC 17
|
||||
#define SYS_VM_FREE 18
|
||||
#define SYS_VM_PROTECT 19
|
||||
#define SYS_VM_QUERY 20
|
||||
#define SYS_CLOSE_HANDLE 21
|
||||
#define SYS_MUTEX_CREATE 22
|
||||
#define SYS_MUTEX_ACQUIRE 23
|
||||
#define SYS_MUTEX_TRY_ACQUIRE 24
|
||||
#define SYS_MUTEX_RELEASE 25
|
||||
#define SYS_SEM_CREATE 26
|
||||
#define SYS_SEM_WAIT 27
|
||||
#define SYS_SEM_TRY_WAIT 28
|
||||
#define SYS_SEM_SIGNAL 29
|
||||
#define SYS_EVENT_CREATE 30
|
||||
#define SYS_EVENT_SIGNAL 31
|
||||
#define SYS_EVENT_CLEAR 32
|
||||
#define SYS_EVENT_WAIT 33
|
||||
#define SYS_QUEUE_CREATE 34
|
||||
#define SYS_QUEUE_SEND 35
|
||||
#define SYS_QUEUE_RECV 36
|
||||
#define SYS_PUBLISH_QUEUE 37
|
||||
#define SYS_OPEN_NAMED_QUEUE 38
|
||||
#define SYS_QUEUE_DUPLICATE 39
|
||||
#define SYS_NAMED_QUEUE_OWNER_PID 40
|
||||
#define SYS_OPEN_FILE 41
|
||||
#define SYS_CREATE_FILE 42
|
||||
#define SYS_READ_FILE 43
|
||||
#define SYS_WRITE_FILE 44
|
||||
#define SYS_READ_FILE_ASYNC 45
|
||||
#define SYS_WRITE_FILE_ASYNC 46
|
||||
#define SYS_CANCEL_IO 47
|
||||
#define SYS_SEEK_FILE 48
|
||||
#define SYS_GET_FILE_POS 49
|
||||
#define SYS_GET_FILE_SIZE 50
|
||||
#define SYS_TRUNCATE_FILE 51
|
||||
#define SYS_DELETE_FILE 52
|
||||
#define SYS_RENAME_FILE 53
|
||||
#define SYS_OPEN_DIR 54
|
||||
#define SYS_READ_DIR 55
|
||||
#define SYS_CREATE_DIR 56
|
||||
#define SYS_REMOVE_DIR 57
|
||||
#define SYS_SET_CWD 58
|
||||
#define SYS_GET_CWD 59
|
||||
#define SYS_WRITE_CONSOLE 60
|
||||
#define SYS_SCREEN_BLIT 61
|
||||
#define SYS_SCREEN_CLEAR 62
|
||||
#define SYS_SCREEN_GET_SIZE 63
|
||||
#define SYS_SCREEN_PUT_CHAR 64
|
||||
#define SYS_KB_POLL 65
|
||||
#define SYS_KB_IS_KEY_DOWN 66
|
||||
#define SYS_KB_READ_CHAR 67
|
||||
#define SYS_KB_READ_KEY 68
|
||||
#define SYS_KB_GET_MODIFIERS 69
|
||||
#define SYS_MOUSE_POLL 70
|
||||
#define SYS_MOUSE_READ 71
|
||||
#define SYS_MOUSE_GET_POS 72
|
||||
#define SYS_GET_TICK 73
|
||||
#define SYS_DEBUG_PRINT 74
|
||||
#define SYS_QUERY_TRAP_FRAME 75
|
||||
#define SYS_SOCKET 76
|
||||
#define SYS_BIND 77
|
||||
#define SYS_LISTEN 78
|
||||
#define SYS_ACCEPT 79
|
||||
#define SYS_CONNECT 80
|
||||
#define SYS_SEND 81
|
||||
#define SYS_RECV 82
|
||||
#define SYS_SHUTDOWN 83
|
||||
#define SYS_SEND_TO 84
|
||||
#define SYS_RECV_FROM 85
|
||||
#define SYS_RESOLVE_HOST 86
|
||||
#define SYS_SET_SOCKET_OPTION 87
|
||||
#define SYS_GET_SOCKET_OPTION 88
|
||||
#define SYS_POLL 89
|
||||
#define SYS_GET_MEMORY_STATUS 90
|
||||
#define SYS_QUERY_KERNEL_STATS 91
|
||||
|
||||
#define SYS_MAX 90
|
||||
#define SYS_MAX 92
|
||||
@@ -57,7 +57,7 @@ static void KiDebugConsoleWrite(const char* text, size_t len) {
|
||||
if (!PrintChar || !text)
|
||||
return;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
PrintChar(text[i], 0x00FF00, 0x000000);
|
||||
PrintChar(text[i], 0xCCCCCC, 0x012456);
|
||||
}
|
||||
|
||||
static volatile long gPanicInProgress = 0;
|
||||
@@ -88,7 +88,7 @@ __declspec(dllexport) int KeHandleNmiIpi(void) {
|
||||
}
|
||||
|
||||
void KiKernelPutChar(char c) {
|
||||
PrintChar(c, 0x00FF00, 0x000000);
|
||||
PrintChar(c, 0xCCCCCC, 0x012456);
|
||||
}
|
||||
|
||||
void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), uint32_t flags) {
|
||||
@@ -231,13 +231,12 @@ __declspec(dllexport) _Noreturn void KePanic(int code, const char* fmt, ...) {
|
||||
for (;;) __halt();
|
||||
}
|
||||
|
||||
// KePrintConsole - write user-visible console text in white-on-black.
|
||||
// Used by SYS_WRITE_CONSOLE so user programs get a distinct color from
|
||||
// kernel debug output (green) and panic output (red).
|
||||
// KePrintConsole - write user-visible console text using the default console palette.
|
||||
// Panic output keeps a distinct color so fatal paths remain visually obvious.
|
||||
__declspec(dllexport) void KePrintConsole(const char* buf, size_t len) {
|
||||
if (!buf || !PrintChar) return;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
PrintChar(buf[i], 0xFFFFFF, 0x000000);
|
||||
PrintChar(buf[i], 0xCCCCCC, 0x012456);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <kernel/ke_idt.h>
|
||||
#include <kernel/ke_irql.h>
|
||||
#include <kernel/ke_dpc.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <ntlite/ddi/hal_api.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
|
||||
@@ -115,6 +117,12 @@ void KiExitInterrupt(void) {
|
||||
// code, leave the request pending instead of switching out of a spinlock or
|
||||
// high-IRQL region.
|
||||
if (cpu->InterruptDepth == 0 && KeGetCurrentIrql() == PASSIVE_LEVEL) {
|
||||
THREAD* current = cpu->CurrentThread;
|
||||
if (current && !current->IsIdleThread && current->Owner && KeIsProcessTerminating(current->Owner)) {
|
||||
KeExitThread(current, current->Owner->ExitCode);
|
||||
while (true) ;
|
||||
}
|
||||
|
||||
KiDrainDpcQueue();
|
||||
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
|
||||
KiScheduleFromInterrupt();
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <kernel/ke_userenv.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global process list
|
||||
@@ -382,16 +384,26 @@ KSTATUS KeTerminateProcess(PROCESS* process, int exitCode) {
|
||||
process->ExitCode = exitCode;
|
||||
_InterlockedExchange(&process->Terminating, 1);
|
||||
|
||||
// Wake alertable waiters so they can notice Terminating at the syscall/
|
||||
// wait boundary. This is intentionally conservative: fully asynchronous
|
||||
// forced thread teardown needs object-specific wait-list locking and is a
|
||||
// larger process-lifecycle project.
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->HandleLock);
|
||||
LIST_ENTRY* head = &process->ThreadList;
|
||||
THREAD* self = KeGetCurrentThread();
|
||||
KCPU* selfCpu = KeGetCurrentCpu();
|
||||
uint32_t selfIndex = selfCpu ? selfCpu->CpuIndex : KE_INVALID_CPU;
|
||||
|
||||
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
|
||||
THREAD* t = CONTAINING_RECORD(node, THREAD, ProcessLink);
|
||||
if (t != KeGetCurrentThread())
|
||||
(void)KeAlertThread(t);
|
||||
if (t == self)
|
||||
continue;
|
||||
|
||||
(void)KeAlertThread(t);
|
||||
|
||||
if (t->RunningCpu != KE_INVALID_CPU && t->RunningCpu != selfIndex && t->RunningCpu < gCpuCount) {
|
||||
KCPU* cpu = &gCpus[t->RunningCpu];
|
||||
if (cpu->Present && cpu->Started && cpu->Online) {
|
||||
_InterlockedExchange(&cpu->ReschedulePending, 1);
|
||||
HalApicSendRescheduleIpi(cpu->LapicId);
|
||||
}
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&process->HandleLock, flags);
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ static uint64_t KiDefaultThreadAffinityMask(void) {
|
||||
return 1ULL;
|
||||
}
|
||||
|
||||
static int KiThreadIsKilledLocked(const THREAD* thread) {
|
||||
return thread && !thread->IsIdleThread && thread->Owner && KeIsProcessTerminating(thread->Owner);
|
||||
}
|
||||
|
||||
static int KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) {
|
||||
if (!thread || !cpu) return 0;
|
||||
if (thread->IsIdleThread) return thread == cpu->IdleThread;
|
||||
@@ -494,6 +498,10 @@ static void KiSchedule(void) {
|
||||
// still runnable and nobody else is ready, keep executing it. Otherwise a
|
||||
// lone CPU-bound thread gets alternated with the idle thread on every timer
|
||||
// tick, effectively turning a periodic preemption check into a 50% throttle.
|
||||
if (cur != idle && KiThreadIsKilledLocked(cur)) {
|
||||
cur->State = ThreadDead;
|
||||
}
|
||||
|
||||
if (cur != idle && cur->State == ThreadRunning && !KiAnyRunnableForCpuLocked(cpu)) {
|
||||
if (cur->QuantumRemaining == 0)
|
||||
KiRefillQuantumLocked(cur);
|
||||
@@ -635,6 +643,8 @@ void KeSchedulerTick(void) {
|
||||
if (cur == idle) {
|
||||
if (KiAnyRunnableForCpuLocked(cpu))
|
||||
requestReschedule = 1;
|
||||
} else if (KiThreadIsKilledLocked(cur)) {
|
||||
requestReschedule = 1;
|
||||
} else {
|
||||
cur->CpuBurstTicks++;
|
||||
cur->QuantaConsumed = cur->CpuBurstTicks;
|
||||
|
||||
+24
-1
@@ -298,13 +298,29 @@ _Noreturn void KiApKernelEntry(KCPU* cpu) {
|
||||
idle->RunningCpu = cpu->CpuIndex;
|
||||
idle->Queued = 0;
|
||||
cpu->Parked = 0;
|
||||
|
||||
// Do not arm the AP's periodic LAPIC timer while it is still in
|
||||
// the raw park loop. Timer IRQs are scheduler-owned events;
|
||||
// the AP may take them only after it has a current idle thread.
|
||||
HalTimerConfigureCurrentCpu();
|
||||
|
||||
_InterlockedExchange(&cpu->SchedulerActive, 1);
|
||||
_enable();
|
||||
KeStartInitialThread(idle);
|
||||
}
|
||||
}
|
||||
|
||||
_mm_pause();
|
||||
// The BSP admits parked APs by storing SchedulerCommand and sending a
|
||||
// wake IPI. Avoid the classic lost wakeup where the command appears
|
||||
// between the poll and HLT: check once with interrupts disabled, then
|
||||
// STI;HLT as a single sleep transition.
|
||||
_disable();
|
||||
if (_InterlockedCompareExchange(&cpu->SchedulerCommand, 0, 0) != 0) {
|
||||
_enable();
|
||||
continue;
|
||||
}
|
||||
_enable();
|
||||
__halt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,6 +782,13 @@ KSTATUS KeAdmitApplicationProcessorsToScheduler(void) {
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(&cpu->SchedulerCommand, 1);
|
||||
|
||||
// Parked APs sleep with HLT and have no LAPIC timer armed yet. The
|
||||
// command store alone is not sufficient; send a fixed-vector IPI only
|
||||
// to wake the parked loop. ReschedulePending is intentionally left
|
||||
// clear, so the interrupt exit path will not try to schedule before
|
||||
// the AP has installed its idle thread.
|
||||
HalApicSendRescheduleIpi(cpu->LapicId);
|
||||
|
||||
int active = 0;
|
||||
for (uint32_t spin = 0; spin < AP_SCHED_TIMEOUT_SPINS; spin++) {
|
||||
if (_InterlockedCompareExchange(&cpu->SchedulerActive, 0, 0) != 0) {
|
||||
|
||||
+335
-111
@@ -34,6 +34,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <kernel/ke_thread.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/ke_sched.h>
|
||||
#include <kernel/ke_process.h>
|
||||
#include <kernel/ke_mutex.h>
|
||||
@@ -354,33 +355,147 @@ static uint64_t SyscallSetThreadPriority(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_ALLOC (8) a0 = size -> void*
|
||||
// SYS_VM_* page-granular user virtual memory
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallAlloc(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (!a0) return 0;
|
||||
return (uint64_t)(uintptr_t)MmAllocateUserMemory((size_t)a0);
|
||||
static KSTATUS KiVmProtectToPageFlags(uint32_t protect, uint64_t* flagsOut) {
|
||||
if (!flagsOut) return STATUS_INVALID_PARAMETER;
|
||||
switch (protect) {
|
||||
case SYS_VM_NOACCESS:
|
||||
*flagsOut = 0;
|
||||
return STATUS_SUCCESS;
|
||||
case SYS_VM_READ:
|
||||
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_NX;
|
||||
return STATUS_SUCCESS;
|
||||
case SYS_VM_READWRITE:
|
||||
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_WRITE | PAGE_NX;
|
||||
return STATUS_SUCCESS;
|
||||
case SYS_VM_EXECUTE:
|
||||
case SYS_VM_EXECUTE_READ:
|
||||
*flagsOut = PAGE_PRESENT | PAGE_USER;
|
||||
return STATUS_SUCCESS;
|
||||
case SYS_VM_EXECUTE_READWRITE:
|
||||
*flagsOut = PAGE_PRESENT | PAGE_USER | PAGE_WRITE;
|
||||
return STATUS_SUCCESS;
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_FREE a0 = ptr
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallFree(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
if (a0) MmFreeUserMemory((void*)(uintptr_t)a0);
|
||||
static uint32_t KiPageFlagsToVmProtect(uint64_t flags) {
|
||||
if (!(flags & PAGE_PRESENT)) return SYS_VM_NOACCESS;
|
||||
bool writable = (flags & PAGE_WRITE) != 0;
|
||||
bool executable = (flags & PAGE_NX) == 0;
|
||||
if (executable && writable) return SYS_VM_EXECUTE_READWRITE;
|
||||
if (executable) return SYS_VM_EXECUTE_READ;
|
||||
if (writable) return SYS_VM_READWRITE;
|
||||
return SYS_VM_READ;
|
||||
}
|
||||
|
||||
static uint64_t SyscallVmAlloc(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a5;
|
||||
void* preferredBase = (void*)(uintptr_t)a0;
|
||||
size_t pageCount = (size_t)a1;
|
||||
uint32_t protect = (uint32_t)a2;
|
||||
uint32_t flags = (uint32_t)a3;
|
||||
void** baseOut = (void**)(uintptr_t)a4;
|
||||
|
||||
if (!pageCount || !baseOut) return STATUS_INVALID_PARAMETER;
|
||||
if (pageCount > ((size_t)-1) / PAGE_SIZE) return STATUS_NO_MEMORY;
|
||||
if (preferredBase || (flags & SYS_VM_FLAG_FIXED)) return STATUS_NOT_SUPPORTED;
|
||||
|
||||
uint64_t pageFlags = 0;
|
||||
KSTATUS s = KiVmProtectToPageFlags(protect, &pageFlags);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process) return STATUS_FAILURE;
|
||||
|
||||
void* base = (void*)0;
|
||||
s = MmCreateUserRegion(process, pageCount * PAGE_SIZE, PAGE_SIZE,
|
||||
pageFlags ? pageFlags : (PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX),
|
||||
USER_REGION_ZERO,
|
||||
UserRegionGeneric,
|
||||
&base);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
if (protect == SYS_VM_NOACCESS) {
|
||||
s = MmProtectUserRegion(process, base, pageCount * PAGE_SIZE, 0);
|
||||
if (!KSUCCESS(s)) {
|
||||
MmDestroyUserRegion(process, base);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
s = CopyToUser(baseOut, &base, sizeof(base));
|
||||
if (!KSUCCESS(s)) {
|
||||
MmDestroyUserRegion(process, base);
|
||||
return s;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_REALLOC (10) a0 = ptr, a1 = newSize -> void*
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallRealloc(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
static uint64_t SyscallVmFree(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process || !a0) return STATUS_INVALID_PARAMETER;
|
||||
return MmDestroyUserRegion(process, (void*)(uintptr_t)a0);
|
||||
}
|
||||
|
||||
static uint64_t SyscallVmProtect(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a4; (void)a5;
|
||||
if (!a0 || !a1) return STATUS_INVALID_PARAMETER;
|
||||
if ((size_t)a1 > ((size_t)-1) / PAGE_SIZE) return STATUS_NO_MEMORY;
|
||||
|
||||
uint64_t pageFlags = 0;
|
||||
KSTATUS s = KiVmProtectToPageFlags((uint32_t)a2, &pageFlags);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process) return STATUS_FAILURE;
|
||||
|
||||
if (a3) {
|
||||
void* regionBase = (void*)0;
|
||||
size_t regionSize = 0;
|
||||
uint64_t oldFlags = 0;
|
||||
USER_REGION_TYPE type = UserRegionGeneric;
|
||||
uint32_t regionFlags = 0;
|
||||
s = MmQueryUserRegion(process, (void*)(uintptr_t)a0, ®ionBase, ®ionSize, &oldFlags, &type, ®ionFlags);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
uint32_t oldProtect = KiPageFlagsToVmProtect(oldFlags);
|
||||
s = CopyToUser((void*)(uintptr_t)a3, &oldProtect, sizeof(oldProtect));
|
||||
if (!KSUCCESS(s)) return s;
|
||||
}
|
||||
|
||||
return MmProtectUserRegion(process, (void*)(uintptr_t)a0, (size_t)a1 * PAGE_SIZE, pageFlags);
|
||||
}
|
||||
|
||||
static uint64_t SyscallVmQuery(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return (uint64_t)(uintptr_t)MmReallocateUserMemory(
|
||||
(void*)(uintptr_t)a0, (size_t)a1);
|
||||
if (!a0 || !a1) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
PROCESS* process = KeGetCurrentProcess();
|
||||
if (!process) return STATUS_FAILURE;
|
||||
|
||||
void* base = (void*)0;
|
||||
size_t size = 0;
|
||||
uint64_t pageFlags = 0;
|
||||
USER_REGION_TYPE type = UserRegionGeneric;
|
||||
uint32_t regionFlags = 0;
|
||||
KSTATUS s = MmQueryUserRegion(process, (void*)(uintptr_t)a0, &base, &size, &pageFlags, &type, ®ionFlags);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
|
||||
SYS_VM_REGION_INFO info;
|
||||
info.Base = base;
|
||||
info.PageCount = size / PAGE_SIZE;
|
||||
info.Protect = KiPageFlagsToVmProtect(pageFlags);
|
||||
info.Flags = regionFlags;
|
||||
info.Type = (uint32_t)type;
|
||||
info.OwnerPid = process->ProcessId;
|
||||
return CopyToUser((void*)(uintptr_t)a1, &info, sizeof(info));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -2565,6 +2680,99 @@ static uint64_t SyscallGetMemoryStatus(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
return CopyToUser((void*)(uintptr_t)a0, &status, sizeof(status));
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_QUERY_KERNEL_STATS a0=classId a1=buffer a2=bufferSize a3=*requiredSizeOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static KSTATUS KiReturnKernelStats(uint64_t bufferArg, size_t bufferSize,
|
||||
uint64_t requiredArg,
|
||||
const void* src, size_t size) {
|
||||
if (requiredArg) {
|
||||
KSTATUS s = KiCopySizeToUser(requiredArg, size);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
}
|
||||
|
||||
if (!bufferArg)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
if (bufferSize < size)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
return CopyToUser((void*)(uintptr_t)bufferArg, src, size);
|
||||
}
|
||||
|
||||
static uint64_t SyscallQueryKernelStats(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a4; (void)a5;
|
||||
|
||||
switch ((uint32_t)a0) {
|
||||
case SYS_KERNEL_STATS_SCHEDULER: {
|
||||
KE_SCHED_STATS ks;
|
||||
SYS_SCHEDULER_STATS us;
|
||||
KeGetSchedulerStats(&ks);
|
||||
memset(&us, 0, sizeof(us));
|
||||
us.Ticks = ks.Ticks;
|
||||
us.ContextSwitches = ks.ContextSwitches;
|
||||
us.KeepCurrentDecisions = ks.KeepCurrentDecisions;
|
||||
us.IdleSelections = ks.IdleSelections;
|
||||
us.Demotions = ks.Demotions;
|
||||
us.AgingPromotions = ks.AgingPromotions;
|
||||
us.QuantumExpirations = ks.QuantumExpirations;
|
||||
us.PriorityPreemptions = ks.PriorityPreemptions;
|
||||
us.VoluntaryBlocks = ks.VoluntaryBlocks;
|
||||
us.CpuBurstDemotions = ks.CpuBurstDemotions;
|
||||
us.SmtSiblingDeferrals = ks.SmtSiblingDeferrals;
|
||||
us.SmtPrimaryPokes = ks.SmtPrimaryPokes;
|
||||
return KiReturnKernelStats(a1, (size_t)a2, a3, &us, sizeof(us));
|
||||
}
|
||||
|
||||
case SYS_KERNEL_STATS_PMM: {
|
||||
MM_PHYSICAL_STATS km;
|
||||
SYS_PMM_STATS um;
|
||||
MmQueryPhysicalStats(&km);
|
||||
memset(&um, 0, sizeof(um));
|
||||
um.TotalFrames = km.TotalFrames;
|
||||
um.FreeFrames = km.FreeFrames;
|
||||
um.UsedFrames = km.UsedFrames;
|
||||
um.LargestFreeRun = km.LargestFreeRun;
|
||||
um.FreeRunCount = km.FreeRunCount;
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
um.FreeRunHistogram[i] = km.FreeRunHistogram[i];
|
||||
return KiReturnKernelStats(a1, (size_t)a2, a3, &um, sizeof(um));
|
||||
}
|
||||
|
||||
case SYS_KERNEL_STATS_CPU: {
|
||||
SYS_CPU_STATS stats;
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
stats.CpuCount = gCpuCount;
|
||||
uint32_t n = gCpuCount;
|
||||
if (n > SYS_KERNEL_STATS_MAX_CPUS)
|
||||
n = SYS_KERNEL_STATS_MAX_CPUS;
|
||||
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
KCPU* cpu = &gCpus[i];
|
||||
SYS_CPU_STAT* out = &stats.Cpu[i];
|
||||
out->CpuIndex = cpu->CpuIndex;
|
||||
out->LapicId = cpu->LapicId;
|
||||
if (cpu->Present) out->Flags |= SYS_CPU_FLAG_PRESENT;
|
||||
if (cpu->Started) out->Flags |= SYS_CPU_FLAG_STARTED;
|
||||
if (cpu->Parked) out->Flags |= SYS_CPU_FLAG_PARKED;
|
||||
if (cpu->Online) out->Flags |= SYS_CPU_FLAG_ONLINE;
|
||||
if (cpu->IsBsp) out->Flags |= SYS_CPU_FLAG_BSP;
|
||||
if (cpu->IsPrimaryThread) out->Flags |= SYS_CPU_FLAG_PRIMARY;
|
||||
out->CurrentTid = cpu->CurrentThread ? cpu->CurrentThread->ThreadId : 0;
|
||||
out->SchedulerTicks = cpu->SchedulerTicks;
|
||||
out->ContextSwitches = cpu->ContextSwitches;
|
||||
}
|
||||
|
||||
return KiReturnKernelStats(a1, (size_t)a2, a3, &stats, sizeof(stats));
|
||||
}
|
||||
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Dispatch table - index must match SYS_* in syscall_nr.h exactly.
|
||||
// ===========================================================================
|
||||
@@ -2572,96 +2780,98 @@ typedef uint64_t (*SYSCALL_HANDLER)(uint64_t, uint64_t, uint64_t,
|
||||
uint64_t, uint64_t, uint64_t);
|
||||
|
||||
static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = {
|
||||
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
|
||||
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
|
||||
/* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 05 SYS_KILL_PROCESS */ SyscallKillProcess,
|
||||
/* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
|
||||
/* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 08 SYS_CREATE_THREAD */ SyscallCreateThread,
|
||||
/* 09 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
|
||||
/* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
|
||||
/* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
|
||||
/* 13 SYS_YIELD */ SyscallYield,
|
||||
/* 14 SYS_SLEEP */ SyscallSleep,
|
||||
/* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher,
|
||||
/* 16 SYS_APC_RETURN */ SyscallApcReturn,
|
||||
/* 17 SYS_ALLOC */ SyscallAlloc,
|
||||
/* 18 SYS_FREE */ SyscallFree,
|
||||
/* 19 SYS_REALLOC */ SyscallRealloc,
|
||||
/* 20 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
|
||||
/* 21 SYS_MUTEX_CREATE */ SyscallMutexCreate,
|
||||
/* 22 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
|
||||
/* 23 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
|
||||
/* 24 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
|
||||
/* 25 SYS_SEM_CREATE */ SyscallSemCreate,
|
||||
/* 26 SYS_SEM_WAIT */ SyscallSemWait,
|
||||
/* 27 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
|
||||
/* 28 SYS_SEM_SIGNAL */ SyscallSemSignal,
|
||||
/* 29 SYS_EVENT_CREATE */ SyscallEventCreate,
|
||||
/* 30 SYS_EVENT_SIGNAL */ SyscallEventSignal,
|
||||
/* 31 SYS_EVENT_CLEAR */ SyscallEventClear,
|
||||
/* 32 SYS_EVENT_WAIT */ SyscallEventWait,
|
||||
/* 33 SYS_QUEUE_CREATE */ SyscallQueueCreate,
|
||||
/* 34 SYS_QUEUE_SEND */ SyscallQueueSend,
|
||||
/* 35 SYS_QUEUE_RECV */ SyscallQueueRecv,
|
||||
/* 36 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 37 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 38 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 39 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 40 SYS_OPEN_FILE */ SyscallOpenFile,
|
||||
/* 41 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 42 SYS_READ_FILE */ SyscallReadFile,
|
||||
/* 43 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 44 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync,
|
||||
/* 45 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync,
|
||||
/* 46 SYS_CANCEL_IO */ SyscallCancelIo,
|
||||
/* 47 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 48 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 49 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 50 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 51 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 52 SYS_RENAME_FILE */ SyscallRenameFile,
|
||||
/* 53 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 54 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 55 SYS_CREATE_DIR */ SyscallCreateDir,
|
||||
/* 56 SYS_REMOVE_DIR */ SyscallRemoveDir,
|
||||
/* 57 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 58 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 59 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 60 SYS_SCREEN_BLIT */ SyscallScreenBlit,
|
||||
/* 61 SYS_SCREEN_CLEAR */ SyscallScreenClear,
|
||||
/* 62 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
|
||||
/* 63 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
|
||||
/* 64 SYS_KB_POLL */ SyscallKbPoll,
|
||||
/* 65 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
|
||||
/* 66 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 67 SYS_KB_READ_KEY */ SyscallKbReadKey,
|
||||
/* 68 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 69 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 70 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 71 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 72 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 73 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 74 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame,
|
||||
/* 75 SYS_SOCKET */ SyscallSocket,
|
||||
/* 76 SYS_BIND */ SyscallBind,
|
||||
/* 77 SYS_LISTEN */ SyscallListen,
|
||||
/* 78 SYS_ACCEPT */ SyscallAccept,
|
||||
/* 79 SYS_CONNECT */ SyscallConnect,
|
||||
/* 80 SYS_SEND */ SyscallSend,
|
||||
/* 81 SYS_RECV */ SyscallRecv,
|
||||
/* 82 SYS_SHUTDOWN */ SyscallShutdown,
|
||||
/* 83 SYS_SEND_TO */ SyscallSendTo,
|
||||
/* 84 SYS_RECV_FROM */ SyscallRecvFrom,
|
||||
/* 85 SYS_RESOLVE_HOST */ SyscallResolveHost,
|
||||
/* 86 SYS_SET_SOCKET_OPTION */ SyscallSetSocketOption,
|
||||
/* 87 SYS_GET_SOCKET_OPTION */ SyscallGetSocketOption,
|
||||
/* 88 SYS_POLL */ SyscallPoll,
|
||||
/* 89 SYS_GET_MEMORY_STATUS */ SyscallGetMemoryStatus
|
||||
/* 00 SYS_EXIT_PROCESS */ SyscallExitProcess,
|
||||
/* 01 SYS_EXIT_THREAD */ SyscallExitThread,
|
||||
/* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess,
|
||||
/* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess,
|
||||
/* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode,
|
||||
/* 05 SYS_KILL_PROCESS */ SyscallKillProcess,
|
||||
/* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList,
|
||||
/* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid,
|
||||
/* 08 SYS_CREATE_THREAD */ SyscallCreateThread,
|
||||
/* 09 SYS_WAIT_THREAD */ SyscallWaitThread,
|
||||
/* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid,
|
||||
/* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid,
|
||||
/* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority,
|
||||
/* 13 SYS_YIELD */ SyscallYield,
|
||||
/* 14 SYS_SLEEP */ SyscallSleep,
|
||||
/* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher,
|
||||
/* 16 SYS_APC_RETURN */ SyscallApcReturn,
|
||||
/* 17 SYS_VM_ALLOC */ SyscallVmAlloc,
|
||||
/* 18 SYS_VM_FREE */ SyscallVmFree,
|
||||
/* 19 SYS_VM_PROTECT */ SyscallVmProtect,
|
||||
/* 20 SYS_VM_QUERY */ SyscallVmQuery,
|
||||
/* 21 SYS_CLOSE_HANDLE */ SyscallCloseHandle,
|
||||
/* 22 SYS_MUTEX_CREATE */ SyscallMutexCreate,
|
||||
/* 23 SYS_MUTEX_ACQUIRE */ SyscallMutexAcquire,
|
||||
/* 24 SYS_MUTEX_TRY_ACQUIRE */ SyscallMutexTryAcquire,
|
||||
/* 25 SYS_MUTEX_RELEASE */ SyscallMutexRelease,
|
||||
/* 26 SYS_SEM_CREATE */ SyscallSemCreate,
|
||||
/* 27 SYS_SEM_WAIT */ SyscallSemWait,
|
||||
/* 28 SYS_SEM_TRY_WAIT */ SyscallSemTryWait,
|
||||
/* 29 SYS_SEM_SIGNAL */ SyscallSemSignal,
|
||||
/* 30 SYS_EVENT_CREATE */ SyscallEventCreate,
|
||||
/* 31 SYS_EVENT_SIGNAL */ SyscallEventSignal,
|
||||
/* 32 SYS_EVENT_CLEAR */ SyscallEventClear,
|
||||
/* 33 SYS_EVENT_WAIT */ SyscallEventWait,
|
||||
/* 34 SYS_QUEUE_CREATE */ SyscallQueueCreate,
|
||||
/* 35 SYS_QUEUE_SEND */ SyscallQueueSend,
|
||||
/* 36 SYS_QUEUE_RECV */ SyscallQueueRecv,
|
||||
/* 37 SYS_PUBLISH_QUEUE */ SyscallPublishQueue,
|
||||
/* 38 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue,
|
||||
/* 39 SYS_QUEUE_DUPLICATE */ SyscallQueueDuplicate,
|
||||
/* 40 SYS_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid,
|
||||
/* 41 SYS_OPEN_FILE */ SyscallOpenFile,
|
||||
/* 42 SYS_CREATE_FILE */ SyscallCreateFile,
|
||||
/* 43 SYS_READ_FILE */ SyscallReadFile,
|
||||
/* 44 SYS_WRITE_FILE */ SyscallWriteFile,
|
||||
/* 45 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync,
|
||||
/* 46 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync,
|
||||
/* 47 SYS_CANCEL_IO */ SyscallCancelIo,
|
||||
/* 48 SYS_SEEK_FILE */ SyscallSeekFile,
|
||||
/* 49 SYS_GET_FILE_POS */ SyscallGetFilePos,
|
||||
/* 50 SYS_GET_FILE_SIZE */ SyscallGetFileSize,
|
||||
/* 51 SYS_TRUNCATE_FILE */ SyscallTruncateFile,
|
||||
/* 52 SYS_DELETE_FILE */ SyscallDeleteFile,
|
||||
/* 53 SYS_RENAME_FILE */ SyscallRenameFile,
|
||||
/* 54 SYS_OPEN_DIR */ SyscallOpenDir,
|
||||
/* 55 SYS_READ_DIR */ SyscallReadDir,
|
||||
/* 56 SYS_CREATE_DIR */ SyscallCreateDir,
|
||||
/* 57 SYS_REMOVE_DIR */ SyscallRemoveDir,
|
||||
/* 58 SYS_SET_CWD */ SyscallSetCwd,
|
||||
/* 59 SYS_GET_CWD */ SyscallGetCwd,
|
||||
/* 60 SYS_WRITE_CONSOLE */ SyscallWriteConsole,
|
||||
/* 61 SYS_SCREEN_BLIT */ SyscallScreenBlit,
|
||||
/* 62 SYS_SCREEN_CLEAR */ SyscallScreenClear,
|
||||
/* 63 SYS_SCREEN_GET_SIZE */ SyscallScreenGetSize,
|
||||
/* 64 SYS_SCREEN_PUT_CHAR */ SyscallScreenPutChar,
|
||||
/* 65 SYS_KB_POLL */ SyscallKbPoll,
|
||||
/* 66 SYS_KB_IS_KEY_DOWN */ SyscallKbIsKeyDown,
|
||||
/* 67 SYS_KB_READ_CHAR */ SyscallKbReadChar,
|
||||
/* 68 SYS_KB_READ_KEY */ SyscallKbReadKey,
|
||||
/* 69 SYS_KB_GET_MODIFIERS */ SyscallKbGetModifiers,
|
||||
/* 70 SYS_MOUSE_POLL */ SyscallMousePoll,
|
||||
/* 71 SYS_MOUSE_READ */ SyscallMouseRead,
|
||||
/* 72 SYS_MOUSE_GET_POS */ SyscallMouseGetPos,
|
||||
/* 73 SYS_GET_TICK */ SyscallGetTick,
|
||||
/* 74 SYS_DEBUG_PRINT */ SyscallDebugPrint,
|
||||
/* 75 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame,
|
||||
/* 76 SYS_SOCKET */ SyscallSocket,
|
||||
/* 77 SYS_BIND */ SyscallBind,
|
||||
/* 78 SYS_LISTEN */ SyscallListen,
|
||||
/* 79 SYS_ACCEPT */ SyscallAccept,
|
||||
/* 80 SYS_CONNECT */ SyscallConnect,
|
||||
/* 81 SYS_SEND */ SyscallSend,
|
||||
/* 82 SYS_RECV */ SyscallRecv,
|
||||
/* 83 SYS_SHUTDOWN */ SyscallShutdown,
|
||||
/* 84 SYS_SEND_TO */ SyscallSendTo,
|
||||
/* 85 SYS_RECV_FROM */ SyscallRecvFrom,
|
||||
/* 86 SYS_RESOLVE_HOST */ SyscallResolveHost,
|
||||
/* 87 SYS_SET_SOCKET_OPTION */ SyscallSetSocketOption,
|
||||
/* 88 SYS_GET_SOCKET_OPTION */ SyscallGetSocketOption,
|
||||
/* 89 SYS_POLL */ SyscallPoll,
|
||||
/* 90 SYS_GET_MEMORY_STATUS */ SyscallGetMemoryStatus,
|
||||
/* 91 SYS_QUERY_KERNEL_STATS */ SyscallQueryKernelStats
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -2681,5 +2891,19 @@ uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1,
|
||||
}
|
||||
|
||||
if (nr >= SYS_MAX || !gSyscallTable[nr]) return STATUS_NOT_SUPPORTED;
|
||||
return gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
|
||||
|
||||
uint64_t result = gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
|
||||
|
||||
// A process may be terminated while one of its threads is already inside a
|
||||
// syscall. Do not allow that thread to return to userspace after the owner
|
||||
// has been marked terminating.
|
||||
owner = self ? self->Owner : (PROCESS*)0;
|
||||
if (owner && KeIsProcessTerminating(owner) &&
|
||||
nr != SYS_EXIT_PROCESS && nr != SYS_EXIT_THREAD) {
|
||||
int exitCode = owner->ExitCode;
|
||||
KeExitThread(self, exitCode);
|
||||
while (true) ;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+1
-1
@@ -409,7 +409,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) {
|
||||
.FramebufferHeight = bootInfo->FramebufferHeight,
|
||||
.FramebufferStride = bootInfo->FramebufferStride,
|
||||
.RsdpPhysical = bootInfo->RsdpPhysical,
|
||||
.Debug = bootInfo->Debug,
|
||||
.Debug = bootInfo->Debug & 1, // bitmask 1 debug prints
|
||||
.AllocatePool = MmAllocatePool
|
||||
};
|
||||
|
||||
|
||||
@@ -325,6 +325,7 @@ static void KiFreeLoadedImage(uintptr_t imageBase, bool user) {
|
||||
|
||||
KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) {
|
||||
if (!imageBase) return STATUS_INVALID_PARAMETER;
|
||||
if (user && !process) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
size_t mappedSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase);
|
||||
if (!mappedSize) return STATUS_FAILURE;
|
||||
@@ -387,9 +388,6 @@ KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool us
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS LdrProtectImage(uintptr_t imageBase, bool user) {
|
||||
return LdrProtectImageForProcess(user ? (PROCESS*)0 : (PROCESS*)0, imageBase, user);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Entry point lookup
|
||||
|
||||
+247
-137
@@ -1,13 +1,12 @@
|
||||
// mm_phys.c - physical memory manager
|
||||
//
|
||||
// The free-frame stack is a flat array of PHYSICAL_ADDRESS values carved out of
|
||||
// the first suitable usable region before any allocation is served. All access
|
||||
// to physical memory goes through the direct physical window established by the
|
||||
// bootloader at PhysicalWindowBase (always 0xFFFF880000000000).
|
||||
//
|
||||
// Lock: a single spinlock guards Push/Pop. O(1) for both operations.
|
||||
// Bitmap allocator over 4 KB physical frames. One bitmap records which PFNs
|
||||
// exist in usable RAM, and one bitmap records which usable PFNs are currently
|
||||
// free. This keeps single-frame allocation simple while making contiguous
|
||||
// allocation and memory visualization deterministic.
|
||||
#include <kernel/mm_phys.h>
|
||||
#include <kernel/ke_spinlock.h>
|
||||
#include <string.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Physical-to-virtual translation via the direct map window.
|
||||
@@ -19,122 +18,198 @@ static inline void* KiPhysToVirt(PHYSICAL_ADDRESS phys) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Frame stack
|
||||
// Frame bitmap
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
PHYSICAL_ADDRESS* Stack; // pointer into physical window
|
||||
size_t Top; // index of next free slot (stack grows up)
|
||||
size_t Capacity;
|
||||
size_t Total; // total frames ever pushed
|
||||
SPINLOCK Lock;
|
||||
} FRAME_STACK;
|
||||
uint8_t* Usable; // bit = 1 when PFN belongs to usable RAM
|
||||
uint8_t* Free; // bit = 1 when PFN is currently free
|
||||
size_t BitmapBytes;
|
||||
size_t MaxPfn;
|
||||
size_t TotalFrames; // usable frames available to the allocator
|
||||
size_t FreeFrames;
|
||||
SPINLOCK Lock;
|
||||
} FRAME_BITMAP;
|
||||
|
||||
static FRAME_STACK gFrameStack;
|
||||
static FRAME_BITMAP gFrameBitmap;
|
||||
|
||||
// Push a physical frame address onto the stack.
|
||||
static void KiPushFrame(PHYSICAL_ADDRESS frame) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
if (gFrameStack.Top < gFrameStack.Capacity) {
|
||||
gFrameStack.Stack[gFrameStack.Top++] = frame;
|
||||
gFrameStack.Total++;
|
||||
static inline PHYSICAL_ADDRESS KiAlignUp(PHYSICAL_ADDRESS value) {
|
||||
return (value + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline PHYSICAL_ADDRESS KiAlignDown(PHYSICAL_ADDRESS value) {
|
||||
return value & PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline int KiBitTest(const uint8_t* bits, size_t index) {
|
||||
return (bits[index >> 3] & (uint8_t)(1u << (index & 7))) != 0;
|
||||
}
|
||||
|
||||
static inline void KiBitSet(uint8_t* bits, size_t index) {
|
||||
bits[index >> 3] |= (uint8_t)(1u << (index & 7));
|
||||
}
|
||||
|
||||
static inline void KiBitClear(uint8_t* bits, size_t index) {
|
||||
bits[index >> 3] &= (uint8_t)~(1u << (index & 7));
|
||||
}
|
||||
|
||||
static inline int KiPfnUsableLocked(size_t pfn) {
|
||||
return pfn < gFrameBitmap.MaxPfn && KiBitTest(gFrameBitmap.Usable, pfn);
|
||||
}
|
||||
|
||||
static inline int KiPfnFreeLocked(size_t pfn) {
|
||||
return KiPfnUsableLocked(pfn) && KiBitTest(gFrameBitmap.Free, pfn);
|
||||
}
|
||||
|
||||
static void KiMarkUsableFreeRange(size_t firstPfn, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t pfn = firstPfn + i;
|
||||
if (pfn >= gFrameBitmap.MaxPfn) break;
|
||||
if (!KiBitTest(gFrameBitmap.Usable, pfn)) {
|
||||
KiBitSet(gFrameBitmap.Usable, pfn);
|
||||
gFrameBitmap.TotalFrames++;
|
||||
}
|
||||
if (!KiBitTest(gFrameBitmap.Free, pfn)) {
|
||||
KiBitSet(gFrameBitmap.Free, pfn);
|
||||
gFrameBitmap.FreeFrames++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void KiRemoveUsablePfn(size_t pfn) {
|
||||
if (pfn >= gFrameBitmap.MaxPfn) return;
|
||||
if (KiBitTest(gFrameBitmap.Free, pfn)) {
|
||||
KiBitClear(gFrameBitmap.Free, pfn);
|
||||
if (gFrameBitmap.FreeFrames) gFrameBitmap.FreeFrames--;
|
||||
}
|
||||
if (KiBitTest(gFrameBitmap.Usable, pfn)) {
|
||||
KiBitClear(gFrameBitmap.Usable, pfn);
|
||||
if (gFrameBitmap.TotalFrames) gFrameBitmap.TotalFrames--;
|
||||
}
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Initialisation
|
||||
// ---------------------------------------------------------------------------
|
||||
bool MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) {
|
||||
if (!map) return false;
|
||||
gPhysBase = physicalWindowBase;
|
||||
|
||||
// --- Phase 0: Count total usable frames so we can size the stack
|
||||
// dynamically instead of capping at a hardcoded 1 GB. ---
|
||||
uint64_t totalUsableBytes = 0;
|
||||
for (uint32_t i = 0; i < map->RegionCount; i++) {
|
||||
if (map->Regions[i].Type == MemoryUsable)
|
||||
totalUsableBytes += map->Regions[i].Length;
|
||||
}
|
||||
const size_t maxFrames = (size_t)(totalUsableBytes / PAGE_SIZE);
|
||||
const size_t stackBytes = maxFrames * sizeof(PHYSICAL_ADDRESS);
|
||||
|
||||
// --- Phase 1: Find a usable region large enough to hold the stack. ---
|
||||
PHYSICAL_ADDRESS stackPhys = 0;
|
||||
for (uint32_t i = 0; i < map->RegionCount; i++) {
|
||||
const MEMORY_REGION* r = &map->Regions[i];
|
||||
if (r->Type == MemoryUsable && r->Length >= stackBytes + PAGE_SIZE) {
|
||||
stackPhys = r->Base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stackPhys) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gFrameStack.Stack = (PHYSICAL_ADDRESS *)KiPhysToVirt(stackPhys);
|
||||
gFrameStack.Top = 0;
|
||||
gFrameStack.Capacity = maxFrames;
|
||||
gFrameStack.Total = 0;
|
||||
gFrameStack.Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
// --- Phase 2: Push all free 4 KB frames, skipping the stack pages. ---
|
||||
const PHYSICAL_ADDRESS stackEnd =
|
||||
stackPhys + ((stackBytes + PAGE_SIZE - 1) & PAGE_MASK);
|
||||
|
||||
PHYSICAL_ADDRESS maxEnd = 0;
|
||||
for (uint32_t i = 0; i < map->RegionCount; i++) {
|
||||
const MEMORY_REGION* r = &map->Regions[i];
|
||||
if (r->Type != MemoryUsable) continue;
|
||||
|
||||
PHYSICAL_ADDRESS base = r->Base;
|
||||
PHYSICAL_ADDRESS end = r->Base + r->Length;
|
||||
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
|
||||
PHYSICAL_ADDRESS end = r->Base + r->Length;
|
||||
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
|
||||
end = KiAlignDown(end);
|
||||
if (end <= base) continue;
|
||||
if (end > maxEnd) maxEnd = end;
|
||||
}
|
||||
|
||||
for (PHYSICAL_ADDRESS frame = base; frame < end; frame += PAGE_SIZE) {
|
||||
if (frame >= stackPhys && frame < stackEnd) continue;
|
||||
KiPushFrame(frame);
|
||||
size_t maxPfn = (size_t)(maxEnd / PAGE_SIZE);
|
||||
if (!maxPfn) return false;
|
||||
|
||||
size_t bitmapBytes = (maxPfn + 7) / 8;
|
||||
size_t metadataBytes = bitmapBytes * 2;
|
||||
size_t metadataPages = (metadataBytes + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
PHYSICAL_ADDRESS metadataSize = (PHYSICAL_ADDRESS)metadataPages * PAGE_SIZE;
|
||||
|
||||
// Keep allocator metadata out of low memory. The bitmap is much smaller
|
||||
// than the old free-frame stack, so a first-fit search can otherwise choose
|
||||
// a conventional-memory hole below 1 MiB. That range is still useful for
|
||||
// AP startup/legacy scratch, and stealing it makes early boot failures
|
||||
// unnecessarily silent because PMM initializes before normal debug output.
|
||||
const PHYSICAL_ADDRESS metadataMin = 0x100000ULL;
|
||||
PHYSICAL_ADDRESS metadataPhys = 0;
|
||||
int metadataFound = 0;
|
||||
for (uint32_t i = 0; i < map->RegionCount; i++) {
|
||||
const MEMORY_REGION* r = &map->Regions[i];
|
||||
if (r->Type != MemoryUsable) continue;
|
||||
|
||||
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
|
||||
if (base < metadataMin) base = metadataMin;
|
||||
PHYSICAL_ADDRESS end = r->Base + r->Length;
|
||||
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
|
||||
end = KiAlignDown(end);
|
||||
if (end <= base) continue;
|
||||
if (end - base >= metadataSize) {
|
||||
metadataPhys = base;
|
||||
metadataFound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!metadataFound) return false;
|
||||
|
||||
gFrameBitmap.BitmapBytes = bitmapBytes;
|
||||
gFrameBitmap.MaxPfn = maxPfn;
|
||||
gFrameBitmap.TotalFrames = 0;
|
||||
gFrameBitmap.FreeFrames = 0;
|
||||
gFrameBitmap.Lock = (SPINLOCK)SPINLOCK_INIT;
|
||||
gFrameBitmap.Usable = (uint8_t*)KiPhysToVirt(metadataPhys);
|
||||
gFrameBitmap.Free = gFrameBitmap.Usable + bitmapBytes;
|
||||
|
||||
memset(gFrameBitmap.Usable, 0, metadataBytes);
|
||||
|
||||
// Mark page-aligned usable RAM as free. Unaligned tails are ignored rather
|
||||
// than handing malformed frame addresses to the rest of the kernel.
|
||||
for (uint32_t i = 0; i < map->RegionCount; i++) {
|
||||
const MEMORY_REGION* r = &map->Regions[i];
|
||||
if (r->Type != MemoryUsable) continue;
|
||||
|
||||
PHYSICAL_ADDRESS base = KiAlignUp(r->Base);
|
||||
PHYSICAL_ADDRESS end = r->Base + r->Length;
|
||||
if (end < r->Base) end = (PHYSICAL_ADDRESS)-1;
|
||||
end = KiAlignDown(end);
|
||||
if (end <= base) continue;
|
||||
|
||||
size_t firstPfn = (size_t)(base / PAGE_SIZE);
|
||||
size_t count = (size_t)((end - base) / PAGE_SIZE);
|
||||
KiMarkUsableFreeRange(firstPfn, count);
|
||||
}
|
||||
|
||||
// PFN 0 is never a valid allocation result because 0 is the failure value.
|
||||
KiRemoveUsablePfn(0);
|
||||
|
||||
// Hide the PMM metadata pages from the allocator entirely. They are not
|
||||
// merely allocated; they are structural storage that must not become free if
|
||||
// some caller accidentally passes their PFNs to MmFreeFrame().
|
||||
size_t metadataFirstPfn = (size_t)(metadataPhys / PAGE_SIZE);
|
||||
for (size_t i = 0; i < metadataPages; i++)
|
||||
KiRemoveUsablePfn(metadataFirstPfn + i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public API
|
||||
// ---------------------------------------------------------------------------
|
||||
static PHYSICAL_ADDRESS KiPopFrameAtIndexLocked(size_t idx) {
|
||||
PHYSICAL_ADDRESS frame = gFrameStack.Stack[idx];
|
||||
size_t tail = gFrameStack.Top - idx - 1;
|
||||
for (size_t j = 0; j < tail; j++)
|
||||
gFrameStack.Stack[idx + j] = gFrameStack.Stack[idx + 1 + j];
|
||||
gFrameStack.Top--;
|
||||
return frame;
|
||||
}
|
||||
|
||||
PHYSICAL_ADDRESS MmAllocateFrameInRange(PHYSICAL_ADDRESS minInclusive,
|
||||
PHYSICAL_ADDRESS maxExclusive) {
|
||||
minInclusive = (minInclusive + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
maxExclusive &= PAGE_MASK;
|
||||
minInclusive = KiAlignUp(minInclusive);
|
||||
maxExclusive = KiAlignDown(maxExclusive);
|
||||
if (maxExclusive <= minInclusive) return (PHYSICAL_ADDRESS)0;
|
||||
|
||||
if (maxExclusive <= minInclusive)
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
size_t firstPfn = (size_t)(minInclusive / PAGE_SIZE);
|
||||
size_t limitPfn = (size_t)(maxExclusive / PAGE_SIZE);
|
||||
if (limitPfn > gFrameBitmap.MaxPfn) limitPfn = gFrameBitmap.MaxPfn;
|
||||
if (firstPfn >= limitPfn) return (PHYSICAL_ADDRESS)0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
|
||||
|
||||
// Search high-to-low within the requested window. For low-memory users
|
||||
// such as the AP trampoline this naturally prefers the traditional
|
||||
// 0x70000-0x9f000 area and avoids consuming lower real-mode space first.
|
||||
for (size_t i = gFrameStack.Top; i > 0; i--) {
|
||||
size_t idx = i - 1;
|
||||
PHYSICAL_ADDRESS frame = gFrameStack.Stack[idx];
|
||||
if (frame >= minInclusive && frame < maxExclusive &&
|
||||
!(frame & (PAGE_SIZE - 1))) {
|
||||
frame = KiPopFrameAtIndexLocked(idx);
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return frame;
|
||||
for (size_t pfn = limitPfn; pfn > firstPfn; pfn--) {
|
||||
size_t candidate = pfn - 1;
|
||||
if (KiPfnFreeLocked(candidate)) {
|
||||
KiBitClear(gFrameBitmap.Free, candidate);
|
||||
if (gFrameBitmap.FreeFrames) gFrameBitmap.FreeFrames--;
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)candidate * PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
}
|
||||
|
||||
@@ -143,74 +218,109 @@ PHYSICAL_ADDRESS MmAllocateFrameBelow(PHYSICAL_ADDRESS maxExclusive) {
|
||||
}
|
||||
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateFrame(void) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
if (gFrameStack.Top == 0) {
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
}
|
||||
PHYSICAL_ADDRESS frame = gFrameStack.Stack[--gFrameStack.Top];
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return frame;
|
||||
return MmAllocateFrameInRange(PAGE_SIZE, (PHYSICAL_ADDRESS)gFrameBitmap.MaxPfn * PAGE_SIZE);
|
||||
}
|
||||
|
||||
void MmFreeFrame(PHYSICAL_ADDRESS frame) {
|
||||
if (!frame || (frame & (PAGE_SIZE - 1))) return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
if (gFrameStack.Top < gFrameStack.Capacity)
|
||||
gFrameStack.Stack[gFrameStack.Top++] = frame;
|
||||
// else: stack full - leak rather than corrupt
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
size_t pfn = (size_t)(frame / PAGE_SIZE);
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
|
||||
if (KiPfnUsableLocked(pfn) && !KiBitTest(gFrameBitmap.Free, pfn)) {
|
||||
KiBitSet(gFrameBitmap.Free, pfn);
|
||||
gFrameBitmap.FreeFrames++;
|
||||
}
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
}
|
||||
|
||||
__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) {
|
||||
if (!count) return (PHYSICAL_ADDRESS)0;
|
||||
if (!count || count > gFrameBitmap.MaxPfn) return (PHYSICAL_ADDRESS)0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock);
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
|
||||
|
||||
if (gFrameStack.Top < count) {
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
}
|
||||
|
||||
// Frames are pushed in ascending address order by MmInitializePhysical,
|
||||
// so physically consecutive pages sit at consecutive stack indices.
|
||||
// Scan from bottom upward for a run of 'count' adjacent frames.
|
||||
size_t run = (size_t)-1;
|
||||
for (size_t i = 0; i + count <= gFrameStack.Top; i++) {
|
||||
int ok = 1;
|
||||
for (size_t j = 1; j < count; j++) {
|
||||
if (gFrameStack.Stack[i + j] != gFrameStack.Stack[i] + j * PAGE_SIZE) {
|
||||
ok = 0;
|
||||
// Skip past this broken run; the next candidate can't start
|
||||
// before the frame that broke the sequence.
|
||||
i += j - 1; // outer loop adds 1 more
|
||||
break;
|
||||
size_t runStart = 0;
|
||||
size_t runLength = 0;
|
||||
for (size_t pfn = 1; pfn < gFrameBitmap.MaxPfn; pfn++) {
|
||||
if (KiPfnFreeLocked(pfn)) {
|
||||
if (!runLength) runStart = pfn;
|
||||
runLength++;
|
||||
if (runLength == count) {
|
||||
for (size_t i = 0; i < count; i++)
|
||||
KiBitClear(gFrameBitmap.Free, runStart + i);
|
||||
if (gFrameBitmap.FreeFrames >= count) gFrameBitmap.FreeFrames -= count;
|
||||
else gFrameBitmap.FreeFrames = 0;
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)runStart * PAGE_SIZE;
|
||||
}
|
||||
} else {
|
||||
runLength = 0;
|
||||
}
|
||||
if (ok) { run = i; break; }
|
||||
}
|
||||
|
||||
if (run == (size_t)-1) {
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
}
|
||||
|
||||
PHYSICAL_ADDRESS base = gFrameStack.Stack[run];
|
||||
|
||||
// Splice out the 'count' entries by sliding the tail down.
|
||||
size_t tail = gFrameStack.Top - run - count;
|
||||
for (size_t i = 0; i < tail; i++)
|
||||
gFrameStack.Stack[run + i] = gFrameStack.Stack[run + count + i];
|
||||
gFrameStack.Top -= count;
|
||||
|
||||
KeReleaseSpinlock(&gFrameStack.Lock, flags);
|
||||
return base;
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
return (PHYSICAL_ADDRESS)0;
|
||||
}
|
||||
|
||||
size_t MmFreeFrameCount(void) {
|
||||
return gFrameStack.Top;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
|
||||
size_t count = gFrameBitmap.FreeFrames;
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t MmTotalFrameCount(void) {
|
||||
return gFrameStack.Total;
|
||||
return gFrameBitmap.TotalFrames;
|
||||
}
|
||||
void MmQueryPhysicalStats(MM_PHYSICAL_STATS* out) {
|
||||
if (!out) return;
|
||||
|
||||
MM_PHYSICAL_STATS stats;
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock);
|
||||
|
||||
stats.TotalFrames = (uint64_t)gFrameBitmap.TotalFrames;
|
||||
stats.FreeFrames = (uint64_t)gFrameBitmap.FreeFrames;
|
||||
stats.UsedFrames = stats.TotalFrames - stats.FreeFrames;
|
||||
|
||||
uint64_t run = 0;
|
||||
for (size_t pfn = 1; pfn < gFrameBitmap.MaxPfn; pfn++) {
|
||||
if (KiPfnFreeLocked(pfn)) {
|
||||
run++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (run) {
|
||||
stats.FreeRunCount++;
|
||||
if (run > stats.LargestFreeRun)
|
||||
stats.LargestFreeRun = run;
|
||||
if (run == 1) stats.FreeRunHistogram[0]++;
|
||||
else if (run <= 3) stats.FreeRunHistogram[1]++;
|
||||
else if (run <= 7) stats.FreeRunHistogram[2]++;
|
||||
else if (run <= 15) stats.FreeRunHistogram[3]++;
|
||||
else if (run <= 63) stats.FreeRunHistogram[4]++;
|
||||
else if (run <= 255) stats.FreeRunHistogram[5]++;
|
||||
else if (run <= 1023) stats.FreeRunHistogram[6]++;
|
||||
else stats.FreeRunHistogram[7]++;
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (run) {
|
||||
stats.FreeRunCount++;
|
||||
if (run > stats.LargestFreeRun)
|
||||
stats.LargestFreeRun = run;
|
||||
if (run == 1) stats.FreeRunHistogram[0]++;
|
||||
else if (run <= 3) stats.FreeRunHistogram[1]++;
|
||||
else if (run <= 7) stats.FreeRunHistogram[2]++;
|
||||
else if (run <= 15) stats.FreeRunHistogram[3]++;
|
||||
else if (run <= 63) stats.FreeRunHistogram[4]++;
|
||||
else if (run <= 255) stats.FreeRunHistogram[5]++;
|
||||
else if (run <= 1023) stats.FreeRunHistogram[6]++;
|
||||
else stats.FreeRunHistogram[7]++;
|
||||
}
|
||||
|
||||
KeReleaseSpinlock(&gFrameBitmap.Lock, flags);
|
||||
*out = stats;
|
||||
}
|
||||
|
||||
+50
-7
@@ -11,7 +11,8 @@
|
||||
//
|
||||
// User heap:
|
||||
// A single best-fit free list in the lower half.
|
||||
// Backed on demand from the PMM. No per-process heaps.
|
||||
// Page-granular lower-half regions owned by PROCESS metadata. Sub-page
|
||||
// allocation is a user-mode runtime concern.
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
@@ -164,7 +165,7 @@ int MmHandleTlbShootdownNmi(void) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Public mapping
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) {
|
||||
__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode) {
|
||||
unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0;
|
||||
|
||||
uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock);
|
||||
@@ -186,6 +187,10 @@ __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, u
|
||||
}
|
||||
|
||||
uint64_t* pte = KiPtePtr(pt, PT_IDX(virt));
|
||||
if ((*pte & PAGE_PRESENT) && mode == MmMapFailIfPresent) {
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
}
|
||||
*pte = phys | flags;
|
||||
|
||||
KeReleaseSpinlock(&gPageTableLock, lockFlags);
|
||||
@@ -525,7 +530,7 @@ static int KiHeapEnsureMapped(HEAP* h, uintptr_t start, size_t size) {
|
||||
|
||||
PHYSICAL_ADDRESS frame = MmAllocateFrame();
|
||||
if (!frame) return 0;
|
||||
KSTATUS ms = MmMapPage(va, frame, h->MapFlags);
|
||||
KSTATUS ms = MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent);
|
||||
if (!KSUCCESS(ms)) {
|
||||
MmFreeFrame(frame);
|
||||
return 0;
|
||||
@@ -544,7 +549,7 @@ static int KiHeapGrow(HEAP* h, size_t need) {
|
||||
for (uintptr_t va = h->Brk; va < h->Brk + grow; va += PAGE_SIZE) {
|
||||
PHYSICAL_ADDRESS frame = MmAllocateFrame();
|
||||
if (!frame) return 0;
|
||||
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags))) {
|
||||
if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags, MmMapFailIfPresent))) {
|
||||
MmFreeFrame(frame);
|
||||
return 0;
|
||||
}
|
||||
@@ -965,7 +970,7 @@ KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment,
|
||||
s = STATUS_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
s = MmMapPage(va, frame, pageFlags);
|
||||
s = MmMapPage(va, frame, pageFlags, MmMapFailIfPresent);
|
||||
if (!KSUCCESS(s)) {
|
||||
MmFreeFrame(frame);
|
||||
break;
|
||||
@@ -1036,7 +1041,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint
|
||||
PHYSICAL_ADDRESS frame = MmAllocateFrame();
|
||||
if (!frame) return STATUS_NO_MEMORY;
|
||||
|
||||
KSTATUS ms = MmMapPage(va, frame, flags);
|
||||
KSTATUS ms = MmMapPage(va, frame, flags, MmMapFailIfPresent);
|
||||
if (!KSUCCESS(ms)) {
|
||||
MmFreeFrame(frame);
|
||||
return ms;
|
||||
@@ -1073,6 +1078,16 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (pageFlags == 0) {
|
||||
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
|
||||
if (va < regionBase || va >= regionEnd) return STATUS_ACCESS_DENIED;
|
||||
PHYSICAL_ADDRESS phys = MmGetPhysicalAddress(va);
|
||||
if (phys && KSUCCESS(MmUnmapPage(va)))
|
||||
MmFreeFrame(phys);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t finalFlags = pageFlags | PAGE_PRESENT | PAGE_USER;
|
||||
|
||||
for (uintptr_t va = alignedStart; va < alignedEnd; va += PAGE_SIZE) {
|
||||
@@ -1091,7 +1106,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
|
||||
if (!KSUCCESS(qs) || !(existingFlags & PAGE_PRESENT)) {
|
||||
PHYSICAL_ADDRESS frame = MmAllocateFrame();
|
||||
if (!frame) return STATUS_NO_MEMORY;
|
||||
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX);
|
||||
KSTATUS ms = MmMapPage(va, frame, PAGE_PRESENT | PAGE_WRITE | PAGE_USER | PAGE_NX, MmMapFailIfPresent);
|
||||
if (!KSUCCESS(ms)) {
|
||||
MmFreeFrame(frame);
|
||||
return ms;
|
||||
@@ -1161,6 +1176,34 @@ void MmDestroyAllUserRegions(PROCESS* process) {
|
||||
}
|
||||
}
|
||||
|
||||
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut,
|
||||
uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut) {
|
||||
if (!process || !address) return STATUS_INVALID_PARAMETER;
|
||||
uintptr_t addr = (uintptr_t)address;
|
||||
|
||||
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
|
||||
for (LIST_ENTRY* node = process->UserRegions.Fwd; node != &process->UserRegions; node = node->Fwd) {
|
||||
USER_VA_REGION* r = CONTAINING_RECORD(node, USER_VA_REGION, ProcessLink);
|
||||
uintptr_t end = r->Base + r->CommittedSize;
|
||||
if (addr >= r->Base && addr < end) {
|
||||
if (baseOut) *baseOut = (void*)r->Base;
|
||||
if (sizeOut) *sizeOut = r->CommittedSize;
|
||||
if (pageFlagsOut) {
|
||||
PHYSICAL_ADDRESS phys = 0;
|
||||
uint64_t flags = 0;
|
||||
KSTATUS qs = MmQueryPage(addr & PAGE_MASK, &phys, &flags);
|
||||
*pageFlagsOut = KSUCCESS(qs) ? flags : 0;
|
||||
}
|
||||
if (typeOut) *typeOut = r->Type;
|
||||
if (regionFlagsOut) *regionFlagsOut = r->Flags;
|
||||
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&process->UserRegionLock, procFlags);
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
|
||||
if (!process || !base) return 0;
|
||||
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#define SYS_STATUS_TIMEOUT 3u
|
||||
#define SYS_STATUS_PENDING 4u
|
||||
#define SYS_STATUS_ALERTED 5u
|
||||
#define SYS_STATUS_INVALID_PARAMETER 0x10u
|
||||
#define SYS_STATUS_NO_MEMORY 0x20u
|
||||
#define SYS_STATUS_KERNEL_APC 6u
|
||||
#define SYS_STATUS_USER_APC 7u
|
||||
#define SYS_STATUS_CANCELLED 0x33u
|
||||
@@ -205,11 +207,33 @@ uint32_t SysSetUserApcDispatcher(void* dispatcher);
|
||||
uint32_t SysApcReturn(const SYS_USER_APC_FRAME* frame);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Memory and handles
|
||||
// Virtual memory and handles
|
||||
// ---------------------------------------------------------------------------
|
||||
void* SysAlloc(size_t size);
|
||||
uint32_t SysFree(void* ptr);
|
||||
void* SysRealloc(void* ptr, size_t newSize);
|
||||
typedef enum SYS_VM_PROTECTION {
|
||||
SYS_VM_NOACCESS = 0,
|
||||
SYS_VM_READ = 1,
|
||||
SYS_VM_READWRITE = 2,
|
||||
SYS_VM_EXECUTE = 3,
|
||||
SYS_VM_EXECUTE_READ = 4,
|
||||
SYS_VM_EXECUTE_READWRITE = 5,
|
||||
} SYS_VM_PROTECTION;
|
||||
|
||||
#define SYS_VM_FLAG_NONE 0u
|
||||
#define SYS_VM_FLAG_FIXED 1u
|
||||
|
||||
typedef struct SYS_VM_REGION_INFO {
|
||||
void* Base;
|
||||
size_t PageCount;
|
||||
uint32_t Protect;
|
||||
uint32_t Flags;
|
||||
uint32_t Type;
|
||||
uint32_t OwnerPid;
|
||||
} SYS_VM_REGION_INFO;
|
||||
|
||||
uint32_t SysVmAlloc(void* preferredBase, size_t pageCount, uint32_t protect, uint32_t flags, void** baseOut);
|
||||
uint32_t SysVmFree(void* base);
|
||||
uint32_t SysVmProtect(void* base, size_t pageCount, uint32_t protect, uint32_t* oldProtectOut);
|
||||
uint32_t SysVmQuery(void* address, SYS_VM_REGION_INFO* out);
|
||||
uint32_t SysCloseHandle(uint32_t handle);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -382,6 +406,58 @@ typedef struct SYS_MEMORY_STATUS {
|
||||
uint64_t UserHeapBytes;
|
||||
} SYS_MEMORY_STATUS;
|
||||
|
||||
#define SYS_KERNEL_STATS_SCHEDULER 1u
|
||||
#define SYS_KERNEL_STATS_PMM 2u
|
||||
#define SYS_KERNEL_STATS_CPU 3u
|
||||
|
||||
#define SYS_KERNEL_STATS_MAX_CPUS 32u
|
||||
|
||||
typedef struct SYS_SCHEDULER_STATS {
|
||||
uint64_t Ticks;
|
||||
uint64_t ContextSwitches;
|
||||
uint64_t KeepCurrentDecisions;
|
||||
uint64_t IdleSelections;
|
||||
uint64_t Demotions;
|
||||
uint64_t AgingPromotions;
|
||||
uint64_t QuantumExpirations;
|
||||
uint64_t PriorityPreemptions;
|
||||
uint64_t VoluntaryBlocks;
|
||||
uint64_t CpuBurstDemotions;
|
||||
uint64_t SmtSiblingDeferrals;
|
||||
uint64_t SmtPrimaryPokes;
|
||||
} SYS_SCHEDULER_STATS;
|
||||
|
||||
typedef struct SYS_PMM_STATS {
|
||||
uint64_t TotalFrames;
|
||||
uint64_t FreeFrames;
|
||||
uint64_t UsedFrames;
|
||||
uint64_t LargestFreeRun;
|
||||
uint64_t FreeRunCount;
|
||||
uint64_t FreeRunHistogram[8];
|
||||
} SYS_PMM_STATS;
|
||||
|
||||
typedef struct SYS_CPU_STAT {
|
||||
uint32_t CpuIndex;
|
||||
uint32_t LapicId;
|
||||
uint32_t Flags;
|
||||
uint32_t CurrentTid;
|
||||
uint64_t SchedulerTicks;
|
||||
uint64_t ContextSwitches;
|
||||
} SYS_CPU_STAT;
|
||||
|
||||
typedef struct SYS_CPU_STATS {
|
||||
uint32_t CpuCount;
|
||||
uint32_t Reserved;
|
||||
SYS_CPU_STAT Cpu[SYS_KERNEL_STATS_MAX_CPUS];
|
||||
} SYS_CPU_STATS;
|
||||
|
||||
#define SYS_CPU_FLAG_PRESENT 0x00000001u
|
||||
#define SYS_CPU_FLAG_STARTED 0x00000002u
|
||||
#define SYS_CPU_FLAG_PARKED 0x00000004u
|
||||
#define SYS_CPU_FLAG_ONLINE 0x00000008u
|
||||
#define SYS_CPU_FLAG_BSP 0x00000010u
|
||||
#define SYS_CPU_FLAG_PRIMARY 0x00000020u
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Time and diagnostics
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -390,3 +466,4 @@ uint32_t SysDebugPrint(const SYS_DEBUG_PRINT_REQUEST* request);
|
||||
uint32_t SysQueryTrapFrame(SYS_TRAP_FRAME_INFO* info);
|
||||
|
||||
uint32_t SysGetMemoryStatus(SYS_MEMORY_STATUS* statusOut);
|
||||
uint32_t SysQueryKernelStats(uint32_t classId, void* buffer, size_t bufferSize, size_t* requiredSizeOut);
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
@@ -28,7 +29,7 @@ static void doom_print_wrapper(const char* msg)
|
||||
// ---------------------------------------------------------------------------
|
||||
static void* doom_malloc_wrapper(int size)
|
||||
{
|
||||
void* p = SysAlloc(size);
|
||||
void* p = malloc(size);
|
||||
if (!p) SysExitProcess(1);
|
||||
return p;
|
||||
}
|
||||
@@ -37,7 +38,7 @@ static void doom_free_wrapper(void* ptr)
|
||||
{
|
||||
if (!ptr) return;
|
||||
|
||||
SysFree(ptr);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -62,7 +63,7 @@ static void* doom_open_wrapper(const char* path, const char* mode)
|
||||
}
|
||||
if (result != 0) return 0;
|
||||
|
||||
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)SysAlloc(sizeof(DOOM_FILE_HANDLE));
|
||||
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)malloc(sizeof(DOOM_FILE_HANDLE));
|
||||
if (!f) {
|
||||
SysCloseHandle(handle);
|
||||
return 0;
|
||||
@@ -79,7 +80,7 @@ static void doom_close_wrapper(void* handle)
|
||||
if (!handle) return;
|
||||
DOOM_FILE_HANDLE* f = (DOOM_FILE_HANDLE*)handle;
|
||||
SysCloseHandle(f->Handle);
|
||||
SysFree(f);
|
||||
free(f);
|
||||
}
|
||||
|
||||
static int doom_read_wrapper(void* handle, void* buf, int count)
|
||||
|
||||
+75
-18
@@ -18,6 +18,8 @@
|
||||
#define MAX_LINE 256
|
||||
#define PATH_MAX2 260
|
||||
#define MSG_MAX 160
|
||||
#define MAX_SCREEN_COLS 256
|
||||
#define MAX_SCREEN_ROWS 128
|
||||
|
||||
#define COL_BG 0x000000u
|
||||
#define COL_FG 0xC8C8C8u
|
||||
@@ -61,8 +63,55 @@ static bool gQuitArmed = false;
|
||||
static char gFilename[PATH_MAX2] = "untitled.txt";
|
||||
static char gMessage[MSG_MAX] = "ready";
|
||||
|
||||
typedef struct SCREEN_CELL {
|
||||
char c;
|
||||
uint32_t fg;
|
||||
uint32_t bg;
|
||||
} SCREEN_CELL;
|
||||
|
||||
static SCREEN_CELL gScreenCache[MAX_SCREEN_COLS * MAX_SCREEN_ROWS];
|
||||
static bool gScreenCacheValid = false;
|
||||
|
||||
static void invalidate_screen_cache(void) {
|
||||
gScreenCacheValid = false;
|
||||
}
|
||||
|
||||
static void update_screen_size(void) {
|
||||
int pxW = 0, pxH = 0;
|
||||
int oldCols = gCols;
|
||||
int oldRows = gRows;
|
||||
|
||||
if (SysScreenGetSize(&pxW, &pxH) == 0 && pxW > 0 && pxH > 0) {
|
||||
gCols = pxW / GLYPH_W;
|
||||
gRows = pxH / GLYPH_H;
|
||||
|
||||
if (gCols < 20) gCols = 20;
|
||||
if (gRows < 5) gRows = 5;
|
||||
if (gCols > MAX_SCREEN_COLS) gCols = MAX_SCREEN_COLS;
|
||||
if (gRows > MAX_SCREEN_ROWS) gRows = MAX_SCREEN_ROWS;
|
||||
}
|
||||
|
||||
if (gCols != oldCols || gRows != oldRows)
|
||||
invalidate_screen_cache();
|
||||
}
|
||||
|
||||
static void put_cell(int col, int row, char c, uint32_t fg, uint32_t bg) {
|
||||
SysScreenPutChar(c ? c : ' ', col * GLYPH_W, row * GLYPH_H, fg, bg);
|
||||
if (col < 0 || row < 0 || col >= gCols || row >= gRows)
|
||||
return;
|
||||
|
||||
if (!c) c = ' ';
|
||||
|
||||
if (col < MAX_SCREEN_COLS && row < MAX_SCREEN_ROWS) {
|
||||
SCREEN_CELL* cell = &gScreenCache[row * MAX_SCREEN_COLS + col];
|
||||
if (gScreenCacheValid && cell->c == c && cell->fg == fg && cell->bg == bg)
|
||||
return;
|
||||
|
||||
cell->c = c;
|
||||
cell->fg = fg;
|
||||
cell->bg = bg;
|
||||
}
|
||||
|
||||
SysScreenPutChar(c, col * GLYPH_W, row * GLYPH_H, fg, bg);
|
||||
}
|
||||
|
||||
static void clear_row(int row, uint32_t bg) {
|
||||
@@ -151,13 +200,7 @@ static void ensure_visible(void) {
|
||||
}
|
||||
|
||||
static void render(void) {
|
||||
int pxW = 0, pxH = 0;
|
||||
if (SysScreenGetSize(&pxW, &pxH) == 0 && pxW > 0 && pxH > 0) {
|
||||
gCols = pxW / GLYPH_W;
|
||||
gRows = pxH / GLYPH_H;
|
||||
if (gCols < 20) gCols = 20;
|
||||
if (gRows < 5) gRows = 5;
|
||||
}
|
||||
update_screen_size();
|
||||
|
||||
clamp_cursor();
|
||||
ensure_visible();
|
||||
@@ -172,28 +215,40 @@ static void render(void) {
|
||||
append_str(status, sizeof(status), &p, ", Col ");
|
||||
append_u32(status, sizeof(status), &p, (uint32_t)(gCx + 1));
|
||||
|
||||
clear_row(0, COL_STATUS);
|
||||
draw_text(0, 0, status, COL_STATUSF, COL_STATUS);
|
||||
size_t statusLen = p;
|
||||
for (int sx = 0; sx < gCols; sx++) {
|
||||
char c = ((size_t)sx < statusLen) ? status[sx] : ' ';
|
||||
put_cell(sx, 0, c, COL_STATUSF, COL_STATUS);
|
||||
}
|
||||
|
||||
int textRows = gRows - 2;
|
||||
for (int sy = 0; sy < textRows; sy++) {
|
||||
int row = sy + 1;
|
||||
int li = gTop + sy;
|
||||
clear_row(row, COL_BG);
|
||||
if (li >= gLineCount) continue;
|
||||
|
||||
LINE* ln = &gLines[li];
|
||||
for (int sx = 0; sx < gCols; sx++) {
|
||||
int ci = gLeft + sx;
|
||||
char c = (ci < ln->len) ? ln->text[ci] : ' ';
|
||||
bool atCursor = (li == gCy && ci == gCx);
|
||||
char c = ' ';
|
||||
bool atCursor = false;
|
||||
|
||||
if (li < gLineCount) {
|
||||
LINE* ln = &gLines[li];
|
||||
c = (ci < ln->len) ? ln->text[ci] : ' ';
|
||||
atCursor = (li == gCy && ci == gCx);
|
||||
}
|
||||
|
||||
put_cell(sx, row, c, atCursor ? COL_CURSORF : COL_FG,
|
||||
atCursor ? COL_CURSOR : COL_BG);
|
||||
}
|
||||
}
|
||||
|
||||
clear_row(gRows - 1, COL_STATUS);
|
||||
draw_text(0, gRows - 1, gMessage, COL_STATUSF, COL_STATUS);
|
||||
size_t messageLen = strlen(gMessage);
|
||||
for (int sx = 0; sx < gCols; sx++) {
|
||||
char c = ((size_t)sx < messageLen) ? gMessage[sx] : ' ';
|
||||
put_cell(sx, gRows - 1, c, COL_STATUSF, COL_STATUS);
|
||||
}
|
||||
|
||||
gScreenCacheValid = true;
|
||||
}
|
||||
|
||||
static void insert_char_at_cursor(char c) {
|
||||
@@ -481,8 +536,10 @@ int main(void) {
|
||||
parse_filename_from_cmdline();
|
||||
load_file();
|
||||
SysScreenClear(COL_BG);
|
||||
invalidate_screen_cache();
|
||||
editor_loop();
|
||||
SysScreenClear(COL_BG);
|
||||
SysScreenClear(0x012456);
|
||||
invalidate_screen_cache();
|
||||
print("edit: goodbye\n");
|
||||
SysExitProcess(0);
|
||||
return 0;
|
||||
|
||||
@@ -95,6 +95,7 @@ static void cmd_help() {
|
||||
print("Available commands:\n"
|
||||
" help - Show this list\n"
|
||||
" mem - Show memory usage\n"
|
||||
" stats - Show scheduler/CPU/PMM telemetry\n"
|
||||
" ps - List running process IDs\n"
|
||||
" dir [path] - List directory contents\n"
|
||||
" cd <path> - Change directory\n"
|
||||
@@ -110,6 +111,96 @@ static void printSizeKiB(uint64_t bytes) {
|
||||
print(" KiB");
|
||||
}
|
||||
|
||||
|
||||
static void printPagesKiB(uint64_t pages) {
|
||||
printUInt64(pages * 4u);
|
||||
print(" KiB");
|
||||
}
|
||||
|
||||
static void printCpuFlags(uint32_t flags) {
|
||||
if (flags & SYS_CPU_FLAG_BSP) print("bsp ");
|
||||
if (flags & SYS_CPU_FLAG_ONLINE) print("online ");
|
||||
if (flags & SYS_CPU_FLAG_PARKED) print("parked ");
|
||||
if (flags & SYS_CPU_FLAG_PRIMARY) print("primary ");
|
||||
if (flags & SYS_CPU_FLAG_STARTED) print("started ");
|
||||
if (flags & SYS_CPU_FLAG_PRESENT) print("present ");
|
||||
}
|
||||
|
||||
static void cmd_stats(void) {
|
||||
SYS_SCHEDULER_STATS sched;
|
||||
SYS_PMM_STATS pmm;
|
||||
SYS_CPU_STATS cpu;
|
||||
uint32_t status;
|
||||
|
||||
status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, &sched, sizeof(sched), NULL);
|
||||
if (status != 0) {
|
||||
print("stats: scheduler query failed: ");
|
||||
printUInt(status);
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = SysQueryKernelStats(SYS_KERNEL_STATS_PMM, &pmm, sizeof(pmm), NULL);
|
||||
if (status != 0) {
|
||||
print("stats: pmm query failed: ");
|
||||
printUInt(status);
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, &cpu, sizeof(cpu), NULL);
|
||||
if (status != 0) {
|
||||
print("stats: cpu query failed: ");
|
||||
printUInt(status);
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
print("Scheduler:\n");
|
||||
print(" ticks: "); printUInt64(sched.Ticks); print("\n");
|
||||
print(" context switches: "); printUInt64(sched.ContextSwitches); print("\n");
|
||||
print(" quantum expires: "); printUInt64(sched.QuantumExpirations); print("\n");
|
||||
print(" priority preempts: "); printUInt64(sched.PriorityPreemptions); print("\n");
|
||||
print(" idle selections: "); printUInt64(sched.IdleSelections); print("\n");
|
||||
print(" keep-current: "); printUInt64(sched.KeepCurrentDecisions); print("\n");
|
||||
print(" demotions: "); printUInt64(sched.Demotions); print("\n");
|
||||
print(" aging promotions: "); printUInt64(sched.AgingPromotions); print("\n");
|
||||
print(" voluntary blocks: "); printUInt64(sched.VoluntaryBlocks); print("\n");
|
||||
print(" SMT deferrals: "); printUInt64(sched.SmtSiblingDeferrals); print("\n");
|
||||
print(" SMT primary pokes: "); printUInt64(sched.SmtPrimaryPokes); print("\n");
|
||||
|
||||
print("CPUs:\n");
|
||||
uint32_t n = cpu.CpuCount;
|
||||
if (n > SYS_KERNEL_STATS_MAX_CPUS)
|
||||
n = SYS_KERNEL_STATS_MAX_CPUS;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
SYS_CPU_STAT* c = &cpu.Cpu[i];
|
||||
print(" cpu"); printUInt(c->CpuIndex);
|
||||
print(" lapic="); printUInt(c->LapicId);
|
||||
print(" tid="); printUInt(c->CurrentTid);
|
||||
print(" ticks="); printUInt64(c->SchedulerTicks);
|
||||
print(" switches="); printUInt64(c->ContextSwitches);
|
||||
print(" flags="); printCpuFlags(c->Flags);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
print("Physical memory:\n");
|
||||
print(" total: "); printPagesKiB(pmm.TotalFrames); print(" (frames="); printUInt64(pmm.TotalFrames); print(")\n");
|
||||
print(" used: "); printPagesKiB(pmm.UsedFrames); print(" (frames="); printUInt64(pmm.UsedFrames); print(")\n");
|
||||
print(" free: "); printPagesKiB(pmm.FreeFrames); print(" (frames="); printUInt64(pmm.FreeFrames); print(")\n");
|
||||
print(" largest free run: "); printPagesKiB(pmm.LargestFreeRun); print(" (frames="); printUInt64(pmm.LargestFreeRun); print(")\n");
|
||||
print(" free runs: "); printUInt64(pmm.FreeRunCount); print("\n");
|
||||
print(" run histogram:\n");
|
||||
print(" 1: "); printUInt64(pmm.FreeRunHistogram[0]); print("\n");
|
||||
print(" 2-3: "); printUInt64(pmm.FreeRunHistogram[1]); print("\n");
|
||||
print(" 4-7: "); printUInt64(pmm.FreeRunHistogram[2]); print("\n");
|
||||
print(" 8-15: "); printUInt64(pmm.FreeRunHistogram[3]); print("\n");
|
||||
print(" 16-63: "); printUInt64(pmm.FreeRunHistogram[4]); print("\n");
|
||||
print(" 64-255: "); printUInt64(pmm.FreeRunHistogram[5]); print("\n");
|
||||
print(" 256-1023: "); printUInt64(pmm.FreeRunHistogram[6]); print("\n");
|
||||
print(" 1024+: "); printUInt64(pmm.FreeRunHistogram[7]); print("\n");
|
||||
}
|
||||
|
||||
static void cmd_mem(void) {
|
||||
SYS_MEMORY_STATUS st;
|
||||
if (SysGetMemoryStatus(&st) != 0) {
|
||||
@@ -240,7 +331,7 @@ static int runCommand(const char* cmd) {
|
||||
if (!cmd || *cmd == '\0') return 0;
|
||||
if (strcmp(cmd, "exit") == 0) return 1;
|
||||
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
|
||||
if (strcmp(cmd, "clear") == 0) { SysScreenClear(0); return 0; }
|
||||
if (strcmp(cmd, "clear") == 0) { SysScreenClear(0x012456); return 0; }
|
||||
if (strncmp(cmd, "crash", 5) == 0) {
|
||||
// Check the sub-option trailing "crash " (offset 6)
|
||||
if (strcmp(cmd + 6, "void") == 0) {
|
||||
@@ -280,6 +371,7 @@ static int runCommand(const char* cmd) {
|
||||
}
|
||||
}
|
||||
if (strcmp(cmd, "mem") == 0) { cmd_mem(); return 0; }
|
||||
if (strcmp(cmd, "stats") == 0 || strcmp(cmd, "telemetry") == 0) { cmd_stats(); return 0; }
|
||||
if (strcmp(cmd, "ps") == 0) { cmd_ps(); return 0; }
|
||||
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
|
||||
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// posix_dir.c - chdir, getcwd, opendir, readdir, closedir
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include <stdlib.h>
|
||||
#include "posix.h"
|
||||
#include "posix_path.h"
|
||||
|
||||
@@ -38,8 +39,8 @@ __declspec(dllexport) DIR* opendir(const char* path) {
|
||||
uint32_t s = SysOpenDir(&req);
|
||||
if (s != 0) { errno = ENOENT; return (DIR*)0; }
|
||||
|
||||
// Allocate DIR on the kernel heap (SysAlloc) so it outlives the stack.
|
||||
DIR* d = (DIR*)SysAlloc(sizeof(DIR));
|
||||
// Allocate DIR on the kernel heap (malloc) so it outlives the stack.
|
||||
DIR* d = (DIR*)malloc(sizeof(DIR));
|
||||
if (!d) { SysCloseHandle(kh); errno = ENOMEM; return (DIR*)0; }
|
||||
d->KHandle = kh;
|
||||
d->Valid = false;
|
||||
@@ -64,6 +65,6 @@ __declspec(dllexport) struct dirent* readdir(DIR* d) {
|
||||
__declspec(dllexport) int closedir(DIR* d) {
|
||||
if (!d) { errno = EBADF; return -1; }
|
||||
SysCloseHandle(d->KHandle);
|
||||
SysFree(d);
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "posix_path.h"
|
||||
|
||||
__declspec(dllexport) void clearscreen(void) {
|
||||
SysScreenClear(0x00000000);
|
||||
SysScreenClear(0x012456);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void clearkeyboard(void) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// posix_socket.c - POSIX-ish socket wrappers over native Sys* sockets.
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
@@ -324,7 +325,7 @@ __declspec(dllexport) int getsockopt(int fd, int level, int optname, void* optva
|
||||
__declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) {
|
||||
if (!fds || nfds == 0 || nfds > 64) { errno = EINVAL; return -1; }
|
||||
|
||||
SYS_POLLFD* kfds = (SYS_POLLFD*)SysAlloc(sizeof(SYS_POLLFD) * nfds);
|
||||
SYS_POLLFD* kfds = (SYS_POLLFD*)malloc(sizeof(SYS_POLLFD) * nfds);
|
||||
if (!kfds) { errno = ENOMEM; return -1; }
|
||||
|
||||
for (nfds_t i = 0; i < nfds; i++) {
|
||||
@@ -348,7 +349,7 @@ __declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) {
|
||||
uint32_t timeoutMs = timeout < 0 ? SYS_POLL_TIMEOUT_INFINITE : (uint32_t)timeout;
|
||||
uint32_t s = SysPoll(kfds, nfds, timeoutMs, &ready);
|
||||
if (s != 0) {
|
||||
SysFree(kfds);
|
||||
free(kfds);
|
||||
errno = PosixStatusToErrno(s);
|
||||
return -1;
|
||||
}
|
||||
@@ -365,7 +366,7 @@ __declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) {
|
||||
if (re) out++;
|
||||
}
|
||||
|
||||
SysFree(kfds);
|
||||
free(kfds);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -446,7 +447,7 @@ __declspec(dllexport) int getaddrinfo(const char* node, const char* service,
|
||||
a.Port = service ? ParsePort(service) : 0;
|
||||
|
||||
size_t total = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
|
||||
struct addrinfo* ai = (struct addrinfo*)SysAlloc(total);
|
||||
struct addrinfo* ai = (struct addrinfo*)malloc(total);
|
||||
if (!ai) return ENOMEM;
|
||||
memset(ai, 0, total);
|
||||
|
||||
@@ -467,5 +468,5 @@ __declspec(dllexport) int getaddrinfo(const char* node, const char* service,
|
||||
}
|
||||
|
||||
__declspec(dllexport) void freeaddrinfo(struct addrinfo* res) {
|
||||
if (res) SysFree(res);
|
||||
if (res) free(res);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// posix_thread.c - pthread_create, pthread_join, pthread_exit, pthread_mutex_*
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <ntlite/syscall.h>
|
||||
#include "posix.h"
|
||||
|
||||
@@ -56,7 +57,7 @@ static void PthreadTrampoline(uintptr_t raw) {
|
||||
PTHREAD_SLOT* slot = PthreadSlotFind(pid, tid);
|
||||
if (!slot) slot = PthreadSlotAlloc(pid, tid);
|
||||
|
||||
SysFree(tr);
|
||||
free(tr);
|
||||
|
||||
void* retval = fn(arg);
|
||||
|
||||
@@ -76,7 +77,7 @@ __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* att
|
||||
|
||||
uint32_t pid = SysGetCurrentPid();
|
||||
|
||||
PTHREAD_TRAMP* tr = (PTHREAD_TRAMP*)SysAlloc(sizeof(PTHREAD_TRAMP));
|
||||
PTHREAD_TRAMP* tr = (PTHREAD_TRAMP*)malloc(sizeof(PTHREAD_TRAMP));
|
||||
if (!tr) return ENOMEM;
|
||||
tr->Fn = fn;
|
||||
tr->Arg = arg;
|
||||
@@ -86,7 +87,7 @@ __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* att
|
||||
uint32_t s = SysCreateThread((uint64_t)PthreadTrampoline,
|
||||
(uint64_t)tr, 1 /*PriorityNormal*/, &tid);
|
||||
if (s != 0) {
|
||||
SysFree(tr);
|
||||
free(tr);
|
||||
return EAGAIN;
|
||||
}
|
||||
// The trampoline allocates the retval slot itself after it knows its real
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// gdi32.c
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#if defined(__SSE2__) || defined(_M_X64) || defined(_M_IX86)
|
||||
@@ -92,14 +93,14 @@ __declspec(dllexport) int StretchDIBits(
|
||||
// Only reallocate if the new size is LARGER than what we already have
|
||||
int requiredPixels = DestWidth * DestHeight;
|
||||
if (requiredPixels > currentDestCapacity) {
|
||||
SysFree(destBuffer);
|
||||
destBuffer = (uint32_t*)SysAlloc(requiredPixels * sizeof(uint32_t));
|
||||
free(destBuffer);
|
||||
destBuffer = (uint32_t*)malloc(requiredPixels * sizeof(uint32_t));
|
||||
currentDestCapacity = requiredPixels;
|
||||
}
|
||||
|
||||
if (DestWidth > currentXMapCapacity) {
|
||||
SysFree(srcX_map);
|
||||
srcX_map = (int*)SysAlloc(DestWidth * sizeof(int));
|
||||
free(srcX_map);
|
||||
srcX_map = (int*)malloc(DestWidth * sizeof(int));
|
||||
currentXMapCapacity = DestWidth;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// HANDLE_TO_KH / KH_TO_HANDLE do that conversion in one place.
|
||||
// - INVALID_HANDLE_VALUE maps to kernel handle 0 (the always-invalid slot).
|
||||
// - HeapAlloc / HeapFree / HeapReAlloc ignore the HANDLE heap argument and
|
||||
// always use the single kernel user-heap. This is fine: we don't expose
|
||||
// always use the single user-mode heap. This is fine: we don't expose
|
||||
// multiple heaps, and NULL is a legal (no-op) heap argument under Win32.
|
||||
// - Win32 per-thread state lives behind SYS_TEB::SubsystemData so the native
|
||||
// TEB ABI stays subsystem-neutral.
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
@@ -66,6 +67,31 @@ typedef struct _MEMORY_BASIC_INFORMATION {
|
||||
DWORD Type;
|
||||
} MEMORY_BASIC_INFORMATION;
|
||||
|
||||
static uint32_t WinProtectToSysVm(DWORD protect) {
|
||||
switch (protect) {
|
||||
case PAGE_NOACCESS: return SYS_VM_NOACCESS;
|
||||
case PAGE_READONLY: return SYS_VM_READ;
|
||||
case PAGE_READWRITE:
|
||||
case PAGE_WRITECOPY: return SYS_VM_READWRITE;
|
||||
case PAGE_EXECUTE: return SYS_VM_EXECUTE;
|
||||
case PAGE_EXECUTE_READ: return SYS_VM_EXECUTE_READ;
|
||||
case PAGE_EXECUTE_READWRITE: return SYS_VM_EXECUTE_READWRITE;
|
||||
default: return SYS_VM_READWRITE;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD SysVmProtectToWin(uint32_t protect) {
|
||||
switch (protect) {
|
||||
case SYS_VM_NOACCESS: return PAGE_NOACCESS;
|
||||
case SYS_VM_READ: return PAGE_READONLY;
|
||||
case SYS_VM_READWRITE: return PAGE_READWRITE;
|
||||
case SYS_VM_EXECUTE: return PAGE_EXECUTE;
|
||||
case SYS_VM_EXECUTE_READ: return PAGE_EXECUTE_READ;
|
||||
case SYS_VM_EXECUTE_READWRITE: return PAGE_EXECUTE_READWRITE;
|
||||
default: return PAGE_NOACCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// File-find structures
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
@@ -228,7 +254,7 @@ static WIN32_THREAD_ENV* K32ThreadEnv(void) {
|
||||
|
||||
WIN32_THREAD_ENV* env = (WIN32_THREAD_ENV*)teb->SubsystemData;
|
||||
if (!env) {
|
||||
env = (WIN32_THREAD_ENV*)SysAlloc(sizeof(WIN32_THREAD_ENV));
|
||||
env = (WIN32_THREAD_ENV*)malloc(sizeof(WIN32_THREAD_ENV));
|
||||
if (!env) return &gFallbackThreadEnv;
|
||||
memset(env, 0, sizeof(*env));
|
||||
teb->SubsystemData = env;
|
||||
@@ -363,28 +389,27 @@ __declspec(dllexport) uint64_t GetTickCount64(void) {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Memory (heap argument is ignored - single kernel user-heap)
|
||||
// Memory (heap argument is ignored - single user-mode heap)
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) void* HeapAlloc(void* heap, DWORD flags, size_t size) {
|
||||
(void)heap;
|
||||
(void)heap; (void)flags;
|
||||
if (!size) return NULL;
|
||||
void* ptr = SysAlloc(size);
|
||||
void* ptr = malloc(size);
|
||||
if (!ptr) gLastError = 8; // ERROR_NOT_ENOUGH_MEMORY
|
||||
return ptr;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL HeapFree(void* heap, DWORD flags, void* ptr) {
|
||||
(void)heap; (void)flags;
|
||||
// Win32's HeapFree doesn't need the size; we pass 0 and the kernel's
|
||||
// allocator handles it (the block header carries the size).
|
||||
if (ptr) SysFree(ptr);
|
||||
// Win32's HeapFree doesn't need the size; we pass 0 and the user-mode heap carries the block size.
|
||||
if (ptr) free(ptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* HeapReAlloc(void* heap, DWORD flags,
|
||||
void* ptr, size_t size) {
|
||||
(void)heap; (void)flags;
|
||||
void* newptr = SysRealloc(ptr, size);
|
||||
void* newptr = realloc(ptr, size);
|
||||
if (!newptr && size) gLastError = 8;
|
||||
return newptr;
|
||||
}
|
||||
@@ -400,23 +425,37 @@ __declspec(dllexport) void* GetProcessHeap(void) {
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize,
|
||||
DWORD flAllocationType, DWORD flProtect) {
|
||||
(void)lpAddress; (void)flAllocationType; (void)flProtect;
|
||||
(void)flAllocationType;
|
||||
if (!dwSize) return NULL;
|
||||
void* ptr = SysAlloc(dwSize);
|
||||
if (!ptr) gLastError = 8; // ERROR_NOT_ENOUGH_MEMORY
|
||||
return ptr;
|
||||
|
||||
size_t pages = (dwSize + 4095u) / 4096u;
|
||||
void* base = NULL;
|
||||
uint32_t flags = lpAddress ? SYS_VM_FLAG_FIXED : SYS_VM_FLAG_NONE;
|
||||
uint32_t s = SysVmAlloc(lpAddress, pages, WinProtectToSysVm(flProtect), flags, &base);
|
||||
if (s != SYS_STATUS_SUCCESS) {
|
||||
gLastError = (s == SYS_STATUS_NOT_FOUND || s == SYS_STATUS_INVALID_PARAMETER) ? 87 : 8;
|
||||
return NULL;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL VirtualFree(void* lpAddress, size_t dwSize, DWORD dwFreeType) {
|
||||
(void)dwSize; (void)dwFreeType;
|
||||
if (lpAddress) SysFree(lpAddress);
|
||||
if (!lpAddress) return TRUE;
|
||||
uint32_t s = SysVmFree(lpAddress);
|
||||
if (s != SYS_STATUS_SUCCESS) { gLastError = 87; return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
__declspec(dllexport) BOOL VirtualProtect(void* lpAddress, size_t dwSize,
|
||||
DWORD flNewProtect, DWORD* lpflOldProtect) {
|
||||
(void)lpAddress; (void)dwSize; (void)flNewProtect;
|
||||
if (lpflOldProtect) *lpflOldProtect = PAGE_EXECUTE_READWRITE;
|
||||
if (!lpAddress || !dwSize) { gLastError = 87; return FALSE; }
|
||||
size_t pages = (dwSize + 4095u) / 4096u;
|
||||
uint32_t oldSysProtect = 0;
|
||||
uint32_t s = SysVmProtect(lpAddress, pages, WinProtectToSysVm(flNewProtect),
|
||||
lpflOldProtect ? &oldSysProtect : NULL);
|
||||
if (s != SYS_STATUS_SUCCESS) { gLastError = 87; return FALSE; }
|
||||
if (lpflOldProtect) *lpflOldProtect = SysVmProtectToWin(oldSysProtect);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -427,13 +466,21 @@ __declspec(dllexport) size_t VirtualQuery(const void* lpAddress,
|
||||
gLastError = 87; // ERROR_INVALID_PARAMETER
|
||||
return 0;
|
||||
}
|
||||
uintptr_t base = (uintptr_t)lpAddress & ~(uintptr_t)0xFFF;
|
||||
lpBuffer->BaseAddress = (void*)base;
|
||||
lpBuffer->AllocationBase = (void*)base;
|
||||
lpBuffer->AllocationProtect = PAGE_EXECUTE_READWRITE;
|
||||
lpBuffer->RegionSize = 0x1000;
|
||||
|
||||
SYS_VM_REGION_INFO info;
|
||||
uint32_t s = SysVmQuery((void*)lpAddress, &info);
|
||||
if (s != SYS_STATUS_SUCCESS) {
|
||||
gLastError = 87;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD protect = SysVmProtectToWin(info.Protect);
|
||||
lpBuffer->BaseAddress = info.Base;
|
||||
lpBuffer->AllocationBase = info.Base;
|
||||
lpBuffer->AllocationProtect = protect;
|
||||
lpBuffer->RegionSize = info.PageCount * 4096u;
|
||||
lpBuffer->State = MEM_COMMIT;
|
||||
lpBuffer->Protect = PAGE_EXECUTE_READWRITE;
|
||||
lpBuffer->Protect = protect;
|
||||
lpBuffer->Type = MEM_PRIVATE;
|
||||
return sizeof(MEMORY_BASIC_INFORMATION);
|
||||
}
|
||||
@@ -512,7 +559,7 @@ __declspec(dllexport) BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput) {
|
||||
|
||||
// !Made-up! clear console api.
|
||||
__declspec(dllexport) BOOL ClearConsoleScreenBuffer(HANDLE hConsole) {
|
||||
SysScreenClear(0x00000000);
|
||||
SysScreenClear(0x012456);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// No COM infrastructure at this stage; all functions fail gracefully.
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -65,7 +66,7 @@ __declspec(dllexport) HRESULT CoCreateInstance(const GUID* clsid, IUnknown* oute
|
||||
// Memory
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) void CoTaskMemFree(void* pv) {
|
||||
if (pv) SysFree(pv);
|
||||
if (pv) free(pv);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
// heap.c - user-mode page-backed heap
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define USER_HEAP_PAGE_SIZE 4096u
|
||||
#define USER_HEAP_MIN_PAGES 16u
|
||||
#define USER_HEAP_ALIGN 16u
|
||||
#define USER_HEAP_MAGIC 0x48424C4Bu /* KLBH */
|
||||
|
||||
/*
|
||||
* Keep the mask pointer-sized. A 32-bit unsigned mask truncates high VA bits.
|
||||
*/
|
||||
#define ALIGN_UP(v, a) (((v) + ((uintptr_t)(a) - 1)) & ~((uintptr_t)(a) - 1))
|
||||
|
||||
typedef struct HEAP_BLOCK {
|
||||
uint32_t Magic;
|
||||
uint32_t Free;
|
||||
size_t Size;
|
||||
struct HEAP_BLOCK* Prev;
|
||||
struct HEAP_BLOCK* Next;
|
||||
} HEAP_BLOCK;
|
||||
|
||||
typedef struct HEAP_SEGMENT {
|
||||
struct HEAP_SEGMENT* Prev;
|
||||
struct HEAP_SEGMENT* Next;
|
||||
size_t PageCount;
|
||||
size_t Size;
|
||||
HEAP_BLOCK* First;
|
||||
} HEAP_SEGMENT;
|
||||
|
||||
static volatile long gHeapLock;
|
||||
static HEAP_SEGMENT* gSegments;
|
||||
|
||||
static void HeapLock(void) {
|
||||
while (_InterlockedCompareExchange(&gHeapLock, 1, 0) != 0)
|
||||
_mm_pause();
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
|
||||
static void HeapUnlock(void) {
|
||||
_ReadWriteBarrier();
|
||||
_InterlockedExchange(&gHeapLock, 0);
|
||||
}
|
||||
|
||||
static size_t AlignSize(size_t size) {
|
||||
return ALIGN_UP(size ? size : 1, USER_HEAP_ALIGN);
|
||||
}
|
||||
|
||||
static void* BlockPayload(HEAP_BLOCK* block) {
|
||||
return (void*)((uint8_t*)block + sizeof(HEAP_BLOCK));
|
||||
}
|
||||
|
||||
static HEAP_BLOCK* PayloadBlock(void* ptr) {
|
||||
return (HEAP_BLOCK*)((uint8_t*)ptr - sizeof(HEAP_BLOCK));
|
||||
}
|
||||
|
||||
static HEAP_SEGMENT* SegmentForPointer(void* ptr) {
|
||||
uintptr_t p = (uintptr_t)ptr;
|
||||
for (HEAP_SEGMENT* seg = gSegments; seg; seg = seg->Next) {
|
||||
uintptr_t base = (uintptr_t)seg;
|
||||
uintptr_t end = base + seg->Size;
|
||||
if (p > base && p < end)
|
||||
return seg;
|
||||
}
|
||||
return (HEAP_SEGMENT*)0;
|
||||
}
|
||||
|
||||
static void SplitBlock(HEAP_BLOCK* block, size_t size) {
|
||||
size_t aligned = AlignSize(size);
|
||||
if (block->Size < aligned + sizeof(HEAP_BLOCK) + USER_HEAP_ALIGN)
|
||||
return;
|
||||
|
||||
HEAP_BLOCK* tail = (HEAP_BLOCK*)((uint8_t*)BlockPayload(block) + aligned);
|
||||
tail->Magic = USER_HEAP_MAGIC;
|
||||
tail->Free = 1;
|
||||
tail->Size = block->Size - aligned - sizeof(HEAP_BLOCK);
|
||||
tail->Prev = block;
|
||||
tail->Next = block->Next;
|
||||
if (tail->Next) tail->Next->Prev = tail;
|
||||
|
||||
block->Size = aligned;
|
||||
block->Next = tail;
|
||||
}
|
||||
|
||||
static void CoalesceBlock(HEAP_BLOCK* block) {
|
||||
if (block->Next && block->Next->Magic == USER_HEAP_MAGIC && block->Next->Free) {
|
||||
HEAP_BLOCK* next = block->Next;
|
||||
block->Size += sizeof(HEAP_BLOCK) + next->Size;
|
||||
block->Next = next->Next;
|
||||
if (block->Next) block->Next->Prev = block;
|
||||
}
|
||||
|
||||
if (block->Prev && block->Prev->Magic == USER_HEAP_MAGIC && block->Prev->Free) {
|
||||
HEAP_BLOCK* prev = block->Prev;
|
||||
prev->Size += sizeof(HEAP_BLOCK) + block->Size;
|
||||
prev->Next = block->Next;
|
||||
if (prev->Next) prev->Next->Prev = prev;
|
||||
}
|
||||
}
|
||||
|
||||
static HEAP_SEGMENT* AddSegment(size_t payloadSize) {
|
||||
size_t need = sizeof(HEAP_SEGMENT) + sizeof(HEAP_BLOCK) + AlignSize(payloadSize);
|
||||
size_t pages = (need + USER_HEAP_PAGE_SIZE - 1) / USER_HEAP_PAGE_SIZE;
|
||||
if (pages < USER_HEAP_MIN_PAGES) pages = USER_HEAP_MIN_PAGES;
|
||||
|
||||
void* base = 0;
|
||||
uint32_t s = SysVmAlloc(0, pages, SYS_VM_READWRITE, SYS_VM_FLAG_NONE, &base);
|
||||
if (s != SYS_STATUS_SUCCESS || !base)
|
||||
return (HEAP_SEGMENT*)0;
|
||||
|
||||
HEAP_SEGMENT* seg = (HEAP_SEGMENT*)base;
|
||||
seg->Prev = 0;
|
||||
seg->Next = gSegments;
|
||||
if (gSegments) gSegments->Prev = seg;
|
||||
gSegments = seg;
|
||||
seg->PageCount = pages;
|
||||
seg->Size = pages * USER_HEAP_PAGE_SIZE;
|
||||
|
||||
uintptr_t blockAddr = ALIGN_UP((uintptr_t)(seg + 1), USER_HEAP_ALIGN);
|
||||
HEAP_BLOCK* block = (HEAP_BLOCK*)blockAddr;
|
||||
block->Magic = USER_HEAP_MAGIC;
|
||||
block->Free = 1;
|
||||
block->Size = seg->Size - (blockAddr - (uintptr_t)seg) - sizeof(HEAP_BLOCK);
|
||||
block->Prev = 0;
|
||||
block->Next = 0;
|
||||
seg->First = block;
|
||||
return seg;
|
||||
}
|
||||
|
||||
static void RemoveSegmentIfEmpty(HEAP_SEGMENT* seg) {
|
||||
if (!seg || !seg->First || !seg->First->Free || seg->First->Prev || seg->First->Next)
|
||||
return;
|
||||
|
||||
if (seg->Prev) seg->Prev->Next = seg->Next;
|
||||
else gSegments = seg->Next;
|
||||
if (seg->Next) seg->Next->Prev = seg->Prev;
|
||||
|
||||
SysVmFree(seg);
|
||||
}
|
||||
|
||||
void* _malloc(size_t size) {
|
||||
if (!size) return 0;
|
||||
size = AlignSize(size);
|
||||
|
||||
HeapLock();
|
||||
for (;;) {
|
||||
for (HEAP_SEGMENT* seg = gSegments; seg; seg = seg->Next) {
|
||||
for (HEAP_BLOCK* block = seg->First; block; block = block->Next) {
|
||||
if (block->Magic == USER_HEAP_MAGIC && block->Free && block->Size >= size) {
|
||||
SplitBlock(block, size);
|
||||
block->Free = 0;
|
||||
void* out = BlockPayload(block);
|
||||
HeapUnlock();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!AddSegment(size)) {
|
||||
HeapUnlock();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _free(void* ptr) {
|
||||
if (!ptr) return;
|
||||
|
||||
HeapLock();
|
||||
HEAP_SEGMENT* seg = SegmentForPointer(ptr);
|
||||
if (!seg) {
|
||||
HeapUnlock();
|
||||
return;
|
||||
}
|
||||
|
||||
HEAP_BLOCK* block = PayloadBlock(ptr);
|
||||
if (block->Magic != USER_HEAP_MAGIC || block->Free) {
|
||||
HeapUnlock();
|
||||
return;
|
||||
}
|
||||
|
||||
block->Free = 1;
|
||||
CoalesceBlock(block);
|
||||
RemoveSegmentIfEmpty(seg);
|
||||
HeapUnlock();
|
||||
}
|
||||
|
||||
void* _calloc(size_t count, size_t size) {
|
||||
if (count && size > ((size_t)-1) / count)
|
||||
return 0;
|
||||
size_t total = count * size;
|
||||
void* ptr = _malloc(total);
|
||||
if (ptr) memset(ptr, 0, total);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* _realloc(void* ptr, size_t newSize) {
|
||||
if (!ptr) return _malloc(newSize);
|
||||
if (!newSize) {
|
||||
_free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HeapLock();
|
||||
HEAP_BLOCK* block = PayloadBlock(ptr);
|
||||
if (block->Magic != USER_HEAP_MAGIC || block->Free) {
|
||||
HeapUnlock();
|
||||
return 0;
|
||||
}
|
||||
size_t oldSize = block->Size;
|
||||
if (oldSize >= newSize) {
|
||||
SplitBlock(block, newSize);
|
||||
HeapUnlock();
|
||||
return ptr;
|
||||
}
|
||||
HeapUnlock();
|
||||
|
||||
void* newPtr = _malloc(newSize);
|
||||
if (!newPtr) return 0;
|
||||
memcpy(newPtr, ptr, oldSize);
|
||||
_free(ptr);
|
||||
return newPtr;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// heap_exports.c - public CRT allocator names
|
||||
// Intentionally includes nothing. MSVC/UCRT headers declare malloc/free with
|
||||
// compiler attributes that conflict with /Gz in this freestanding build.
|
||||
// Keep the real heap implementation in heap.c under private names and expose
|
||||
// only these tiny forwarding thunks here.
|
||||
|
||||
#ifdef USER_HEAP_EXPORTS
|
||||
#define HEAP_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define HEAP_EXPORT
|
||||
#endif
|
||||
|
||||
typedef unsigned __int64 size_t;
|
||||
|
||||
void* _malloc(size_t size);
|
||||
void _free(void* ptr);
|
||||
void* _calloc(size_t count, size_t size);
|
||||
void* _realloc(void* ptr, size_t size);
|
||||
|
||||
HEAP_EXPORT void* malloc(size_t size) {
|
||||
return _malloc(size);
|
||||
}
|
||||
|
||||
HEAP_EXPORT void free(void* ptr) {
|
||||
_free(ptr);
|
||||
}
|
||||
|
||||
HEAP_EXPORT void* calloc(size_t count, size_t size) {
|
||||
return _calloc(count, size);
|
||||
}
|
||||
|
||||
HEAP_EXPORT void* realloc(void* ptr, size_t size) {
|
||||
return _realloc(ptr, size);
|
||||
}
|
||||
@@ -1,94 +1,96 @@
|
||||
; syscall_nr.inc
|
||||
|
||||
SYS_EXIT_PROCESS EQU 0
|
||||
SYS_EXIT_THREAD EQU 1
|
||||
SYS_CREATE_PROCESS EQU 2
|
||||
SYS_WAIT_FOR_PROCESS EQU 3
|
||||
SYS_GET_PROCESS_EXIT_CODE EQU 4
|
||||
SYS_KILL_PROCESS EQU 5
|
||||
SYS_GET_PROCESS_LIST EQU 6
|
||||
SYS_GET_PROCESS_PID EQU 7
|
||||
SYS_CREATE_THREAD EQU 8
|
||||
SYS_WAIT_THREAD EQU 9
|
||||
SYS_GET_CURRENT_TID EQU 10
|
||||
SYS_GET_CURRENT_PID EQU 11
|
||||
SYS_SET_THREAD_PRIORITY EQU 12
|
||||
SYS_YIELD EQU 13
|
||||
SYS_SLEEP EQU 14
|
||||
SYS_SET_USER_APC_DISPATCHER EQU 15
|
||||
SYS_APC_RETURN EQU 16
|
||||
SYS_ALLOC EQU 17
|
||||
SYS_FREE EQU 18
|
||||
SYS_REALLOC EQU 19
|
||||
SYS_CLOSE_HANDLE EQU 20
|
||||
SYS_MUTEX_CREATE EQU 21
|
||||
SYS_MUTEX_ACQUIRE EQU 22
|
||||
SYS_MUTEX_TRY_ACQUIRE EQU 23
|
||||
SYS_MUTEX_RELEASE EQU 24
|
||||
SYS_SEM_CREATE EQU 25
|
||||
SYS_SEM_WAIT EQU 26
|
||||
SYS_SEM_TRY_WAIT EQU 27
|
||||
SYS_SEM_SIGNAL EQU 28
|
||||
SYS_EVENT_CREATE EQU 29
|
||||
SYS_EVENT_SIGNAL EQU 30
|
||||
SYS_EVENT_CLEAR EQU 31
|
||||
SYS_EVENT_WAIT EQU 32
|
||||
SYS_QUEUE_CREATE EQU 33
|
||||
SYS_QUEUE_SEND EQU 34
|
||||
SYS_QUEUE_RECV EQU 35
|
||||
SYS_PUBLISH_QUEUE EQU 36
|
||||
SYS_OPEN_NAMED_QUEUE EQU 37
|
||||
SYS_QUEUE_DUPLICATE EQU 38
|
||||
SYS_NAMED_QUEUE_OWNER_PID EQU 39
|
||||
SYS_OPEN_FILE EQU 40
|
||||
SYS_CREATE_FILE EQU 41
|
||||
SYS_READ_FILE EQU 42
|
||||
SYS_WRITE_FILE EQU 43
|
||||
SYS_READ_FILE_ASYNC EQU 44
|
||||
SYS_WRITE_FILE_ASYNC EQU 45
|
||||
SYS_CANCEL_IO EQU 46
|
||||
SYS_SEEK_FILE EQU 47
|
||||
SYS_GET_FILE_POS EQU 48
|
||||
SYS_GET_FILE_SIZE EQU 49
|
||||
SYS_TRUNCATE_FILE EQU 50
|
||||
SYS_DELETE_FILE EQU 51
|
||||
SYS_RENAME_FILE EQU 52
|
||||
SYS_OPEN_DIR EQU 53
|
||||
SYS_READ_DIR EQU 54
|
||||
SYS_CREATE_DIR EQU 55
|
||||
SYS_REMOVE_DIR EQU 56
|
||||
SYS_SET_CWD EQU 57
|
||||
SYS_GET_CWD EQU 58
|
||||
SYS_WRITE_CONSOLE EQU 59
|
||||
SYS_SCREEN_BLIT EQU 60
|
||||
SYS_SCREEN_CLEAR EQU 61
|
||||
SYS_SCREEN_GET_SIZE EQU 62
|
||||
SYS_SCREEN_PUT_CHAR EQU 63
|
||||
SYS_KB_POLL EQU 64
|
||||
SYS_KB_IS_KEY_DOWN EQU 65
|
||||
SYS_KB_READ_CHAR EQU 66
|
||||
SYS_KB_READ_KEY EQU 67
|
||||
SYS_KB_GET_MODIFIERS EQU 68
|
||||
SYS_MOUSE_POLL EQU 69
|
||||
SYS_MOUSE_READ EQU 70
|
||||
SYS_MOUSE_GET_POS EQU 71
|
||||
SYS_GET_TICK EQU 72
|
||||
SYS_DEBUG_PRINT EQU 73
|
||||
SYS_QUERY_TRAP_FRAME EQU 74
|
||||
SYS_SOCKET EQU 75
|
||||
SYS_BIND EQU 76
|
||||
SYS_LISTEN EQU 77
|
||||
SYS_ACCEPT EQU 78
|
||||
SYS_CONNECT EQU 79
|
||||
SYS_SEND EQU 80
|
||||
SYS_RECV EQU 81
|
||||
SYS_SHUTDOWN EQU 82
|
||||
SYS_SEND_TO EQU 83
|
||||
SYS_RECV_FROM EQU 84
|
||||
SYS_RESOLVE_HOST EQU 85
|
||||
SYS_SET_SOCKET_OPTION EQU 86
|
||||
SYS_GET_SOCKET_OPTION EQU 87
|
||||
SYS_POLL EQU 88
|
||||
SYS_GET_MEMORY_STATUS EQU 89
|
||||
SYS_EXIT_PROCESS EQU 0
|
||||
SYS_EXIT_THREAD EQU 1
|
||||
SYS_CREATE_PROCESS EQU 2
|
||||
SYS_WAIT_FOR_PROCESS EQU 3
|
||||
SYS_GET_PROCESS_EXIT_CODE EQU 4
|
||||
SYS_KILL_PROCESS EQU 5
|
||||
SYS_GET_PROCESS_LIST EQU 6
|
||||
SYS_GET_PROCESS_PID EQU 7
|
||||
SYS_CREATE_THREAD EQU 8
|
||||
SYS_WAIT_THREAD EQU 9
|
||||
SYS_GET_CURRENT_TID EQU 10
|
||||
SYS_GET_CURRENT_PID EQU 11
|
||||
SYS_SET_THREAD_PRIORITY EQU 12
|
||||
SYS_YIELD EQU 13
|
||||
SYS_SLEEP EQU 14
|
||||
SYS_SET_USER_APC_DISPATCHER EQU 15
|
||||
SYS_APC_RETURN EQU 16
|
||||
SYS_VM_ALLOC EQU 17
|
||||
SYS_VM_FREE EQU 18
|
||||
SYS_VM_PROTECT EQU 19
|
||||
SYS_VM_QUERY EQU 20
|
||||
SYS_CLOSE_HANDLE EQU 21
|
||||
SYS_MUTEX_CREATE EQU 22
|
||||
SYS_MUTEX_ACQUIRE EQU 23
|
||||
SYS_MUTEX_TRY_ACQUIRE EQU 24
|
||||
SYS_MUTEX_RELEASE EQU 25
|
||||
SYS_SEM_CREATE EQU 26
|
||||
SYS_SEM_WAIT EQU 27
|
||||
SYS_SEM_TRY_WAIT EQU 28
|
||||
SYS_SEM_SIGNAL EQU 29
|
||||
SYS_EVENT_CREATE EQU 30
|
||||
SYS_EVENT_SIGNAL EQU 31
|
||||
SYS_EVENT_CLEAR EQU 32
|
||||
SYS_EVENT_WAIT EQU 33
|
||||
SYS_QUEUE_CREATE EQU 34
|
||||
SYS_QUEUE_SEND EQU 35
|
||||
SYS_QUEUE_RECV EQU 36
|
||||
SYS_PUBLISH_QUEUE EQU 37
|
||||
SYS_OPEN_NAMED_QUEUE EQU 38
|
||||
SYS_QUEUE_DUPLICATE EQU 39
|
||||
SYS_NAMED_QUEUE_OWNER_PID EQU 40
|
||||
SYS_OPEN_FILE EQU 41
|
||||
SYS_CREATE_FILE EQU 42
|
||||
SYS_READ_FILE EQU 43
|
||||
SYS_WRITE_FILE EQU 44
|
||||
SYS_READ_FILE_ASYNC EQU 45
|
||||
SYS_WRITE_FILE_ASYNC EQU 46
|
||||
SYS_CANCEL_IO EQU 47
|
||||
SYS_SEEK_FILE EQU 48
|
||||
SYS_GET_FILE_POS EQU 49
|
||||
SYS_GET_FILE_SIZE EQU 50
|
||||
SYS_TRUNCATE_FILE EQU 51
|
||||
SYS_DELETE_FILE EQU 52
|
||||
SYS_RENAME_FILE EQU 53
|
||||
SYS_OPEN_DIR EQU 54
|
||||
SYS_READ_DIR EQU 55
|
||||
SYS_CREATE_DIR EQU 56
|
||||
SYS_REMOVE_DIR EQU 57
|
||||
SYS_SET_CWD EQU 58
|
||||
SYS_GET_CWD EQU 59
|
||||
SYS_WRITE_CONSOLE EQU 60
|
||||
SYS_SCREEN_BLIT EQU 61
|
||||
SYS_SCREEN_CLEAR EQU 62
|
||||
SYS_SCREEN_GET_SIZE EQU 63
|
||||
SYS_SCREEN_PUT_CHAR EQU 64
|
||||
SYS_KB_POLL EQU 65
|
||||
SYS_KB_IS_KEY_DOWN EQU 66
|
||||
SYS_KB_READ_CHAR EQU 67
|
||||
SYS_KB_READ_KEY EQU 68
|
||||
SYS_KB_GET_MODIFIERS EQU 69
|
||||
SYS_MOUSE_POLL EQU 70
|
||||
SYS_MOUSE_READ EQU 71
|
||||
SYS_MOUSE_GET_POS EQU 72
|
||||
SYS_GET_TICK EQU 73
|
||||
SYS_DEBUG_PRINT EQU 74
|
||||
SYS_QUERY_TRAP_FRAME EQU 75
|
||||
SYS_SOCKET EQU 76
|
||||
SYS_BIND EQU 77
|
||||
SYS_LISTEN EQU 78
|
||||
SYS_ACCEPT EQU 79
|
||||
SYS_CONNECT EQU 80
|
||||
SYS_SEND EQU 81
|
||||
SYS_RECV EQU 82
|
||||
SYS_SHUTDOWN EQU 83
|
||||
SYS_SEND_TO EQU 84
|
||||
SYS_RECV_FROM EQU 85
|
||||
SYS_RESOLVE_HOST EQU 86
|
||||
SYS_SET_SOCKET_OPTION EQU 87
|
||||
SYS_GET_SOCKET_OPTION EQU 88
|
||||
SYS_POLL EQU 89
|
||||
SYS_GET_MEMORY_STATUS EQU 90
|
||||
SYS_QUERY_KERNEL_STATS EQU 91
|
||||
|
||||
SYS_MAX EQU 90
|
||||
SYS_MAX EQU 92
|
||||
@@ -108,11 +108,12 @@ SysUserApcDispatcher_Failed:
|
||||
SysUserApcDispatcher ENDP
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Memory and handles
|
||||
; Virtual memory and handles
|
||||
; ---------------------------------------------------------------------------
|
||||
SYSCALL_STUB2 Alloc, SYS_ALLOC
|
||||
SYSCALL_STUB2 Free, SYS_FREE
|
||||
SYSCALL_STUB2 Realloc, SYS_REALLOC
|
||||
SYSCALL_STUB6 VmAlloc, SYS_VM_ALLOC
|
||||
SYSCALL_STUB2 VmFree, SYS_VM_FREE
|
||||
SYSCALL_STUB2 VmProtect, SYS_VM_PROTECT
|
||||
SYSCALL_STUB2 VmQuery, SYS_VM_QUERY
|
||||
SYSCALL_STUB2 CloseHandle, SYS_CLOSE_HANDLE
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
@@ -216,5 +217,6 @@ SYSCALL_STUB2 GetSocketOption, SYS_GET_SOCKET_OPTION
|
||||
SYSCALL_STUB2 Poll, SYS_POLL
|
||||
|
||||
SYSCALL_STUB2 GetMemoryStatus, SYS_GET_MEMORY_STATUS
|
||||
SYSCALL_STUB2 QueryKernelStats, SYS_QUERY_KERNEL_STATS
|
||||
|
||||
END
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
#include <ntlite/syscall.h>
|
||||
@@ -82,7 +83,7 @@ int main(void) {
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
uint8_t* buffer = (uint8_t*)SysAlloc(512);
|
||||
uint8_t* buffer = (uint8_t*)malloc(512);
|
||||
if (!buffer) {
|
||||
print("async_apc: allocation failed\n");
|
||||
SysExitProcess(1);
|
||||
@@ -141,7 +142,7 @@ int main(void) {
|
||||
|
||||
SysCloseHandle(event);
|
||||
SysCloseHandle(file);
|
||||
SysFree(buffer);
|
||||
free(buffer);
|
||||
|
||||
if (!ok) {
|
||||
print("async_apc: FAIL\n");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
@@ -51,7 +52,7 @@ int main(void) {
|
||||
SysExitProcess(1);
|
||||
}
|
||||
|
||||
uint8_t* buffer = (uint8_t*)SysAlloc(512);
|
||||
uint8_t* buffer = (uint8_t*)malloc(512);
|
||||
if (!buffer) {
|
||||
print("async_cancel: alloc failed\n");
|
||||
SysExitProcess(1);
|
||||
@@ -101,7 +102,7 @@ int main(void) {
|
||||
SysCloseHandle(request);
|
||||
SysCloseHandle(event);
|
||||
SysCloseHandle(file);
|
||||
SysFree(buffer);
|
||||
free(buffer);
|
||||
|
||||
if (!ok) {
|
||||
print("async_cancel: FAIL\n");
|
||||
|
||||
Reference in new issue
Block a user