// User application entry points for shell_native. #include #include #include #include #include #include #define MAX_CMD 256 #define SHELL_FOREGROUND_POLL_MS 30u #define MAX_PROCS 64 // Maximum number of processes we will fetch at once #define MAX_THREADS 128 #define SHELL_PROMPT "> " // Output helpers. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } // Opens file. static uint32_t open_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } // Creates file. static uint32_t create_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysCreateFile(&req); } // Opens dir. static uint32_t open_dir(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenDir(&req); } // Updates cwd. static uint32_t set_cwd(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysSetCwd(&req); } // Releases file. static uint32_t delete_file(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysDeleteFile(&req); } // Creates process. 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); } // Prints u Int. 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); } } // Prints int. static void printInt(int32_t n) { if (n < 0) { print("-"); printUInt((uint32_t)-(n + 1) + 1); } else { printUInt((uint32_t)n); } } // Parses an unsigned decimal integer. static bool parseUInt(const char* text, uint32_t* out) { if (!text || !out) return false; while (*text == ' ' || *text == '\t') text++; if (*text < '0' || *text > '9') return false; uint32_t value = 0; while (*text >= '0' && *text <= '9') { uint32_t digit = (uint32_t)(*text - '0'); if (value > (0xffffffffu - digit) / 10u) return false; value = value * 10u + digit; text++; } while (*text == ' ' || *text == '\t') text++; if (*text != '\0') return false; *out = value; return true; } // Prints u Int64. 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); } } // Implements the u64 Digits operation. static uint32_t u64Digits(uint64_t n) { uint32_t digits = 1; while (n >= 10u) { n /= 10u; digits++; } return digits; } // Prints spaces. static void printSpaces(size_t count) { while (count--) print(" "); } // Prints u Int Width. static void printUIntWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt(n); } // Prints u Int Zero Width. static void printUIntZeroWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); while (width > digits) { print("0"); width--; } printUInt(n); } // Prints u Int64 Width. static void printUInt64Width(uint64_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt64(n); } // Names nt-lite process-abort exit statuses. static const char* processExitStatusName(uint32_t code) { switch (code) { case STATUS_PROCESS_KILLED: return "killed"; case STATUS_PROCESS_PAGE_FAULT: return "page-fault"; case STATUS_PROCESS_GENERAL_PROTECTION: return "general-protection"; case STATUS_PROCESS_ILLEGAL_OPCODE: return "illegal-opcode"; case STATUS_PROCESS_DIVIDE_BY_ZERO: return "divide-by-zero"; case STATUS_PROCESS_BREAKPOINT: return "breakpoint"; case STATUS_PROCESS_ALIGNMENT_FAULT: return "alignment-fault"; case STATUS_PROCESS_UNKNOWN_FAULT: return "unknown-fault"; default: return NULL; } } // Prints hex32. 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); } // Prints dir Time. 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(" "); } // Prints string Width. 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); } #define SHELL_HISTORY_DEPTH 16 static char gHistory[SHELL_HISTORY_DEPTH][MAX_CMD]; static size_t gHistoryCount; static const char* const gShellBuiltinCommands[] = { "cd", "clear", "crash", "date", "del", "dir", "display", "exit", "gpu", "help", "kill", "mem", "ps", "stats", "telemetry", "threads", "time", "type", "write", }; // Converts a key event into the shell's printable character model. static char shellKeyToChar(INPUT_KEY key, uint32_t modifiers) { bool shifted = (modifiers & INPUT_MOD_SHIFT) != 0; bool caps = (modifiers & INPUT_MOD_CAPS_LOCK) != 0; if (key >= INPUT_KEY_A && key <= INPUT_KEY_Z) { char c = (char)('a' + (key - INPUT_KEY_A)); if (shifted ^ caps) c = (char)(c - 'a' + 'A'); return c; } if (key >= INPUT_KEY_1 && key <= INPUT_KEY_9) { static const char shiftedDigits[] = "!@#$%^&*("; char normal = (char)('1' + (key - INPUT_KEY_1)); return shifted ? shiftedDigits[key - INPUT_KEY_1] : normal; } switch (key) { case INPUT_KEY_0: return shifted ? ')' : '0'; case INPUT_KEY_MINUS: return shifted ? '_' : '-'; case INPUT_KEY_EQUAL: return shifted ? '+' : '='; case INPUT_KEY_LEFT_BRACKET: return shifted ? '{' : '['; case INPUT_KEY_RIGHT_BRACKET: return shifted ? '}' : ']'; case INPUT_KEY_BACKSLASH: return shifted ? '|' : '\\'; case INPUT_KEY_SEMICOLON: return shifted ? ':' : ';'; case INPUT_KEY_APOSTROPHE: return shifted ? '"' : '\''; case INPUT_KEY_GRAVE: return shifted ? '~' : '`'; case INPUT_KEY_COMMA: return shifted ? '<' : ','; case INPUT_KEY_PERIOD: return shifted ? '>' : '.'; case INPUT_KEY_SLASH: return shifted ? '?' : '/'; case INPUT_KEY_SPACE: return ' '; case INPUT_KEY_TAB: return '\t'; case INPUT_KEY_KP_DIVIDE: return '/'; case INPUT_KEY_KP_MULTIPLY: return '*'; case INPUT_KEY_KP_MINUS: return '-'; case INPUT_KEY_KP_PLUS: return '+'; case INPUT_KEY_KP_0: return '0'; case INPUT_KEY_KP_1: return '1'; case INPUT_KEY_KP_2: return '2'; case INPUT_KEY_KP_3: return '3'; case INPUT_KEY_KP_4: return '4'; case INPUT_KEY_KP_5: return '5'; case INPUT_KEY_KP_6: return '6'; case INPUT_KEY_KP_7: return '7'; case INPUT_KEY_KP_8: return '8'; case INPUT_KEY_KP_9: return '9'; case INPUT_KEY_KP_PERIOD: return '.'; default: return 0; } } // Adds a non-empty command to the in-memory history ring. static void shellHistoryAdd(const char* cmd) { if (!cmd || !*cmd) return; if (gHistoryCount > 0 && strcmp(gHistory[gHistoryCount - 1], cmd) == 0) return; if (gHistoryCount == SHELL_HISTORY_DEPTH) { memmove(gHistory[0], gHistory[1], (SHELL_HISTORY_DEPTH - 1) * MAX_CMD); gHistoryCount--; } strncpy(gHistory[gHistoryCount], cmd, MAX_CMD - 1); gHistory[gHistoryCount][MAX_CMD - 1] = '\0'; gHistoryCount++; } // Replaces the visible line while keeping the cursor at the end. static void shellEditorReplaceLine(char* buf, int len, int* pos, const char* text) { int oldPos = *pos; for (int i = 0; i < oldPos; i++) print("\b"); for (int i = 0; i < oldPos; i++) print(" "); for (int i = 0; i < oldPos; i++) print("\b"); int newPos = 0; if (text) { while (text[newPos] && newPos < len - 1) { buf[newPos] = text[newPos]; newPos++; } } buf[newPos] = '\0'; *pos = newPos; print(buf); } // Returns true when a character separates shell tokens. static bool shellIsTokenSeparator(char c) { return c == ' ' || c == '\t'; } // Returns true when a character separates path components. static bool shellIsPathSeparator(char c) { return c == '/' || c == '\\'; } // Returns true when the token already names an explicit path. static bool shellTokenHasPathSeparator(const char* token, size_t length) { for (size_t i = 0; i < length; i++) { if (shellIsPathSeparator(token[i])) return true; } return false; } // Returns true when name starts with prefix. static bool shellNameStartsWith(const char* name, const char* prefix, size_t prefixLength) { if (!name || !prefix) return false; for (size_t i = 0; i < prefixLength; i++) { if (name[i] == '\0' || name[i] != prefix[i]) return false; } return true; } // Extends an in-progress common prefix with one completion candidate. static void shellUpdateCommonPrefix(char* common, size_t commonSize, const char* name, uint32_t matchCount) { if (!common || commonSize == 0 || !name) return; if (matchCount == 0) { strncpy(common, name, commonSize - 1); common[commonSize - 1] = '\0'; return; } size_t i = 0; while (common[i] && name[i] && common[i] == name[i]) i++; common[i] = '\0'; } // Appends text to the edited line and echoes it. static bool shellEditorAppend(char* buf, int len, int* pos, const char* text) { if (!buf || len <= 0 || !pos || !text) return false; bool changed = false; while (*text && *pos < len - 1) { buf[*pos] = *text; (*pos)++; buf[*pos] = '\0'; char echo[2] = { *text, '\0' }; print(echo); text++; changed = true; } return changed; } // Prints one completion candidate. static void shellPrintCompletionCandidate(const char* name, bool directory) { print(" "); print(name); if (directory) print("/"); print("\n"); } // Tracks completion candidates without storing the full candidate list. typedef struct SHELL_COMPLETION_STATE { uint32_t MatchCount; bool LastIsDirectory; bool LastAddsSpace; char Common[SYS_DIR_NAME_MAX]; } SHELL_COMPLETION_STATE; // Records one completion candidate. static void shellRecordCompletion(SHELL_COMPLETION_STATE* state, const char* name, bool directory, bool addsSpace) { if (!state || !name || !*name) return; shellUpdateCommonPrefix(state->Common, sizeof(state->Common), name, state->MatchCount); state->MatchCount++; state->LastIsDirectory = directory; state->LastAddsSpace = addsSpace; } // Collects builtin command matches for a command-position token. static void shellCollectBuiltinCompletions(const char* prefix, size_t prefixLength, SHELL_COMPLETION_STATE* state, bool printMatches) { size_t count = sizeof(gShellBuiltinCommands) / sizeof(gShellBuiltinCommands[0]); for (size_t i = 0; i < count; i++) { const char* name = gShellBuiltinCommands[i]; if (!shellNameStartsWith(name, prefix, prefixLength)) continue; if (printMatches) shellPrintCompletionCandidate(name, false); else shellRecordCompletion(state, name, false, true); } } // Splits a token into a directory to scan and a filename prefix to match. static bool shellSplitCompletionPath(const char* token, size_t tokenLength, char* dir, size_t dirSize, const char** prefixOut, size_t* prefixLengthOut) { if (!token || !dir || dirSize == 0 || !prefixOut || !prefixLengthOut) return false; size_t lastSeparator = (size_t)-1; for (size_t i = 0; i < tokenLength; i++) { if (shellIsPathSeparator(token[i])) lastSeparator = i; } if (lastSeparator == (size_t)-1) { if (dirSize < 2) return false; dir[0] = '.'; dir[1] = '\0'; *prefixOut = token; *prefixLengthOut = tokenLength; return true; } size_t dirLength = lastSeparator; if (lastSeparator == 0) dirLength = 1; if (lastSeparator >= 2 && token[1] == ':' && shellIsPathSeparator(token[2])) dirLength = lastSeparator + 1; if (dirLength + 1 > dirSize) return false; memcpy(dir, token, dirLength); dir[dirLength] = '\0'; *prefixOut = token + lastSeparator + 1; *prefixLengthOut = tokenLength - lastSeparator - 1; return true; } // Collects filesystem path matches using the existing directory enumeration ABI. static void shellCollectPathCompletions(const char* token, size_t tokenLength, SHELL_COMPLETION_STATE* state, bool printMatches) { char dir[MAX_CMD]; const char* prefix = token; size_t prefixLength = tokenLength; if (!shellSplitCompletionPath(token, tokenLength, dir, sizeof(dir), &prefix, &prefixLength)) return; uint32_t hDir = 0; if (open_dir(dir, &hDir) != 0) return; SYS_DIR_ENTRY entry; while (SysReadDir(hDir, &entry) == 0) { if (!entry.Name[0]) continue; if (!shellNameStartsWith(entry.Name, prefix, prefixLength)) continue; bool directory = (entry.Attr & 0x10u) != 0; if (printMatches) shellPrintCompletionCandidate(entry.Name, directory); else shellRecordCompletion(state, entry.Name, directory, true); } SysCloseHandle(hDir); } // Redraws the prompt and current edit buffer after a completion list. static void shellRedrawPromptAndLine(const char* buf) { print(SHELL_PROMPT); print(buf ? buf : ""); } // Completes the token at the end of the current line. static void shellCompleteLine(char* buf, int len, int* pos) { if (!buf || len <= 0 || !pos || *pos < 0) return; size_t cursor = (size_t)*pos; size_t tokenStart = cursor; while (tokenStart > 0 && !shellIsTokenSeparator(buf[tokenStart - 1])) tokenStart--; const char* token = buf + tokenStart; size_t tokenLength = cursor - tokenStart; bool commandPosition = tokenStart == 0; bool explicitPath = shellTokenHasPathSeparator(token, tokenLength); char completionDir[MAX_CMD]; const char* namePrefix = token; size_t namePrefixLength = tokenLength; (void)shellSplitCompletionPath(token, tokenLength, completionDir, sizeof(completionDir), &namePrefix, &namePrefixLength); SHELL_COMPLETION_STATE state; memset(&state, 0, sizeof(state)); if (commandPosition && !explicitPath) { shellCollectBuiltinCompletions(token, tokenLength, &state, false); } shellCollectPathCompletions(token, tokenLength, &state, false); if (state.MatchCount == 0) return; size_t commonLength = strlen(state.Common); bool expanded = commonLength > namePrefixLength; if (expanded) { shellEditorAppend(buf, len, pos, state.Common + namePrefixLength); } if (state.MatchCount == 1) { if (state.LastIsDirectory) { if (*pos < len - 1 && *pos > 0 && !shellIsPathSeparator(buf[*pos - 1])) shellEditorAppend(buf, len, pos, "/"); } else if (state.LastAddsSpace) { if (*pos < len - 1 && (*pos == 0 || buf[*pos - 1] != ' ')) shellEditorAppend(buf, len, pos, " "); } return; } if (expanded) return; print("\n"); if (commandPosition && !explicitPath) { shellCollectBuiltinCompletions(token, tokenLength, NULL, true); } shellCollectPathCompletions(token, tokenLength, NULL, true); shellRedrawPromptAndLine(buf); } // Reads one editable command line from the keyboard. static bool readLine(char* buf, int len) { int pos = 0; size_t historyCursor = gHistoryCount; if (len <= 0) return false; buf[0] = '\0'; while (true) { INPUT_KEY_RECORD input; if (SysReadInputEvent(&input) != 0) { SysYield(); continue; } INPUT_KEY key = input.Key; if (key == INPUT_KEY_NONE) { SysYield(); continue; } uint32_t modifiers = input.Modifiers; if ((modifiers & INPUT_MOD_CTRL) && key == INPUT_KEY_C) { buf[0] = '\0'; print("^C\n"); return true; } if (key == INPUT_KEY_ENTER || key == INPUT_KEY_KP_ENTER) { print("\n"); break; } if (key == INPUT_KEY_BACKSPACE) { if (pos > 0) { pos--; buf[pos] = '\0'; print("\b \b"); } continue; } if (key == INPUT_KEY_UP) { if (historyCursor > 0) { historyCursor--; shellEditorReplaceLine(buf, len, &pos, gHistory[historyCursor]); } continue; } if (key == INPUT_KEY_DOWN) { if (historyCursor < gHistoryCount) { historyCursor++; shellEditorReplaceLine(buf, len, &pos, historyCursor < gHistoryCount ? gHistory[historyCursor] : ""); } continue; } if (key == INPUT_KEY_TAB) { shellCompleteLine(buf, len, &pos); continue; } char c = input.Char ? input.Char : shellKeyToChar(key, modifiers); if (c < 0x20 || c == 127) continue; if (pos < len - 1) { buf[pos++] = c; buf[pos] = '\0'; char echo[2] = { c, '\0' }; print(echo); } } return false; } // Implements the trim operation. 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/MM telemetry\n" " ps - List processes\n" " threads - Show one process's thread statuses\n" " kill - Terminate a process\n" " dir [path] - List directory contents\n" " cd - Change directory\n" " type - Display file contents\n" " del - Delete a file\n" " write - Create a file with text\n" " clear - Clear the screen\n" " exit - Close the shell\n"); } // Prints size Ki B. static void printSizeKiB(uint64_t bytes) { printUInt64(bytes / 1024u); print(" KiB"); } // Prints pages Ki B. static void printPagesKiB(uint64_t pages) { printUInt64(pages * 4u); print(" KiB"); } // Prints cpu Flags. 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 "); } // Implements the cmd stats operation. static void cmd_stats(void) { SYS_SCHEDULER_STATS sched; SYS_PMM_STATS pmm; SYS_CPU_STATS cpu; SYS_PFN_STATS pfn; SYS_VAD_STATS vad; SYS_SWAP_STATS swap; SYS_FILE_CACHE_STATS fileCache; SYS_FILESYSTEM_STATS filesystem; SYS_DISK_STATS disk; SYS_PTE_STATS pte; SYS_SURFACE_STATS surface; 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; } status = SysQueryKernelStats(SYS_KERNEL_STATS_PFN, &pfn, sizeof(pfn), NULL); if (status != 0) { print("stats: pfn query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_VAD, &vad, sizeof(vad), NULL); if (status != 0) { print("stats: vad query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_SWAP, &swap, sizeof(swap), NULL); if (status != 0) { print("stats: swap query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_FILE_CACHE, &fileCache, sizeof(fileCache), NULL); if (status != 0) { print("stats: file cache query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_FILESYSTEM, &filesystem, sizeof(filesystem), NULL); if (status != 0) { print("stats: filesystem query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_DISK, &disk, sizeof(disk), NULL); if (status != 0) { print("stats: disk query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_PTE, &pte, sizeof(pte), NULL); if (status != 0) { print("stats: pte query failed: "); printUInt(status); print("\n"); return; } status = SysQueryKernelStats(SYS_KERNEL_STATS_SURFACE, &surface, sizeof(surface), NULL); if (status != 0) { print("stats: surface 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(" current="); if (c->CurrentThreadFlags & SYS_CPU_THREAD_FLAG_IDLE) { print("idle/"); printUInt(c->CpuIndex); } else { 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(" available+reclaim: "); printSizeKiB(pfn.AvailableFrames * 4096ull); print(" (reclaimable="); printSizeKiB(pfn.ReclaimableFrames * 4096ull); 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"); print("PFN database:\n"); print(" states: active="); printUInt64(pfn.ActiveFrames); print(" free="); printUInt64(pfn.FreeFrames); print(" zeroed="); printUInt64(pfn.ZeroedFrames); print(" standby="); printUInt64(pfn.StandbyFrames); print(" modified="); printUInt64(pfn.ModifiedFrames); print(" reserved="); printUInt64(pfn.ReservedFrames); print("\n"); print(" eviction: evictable="); printUInt64(pfn.EvictableFrames); print(" reclaimable="); printUInt64(pfn.ReclaimableFrames); print(" available="); printUInt64(pfn.AvailableFrames); print(" mapped="); printUInt64(pfn.MappedFrames); print(" non-evictable="); printUInt64(pfn.NonEvictableFrames); print(" pinned="); printUInt64(pfn.PinnedFrames); print("\n"); print(" usage frames: kernel="); printUInt64(pfn.KernelFrames); print(" pt="); printUInt64(pfn.PageTableFrames); print(" user="); printUInt64(pfn.UserFrames); print(" driver="); printUInt64(pfn.DriverFrames); print(" dma="); printUInt64(pfn.DmaFrames); print(" boot="); printUInt64(pfn.BootloaderFrames); print(" pfn-db="); printUInt64(pfn.PfnDatabaseFrames); print(" mmio="); printUInt64(pfn.MmioFrames); print("\n"); print(" buckets: clean-file="); printUInt64(pfn.CleanFileCacheFrames); print(" (active="); printUInt64(pfn.ActiveCleanFileCacheFrames); print(" standby="); printUInt64(pfn.StandbyCleanFileCacheFrames); print(")"); print(" image="); printUInt64(pfn.ImageFrames); print(" (active="); printUInt64(pfn.ActiveImageFrames); print(" standby="); printUInt64(pfn.StandbyImageFrames); print(")"); print(" mapped-file="); printUInt64(pfn.MappedFileFrames); print(" anon="); printUInt64(pfn.AnonymousFrames); print(" cow="); printUInt64(pfn.CowFrames); print(" surface="); printUInt64(pfn.SurfaceFrames); print("\n"); print(" operations: alloc="); printUInt64(pfn.AllocationCount); print(" free="); printUInt64(pfn.FreeCount); print(" retain="); printUInt64(pfn.RetainCount); print(" release="); printUInt64(pfn.ReleaseCount); print(" pin="); printUInt64(pfn.PinCount); print(" unpin="); printUInt64(pfn.UnpinCount); print("\n"); print(" failures: alloc="); printUInt64(pfn.FailedAllocations); print(" contiguous="); printUInt64(pfn.FailedContiguousAllocations); print("\n"); print(" alloc reasons: invalid-range="); printUInt64(pfn.FailedInvalidRange); print(" empty-range="); printUInt64(pfn.FailedEmptyRange); print(" reserve-denied="); printUInt64(pfn.FailedReserveDenied); print(" no-frame="); printUInt64(pfn.FailedNoFrame); print("\n"); print(" contig reasons: invalid="); printUInt64(pfn.FailedContiguousInvalidRequest); print(" reserve-denied="); printUInt64(pfn.FailedContiguousReserveDenied); print(" no-run="); printUInt64(pfn.FailedContiguousNoRun); print("\n"); print(" reclaim: attempts="); printUInt64(pfn.ReclaimAttempts); print(" requested="); printUInt64(pfn.ReclaimPagesRequested); print(" succeeded="); printUInt64(pfn.ReclaimPagesSucceeded); print(" failed="); printUInt64(pfn.ReclaimPagesFailed); print(" reentrant-skips="); printUInt64(pfn.ReclaimReentrantSkips); print("\n"); print("VAD faults:\n"); print(" resolve: calls="); printUInt64(vad.ResolveFaultCalls); print(" resolved="); printUInt64(vad.ResolvedFaults); print(" failed="); printUInt64(vad.FailedFaults); print("\n"); print(" failure reasons: protection="); printUInt64(vad.ProtectionFaults); print(" no-vad="); printUInt64(vad.NoVadFaults); print(" uncommitted="); printUInt64(vad.UncommittedFaults); print(" noaccess="); printUInt64(vad.NoAccessFaults); print("\n"); print(" materialization: demand-zero="); printUInt64(vad.DemandZeroPages); print(" zero-maps="); printUInt64(vad.ZeroPageMaps); print(" zero-splits="); printUInt64(vad.ZeroPageCowSplits); print(" ensure-calls="); printUInt64(vad.EnsureResidentCalls); print(" ensure-pages="); printUInt64(vad.EnsureResidentPages); print(" already-resident="); printUInt64(vad.AlreadyResidentPages); print("\n"); print(" cow: faults="); printUInt64(vad.CowFaults); print(" copied="); printUInt64(vad.CowPagesCopied); print(" views="); printUInt64(vad.CowViewsCreated); print(" shared-pages="); printUInt64(vad.CowPagesShared); print("\n"); print(" file-backed: faults="); printUInt64(vad.FileBackedFaults); print(" reads="); printUInt64(vad.FileBackedReads); print(" read-fail="); printUInt64(vad.FileBackedReadFailures); print(" discards="); printUInt64(vad.FileBackedDiscards); print("\n"); print(" mapped-file: shared-faults="); printUInt64(vad.FileBackedSharedWritableFaults); print(" dirty-faults="); printUInt64(vad.FileBackedDirtyFaults); print(" dirty-syncs="); printUInt64(vad.FileBackedDirtySyncs); print("\n"); print(" image-backed: faults="); printUInt64(vad.ImageBackedFaults); print(" zero-faults="); printUInt64(vad.ImageBackedZeroFaults); print(" private-faults="); printUInt64(vad.ImageBackedPrivateFaults); print("\n"); print(" image fixups: calls="); printUInt64(vad.ImageFixupPrivateCalls); print(" private-pages="); printUInt64(vad.ImageFixupPrivatePages); print("\n"); print(" swap-backed: page-outs="); printUInt64(vad.SwapPageOuts); print(" page-ins="); printUInt64(vad.SwapPageIns); print("\n"); print("Swap:\n"); print(" enabled: "); printUInt64(swap.Enabled); print("\n"); print(" slots: total="); printUInt64(swap.TotalSlots); print(" used="); printUInt64(swap.UsedSlots); print(" free="); printUInt64(swap.FreeSlots); print(" high-water="); printUInt64(swap.HighWaterSlots); print("\n"); print(" io: out="); printUInt64(swap.PageOuts); print(" in="); printUInt64(swap.PageIns); print(" out-fail="); printUInt64(swap.PageOutFailures); print(" in-fail="); printUInt64(swap.PageInFailures); print("\n"); print(" slots ops: alloc="); printUInt64(swap.SlotAllocations); print(" free="); printUInt64(swap.SlotFrees); print(" alloc-fail="); printUInt64(swap.SlotAllocationFailures); print("\n"); print("File cache:\n"); print(" lookups: total="); printUInt64(fileCache.Lookups); print(" hits="); printUInt64(fileCache.Hits); print(" misses="); printUInt64(fileCache.Misses); print("\n"); print(" loads: ok="); printUInt64(fileCache.Loads); print(" fail="); printUInt64(fileCache.LoadFailures); print(" races="); printUInt64(fileCache.RaceDiscards); print(" waits="); printUInt64(fileCache.InflightWaits); print("\n"); print(" lifetime: resident="); printUInt64(fileCache.ResidentPages); print(" active="); printUInt64(fileCache.ActivePages); print(" standby="); printUInt64(fileCache.StandbyPages); print(" max="); printUInt64(fileCache.MaxResidentPages); print(" invalidations="); printUInt64(fileCache.Invalidations); print("\n"); print(" dirty/writeback: dirty="); printUInt64(fileCache.DirtyPages); print(" max-dirty="); printUInt64(fileCache.MaxDirtyPages); print(" marks="); printUInt64(fileCache.DirtyMarks); print(" wb-req="); printUInt64(fileCache.WritebackRequests); print(" wb-pages="); printUInt64(fileCache.WritebackPages); print(" wb-bytes="); printUInt64(fileCache.WritebackBytes); print(" wb-fail="); printUInt64(fileCache.WritebackFailures); print("\n"); print(" mapped dirty: syncs="); printUInt64(fileCache.MappedDirtySyncs); print(" pages="); printUInt64(fileCache.MappedDirtyPages); print("\n"); print(" flushes: calls="); printUInt64(fileCache.FlushFileCalls); print(" fail="); printUInt64(fileCache.FlushFileFailures); print("\n"); print(" reclaim: drops="); printUInt64(fileCache.Drops); print(" standby="); printUInt64(fileCache.StandbyTransitions); print(" standby-hits="); printUInt64(fileCache.StandbyHits); print(" drop-fail="); printUInt64(fileCache.DropFailures); print("\n"); print(" read-ahead: requests="); printUInt64(fileCache.ReadAheadRequests); print(" requested="); printUInt64(fileCache.ReadAheadPagesRequested); print(" queued="); printUInt64(fileCache.ReadAheadPagesQueued); print(" loaded="); printUInt64(fileCache.ReadAheadPagesLoaded); print(" skipped="); printUInt64(fileCache.ReadAheadPagesSkipped); print(" fail="); printUInt64(fileCache.ReadAheadFailures); print(" throttled="); printUInt64(fileCache.ReadAheadPagesThrottled); print("\n"); print(" read-ahead max: pages/request="); printUInt64(fileCache.MaxReadAheadPagesPerRequest); print("\n"); print(" batch fills: reads="); printUInt64(fileCache.BatchReads); print(" requested="); printUInt64(fileCache.BatchPagesRequested); print(" loaded="); printUInt64(fileCache.BatchPagesLoaded); print(" max-request="); printUInt64(fileCache.MaxBatchPagesRequested); print(" max-loaded="); printUInt64(fileCache.MaxBatchPagesLoaded); print("\n"); print("Filesystem:\n"); print(" path cache: lookups="); printUInt64(filesystem.PathLookups); print(" hits="); printUInt64(filesystem.PathCacheHits); print(" misses="); printUInt64(filesystem.PathCacheMisses); print(" stores="); printUInt64(filesystem.PathCacheStores); print("\n"); print(" invalidation: count="); printUInt64(filesystem.PathCacheInvalidations); print(" generation="); printUInt64(filesystem.PathCacheGeneration); print("\n"); print(" directory search: searches="); printUInt64(filesystem.DirectorySearches); print(" clusters="); printUInt64(filesystem.DirectoryClustersRead); print(" entries="); printUInt64(filesystem.DirectoryEntriesScanned); print("\n"); print(" FAT chain cache: lookups="); printUInt64(filesystem.FatChainCacheLookups); print(" hits="); printUInt64(filesystem.FatChainCacheHits); print(" misses="); printUInt64(filesystem.FatChainCacheMisses); print(" stores="); printUInt64(filesystem.FatChainCacheStores); print("\n"); print(" FAT chain work: invalidations="); printUInt64(filesystem.FatChainCacheInvalidations); print(" fat-steps="); printUInt64(filesystem.FatChainWalkSteps); print("\n"); print(" data read spans: runs="); printUInt64(filesystem.DataReadRuns); print(" sectors="); printUInt64(filesystem.DataReadSectors); print(" merges="); printUInt64(filesystem.DataReadRunMerges); print(" max-sectors="); printUInt64(filesystem.MaxDataReadSpanSectors); print("\n"); print("Disk I/O:\n"); print(" devices: registered="); printUInt64(disk.RegisteredDisks); print("\n"); print(" reads: requests="); printUInt64(disk.ReadRequests); print(" sectors="); printUInt64(disk.ReadSectors); print(" max-sectors="); printUInt64(disk.MaxReadSectors); print("\n"); print(" writes: requests="); printUInt64(disk.WriteRequests); print(" sectors="); printUInt64(disk.WriteSectors); print(" max-sectors="); printUInt64(disk.MaxWriteSectors); print("\n"); print(" read-ahead: hits="); printUInt64(disk.ReadaheadHits); print(" misses="); printUInt64(disk.ReadaheadMisses); print(" stores="); printUInt64(disk.ReadaheadStores); print(" sectors="); printUInt64(disk.ReadaheadSectorsLoaded); print(" max-sectors="); printUInt64(disk.MaxReadaheadSectors); print("\n"); print(" read-ahead misc: served-bytes="); printUInt64(disk.ReadaheadBytesServed); print(" seq="); printUInt64(disk.ReadaheadSequentialDetections); print(" invalidations="); printUInt64(disk.ReadaheadInvalidations); print(" suppressed="); printUInt64(disk.ReadaheadSuppressed); print(" alloc-fail="); printUInt64(disk.ReadaheadAllocFailures); print(" read-fail="); printUInt64(disk.ReadaheadReadFailures); print("\n"); print("Surfaces:\n"); print(" lifetime: created="); printUInt64(surface.CreatedSurfaces); print(" destroyed="); printUInt64(surface.DestroyedSurfaces); print(" live="); printUInt64(surface.LiveSurfaces); print("\n"); print(" live memory: pages="); printUInt64(surface.LivePages); print(" bytes="); printUInt64(surface.LiveBytes); print("\n"); print(" maps/presents: maps="); printUInt64(surface.MapCalls); print(" presents="); printUInt64(surface.PresentCalls); print(" input-rects="); printUInt64(surface.PresentRectInputs); print("\n"); print(" present work: clipped="); printUInt64(surface.PresentClippedRects); print(" empty="); printUInt64(surface.PresentEmptyClips); print(" rows="); printUInt64(surface.PresentRowsCopied); print(" bytes="); printUInt64(surface.PresentBytesCopied); print("\n"); print("Page tables:\n"); print(" leaf mappings: "); printUInt64(pte.CurrentLeafMappings); print("\n"); print(" page-table pages: "); printUInt64(pte.PageTablePagesAllocated); print("\n"); print(" map/unmap: map="); printUInt64(pte.MapCalls); print(" failed="); printUInt64(pte.MapFailures); print(" unmap="); printUInt64(pte.UnmapCalls); print(" failed="); printUInt64(pte.UnmapFailures); print("\n"); print(" protect: calls="); printUInt64(pte.ProtectCalls); print(" failed="); printUInt64(pte.ProtectFailures); print("\n"); print(" query: total="); printUInt64(pte.QueryCalls); print(" failed="); printUInt64(pte.QueryFailures); print(" translate="); printUInt64(pte.TranslateCalls); print("\n"); print(" generic: "); printUInt64(pte.QueryByPurpose[0]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[0]); print("\n"); print(" user-probe: "); printUInt64(pte.QueryByPurpose[1]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[1]); print("\n"); print(" heap: "); printUInt64(pte.QueryByPurpose[2]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[2]); print("\n"); print(" vad: "); printUInt64(pte.QueryByPurpose[3]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[3]); print("\n"); print(" debug: "); printUInt64(pte.QueryByPurpose[4]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[4]); print("\n"); print(" self-test: "); printUInt64(pte.QueryByPurpose[5]); print(" failed="); printUInt64(pte.QueryFailuresByPurpose[5]); print("\n"); print(" tlb: local="); printUInt64(pte.LocalFlushes); print(" global="); printUInt64(pte.GlobalFlushes); print(" new-map-skip="); printUInt64(pte.NewMappingNoFlushes); print(" replace-flush="); printUInt64(pte.ReplacedMappingFlushes); print("\n"); print(" shootdowns: requests="); printUInt64(pte.ShootdownRequests); print(" targets="); printUInt64(pte.ShootdownTargetCpus); print(" skipped="); printUInt64(pte.ShootdownSkippedNoTargets); print(" acks="); printUInt64(pte.ShootdownAcks); print(" timeouts="); printUInt64(pte.ShootdownTimeouts); print("\n"); } // Implements the cmd time operation. 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"); } // Prints display Caps. 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"); } // Prints display Stats. 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"); } // Implements the cmd display operation. 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); } // Implements the cmd mem operation. 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 Reclaimable: "); printSizeKiB(st.ReclaimablePhysicalBytes); print("\n Available physical: "); printSizeKiB(st.AvailablePhysicalBytes); print("\n Pinned physical: "); printSizeKiB(st.PinnedPhysicalBytes); print("\n Non-evictable: "); printSizeKiB(st.NonEvictablePhysicalBytes); print("\n User frames: "); printSizeKiB(st.UserPhysicalBytes); print("\n Page tables: "); printSizeKiB(st.PageTablePhysicalBytes); print("\n Kernel pool: "); printSizeKiB(st.KernelPoolBytes); print("\n User heap: "); printSizeKiB(st.UserHeapBytes); print("\n"); } // Processes state Name. 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 "?"; } } // Names public thread states. static const char* threadStateName(uint32_t state) { switch (state) { case SYS_THREAD_STATE_READY: return "ready"; case SYS_THREAD_STATE_RUNNING: return "run"; case SYS_THREAD_STATE_WAITING: return "wait"; case SYS_THREAD_STATE_DEAD: return "dead"; default: return "?"; } } // Names public wait object types. static const char* threadWaitName(uint32_t waitType) { switch (waitType) { case SYS_THREAD_WAIT_NONE: return "-"; case SYS_THREAD_WAIT_PROCESS: return "process"; case SYS_THREAD_WAIT_THREAD: return "thread"; case SYS_THREAD_WAIT_MUTEX: return "mutex"; case SYS_THREAD_WAIT_SEMAPHORE: return "sem"; case SYS_THREAD_WAIT_EVENT: return "event"; case SYS_THREAD_WAIT_QUEUE: return "queue"; case SYS_THREAD_WAIT_FILE: return "file"; case SYS_THREAD_WAIT_DIR: return "dir"; case SYS_THREAD_WAIT_ASYNC_IO: return "async"; case SYS_THREAD_WAIT_SOCKET: return "socket"; case SYS_THREAD_WAIT_DEVICE: return "device"; case SYS_THREAD_WAIT_DRIVER: return "driver"; case SYS_THREAD_WAIT_USB_DEVICE: return "usbdev"; case SYS_THREAD_WAIT_USB_PIPE: return "usbpipe"; case SYS_THREAD_WAIT_FILE_MAPPING: return "mapping"; case SYS_THREAD_WAIT_SURFACE: return "surface"; default: return "unknown"; } } // Prints thread status flags. static void printThreadFlags(uint32_t flags) { char buf[8]; size_t n = 0; if (flags & SYS_THREAD_FLAG_CURRENT) buf[n++] = '*'; if (flags & SYS_THREAD_FLAG_IDLE) buf[n++] = 'I'; if (flags & SYS_THREAD_FLAG_KERNEL) buf[n++] = 'K'; if (flags & SYS_THREAD_FLAG_QUEUED) buf[n++] = 'Q'; if (flags & SYS_THREAD_FLAG_ALERTABLE_WAIT) buf[n++] = 'A'; if (flags & SYS_THREAD_FLAG_KERNEL_APC_PENDING) buf[n++] = 'k'; if (flags & SYS_THREAD_FLAG_USER_APC_PENDING) buf[n++] = 'u'; if (n == 0) buf[n++] = '-'; buf[n] = '\0'; printStringWidth(buf, 7); } // Implements the cmd ps operation. 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"); print(" Flags: S=system I=idle *=current T=terminating X=exited.\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[6]; size_t flagLen = 0; if (p->Flags & SYS_PROCESS_FLAG_SYSTEM) flags[flagLen++] = 'S'; if (p->Flags & SYS_PROCESS_FLAG_IDLE) flags[flagLen++] = 'I'; 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"); } } // Implements the cmd threads operation. static void cmd_threads(const char* args) { uint32_t pid = 0; if (!parseUInt(args, &pid)) { print("threads: usage: threads \n"); return; } SYS_THREAD_INFO threads[MAX_THREADS]; size_t count = 0; uint32_t status = SysGetThreadList(pid, threads, MAX_THREADS, &count); if (status != 0) { print("threads: query failed status="); printUInt(status); print("\n"); return; } print("Threads for PID "); printUInt(pid); print(" (Count: "); printUInt((uint32_t)count); print("):\n"); print(" TID State Pri CPU LastCPU QRem QTick Burst Wait WStat Flags\n"); print(" Flags: *=current I=idle K=kernel Q=queued A=alertable k=kernel-apc u=user-apc.\n"); size_t displayCount = count < MAX_THREADS ? count : MAX_THREADS; for (size_t i = 0; i < displayCount; i++) { SYS_THREAD_INFO* t = &threads[i]; print(" "); printUIntWidth(t->ThreadId, 3); print(" "); printStringWidth(threadStateName(t->State), 5); print(" "); printUIntWidth(t->Priority, 3); print(" "); if (t->RunningCpu == 0xffffffffu) printStringWidth("-", 3); else printUIntWidth(t->RunningCpu, 3); print(" "); if (t->LastCpu == 0xffffffffu) printStringWidth("-", 7); else printUIntWidth(t->LastCpu, 7); print(" "); printUIntWidth(t->QuantumRemaining, 4); print(" "); printUIntWidth(t->QuantumTicks, 5); print(" "); printUIntWidth(t->CpuBurstTicks, 5); print(" "); printStringWidth(threadWaitName(t->WaitObjectType), 8); print(" "); printUIntWidth(t->WaitStatus, 5); print(" "); printThreadFlags(t->Flags); print("\n"); } if (count > MAX_THREADS) { print(" ... and "); printUInt((uint32_t)(count - MAX_THREADS)); print(" more threads.\n"); } } static void cmd_kill(const char* args) { uint32_t pid = 0; if (!parseUInt(args, &pid) || pid == 0) { print("kill: usage: kill \n"); return; } uint32_t status = SysKillProcess(pid, (int)STATUS_PROCESS_KILLED); if (status != 0) { print("shell: failed to kill process "); printUInt(pid); print(", error code: "); printUInt(status); print("\n"); } else { print("Process "); printUInt(pid); print(" terminated successfully.\n"); } } // Implements the cmd write operation. 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 \n"); return; } uint32_t hFile; if (create_file(filename, &hFile) != 0) { print("write: could not create file\n"); return; } size_t written; SYS_FILE_IO_REQUEST writeReq = SysMakeFileIoRequest(hFile, args + i + 1, strlen(args + i + 1), &written); SysWriteFile(&writeReq); SysCloseHandle(hFile); print("File written successfully.\n"); } // Implements the cmd dir operation. 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); if (ke.Attr & 0x10) { print(" "); print(ke.Name); } else { print(" "); print(ke.Name); print(" ("); printUInt64(ke.FileSize); print(" bytes)"); } print("\n"); } SysCloseHandle(hDir); } // Implements the cmd type operation. 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; for (;;) { SYS_FILE_IO_REQUEST readReq = SysMakeFileIoRequest(hFile, buffer, sizeof(buffer) - 1, &bytesRead); if (SysReadFile(&readReq) != 0 || bytesRead == 0) break; buffer[bytesRead] = '\0'; print(buffer); } SysCloseHandle(hFile); print("\n"); } // Implements the extract Program Path operation. 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; } // Consumes queued Ctrl-C input without taking ordinary foreground stdin. static bool shellConsumeQueuedCtrlC(void) { for (int i = 0; i < 4; i++) { INPUT_KEY_RECORD input; if (SysPeekInputEvent(&input) != 0) return false; if ((input.Modifiers & INPUT_MOD_CTRL) && input.Key == INPUT_KEY_C) { (void)SysReadInputEvent(&input); return true; } if (input.Key == INPUT_KEY_LEFT_CTRL || input.Key == INPUT_KEY_RIGHT_CTRL) { (void)SysReadInputEvent(&input); continue; } return false; } return false; } // Waits for a foreground process while watching Ctrl-C without stealing ordinary stdin. static uint32_t waitForegroundProcess(uint32_t hProc) { uint32_t pid = 0; bool havePid = SysGetProcessPid(hProc, &pid) == 0 && pid != 0; bool sentBreak = false; uint32_t inputQueue = 0; if (SysOpenInputQueue(0, &inputQueue) != 0) return SysWait(hProc, SYS_WAIT_FLAG_NONE); uint32_t handles[2] = { hProc, inputQueue }; uint32_t index = 0; SYS_WAIT_MANY_REQUEST waitReq; waitReq.Size = sizeof(waitReq); waitReq.Flags = SYS_WAIT_FLAG_NONE; waitReq.Handles = handles; waitReq.Count = 2; waitReq.SignaledIndexOut = &index; waitReq.TimeoutMilliseconds = SYS_WAIT_TIMEOUT_INFINITE; for (;;) { index = 0; uint32_t status = SysWaitMany(&waitReq); if (status != SYS_STATUS_SUCCESS) { SysCloseHandle(inputQueue); return status; } if (index == 0) { SysCloseHandle(inputQueue); return status; } uint32_t modifiers = SysGetKeyModifiers(); if (((modifiers & INPUT_MOD_CTRL) && SysIsKeyDown(INPUT_KEY_C)) || shellConsumeQueuedCtrlC()) { if (!sentBreak) { print("^C\n"); if (havePid) (void)SysKillProcess(pid, (int)STATUS_PROCESS_KILLED); sentBreak = true; } } } } // 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 (strncmp(cmd, "threads ", 8) == 0) { cmd_threads(cmd + 8); return 0; } if (strncmp(cmd, "kill ", 5) == 0) { cmd_kill(cmd + 5); 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; } // Make a local copy of the command line so we can mutate it safely if needed char modifiedCmd[MAX_CMD]; strncpy(modifiedCmd, cmd, sizeof(modifiedCmd) - 1); modifiedCmd[sizeof(modifiedCmd) - 1] = '\0'; // Parse background indicator execution flag (&) bool background = false; size_t cmdLen = strlen(modifiedCmd); if (cmdLen > 0 && modifiedCmd[cmdLen - 1] == '&') { background = true; modifiedCmd[cmdLen - 1] = '\0'; // Strip the ampersand // Clean up any trailing whitespace left before the ampersand cmdLen = strlen(modifiedCmd); while (cmdLen > 0 && (modifiedCmd[cmdLen - 1] == ' ' || modifiedCmd[cmdLen - 1] == '\t')) { modifiedCmd[cmdLen - 1] = '\0'; cmdLen--; } } char program[MAX_CMD]; if (!extractProgramPath(modifiedCmd, program, sizeof(program))) return 0; uint32_t hProc; if (create_process(program, &hProc, modifiedCmd) == 0) { if (background) { // Background mode: Clean up the handle immediately and skip waiting. print("[Launched in background, handle: "); printUInt(hProc); print("]\n"); SysCloseHandle(hProc); } else { // Foreground mode: Wait for completion and flush standard keyboard stream. uint32_t waitStatus = waitForegroundProcess(hProc); if (waitStatus != SYS_STATUS_SUCCESS) { print("shell: wait failed: "); printUInt(waitStatus); print("\n"); } print("Process exited with code: "); int exitCode; SysGetProcessExitCode(hProc, &exitCode); printInt(exitCode); const char* exitName = processExitStatusName((uint32_t)exitCode); if (exitName) { print(" (0x"); printHex32((uint32_t)exitCode); print(" "); print(exitName); print(")"); } print("\n"); SysCloseHandle(hProc); while (SysPollKeyboard()) (void)SysReadKey(); } } else { print("shell: launch failed\n"); } return 0; } // Runs the requested operation. 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(SHELL_PROMPT); if (readLine(lineBuf, MAX_CMD)) continue; char* cmd = trim(lineBuf); shellHistoryAdd(cmd); if (runCommand(cmd)) break; } print("shell: goodbye\n"); SysExitProcess(0); return 0; }