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
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user