594 lines
21 KiB
C
594 lines
21 KiB
C
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <ntlite/syscall.h>
|
|
|
|
#define MAX_CMD 256
|
|
#define MAX_PROCS 64 // Maximum number of processes we will fetch at once
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Output helpers
|
|
// ---------------------------------------------------------------------------
|
|
static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
|
|
|
|
static uint32_t open_file(const char* path, uint32_t* handleOut) {
|
|
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
|
|
return SysOpenFile(&req);
|
|
}
|
|
|
|
static uint32_t create_file(const char* path, uint32_t* handleOut) {
|
|
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
|
|
return SysCreateFile(&req);
|
|
}
|
|
|
|
static uint32_t open_dir(const char* path, uint32_t* handleOut) {
|
|
SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut };
|
|
return SysOpenDir(&req);
|
|
}
|
|
|
|
static uint32_t set_cwd(const char* path) {
|
|
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
|
|
return SysSetCwd(&req);
|
|
}
|
|
|
|
static uint32_t delete_file(const char* path) {
|
|
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
|
|
return SysDeleteFile(&req);
|
|
}
|
|
|
|
static uint32_t create_process(const char* path, uint32_t* handleOut, const char* cmdline) {
|
|
SYS_CREATE_PROCESS_REQUEST req = { SysSvFromCstr(path), SysSvFromCstr(cmdline), handleOut };
|
|
return SysCreateProcess(&req);
|
|
}
|
|
|
|
static void printUInt(uint32_t n) {
|
|
char buf[12]; int i = 0;
|
|
if (n == 0) { print("0"); return; }
|
|
while (n > 0) { buf[i++] = (char)('0' + n % 10); n /= 10; }
|
|
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
|
|
}
|
|
|
|
static void printInt(int32_t n) {
|
|
if (n < 0) { print("-"); printUInt((uint32_t)-(n + 1) + 1); }
|
|
else { printUInt((uint32_t)n); }
|
|
}
|
|
|
|
static void printUInt64(uint64_t n) {
|
|
if (n == 0) { print("0"); return; }
|
|
char buf[20]; int i = 0;
|
|
while (n > 0) { buf[i++] = (char)('0' + (int)(n % 10)); n /= 10; }
|
|
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
|
|
}
|
|
|
|
static uint32_t u64Digits(uint64_t n) {
|
|
uint32_t digits = 1;
|
|
while (n >= 10u) { n /= 10u; digits++; }
|
|
return digits;
|
|
}
|
|
|
|
static void printSpaces(size_t count) {
|
|
while (count--) print(" ");
|
|
}
|
|
|
|
static void printUIntWidth(uint32_t n, size_t width) {
|
|
uint32_t digits = u64Digits(n);
|
|
if (width > digits) printSpaces(width - digits);
|
|
printUInt(n);
|
|
}
|
|
|
|
static void printUIntZeroWidth(uint32_t n, size_t width) {
|
|
uint32_t digits = u64Digits(n);
|
|
while (width > digits) { print("0"); width--; }
|
|
printUInt(n);
|
|
}
|
|
|
|
static void printUInt64Width(uint64_t n, size_t width) {
|
|
uint32_t digits = u64Digits(n);
|
|
if (width > digits) printSpaces(width - digits);
|
|
printUInt64(n);
|
|
}
|
|
|
|
static void printHex32(uint32_t v) {
|
|
static const char hex[] = "0123456789abcdef";
|
|
char buf[9];
|
|
for (int i = 7; i >= 0; i--) {
|
|
buf[i] = hex[v & 0xFu];
|
|
v >>= 4;
|
|
}
|
|
buf[8] = '\0';
|
|
print(buf);
|
|
}
|
|
|
|
static void printDirTime(const SYS_SYSTEM_TIME* t) {
|
|
if (!t || !(t->Flags & SYS_TIME_FLAG_VALID)) {
|
|
print("---- -- -- --:-- ");
|
|
return;
|
|
}
|
|
printUIntZeroWidth(t->Year, 4);
|
|
print("-");
|
|
printUIntZeroWidth(t->Month, 2);
|
|
print("-");
|
|
printUIntZeroWidth(t->Day, 2);
|
|
print(" ");
|
|
printUIntZeroWidth(t->Hour, 2);
|
|
print(":");
|
|
printUIntZeroWidth(t->Minute, 2);
|
|
print(" ");
|
|
}
|
|
|
|
static void printStringWidth(const char* s, size_t width) {
|
|
size_t len = s ? strlen(s) : 0;
|
|
if (s) print(s);
|
|
if (width > len) printSpaces(width - len);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Line editor
|
|
// ---------------------------------------------------------------------------
|
|
static void readLine(char* buf, int len) {
|
|
int pos = 0;
|
|
while (true) {
|
|
char c = SysReadKeyboardChar();
|
|
if (!c) { SysYield(); continue; }
|
|
if (c == '\r' || c == '\n') { print("\n"); break; }
|
|
if ((c == '\b' || c == 127) && pos > 0) { pos--; print("\b \b"); continue; }
|
|
if (c < 0x20 || c == 127) continue;
|
|
if (pos < len - 1) { buf[pos++] = c; char echo[2] = {c, '\0'}; print(echo); }
|
|
}
|
|
buf[pos] = '\0';
|
|
}
|
|
|
|
static char* trim(char* s) {
|
|
while (*s == ' ') s++;
|
|
int len = (int)strlen(s);
|
|
while (len > 0 && s[len - 1] == ' ') len--;
|
|
s[len] = '\0';
|
|
return s;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Built-in commands
|
|
// ---------------------------------------------------------------------------
|
|
static void cmd_help() {
|
|
print("Available commands:\n"
|
|
" help - Show this list\n"
|
|
" mem - Show memory usage\n"
|
|
" time - Show system wall-clock time\n"
|
|
" display - Show display provider and counters\n"
|
|
" stats - Show scheduler/CPU/PMM telemetry\n"
|
|
" ps - List processes\n"
|
|
" dir [path] - List directory contents\n"
|
|
" cd <path> - Change directory\n"
|
|
" type <file> - Display file contents\n"
|
|
" del <file> - Delete a file\n"
|
|
" write <file> <tx> - Create a file with text\n"
|
|
" clear - Clear the screen\n"
|
|
" exit - Close the shell\n");
|
|
}
|
|
|
|
static void printSizeKiB(uint64_t bytes) {
|
|
printUInt64(bytes / 1024u);
|
|
print(" KiB");
|
|
}
|
|
|
|
|
|
static void printPagesKiB(uint64_t pages) {
|
|
printUInt64(pages * 4u);
|
|
print(" KiB");
|
|
}
|
|
|
|
static void printCpuFlags(uint32_t flags) {
|
|
if (flags & SYS_CPU_FLAG_BSP) print("bsp ");
|
|
if (flags & SYS_CPU_FLAG_ONLINE) print("online ");
|
|
if (flags & SYS_CPU_FLAG_PARKED) print("parked ");
|
|
if (flags & SYS_CPU_FLAG_PRIMARY) print("primary ");
|
|
if (flags & SYS_CPU_FLAG_STARTED) print("started ");
|
|
if (flags & SYS_CPU_FLAG_PRESENT) print("present ");
|
|
}
|
|
|
|
static void cmd_stats(void) {
|
|
SYS_SCHEDULER_STATS sched;
|
|
SYS_PMM_STATS pmm;
|
|
SYS_CPU_STATS cpu;
|
|
uint32_t status;
|
|
|
|
status = SysQueryKernelStats(SYS_KERNEL_STATS_SCHEDULER, &sched, sizeof(sched), NULL);
|
|
if (status != 0) {
|
|
print("stats: scheduler query failed: ");
|
|
printUInt(status);
|
|
print("\n");
|
|
return;
|
|
}
|
|
|
|
status = SysQueryKernelStats(SYS_KERNEL_STATS_PMM, &pmm, sizeof(pmm), NULL);
|
|
if (status != 0) {
|
|
print("stats: pmm query failed: ");
|
|
printUInt(status);
|
|
print("\n");
|
|
return;
|
|
}
|
|
|
|
status = SysQueryKernelStats(SYS_KERNEL_STATS_CPU, &cpu, sizeof(cpu), NULL);
|
|
if (status != 0) {
|
|
print("stats: cpu query failed: ");
|
|
printUInt(status);
|
|
print("\n");
|
|
return;
|
|
}
|
|
|
|
print("Scheduler:\n");
|
|
print(" ticks: "); printUInt64(sched.Ticks); print("\n");
|
|
print(" context switches: "); printUInt64(sched.ContextSwitches); print("\n");
|
|
print(" quantum expires: "); printUInt64(sched.QuantumExpirations); print("\n");
|
|
print(" priority preempts: "); printUInt64(sched.PriorityPreemptions); print("\n");
|
|
print(" idle selections: "); printUInt64(sched.IdleSelections); print("\n");
|
|
print(" keep-current: "); printUInt64(sched.KeepCurrentDecisions); print("\n");
|
|
print(" demotions: "); printUInt64(sched.Demotions); print("\n");
|
|
print(" aging promotions: "); printUInt64(sched.AgingPromotions); print("\n");
|
|
print(" voluntary blocks: "); printUInt64(sched.VoluntaryBlocks); print("\n");
|
|
print(" SMT deferrals: "); printUInt64(sched.SmtSiblingDeferrals); print("\n");
|
|
print(" SMT primary pokes: "); printUInt64(sched.SmtPrimaryPokes); print("\n");
|
|
|
|
print("CPUs:\n");
|
|
uint32_t n = cpu.CpuCount;
|
|
if (n > SYS_KERNEL_STATS_MAX_CPUS)
|
|
n = SYS_KERNEL_STATS_MAX_CPUS;
|
|
for (uint32_t i = 0; i < n; i++) {
|
|
SYS_CPU_STAT* c = &cpu.Cpu[i];
|
|
print(" cpu"); printUInt(c->CpuIndex);
|
|
print(" lapic="); printUInt(c->LapicId);
|
|
print(" tid="); printUInt(c->CurrentTid);
|
|
print(" ticks="); printUInt64(c->SchedulerTicks);
|
|
print(" switches="); printUInt64(c->ContextSwitches);
|
|
print(" flags="); printCpuFlags(c->Flags);
|
|
print("\n");
|
|
}
|
|
|
|
print("Physical memory:\n");
|
|
print(" total: "); printPagesKiB(pmm.TotalFrames); print(" (frames="); printUInt64(pmm.TotalFrames); print(")\n");
|
|
print(" used: "); printPagesKiB(pmm.UsedFrames); print(" (frames="); printUInt64(pmm.UsedFrames); print(")\n");
|
|
print(" free: "); printPagesKiB(pmm.FreeFrames); print(" (frames="); printUInt64(pmm.FreeFrames); print(")\n");
|
|
print(" largest free run: "); printPagesKiB(pmm.LargestFreeRun); print(" (frames="); printUInt64(pmm.LargestFreeRun); print(")\n");
|
|
print(" free runs: "); printUInt64(pmm.FreeRunCount); print("\n");
|
|
print(" run histogram:\n");
|
|
print(" 1: "); printUInt64(pmm.FreeRunHistogram[0]); print("\n");
|
|
print(" 2-3: "); printUInt64(pmm.FreeRunHistogram[1]); print("\n");
|
|
print(" 4-7: "); printUInt64(pmm.FreeRunHistogram[2]); print("\n");
|
|
print(" 8-15: "); printUInt64(pmm.FreeRunHistogram[3]); print("\n");
|
|
print(" 16-63: "); printUInt64(pmm.FreeRunHistogram[4]); print("\n");
|
|
print(" 64-255: "); printUInt64(pmm.FreeRunHistogram[5]); print("\n");
|
|
print(" 256-1023: "); printUInt64(pmm.FreeRunHistogram[6]); print("\n");
|
|
print(" 1024+: "); printUInt64(pmm.FreeRunHistogram[7]); print("\n");
|
|
}
|
|
|
|
|
|
static void cmd_time(void) {
|
|
SYS_SYSTEM_TIME t;
|
|
uint32_t status = SysGetSystemTime(&t);
|
|
if (status != 0) {
|
|
print("time: failed: ");
|
|
printUInt(status);
|
|
print("\n");
|
|
return;
|
|
}
|
|
|
|
printUIntZeroWidth(t.Year, 4); print("-");
|
|
printUIntZeroWidth(t.Month, 2); print("-");
|
|
printUIntZeroWidth(t.Day, 2); print(" ");
|
|
printUIntZeroWidth(t.Hour, 2); print(":");
|
|
printUIntZeroWidth(t.Minute, 2); print(":");
|
|
printUIntZeroWidth(t.Second, 2); print(".");
|
|
printUIntZeroWidth(t.Millisecond, 3);
|
|
print(" epoch="); printUInt64(t.EpochSeconds);
|
|
print(" flags=0x"); printUInt(t.Flags);
|
|
if (t.Flags & SYS_TIME_FLAG_TZ_KNOWN) {
|
|
print(" tz="); printInt(t.TimeZoneMinutes);
|
|
} else {
|
|
print(" tz=unspecified");
|
|
}
|
|
print("\n");
|
|
}
|
|
|
|
static void printDisplayCaps(uint32_t caps) {
|
|
bool any = false;
|
|
if (caps & DISPLAY_CAP_FRAMEBUFFER) { print("framebuffer"); any = true; }
|
|
if (caps & DISPLAY_CAP_SOFTWARE_CURSOR) { if (any) print(","); print("software-cursor"); any = true; }
|
|
if (caps & DISPLAY_CAP_HARDWARE_CURSOR) { if (any) print(","); print("hardware-cursor"); any = true; }
|
|
if (caps & DISPLAY_CAP_ACCEL_FILL) { if (any) print(","); print("accel-fill"); any = true; }
|
|
if (caps & DISPLAY_CAP_ACCEL_COPY) { if (any) print(","); print("accel-copy"); any = true; }
|
|
if (caps & DISPLAY_CAP_PRESENT_SYNC) { if (any) print(","); print("present-sync"); any = true; }
|
|
if (caps & DISPLAY_CAP_VBLANK) { if (any) print(","); print("vblank"); any = true; }
|
|
if (caps & DISPLAY_CAP_3D) { if (any) print(","); print("3d"); any = true; }
|
|
if (!any) print("none");
|
|
}
|
|
|
|
static void printDisplayStats(const char* title, const DISPLAY_STATS* st) {
|
|
print(title); print(":\n");
|
|
print(" blit: "); printUInt64(st->BlitCount); print("\n");
|
|
print(" fill: "); printUInt64(st->FillRectCount); print("\n");
|
|
print(" copy: "); printUInt64(st->CopyRectCount); print("\n");
|
|
print(" read: "); printUInt64(st->ReadRectCount); print("\n");
|
|
print(" present: "); printUInt64(st->PresentCount); print(" rects="); printUInt64(st->PresentRectCount); print("\n");
|
|
print(" dirty: "); printUInt64(st->DirtyRectCount); print(" all="); printUInt64(st->DirtyAllCount); print("\n");
|
|
print(" bytes: "); printUInt64(st->BytesCopied); print("\n");
|
|
print(" sync: "); printUInt64(st->SyncCount); print("\n");
|
|
print(" cursor: move="); printUInt64(st->CursorMoveCount);
|
|
print(" show="); printUInt64(st->CursorShowCount);
|
|
print(" hide="); printUInt64(st->CursorHideCount); print("\n");
|
|
}
|
|
|
|
static void cmd_display(void) {
|
|
SYS_DISPLAY_INFO info;
|
|
uint32_t status = SysQueryDisplayInfo(&info);
|
|
if (status != 0) {
|
|
print("display: query failed: ");
|
|
printUInt(status);
|
|
print("\n");
|
|
return;
|
|
}
|
|
|
|
print("Display:\n");
|
|
print(" primary: "); print(info.PrimaryName[0] ? info.PrimaryName : "?"); print("\n");
|
|
print(" devices: "); printUInt(info.DeviceCount); print("\n");
|
|
print(" mode: "); printUInt(info.Mode.Width); print("x"); printUInt(info.Mode.Height);
|
|
print(" stride="); printUInt(info.Mode.Stride); print(" format="); printUInt((uint32_t)info.Mode.Format); print("\n");
|
|
print(" caps: 0x"); printHex32(info.Caps); print(" ["); printDisplayCaps(info.Caps); print("]\n");
|
|
printDisplayStats("Manager counters", &info.ManagerStats);
|
|
printDisplayStats("Provider counters", &info.DeviceStats);
|
|
}
|
|
|
|
static void cmd_mem(void) {
|
|
SYS_MEMORY_STATUS st;
|
|
if (SysGetMemoryStatus(&st) != 0) {
|
|
print("mem: failed\n");
|
|
return;
|
|
}
|
|
|
|
print("Memory Status:\n");
|
|
print(" Free physical: ");
|
|
printSizeKiB(st.FreePhysicalBytes);
|
|
print("\n Kernel pool: ");
|
|
printSizeKiB(st.KernelPoolBytes);
|
|
print("\n User heap: ");
|
|
printSizeKiB(st.UserHeapBytes);
|
|
print("\n");
|
|
}
|
|
|
|
static const char* processStateName(uint32_t state) {
|
|
switch (state) {
|
|
case SYS_PROCESS_STATE_RUNNING: return "run";
|
|
case SYS_PROCESS_STATE_TERMINATING: return "term";
|
|
case SYS_PROCESS_STATE_EXITED: return "exit";
|
|
default: return "?";
|
|
}
|
|
}
|
|
|
|
static void cmd_ps(void) {
|
|
SYS_PROCESS_INFO procs[MAX_PROCS];
|
|
size_t count = 0;
|
|
|
|
uint32_t status = SysGetProcessList(procs, MAX_PROCS, &count);
|
|
if (status != 0) {
|
|
print("ps: failed to retrieve process list\n");
|
|
return;
|
|
}
|
|
|
|
print("Processes (Count: ");
|
|
printUInt((uint32_t)count);
|
|
print("):\n");
|
|
print(" PID State Thr Hnd Mod UserKiB ImageKiB Flags Name\n");
|
|
|
|
size_t displayCount = count < MAX_PROCS ? count : MAX_PROCS;
|
|
for (size_t i = 0; i < displayCount; i++) {
|
|
SYS_PROCESS_INFO* p = &procs[i];
|
|
char flags[5];
|
|
size_t flagLen = 0;
|
|
|
|
if (p->Flags & SYS_PROCESS_FLAG_SYSTEM) flags[flagLen++] = 'S';
|
|
if (p->Flags & SYS_PROCESS_FLAG_CURRENT) flags[flagLen++] = '*';
|
|
if (p->Flags & SYS_PROCESS_FLAG_TERMINATING) flags[flagLen++] = 'T';
|
|
if (p->Flags & SYS_PROCESS_FLAG_EXITED) flags[flagLen++] = 'X';
|
|
if (flagLen == 0) flags[flagLen++] = '-';
|
|
flags[flagLen] = '\0';
|
|
|
|
print(" ");
|
|
printUIntWidth(p->ProcessId, 3);
|
|
print(" ");
|
|
printStringWidth(processStateName(p->State), 5);
|
|
print(" ");
|
|
printUIntWidth(p->ThreadCount, 3);
|
|
print(" ");
|
|
printUIntWidth(p->HandleCount, 3);
|
|
print(" ");
|
|
printUIntWidth(p->ModuleCount, 3);
|
|
print(" ");
|
|
printUInt64Width((uint64_t)p->UserCommittedBytes / 1024u, 7);
|
|
print(" ");
|
|
printUInt64Width((uint64_t)p->ImageSize / 1024u, 8);
|
|
print(" ");
|
|
printStringWidth(flags, 5);
|
|
print(" ");
|
|
print(p->Name);
|
|
if (p->CurrentDirectory[0]) {
|
|
print(" cwd=");
|
|
print(p->CurrentDirectory);
|
|
}
|
|
print("\n");
|
|
}
|
|
|
|
if (count > MAX_PROCS) {
|
|
print(" ... and ");
|
|
printUInt((uint32_t)(count - MAX_PROCS));
|
|
print(" more processes.\n");
|
|
}
|
|
}
|
|
|
|
static void cmd_write(const char* args) {
|
|
char filename[MAX_CMD]; int i = 0;
|
|
while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) {
|
|
filename[i] = args[i]; i++;
|
|
}
|
|
filename[i] = '\0';
|
|
if (args[i] == '\0' || args[i+1] == '\0') { print("write: usage: write <filename> <text>\n"); return; }
|
|
uint32_t hFile;
|
|
if (create_file(filename, &hFile) != 0) { print("write: could not create file\n"); return; }
|
|
size_t written;
|
|
SysWriteFile(hFile, args + i + 1, strlen(args + i + 1), &written);
|
|
SysCloseHandle(hFile);
|
|
print("File written successfully.\n");
|
|
}
|
|
|
|
static void cmd_dir(const char* path) {
|
|
uint32_t hDir;
|
|
const char* target = (path && *path != '\0') ? path : ".";
|
|
|
|
if (open_dir(target, &hDir) != 0) {
|
|
print("dir: failed to open directory\n");
|
|
return;
|
|
}
|
|
|
|
SYS_DIR_ENTRY ke;
|
|
while (SysReadDir(hDir, &ke) == 0) {
|
|
printDirTime(&ke.LastWriteTime);
|
|
|
|
// Corrected Attribute Check: 0x10 is the Directory bit in FAT
|
|
if (ke.Attr & 0x10) {
|
|
print("<DIR> ");
|
|
} else {
|
|
print(" ");
|
|
}
|
|
|
|
print(ke.Name);
|
|
|
|
// Optional: print file size for non-directories
|
|
if (!(ke.Attr & 0x10)) {
|
|
print(" (");
|
|
printUInt(ke.FileSize);
|
|
print(" bytes)");
|
|
}
|
|
|
|
print("\n");
|
|
}
|
|
SysCloseHandle(hDir);
|
|
}
|
|
|
|
static void cmd_type(const char* filename) {
|
|
uint32_t hFile;
|
|
if (open_file(filename, &hFile) != 0) { print("type: cannot open file\n"); return; }
|
|
char buffer[512]; size_t bytesRead;
|
|
while (SysReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead) == 0 && bytesRead > 0) {
|
|
buffer[bytesRead] = '\0'; print(buffer);
|
|
}
|
|
SysCloseHandle(hFile); print("\n");
|
|
}
|
|
|
|
|
|
static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) {
|
|
if (!cmdline || !out || outSize == 0) return false;
|
|
|
|
while (*cmdline == ' ' || *cmdline == '\t') cmdline++;
|
|
if (*cmdline == '\0') return false;
|
|
|
|
size_t pos = 0;
|
|
if (*cmdline == '"') {
|
|
cmdline++;
|
|
while (*cmdline && *cmdline != '"' && pos + 1 < outSize)
|
|
out[pos++] = *cmdline++;
|
|
} else {
|
|
while (*cmdline && *cmdline != ' ' && *cmdline != '\t' && pos + 1 < outSize)
|
|
out[pos++] = *cmdline++;
|
|
}
|
|
|
|
out[pos] = '\0';
|
|
return pos != 0;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Run one command
|
|
// ---------------------------------------------------------------------------
|
|
static int runCommand(const char* cmd) {
|
|
if (!cmd || *cmd == '\0') return 0;
|
|
if (strcmp(cmd, "exit") == 0) return 1;
|
|
if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; }
|
|
if (strcmp(cmd, "clear") == 0) { SysClearScreen(0x012456); return 0; }
|
|
if (strncmp(cmd, "crash", 5) == 0) {
|
|
// Check the sub-option trailing "crash " (offset 6)
|
|
if (strcmp(cmd + 6, "void") == 0) {
|
|
// Jumping into the void
|
|
void (*invalid_func)(void) = NULL;
|
|
invalid_func();
|
|
return 0;
|
|
}
|
|
else if (strcmp(cmd + 6, "noncanonical") == 0) {
|
|
// Non-canonical pointer dereference
|
|
volatile int *ptr = (volatile int*)0x4242424242424242ULL;
|
|
*ptr = 1337;
|
|
return 0;
|
|
}
|
|
else if (strcmp(cmd + 6, "ud2") == 0) {
|
|
__ud2();
|
|
return 0;
|
|
}
|
|
else if (strcmp(cmd + 6, "nx") == 0) {
|
|
// NX / DEP Violation
|
|
unsigned char code[] = { 0xC3 };
|
|
void (*execute_stack)(void) = (void (*)(void))code;
|
|
execute_stack();
|
|
return 0;
|
|
}
|
|
else if (strcmp(cmd + 6, "divzero") == 0) {
|
|
// Division by zero
|
|
volatile int zero = 0;
|
|
volatile int result = 1 / zero;
|
|
(void)result;
|
|
return 0;
|
|
}
|
|
else {
|
|
// Default fallback if just "crash" or an unknown sub-option is passed
|
|
*(volatile int*)0 = 42;
|
|
return 0;
|
|
}
|
|
}
|
|
if (strcmp(cmd, "mem") == 0) { cmd_mem(); return 0; }
|
|
if (strcmp(cmd, "time") == 0 || strcmp(cmd, "date") == 0) { cmd_time(); return 0; }
|
|
if (strcmp(cmd, "display") == 0 || strcmp(cmd, "gpu") == 0) { cmd_display(); return 0; }
|
|
if (strcmp(cmd, "stats") == 0 || strcmp(cmd, "telemetry") == 0) { cmd_stats(); return 0; }
|
|
if (strcmp(cmd, "ps") == 0) { cmd_ps(); return 0; }
|
|
if (strcmp(cmd, "dir") == 0) { cmd_dir("."); return 0; }
|
|
if (strncmp(cmd, "dir ", 4) == 0) { cmd_dir(cmd + 4); return 0; }
|
|
if (strncmp(cmd, "cd ", 3) == 0) { if (set_cwd(cmd + 3) != 0) print("cd: failed\n"); return 0; }
|
|
if (strncmp(cmd, "del ", 4) == 0) { delete_file(cmd + 4); return 0; }
|
|
if (strncmp(cmd, "type ", 5) == 0) { cmd_type(cmd + 5); return 0; }
|
|
if (strncmp(cmd, "write ", 6) == 0) { cmd_write(cmd + 6); return 0; }
|
|
|
|
char program[MAX_CMD];
|
|
if (!extractProgramPath(cmd, program, sizeof(program))) return 0;
|
|
|
|
uint32_t hProc;
|
|
if (create_process(program, &hProc, cmd) == 0) {
|
|
SysWaitForProcess(hProc);
|
|
SysCloseHandle(hProc);
|
|
while (SysPollKeyboard()) (void)SysReadKeyboardChar();
|
|
} else { print("shell: launch failed\n"); }
|
|
return 0;
|
|
}
|
|
|
|
int main(void) {
|
|
const char* cmdline = SysGetPeb()->CommandLine.Data;
|
|
char lineBuf[MAX_CMD];
|
|
|
|
print("shell: command line: ");
|
|
print(cmdline);
|
|
print("\n");
|
|
print("shell: ready\n");
|
|
while (true) {
|
|
print("> ");
|
|
readLine(lineBuf, MAX_CMD);
|
|
if (runCommand(trim(lineBuf))) break;
|
|
}
|
|
print("shell: goodbye\n");
|
|
SysExitProcess(0);
|
|
return 0;
|
|
}
|