//----------------------------------------------------------------------------// // OS on Kaleid // // // // Desc: Kernel shell // // // // // // Copyright © 2018-2021 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include #include #include #include #include #include #include #include #include #include static Command_t testcmdtable[]; error_t CmdTest(int argc, char **argv, char *cmdline) { ExecuteCommand(cmdline+5, testcmdtable); KernLog ("\n"); return EOK; } error_t CmdArgs(int argc, char **argv, char *cmdline) { int i; KernLog("cmdline: '%s'\nargc: %d\n", cmdline, argc); for (i = 0; i < argc; i++) { KernLog("argv[%d]: '%s'\n", i, argv[i]); } return EOK; } error_t CmdAtoi(int argc, char **argv, char *cmdline) { int i; KernLog("cmdline: '%s'\nargc: %d\n", cmdline, argc); for (i = 0; i < argc; i++) { KernLog("argv[%d]: '%u'\n", i, atoi(argv[i])); } return EOK; } error_t CmdDumpATASect(int argc, char **argv, char *cmdline) { char sector[512] = {0}; int sectNumber = atoi(argv[1]); int nb = 1; //atoi(argv[2]); int x = 0; int step = 16; if (sectNumber <= 0 || sectNumber > 255) { KernLog("Bad argument\n\n"); return EINVAL; } if (!nb) nb = 1; KernLog("Sector begin: %d\n", (sectNumber - 1)*512); IoReadATA(sector, nb, sectNumber); while(x < 512*nb) { KernLog("%C", shcol); for (int i = 0; i < step; i++) { KernLog("%02x ", (uchar)sector[i+x]); } KernLog(" %C ", VGA_COLOR_LIGHT_BLUE); for (int i = 0; i < step; i++) { if (isprint(sector[i+x])) KernLog("%c", sector[i+x] ); else KernLog("%c", 0); } KernLog("\n"); x += step; } KernLog("\n\n"); return EOK; } error_t CmdFloatDiv(int argc, char **argv, char *cmdline) { double a = (double)atoi(argv[1]); double b = (double)atoi(argv[2]); double number = a / b; double number_ent = (double)(ulong)number; double dec = number - number_ent; double sub = 0.0; char res[17]; // 10e-16 is the max precision for(int i = 0; i < 16; i++) { dec = (dec * 10.0) - (sub * 10.0); sub = (double)(ulong)dec; snprintf(&res[i], 17-i, "%d", (ulong)dec); } KernLog("%d / %d = %d.%s \n", (ulong)a, (ulong)b, (ulong)number_ent, res); return EOK; } error_t CmdHelpTest(int argc, char **argv, char *cmdline) { uint i, count = 0; Command_t *cmd; if (argc == 1) { KernLog("List of all test built-ins:\n"); for (cmd = testcmdtable; cmd->name != NULL; cmd++, count++) { KernLog("\t%s", cmd->name); for (i = strlen(cmd->name)/4; i<3; i++) { KernLog("\t"); } KernLog("%C%s%C\n", VGA_COLOR_DARK_GREY, cmd->help, shcol); } KernLog("End of list; %u commands total\n", count); } return EOK; } error_t CmdPageTranslateVirtToPhy(int argc, char **argv, char *cmdline) { void *address = (void*)atoul(argv[1]); if (!(void*)strtoul(argv[1], NULL, 16)) { KernLog("No argument : translating the userspace address\n"); address = (void *)0x80000000; } void *translation = MmTransVirtToPhyAddr(address); KernLog("Translation of %p is %p\n", address, translation); return EOK; } error_t CmdPageTranslatePhyToVirt(int argc, char **argv, char *cmdline) { void *address = (void*)strtoul(argv[1], NULL, 16); /* if (!(void*)atoul(argv[1])) { */ /* address = (ulong *)0x80000000; */ /* } */ void *translation = MmTransPhyToVirtAddr(address); KernLog("Translation of %p is %p\n", address, translation); return EOK; } error_t CmdPageMap(int argc, char **argv, char *cmdline) { void *virtual = (void*)strtoul(argv[1], NULL, 16); void *physical = (void*)strtoul(argv[2], NULL, 16); MmMapPage(virtual, physical, PRESENT | READWRITE); return EOK; } error_t CmdPageUnmap(int argc, char **argv, char *cmdline) { void *virtual = (void*)strtoul(argv[1], NULL, 16); MmUnmapPage(virtual); return EOK; } error_t CmdPageAlloc(int argc, char **argv, char *cmdline) { if (argc != 4) { KernLog("Invalid arguments !\n"); return EINVAL; } size_t size = (size_t)atol(argv[1]); void *virtaddr = (void *)strtol(argv[2], NULL, 16); ulong flags = (ulong)atol(argv[3]); KernLog("Allocating %u o...\n", size); ulong id = MmAllocPageFrame(size, false); KernLog("Allocated with id : %lu\n", id); KernLog("Mapping pages id %d at %p (flags %#x)...\n", id, virtaddr, flags); error_t err = MmMapPageFrame(id, virtaddr, flags); if (err == EOK) KernLog("Successful mapped.\n"); else KernLog("Failed to map !\n"); return EOK; } error_t CmdPageFree(int argc, char **argv, char *cmdline) { if (argc != 2) { KernLog("Invalid arguments !\n"); return EINVAL; } ulong id = (ulong)atol(argv[1]); KernLog("Unmapping pages id %d...\n", id); error_t err = MmUnmapPageFrame(id); if (err == EOK) KernLog("Success unmaping.\n"); else { KernLog("Failed to unmap !\n"); return EFAILED; } KernLog("Freeing pages id %d...\n", id); MmFreePageFrame(id); return EOK; } error_t CmdPF(int argc, char **argv, char *cmdline) { register ulong *address = (ulong*)(ulong)strtoul(argv[1], NULL, 16); KernLog("Test provoking a fault at %p\n", address); KernLog("It contained %p\n", *address); *address = 1; KernLog("Now it contains %p\n", *address); KernLog("No page fault : address was valid/present\n"); return EOK; } extern void pstest(void); error_t CmdPS(int argc, char **argv, char *cmdline) { pstest(); return EOK; } error_t CmdShell(int argc, char **argv, char *cmdline) { ShStartShell(); return EOK; } error_t CmdStackOverflow(int argc, char **argv, char *cmdline) { CmdStackOverflow(0, 0, 0); return EOK; } error_t CmdStackUnderflow(int argc, char **argv, char *cmdline) { for (int i = 0 ;; i++) { asm volatile ("pop %rax\n"); } return EOK; } error_t CmdTimerTest(int argc, char **argv, char *cmdline) { int delay = atoi(argv[1]); Timer_t *timer = KeSetTimer(delay); while(!(KeGetTimer(timer))) { bprintf(BStdOut,"."); BStdOut->flusher(BStdOut); } KernLog("Finished !\n"); return EOK; } error_t CmdSyscallTest(int argc, char **argv, char *cmdline) { if (argc != 2) { KernLog("Invalid arguments !\n"); return EINVAL; } ulong code = (ulong)atol(argv[1]); error_t err = KeSyscall(code); KernLog("Exit : %s\n", strerror(err)); return err; } error_t CmdRing3Test(int argc, char **argv, char *cmdline) { size_t size = 1*KPAGESIZE; void *entryPoint = (void*)USERSPACE; ulong flags = PRESENT | READWRITE | USERMODE; KernLog("Allocating %u o...\n", size); ulong id = MmAllocPageFrame(size, false); KernLog("Allocated with id : %lu\n", id); KernLog("Mapping pages id %d at %p (flags %#x)...\n", id, entryPoint, flags); error_t err = MmMapPageFrame(id, entryPoint, flags); if (err == EOK) KernLog("Successfully mapped.\n"); else { KernLog("Failed to map !\n"); return ENOMEM; } size = 1*KPAGESIZE; void *stackAddr = (void*)USERSPACE + 4*KPAGESIZE; flags = PRESENT | READWRITE | USERMODE; KernLog("Allocating %u o...\n", size); id = MmAllocPageFrame(size, false); KernLog("Allocated with id : %lu\n", id); KernLog("Mapping pages id %d at %p (flags %#x)...\n", id, stackAddr, flags); err = MmMapPageFrame(id, stackAddr, flags); if (err == EOK) KernLog("Successfully mapped.\n"); else { KernLog("Failed to map !\n"); return ENOMEM; } KernLog("Entrypoint : %p, stack address : %p\n", entryPoint, stackAddr+size); extern void UserTest(); memmove(entryPoint, UserTest, KPAGESIZE); KeJumpToUserspace(0, entryPoint, stackAddr+size); return EOK; } static Command_t testcmdtable[] = { { "args", CmdArgs, "Print command line" }, { "atoi", CmdAtoi, "Print command line atoised" }, { "dmpsec", CmdDumpATASect, "Dump an ATA sector on screen" }, { "help", CmdHelpTest, "Show this message" }, { "div", CmdFloatDiv, "Float div. Usage : div a b. Returns a/b"}, { "transvtp", CmdPageTranslateVirtToPhy, "Translate a virtual to" " physical address (paging)"}, { "transptv", CmdPageTranslatePhyToVirt, "Translate a physical to" " virtual address (paging)"}, { "pmap", CmdPageMap, "Map a page to given physical addr" }, { "punmap", CmdPageUnmap, "Unmap a page" }, { "palloc", CmdPageAlloc, "Alloc x B of pages at y address" "with z flags"}, { "pfree", CmdPageFree, "Free a page block of id x" }, { "pf", CmdPF, "Provoke a PF. Usage: pfault
"}, { "ps", CmdPS, "Scheduler algorithm test" }, { "ring3", CmdRing3Test, "Jump to a userspace function" }, { "shell", CmdShell, "Start a new shell (nested)", }, { "stkov", CmdStackOverflow, "Provoke a stack overflow" }, { "stkun", CmdStackUnderflow, "Provoke a stack underflow" }, { "syscall", CmdSyscallTest, "Trigger a system call" }, { "timer", CmdTimerTest, "test timer of x ms" }, { NULL, NULL, NULL } };