From fafae757e107d7924f14557d4b0b0f529acee72b Mon Sep 17 00:00:00 2001 From: Xnoe Date: Wed, 8 Jan 2025 18:46:58 +0000 Subject: [PATCH] Miscellaneous changes and fixed (I think?) virtual 8086 mode --- .vscode/settings.json | 5 + Makefile | 2 +- src/bootstage2/atapio.c | 8 +- src/bootstage2/main.c | 26 +- src/bootstage2/paging.h | 1 + src/c_code_entry.asm | 1 + src/common/common.c | 111 +++++++- src/common/common.h | 10 + src/common/syscalls.h | 10 +- src/kernel/ata.cpp | 8 +- src/kernel/ata.h | 4 +- src/kernel/datatypes/dynarray.h | 8 + src/kernel/datatypes/hashtable.h | 3 +- src/kernel/filesystem/devfs.cpp | 2 +- src/kernel/filesystem/fat16.cpp | 16 +- src/kernel/filesystem/fat16.h | 6 +- src/kernel/filesystem/fstree.cpp | 12 +- src/kernel/filesystem/sysfs.cpp | 8 +- src/kernel/filesystem/vfs.cpp | 2 +- src/kernel/idt.cpp | 178 +++++++------ src/kernel/idt.h | 32 +-- src/kernel/isr.S.base | 84 +++--- src/kernel/kernel.cpp | 108 ++++++-- src/kernel/kernel.h | 12 +- src/kernel/kmain.cpp | 18 +- src/kernel/process.cpp | 178 +++++++++++-- src/kernel/process.h | 60 ++++- src/kernel/stdio/circularrwbuffer.cpp | 10 +- src/kernel/stdio/circularrwbuffer.h | 3 +- src/kernel/stdio/oneshotreadwriter.cpp | 2 +- src/kernel/stdio/oneshotreadwriter.h | 2 +- src/kernel/stdio/readwriter.cpp | 44 +--- src/kernel/stdio/readwriter.h | 15 +- src/kernel/terminal.cpp | 24 +- src/kernel/terminal.h | 10 +- src/programs/cat/main.c | 17 ++ src/programs/crash/crash.c | 4 - src/programs/echo/main.c | 7 + src/programs/entry.asm | 5 +- src/programs/forktest/main.c | 10 + src/programs/hello/hello.c | 42 --- src/programs/init/main.c | 21 ++ src/programs/listenvp/main.c | 8 + src/programs/ls/main.c | 35 +++ src/programs/timer/timer.c | 16 -- src/programs/world/world.c | 340 ------------------------- src/programs/xosh/main.c | 107 ++++++++ 47 files changed, 908 insertions(+), 727 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/programs/cat/main.c delete mode 100644 src/programs/crash/crash.c create mode 100644 src/programs/echo/main.c create mode 100644 src/programs/forktest/main.c delete mode 100644 src/programs/hello/hello.c create mode 100644 src/programs/init/main.c create mode 100644 src/programs/listenvp/main.c create mode 100644 src/programs/ls/main.c delete mode 100644 src/programs/timer/timer.c delete mode 100644 src/programs/world/world.c create mode 100644 src/programs/xosh/main.c diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1428c38 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "random": "cpp" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index f5751de..56131da 100644 --- a/Makefile +++ b/Makefile @@ -96,4 +96,4 @@ src/kernel/isr.S: src/kernel/isr.S.base src/kernel/gen_isr_asm.sh .SECONDEXPANSION: build/programs/%.bin: src/programs/userspace.ld build/programs/entry.o $$(src/programs/$$(basename $$(notdir $$*))_OBJS) $(PROGRAM_COMMON) - ld -o $@ -T $^ \ No newline at end of file + ld -o $@ -T $^ diff --git a/src/bootstage2/atapio.c b/src/bootstage2/atapio.c index c6e7745..edb6e88 100644 --- a/src/bootstage2/atapio.c +++ b/src/bootstage2/atapio.c @@ -11,8 +11,8 @@ uint16_t identify_result[256]; uint32_t total_28_lbas = 0; -uint8_t* rootDirEntries = 0x1000000; -uint16_t* FAT1 = 0x1002000; +uint8_t* rootDirEntries = (uint8_t*)0x1000000; +uint16_t* FAT1 = (uint16_t*)0x1002000; uint16_t countReserved; uint8_t countFATs; @@ -60,7 +60,7 @@ void init_atapio() { // We've initialised now, let's load the FAT and RootDirEntries. read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, rootDirEntries); - read_sectors(countReserved, sectorsPerFAT, FAT1); + read_sectors(countReserved, sectorsPerFAT, (uint8_t*)FAT1); } void read_sector(uint32_t address, uint8_t* buffer) { @@ -95,7 +95,7 @@ uint16_t file_exists(char* filename) { for (int i=0; i= 0x30 && c <= 0x39; +} + void printf(const char* string, ...) { va_list ptr; va_start(ptr, string); @@ -68,23 +129,48 @@ void printf(const char* string, ...) { while (current=string[index++]) { if (current == '%') { + uint32_t width = 0; + bool lp = false; + if (string[index] == '.') { + lp = true; + index++; + } else { + while (isnum(string[index])) { + width *= 10; + width += string[index] - 0x30; + index++; + } + } int type = string[index++]; int offset; switch (type) { case 'd': { char decimal_buffer[11]; offset = int_to_decimal(va_arg(ptr, int), decimal_buffer); - printf(decimal_buffer + offset); + print(decimal_buffer + offset); break; } case 'x': { char hex_buffer[8]; offset = int_to_hex(va_arg(ptr, int), hex_buffer); - printf(hex_buffer); + print(hex_buffer); break; } case 's': { - printf(va_arg(ptr, const char*)); + if (width) { + char s[width+1]; + s[width] = 0; + memcpy(s, va_arg(ptr, const char*), width); + print(s); + } else if (lp) { + int width = va_arg(ptr, int); + char s[width+1]; + s[width] = 0; + memcpy(s, va_arg(ptr, const char*), width); + print(s); + } else { + print(va_arg(ptr, const char*)); + } break; } case 'c': { @@ -102,4 +188,23 @@ void printf(const char* string, ...) { } va_end(ptr); +} + +void memset(void* ptr, char c, uint32_t count) { + for (int i=0; icurrentPosition = 0; } @@ -166,4 +165,5 @@ uint32_t ATAReadWriter::size() { } uint32_t ATAReadWriter::seek(uint32_t position) { this->currentPosition = position; -} \ No newline at end of file + return position; +} diff --git a/src/kernel/ata.h b/src/kernel/ata.h index f54df00..026ab60 100644 --- a/src/kernel/ata.h +++ b/src/kernel/ata.h @@ -99,7 +99,7 @@ private: Spinlock driveLock; public: - ATAReadWriter(uint32_t owner, uint32_t bus); + ATAReadWriter(uint32_t bus); uint32_t read(uint32_t count, uint8_t* buffer) override; uint32_t write(uint32_t count, uint8_t* buffer) override; @@ -107,4 +107,4 @@ public: uint32_t seek(uint32_t position) override; }; -#endif \ No newline at end of file +#endif diff --git a/src/kernel/datatypes/dynarray.h b/src/kernel/datatypes/dynarray.h index 72715ca..71ed7c7 100644 --- a/src/kernel/datatypes/dynarray.h +++ b/src/kernel/datatypes/dynarray.h @@ -21,6 +21,14 @@ namespace xnoe { this->index = this->start_index = start_index; } + dynarray(dynarray* d) { + this->size = d->size; + this->buffer = new T[size]; + this->index = d->index; + this->start_index = d->start_index; + memcpy((uint8_t*)this->buffer, (uint8_t*)d->buffer, sizeof(T)*d->size); + } + void push(T t) { if (index == size) { lock.lock(); diff --git a/src/kernel/datatypes/hashtable.h b/src/kernel/datatypes/hashtable.h index 5ab3659..33a4d98 100644 --- a/src/kernel/datatypes/hashtable.h +++ b/src/kernel/datatypes/hashtable.h @@ -59,11 +59,12 @@ namespace xnoe { xnoe::linkedlistelem>* current = list->start; if (current) { while (current) { + xnoe::linkedlistelem>* next = current->next; if (xnoe::get<0>(current->elem) == k) { list->remove(current); delete current; } - current = current->next; + current = next; } } } diff --git a/src/kernel/filesystem/devfs.cpp b/src/kernel/filesystem/devfs.cpp index 883ab8b..16fd304 100644 --- a/src/kernel/filesystem/devfs.cpp +++ b/src/kernel/filesystem/devfs.cpp @@ -1,5 +1,5 @@ #include "devfs.h" DevFS::DevFS() { - addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0,0);}); + addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0);}); } \ No newline at end of file diff --git a/src/kernel/filesystem/fat16.cpp b/src/kernel/filesystem/fat16.cpp index 95cb7f7..c0e01c4 100644 --- a/src/kernel/filesystem/fat16.cpp +++ b/src/kernel/filesystem/fat16.cpp @@ -11,8 +11,7 @@ uint32_t FAT16FileReadWriter::offsetBytesToCluster(uint32_t offset) { return cluster; } -FAT16FileReadWriter::FAT16FileReadWriter(uint32_t owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS) -: ReadWriter(owner) { +FAT16FileReadWriter::FAT16FileReadWriter(uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS) { this->firstCluster = firstCluster; this->sizeBytes = sizeBytes; this->currentPosition = 0; @@ -55,7 +54,7 @@ uint32_t FAT16FileReadWriter::read(uint32_t count, uint8_t* buffer) { return index; } -uint32_t FAT16FileReadWriter::write(uint32_t count, uint8_t* buffer) {} +uint32_t FAT16FileReadWriter::write(uint32_t count, uint8_t* buffer) {return;} uint32_t FAT16FileReadWriter::size() { return this->sizeBytes; @@ -78,7 +77,7 @@ char safeUppercase(char c) { } } -bool FAT16FS::pathEntryTo83(PathEntry pe, char* buffer) { +void FAT16FS::pathEntryTo83(PathEntry pe, char* buffer) { uint32_t maxSize = pe.length; uint8_t* data = pe.path; @@ -244,7 +243,8 @@ bool FAT16FS::exists(Path p) { if (!end) return false; - char name83[11] = {' '}; + char name83[12] = " "; + name83[11] = 0; pathEntryTo83(end->elem, name83); for (int i=0; ielem, name83); for (int i=0; iphys->remainingPages; char str[11]; uint32_t offset = int_to_decimal(remainingPages, str); - return new OneShotReadWriter(0, str+offset); + return new OneShotReadWriter(str+offset); }); addEntry(createPathFromString("initPages"), [](){ uint32_t initPages = Global::kernel->phys->initPages; char str[11]; uint32_t offset = int_to_decimal(initPages, str); - return new OneShotReadWriter(0, str+offset); + return new OneShotReadWriter(str+offset); }); addEntry(createPathFromString("terminalWidth"), [](){ uint32_t termWidth = Global::kernel->terminal->width; char str[11]; uint32_t offset = int_to_decimal(termWidth, str); - return new OneShotReadWriter(0, str+offset); + return new OneShotReadWriter(str+offset); }); addEntry(createPathFromString("terminalHeight"), [](){ uint32_t termHeight = Global::kernel->terminal->height; char str[11]; uint32_t offset = int_to_decimal(termHeight, str); - return new OneShotReadWriter(0, str+offset); + return new OneShotReadWriter(str+offset); }); } \ No newline at end of file diff --git a/src/kernel/filesystem/vfs.cpp b/src/kernel/filesystem/vfs.cpp index 940ca3c..cf47f20 100644 --- a/src/kernel/filesystem/vfs.cpp +++ b/src/kernel/filesystem/vfs.cpp @@ -80,7 +80,7 @@ nextPE: } bool VFS::exists(Path p) { - return false; + return getEntry(p); } ReadWriter* VFS::open(Path p) { diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index 63beafd..28a131d 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -22,39 +22,42 @@ void set_entry(uint8_t interrupt_number, uint16_t code_segment, void(*handler)() } void handle_fault(frame_struct* frame) { + //frame_struct* frame = &Global::currentThread->frame; // Clear interrupts, we don't want to perform a context switch whilst handling a fault. asm ("cli"); uint32_t problem_address; asm ("mov %%cr2, %0" : "=a" (problem_address):); - /*Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip);*/ + Global::kernel->terminal->printf("\x1b[44;37;1m(CS %x EIP %x): ", frame->cs, frame->eip); switch (frame->gate) { case 0: // Divide by zero - //Global::kernel->terminal->printf("Divide by Zero"); + Global::kernel->terminal->printf("Divide by Zero"); break; case 6: // Invalid Opcode - //Global::kernel->terminal->printf("Invalid Opcode"); + Global::kernel->terminal->printf("Invalid Opcode"); break; case 13: // GPF - //Global::kernel->terminal->printf("General Protection Fault!"); + Global::kernel->terminal->printf("General Protection Fault!"); if (frame->eflags & 0x00020000) { + Global::kernel->terminal->printf("\x1b[42;37;1mv86 GPF! All is good!\n"); v86_monitor((v8086_frame_struct*)frame); return; } break; case 14: // Page Fault - //Global::kernel->terminal->printf("Page Fault at %x", problem_address); + Global::kernel->terminal->printf("Page Fault at %x", problem_address); break; default: - //Global::kernel->terminal->printf("Unkown Fault!"); + Global::kernel->terminal->printf("Unkown Fault! Gate: %d", frame->gate); break; } - /*Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);*/ + Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode); if (!(frame->cs & 3)) { Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n"); + ((VGAModeTerminal*)Global::kernel->terminal)->bufferToVRAM(); while (1) asm("hlt"); } else { // Print an error message. - //Global::kernel->terminal->printf("PID %d Terminated due to fault!\n", Global::currentProc->PID); + Global::kernel->terminal->printf("PID %d Terminated due to fault!\n", Global::currentProc->PID); asm volatile ("mov %0, %%esp" ::"m"(Global::kernel->globalISRStack)); Global::kernel->PD->select(); @@ -62,13 +65,14 @@ void handle_fault(frame_struct* frame) { Global::kernel->destroyProcess(Global::currentProc); Global::currentProcValid = false; - context_switch(frame); + context_switch(); } } -void ignore_interrupt(frame_struct* frame) {} +void ignore_interrupt(frame_struct* _) {} -void context_switch(frame_struct* frame) { +void context_switch() { + frame_struct* frame = &Global::currentThread->frame; // When any interrupt occurs (including context_switch), SS:ESP is set to // the values of SS0:ESP0 in Global::tss // @@ -90,9 +94,6 @@ void context_switch(frame_struct* frame) { Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n"); while (1) asm ("hlt"); } - - if (Global::currentProcValid) - Global::currentThread->kernelStackPtr = frame->new_esp; // This cursed bit of code first determines if the processes list is longer than 1 and if it is // - Determines if it has 2 or more elements @@ -128,13 +129,10 @@ void context_switch(frame_struct* frame) { Global::currentProc = threads->start->elem->parent; } while (Global::currentThread->state != Running); - // Select the next processes page directory - frame->new_cr3 = Global::currentThread->parent->PD->phys_addr; - // Restore kernelStackPtr of the new process. - frame->new_esp = Global::currentThread->kernelStackPtr; + Global::currentThread->frame.new_cr3 = Global::currentThread->parent->PD->phys_addr; - Global::tss->esp0 = Global::currentThread->kernelStackPtrDefault; + Global::tss->esp0 = (uint32_t)Global::currentThread->kernelStackPtrDefault; // Set the current proc to valid Global::currentProcValid = true; @@ -142,15 +140,15 @@ void context_switch(frame_struct* frame) { namespace Timer { // counter, default count, function, argument, oneshot - using TimedEvent = xnoe::tuple; + using TimedEvent = xnoe::tuple; xnoe::linkedlist timed_events; - void tick(frame_struct* frame) { + void tick(frame_struct* _) { xnoe::linkedlistelem* current = timed_events.start; while (current) { TimedEvent t = current->elem; uint32_t count = xnoe::get<0>(t); if (--count == 0) { - xnoe::get<2>(t)(frame, xnoe::get<3>(t)); + xnoe::get<2>(t)(xnoe::get<3>(t)); count = xnoe::get<1>(t); if (xnoe::get<4>(t)) { @@ -167,16 +165,16 @@ namespace Timer { Global::milliseconds_elapsed++; } - void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary, bool oneshot=false) { + void register_event(uint32_t milliseconds, void(*function)(void*), void* auxiliary, bool oneshot=false) { timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary, oneshot)); } } -void awaken(frame_struct* frame, Thread* t) { +void awaken(Thread* t) { t->state = Running; } -void syscall(frame_struct* frame) { +void syscall(frame_struct* _) { // Syscall ABI: // 0: getDentsSize :: char* path -> uint32_t size // 1: getDents :: char* path -> uint8_t* buffer -> void @@ -214,87 +212,93 @@ void syscall(frame_struct* frame) { // 2..7: Reserved // _: General use - uint32_t rval = frame->eax; + frame_struct* frame = &Global::currentThread->frame; Process* currentProc = Global::currentProc; switch (frame->eax) { case 0: // getDentsSize - rval = Global::kernel->rootfs->getDentsSize(createPathFromString(frame->ebx)); + frame->eax = Global::kernel->rootfs->getDentsSize(createPathFromString((char*)frame->ebx)); break; case 1: // getDents - Global::kernel->rootfs->getDents(createPathFromString(frame->ebx), frame->ecx); + Global::kernel->rootfs->getDents(createPathFromString((char*)frame->ebx), (FSDirectoryListing*)frame->ecx); break; case 2: // exists - rval = Global::kernel->rootfs->exists(createPathFromString(frame->ebx)); + frame->eax = Global::kernel->rootfs->exists(createPathFromString((char*)frame->ebx)); break; case 3: // type - rval = Global::kernel->rootfs->type(createPathFromString(frame->ebx)); + frame->eax = Global::kernel->rootfs->type(createPathFromString((char*)frame->ebx)); break; case 4: // malloc - rval = currentProc->allocate(frame->ebx); + frame->eax = (uint32_t)currentProc->allocate(frame->ebx); break; case 5: // free currentProc->deallocate(frame->ebx); break; case 6: // getMillisecondsElapsed - rval = Global::milliseconds_elapsed; + frame->eax = Global::milliseconds_elapsed; break; - case 7: { // exec + + case 7: {// execve asm("cli"); xnoe::maybe file = Global::currentProc->getFH(frame->ebx); if (file.is_ok()) { - Process* p = Global::kernel->createProcess(file.get()); - rval = p->PID; + Process* p = Global::kernel->createProcess(file.get(), (uint8_t**)frame->ecx, (uint8_t**)frame->edx); + + // Suspend the current thread and forward the current process's stdin and stdout to the new one. + Global::currentThread->state = Suspended; + p->stdin = Global::currentProc->stdin; + p->stdout = Global::currentProc->stdout; + p->threads.start->elem->suspending = Global::currentThread->TID; + context_switch(); } else { - rval = 0; + frame->eax = 0; } asm("sti"); break; } + case 8: // getPID - rval = currentProc->PID; + frame->eax = currentProc->PID; break; - case 9: // die + case 9: { // die Global::kernel->PD->select(); - - // We can now safely delete the current process - Global::kernel->destroyProcess(Global::currentProc); - + Global::kernel->destroyProcess(Global::currentProc, frame->ebx); Global::currentProcValid = false; - context_switch(frame); - break; + context_switch(); + return; + } case 10: { // read xnoe::maybe fh = Global::currentProc->getFH(frame->ecx); if (!fh.is_ok()) { - rval = 0; + frame->eax = 0; break; } ReadWriter* rw = fh.get(); - rval = rw->read(frame->ebx, frame->edx); + frame->eax = rw->read(frame->ebx, (uint8_t*)frame->edx); break; } case 11: { // write xnoe::maybe fh = Global::currentProc->getFH(frame->ecx); if (!fh.is_ok()) { - rval = 0; + frame->eax = 0; break; } ReadWriter* rw = fh.get(); - rval = rw->write(frame->ebx, frame->edx); + frame->eax = rw->write(frame->ebx, (uint8_t*)frame->edx); break; } case 12: // bindToKeyboard if (currentProc->stdin) - break; + currentProc->stdin->close(); - currentProc->stdin = new CircularRWBuffer(currentProc->PID, 0); + currentProc->stdin = new CircularRWBuffer(); Global::kernel->KBListeners.append(currentProc); break; @@ -303,11 +307,12 @@ void syscall(frame_struct* frame) { if (!pm.is_ok()) break; Process* p = pm.get(); - if (!p->stdout) { - ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx); - p->stdout = buffer; - rval = Global::currentProc->mapFH(buffer); - } + //if (!p->stdout) { + //ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx); + //p->stdout = buffer; + p->stdout->open(); + frame->eax = Global::currentProc->mapFH(p->stdout); + //} break; } @@ -316,25 +321,26 @@ void syscall(frame_struct* frame) { if (!pm.is_ok()) break; Process* p = pm.get(); - if (!p->stdin) { - ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID); - p->stdin = buffer; - rval = Global::currentProc->mapFH(buffer); - } + //if (!p->stdin) { + //ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID); + //p->stdin = buffer; + p->stdin->open(); + frame->eax = Global::currentProc->mapFH(p->stdin); + //} break; } case 15: { // fopen - ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(frame->ebx)); + ReadWriter* file = Global::kernel->rootfs->open(createPathFromString((char*)frame->ebx)); if (file) - rval = Global::currentProc->mapFH(file); + frame->eax = Global::currentProc->mapFH(file); break; } case 16: { // fclose xnoe::maybe f = Global::currentProc->getFH(frame->ebx); if (f.is_ok()) { - delete f.get(); + f.get()->close(); Global::currentProc->unmapFH(frame->ebx); } break; @@ -353,46 +359,62 @@ void syscall(frame_struct* frame) { case 18: { // sleep Global::currentThread->state = Suspended; - Timer::register_event(frame->ebx, &awaken, (void*)Global::currentThread, true); - context_switch(frame); + Timer::register_event(frame->ebx, (void(*)(void*))&awaken, (void*)Global::currentThread, true); + context_switch(); break; } case 19: // getRemainingPages - rval = Global::kernel->phys->remainingPages; + frame->eax = Global::kernel->phys->remainingPages; break; case 20: // getInitPages - rval = Global::kernel->phys->initPages; + frame->eax = Global::kernel->phys->initPages; break; case 21: // getTerminalWidth - rval = Global::kernel->terminal->width; + frame->eax = Global::kernel->terminal->width; break; case 22: // getTerminalHeight - rval = Global::kernel->terminal->height; + frame->eax = Global::kernel->terminal->height; break; case 23: { // getProcessState xnoe::maybe p = Global::kernel->pid_map->get(frame->ebx); if (p.is_ok()) { Process* proc = p.get(); - //rval = proc->state; + //frame->eax = proc->state; } break; } - case 24: { // Spawn Thread + case 25: { // fork + Process* p = new Process(Global::currentProc); + Thread* t = new Thread(Global::currentThread, p); + t->parent = p; + p->threads.append(t); + Global::kernel->registerThread(t); + Global::kernel->registerProcess(p); + frame->eax = p->PID; + t->frame.eax = 0; + break; + } + + case 24: { // spawnThread Thread* thread = new Thread(Global::currentProc); - thread->initKernelStack(frame->ebx, thread->stack); - Global::kernel->threads.append(thread); + thread->initKernelStack((void*)frame->ebx, thread->stack); + Global::kernel->registerThread(thread); + break; + } + + case 26: {// programRunning + xnoe::maybe p = Global::kernel->pid_map->get(frame->ebx); + frame->eax = p.is_ok(); break; } default: break; } - - frame->eax = rval; } void v86_monitor(v8086_frame_struct* frame) { @@ -428,7 +450,7 @@ void v86_monitor(v8086_frame_struct* frame) { } case 0xcf: { // Handle iret - frame->eip = *(sp++); + frame->eip = *(sp++) + 2; frame->cs = *(sp++); frame->eflags &= 0xffff0000; frame->eflags |= *(sp++); @@ -446,7 +468,7 @@ void v86_monitor(v8086_frame_struct* frame) { break; } } - frame->esp = sp; + frame->esp = (uint16_t)sp; } void init_idt() { @@ -499,7 +521,7 @@ void init_idt() { outb(0x40, _counter[0]); outb(0x40, _counter[1]); - Timer::register_event(30, &context_switch, 0); + Timer::register_event(30, (void(*)(void*))&context_switch, 0); } void enable_idt() { diff --git a/src/kernel/idt.h b/src/kernel/idt.h index c61d94c..26367e8 100644 --- a/src/kernel/idt.h +++ b/src/kernel/idt.h @@ -7,32 +7,6 @@ #include "gdt.h" #include "stdio/circularrwbuffer.h" -struct __attribute__((packed)) frame_struct { - uint32_t new_cr3; - uint32_t new_esp; - - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t oesp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - - uint32_t gate; - uint32_t __ignored2; - uint32_t errcode; - - uint32_t eip; - uint16_t cs; - uint16_t _ignored0; - uint32_t eflags; - uint32_t esp; - uint16_t ss; - uint16_t _ignored1; -}; - struct __attribute__((packed)) v8086_frame_struct { uint32_t new_cr3; uint32_t new_esp; @@ -90,10 +64,10 @@ struct __attribute__((packed)) idt_desc { uint32_t offset; }; -void context_switch(frame_struct* frame); +void context_switch(); void handle_fault(frame_struct* frame); -void syscall(frame_struct* frame); -void ignore_interrupt(frame_struct* frame); +void syscall(); +void ignore_interrupt(); void v86_monitor(v8086_frame_struct* frame); #endif \ No newline at end of file diff --git a/src/kernel/isr.S.base b/src/kernel/isr.S.base index 3a5c3c5..3c8cc14 100644 --- a/src/kernel/isr.S.base +++ b/src/kernel/isr.S.base @@ -6,64 +6,72 @@ global catchall_return catchall: ; At this point the gate number has been pushed to the stack pushad - - push esp - sub esp, 4 - push eax mov eax, cr3 - mov [esp+4], eax - pop eax + push eax + push 0 ; Pushed 40 bytes mov eax, [esp+40] mov ebx, gates mov eax, [ebx+4*eax] + + ; Check if we came from Ring 3 + movzx ecx, word [esp+56] + and ecx, 3 + cmp ecx, 3 + jne no_copy + + mov ecx, 72 + mov esi, esp + mov edi, [_ZN6Global13currentThreadE] + rep movsb + mov ecx, [_ZN6Global13currentThreadE] + push ecx + jmp call +no_copy: push esp + jmp call +call: + ; Increment the current thread's count + mov ecx, [_ZN6Global13currentThreadE] + mov edx, [ecx] + add edx, 1 + mov [ecx], edx + call eax catchall_return: add esp, 4 - push 0x20 push 0x20 call outb add esp, 8 - push eax - mov eax, [esp+4] - mov cr3, eax - pop eax + ; Decrement and check the current thread's count + + mov ecx, [_ZN6Global13currentThreadE] + mov edx, [ecx] + sub edx, 1 + mov [ecx], edx + cmp edx, 0 + jne skip_copying + + sub esp, 72 + mov ecx, 72 + mov esi, [_ZN6Global13currentThreadE] + mov edi, esp + rep movsb + +skip_copying: add esp, 4 - pop esp + pop eax + mov cr3, eax popad - - mov esp, ebp + add esp, 8 pop ebp iret extern gates ; (void(*)(frame_struct))* -extern outb - -; struct frame_struct __attribute__((packed)) { -; popad -; uint32_t edi; -; uint32_t esi; -; uint32_t ebp; -; uint32_t esp; -; uint32_t ebx; -; uint32_t edx; -; uint32_t ecx; -; uint32_t eax; -; -; interrupt -; uint32_t eip; -; uint32_t cs; -; uint32_t eflags; -; uint32_t esp; -; uint32_t ss; -; -; if it's an error -; uint32_t err_code; -; } - +extern outb +extern _ZN6Global13currentThreadE diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 73c7894..13ce7bd 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -1,13 +1,12 @@ #include "kernel.h" Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack) - : Process(0, 0x8a000, page_directory, phys, virt, virt_alloc_base) + : Process(0x8a000, page_directory, phys, virt, virt_alloc_base) { - this->currentPID = 1; Global::allocator = this; Global::kernel = this; - Global::currentProc = 0; + Global::currentProc = this; this->stack = stack; @@ -16,38 +15,117 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint void Kernel::init_kernel() { this->pid_map = new xnoe::hashtable(); + this->tid_map = new xnoe::hashtable(); this->globalISRStack = (new uint8_t[0x8000]) + 0x8000; + Global::currentThread = new Thread(this); + Global::currentThread->frame.count++; } -Process* Kernel::createProcess(ReadWriter* file) { - char* name = "test"; - Process* p = new Process(currentPID, this->PD, 0xc0000000, file, 1, &name); - this->pid_map->set(currentPID, p); - currentPID++; +Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp) { + // argv is currently stored on the stack of the calling process + // We need to create a copy of it in the kernel stack for createProcess - this->threads.append(p->threads.start->elem); + // Determine the length of argv (null terminated) + uint32_t argc = 0; + for (int i=0; argv[i]; i++) + argc++; + + // Determine the length of all stings under argv + + uint32_t argv_strings_length = 0; + for (int i=0; iPD, 0xc0000000, file, argc, argv_new, envc, envp_new); + this->pid_map->set(p->PID, p); + + registerThread(p->threads.start->elem); return p; } -Process* Kernel::createProcess(ReadWriter* file, ReadWriter* stdout) { - Process* p = this->createProcess(file); +Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout) { + char* zero = 0; + Process* p = this->createProcess(file, argv, &zero); p->stdout = stdout; return p; } -void Kernel::destroyProcess(Process* p) { - if (Global::currentProc == p) - Global::currentProcValid = false; +void Kernel::registerProcess(Process* p) { + this->pid_map->set(p->PID, p); +} + +void Kernel::destroyProcess(Process* p, uint32_t exit_code) { xnoe::linkedlistelem* currentThread = p->threads.start; while (currentThread) { - this->threads.remove(currentThread->elem); + destroyThread(currentThread->elem, exit_code); currentThread = currentThread->next; } this->pid_map->remove(p->PID); delete p; } +void Kernel::registerThread(Thread* t) { + this->threads.append(t); + this->tid_map->set(t->TID, t); +} + +void Kernel::destroyThread(Thread* t, uint32_t exit_code) { + this->tid_map->remove(t->TID); + t->parent->threads.remove(t); + this->threads.remove(t); + + if (t->suspending) { + xnoe::maybe ts = this->tid_map->get(t->suspending); + if (ts.is_ok()) { + Thread* st = ts.get(); + st->state = Running; + st->frame.eax = exit_code; + } + } + + delete t; +} + void Kernel::v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn) { // Create the payload to perform an interrupt. uint8_t payload[21] = { diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index 16f8997..c1bb64a 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -12,12 +12,12 @@ class Kernel : public Process { private: int lastFH; public: - uint32_t currentPID; uint32_t stack; uint32_t globalISRStack; Terminal* terminal; xnoe::hashtable* pid_map; // Map of PIDs -> Process*s + xnoe::hashtable* tid_map; // Map of TIDs -> Thread*s xnoe::linkedlist processes; xnoe::linkedlist KBListeners; @@ -28,9 +28,13 @@ public: void init_kernel(); - Process* createProcess(ReadWriter* file); - Process* createProcess(ReadWriter* file, ReadWriter* stdout); - void destroyProcess(Process* p); + Process* createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp); + Process* createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout); + void registerProcess(Process* p); + void destroyProcess(Process* p, uint32_t exit_code=0); + + void registerThread(Thread* t); + void destroyThread(Thread* t, uint32_t exit_code=0); void v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn); }; diff --git a/src/kernel/kmain.cpp b/src/kernel/kmain.cpp index 0f445d7..098b878 100644 --- a/src/kernel/kmain.cpp +++ b/src/kernel/kmain.cpp @@ -51,19 +51,27 @@ int main(KernelInformationStruct kstruct) { term->activate(); term->clear_screen(); + /*kernel.v86( + 0x4F00, + 0, + 0, + 0, + 0, + 0x10 + );*/ + term->printf("Hello, World!\n\nWe are running XnoeOS Code in C++ now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n"); term->printf("KERNEL OK!\n"); - ReadWriter* atareadwriter = new ATAReadWriter(0, 0); - kernel.rootfs = new RootFSTree(); kernel.rootfs->mount(createPathFromString("/dev"), new DevFS()); kernel.rootfs->mount(createPathFromString("/sys"), new SysFS()); kernel.rootfs->mount(createPathFromString("/"), new FAT16FS(kernel.rootfs->open(createPathFromString("/dev/ata")))); - ReadWriter* worldbin = kernel.rootfs->open(createPathFromString("/world.bin")); + ReadWriter* init = kernel.rootfs->open(createPathFromString("/init.bin")); - Process* p1 = kernel.createProcess(worldbin, term); + char* zero = 0; + Process* p1 = kernel.createProcess(init, &zero, term); Global::tss->esp0 = (new uint8_t[8192]) + 8192; @@ -71,4 +79,4 @@ int main(KernelInformationStruct kstruct) { enable_idt(); while (1) asm ("hlt"); -} \ No newline at end of file +} diff --git a/src/kernel/process.cpp b/src/kernel/process.cpp index 99df2f2..25c9973 100644 --- a/src/kernel/process.cpp +++ b/src/kernel/process.cpp @@ -3,6 +3,7 @@ extern void(*catchall_return)(); AllocTracker::AllocTracker(void* base, uint32_t size, uint32_t count) : page_base(base), page_size(size), alloc_count(count) {} +AllocTracker::AllocTracker() {} xnoe::maybe*> Process::get_alloc_tracker(uint32_t address) { xnoe::linkedlistelem* current = this->allocations.start; @@ -16,27 +17,29 @@ xnoe::maybe*> Process::get_alloc_tracker(uint return xnoe::maybe*>(); } -Process::Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base) +uint32_t Process::currentPID = 0; + +Process::Process(void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base) : Allocator(page_directory, phys, virt, virt_alloc_base) { - this->PID = PID; + this->PID = this->currentPID++; this->page_remaining = 0; this->last_page_pointer = virt_alloc_base; } -Process::Process(uint32_t PID) +Process::Process() : Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) { - this->PID = PID; + this->PID = 0; this->page_remaining = 0; this->last_page_pointer = 0; this->file_handlers = new xnoe::dynarray(8); } -Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc, char** argv) +Process::Process(PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc, char** argv, uint32_t envc, char** envp) : Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) { this->stdout = 0; this->stdin = 0; - this->PID = PID; + this->PID = this->currentPID++; this->page_remaining = 0; this->last_page_pointer = 0; @@ -55,17 +58,30 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea this->PD->select(); uint32_t* stack = thread->stack + 0x8000; - uint8_t* argenvarea = this->allocate(0x2000); - uint32_t argenv = argenvarea + 0x2000; + uint8_t* argenvarea = this->allocate(0x2000) + 0x2000; + + // Copy envp + // envp is null terminated + *(--stack) = 0; + for (int i=envc; i>0; i--) { + char* s = envp[i-1]; + uint32_t c = strlen(s); + memcpy((uint8_t*)(argenvarea -= c), (uint8_t*)envp[i-1], c); + *(--stack) = argenvarea; + } + uint32_t envp_p = ((uint32_t)stack); + + // Copy argv for (int i=argc; i>0; i--) { char* s = argv[i-1]; - uint32_t c = 0; - while (*(c++, s++)); - memcpy((uint8_t*)(argenv -= c), (uint8_t*)argv[i-1], c); - *(--stack) = argenv; + uint32_t c = strlen(s); + memcpy((uint8_t*)(argenvarea -= c), (uint8_t*)argv[i-1], c); + *(--stack) = argenvarea; } - *(--stack) = ((uint32_t)stack); + uint32_t argv_p = ((uint32_t)stack); + *(--stack) = envp_p; + *(--stack) = argv_p; *(--stack) = argc; filereader->seek(0); @@ -78,16 +94,91 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea this->threads.append(thread); } +Process::Process(Process* p) +: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) { + // Clone a Process and produce an entirely new process. + + this->file_handlers = new xnoe::dynarray(p->file_handlers); + + this->PID = this->currentPID++; + + // Set up page directory. + for (int index = 0xc0000000 >> 22; index < 1024; index++) + this->PD->page_directory[index] = p->PD->page_directory[index]; + + // First, we need to switch in to p's memory space + uint32_t pCR3; + asm("mov %%cr3, %0":"=a"(pCR3)::); + p->PD->select(); + + // First, we need to copy all of p's allocations. + + xnoe::linkedlist> allocations; + + xnoe::linkedlistelem* current_old = p->allocations.start; + while (current_old) { + allocations.append(xnoe::tuple(current_old->elem, new uint8_t[4096 * current_old->elem.page_size])); + void* location = xnoe::get<1>(allocations.end->elem); + memcpy((uint8_t*)location, (uint8_t*)current_old->elem.page_base, 4096 * current_old->elem.page_size); + current_old = current_old->next; + } + + // Select our own CR3 + this->PD->select(); + + // Go through every allocation from the old process, allocate it here, copy the data over, then free the buffer we created. + xnoe::linkedlistelem>* current_new = allocations.start; + while (current_new) { + AllocTracker at = xnoe::get<0>(current_new->elem); + uint8_t* buf = (uint8_t*)xnoe::get<1>(current_new->elem); + uint8_t* dbuf = (uint8_t*)this->allocate((at.page_size-1) * 4096, at.alloc_count); + memcpy(dbuf, buf + 0x14, at.page_size * 4096 - 0x14); + delete buf; + current_new = current_new->next; + } + + // Restore CR3 + asm("mov %0, %%cr3"::"r"(pCR3):); + + // Setting up threads, etc will be left to the caller. + this->stdin = p->stdin; + this->stdout = p->stdout; +} + +uint32_t Thread::currentTID = 1; + Thread::Thread(Process* parent) { + this->TID = this->currentTID++; this->parent = parent; this->stack = this->parent->allocate(0x8000); - this->kernelStackPtr = (new uint8_t[0x4000]) + 0x4000; + this->kspRaw = (new uint8_t[0x4000]); + this->kernelStackPtr = this->kspRaw + 0x4000; this->kernelStackPtrDefault = this->kernelStackPtr; } +Thread::Thread(Thread* t, Process* parent) { + this->TID = this->currentTID++; + this->stack = t->stack; + + uint8_t* s = new uint8_t[0x8000]; + + // Copy the kernel stack + this->kspRaw = (new uint8_t[0x4000]); + memcpy(this->kspRaw, t->kspRaw, 0x4000); + memcpy((uint8_t*)&this->frame, (uint8_t*)&t->frame, sizeof(frame_struct)); + + this->frame.new_cr3 = parent->PD->phys_addr; + + this->kernelStackPtr = this->kspRaw + 0x4000; + this->kernelStackPtrDefault = this->kernelStackPtr; + + this->frame.ebp = this->kernelStackPtr; + this->frame.oesp = this->kernelStackPtr; +} + Thread::~Thread() { - delete kernelStackPtr; + //delete kernelStackPtr; } void Thread::initKernelStack(void* entryPoint, void* esp) { @@ -100,19 +191,24 @@ void Thread::initKernelStack(void* entryPoint, void* esp) { *(--stack32) = 0x200; // EFLAGS *(--stack32) = 27; // CS *(--stack32) = (uint32_t)entryPoint; // EIP - *(--stack32) = ((uint32_t)esp); // EBP - - uint32_t rEBP = stack32; + *(--stack32); + *(--stack32); + *(--stack32); *(--stack32) = 0; // EAX *(--stack32) = 0; // ECX *(--stack32) = 0; // EDX *(--stack32) = 0; // EBX *(--stack32) = 0; // ESP - *(--stack32) = rEBP; // EBP + *(--stack32) = 0; // EBP *(--stack32) = 0; // ESI *(--stack32) = 0; // EDI + *(--stack32) = 0; // CR3 + *(--stack32) = 1; + + memcpy((uint8_t*)&this->frame, (uint8_t*)stack32, 72); + this->kernelStackPtr = stack32; asm ("mov %0, %%cr3" : : "r" (pCR3)); } @@ -134,14 +230,52 @@ Process::~Process() { xnoe::maybe r; if ((r=file_handlers->get(i)).is_ok()) if (r.get()) - delete r.get(); + r.get()->close(); } - xnoe::linkedlistelem* currentThread = threads.start; + /*xnoe::linkedlistelem* currentThread = threads.start; while (currentThread) { delete currentThread->elem; currentThread = currentThread->next; + }*/ +} + +void* Process::allocate(uint32_t size, uint32_t alloc_count) { + bool switched_PD = false; + uint32_t pCR3; + asm ("mov %%cr3, %0" : "=a" (pCR3) :); + if (Global::currentProc != this) { + switched_PD = true; + this->PD->select(); } + void* ptr; + + // For cloning a process, always allocate new + + uint32_t elem_size = sizeof(xnoe::linkedlistelem); + + // Determine how many pages we'll allocate, and the remainder + uint32_t pages = size / 4096; + uint32_t remainder = 4096 - (size % 4096); + + ptr = this->Allocator::allocate(size); + + // Update local values + this->last_page_pointer = ptr + pages * 4096; + this->page_remaining = remainder; + + // Create allocations entry + xnoe::linkedlistelem* elem = (xnoe::linkedlistelem*)ptr; + elem->next = 0; + elem->prev = 0; + elem->elem = AllocTracker(ptr, pages + 1, alloc_count); + this->allocations.append(elem); + + ptr += elem_size; + + asm ("mov %0, %%cr3" : : "r" (pCR3)); + + return ptr; } void* Process::allocate(uint32_t size) { @@ -163,7 +297,7 @@ void* Process::allocate(uint32_t size) { uint32_t elem_size = sizeof(xnoe::linkedlistelem); size += elem_size; - // Determine how many pages we'll allocate, and the remainder; + // Determine how many pages we'll allocate, and the remainder uint32_t pages = size / 4096; uint32_t remainder = 4096 - (size % 4096); diff --git a/src/kernel/process.h b/src/kernel/process.h index 18ad990..e22385a 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -11,28 +11,65 @@ #include "stdio/readwriter.h" #include "datatypes/dynarray.h" #include "filesystem/fstree.h" +#include "stdio/circularrwbuffer.h" + +struct __attribute__((packed)) frame_struct { + uint32_t count; + uint32_t new_cr3; + + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t oesp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + + uint32_t gate; + uint32_t __ignored2; + uint32_t errcode; + + uint32_t eip; + uint16_t cs; + uint16_t _ignored0; + uint32_t eflags; + uint32_t esp; + uint16_t ss; + uint16_t _ignored1; +}; class Process; class Thread { +private: + static uint32_t currentTID; public: + frame_struct frame; + uint32_t TID; + void* stack; + void* kspRaw; void* kernelStackPtr; void* kernelStackPtrDefault; Process* parent; ProcessState state; bool firstRun; + uint32_t suspending=0; + Thread(Process* parent); + Thread(Thread* t, Process* parent); ~Thread(); void Thread::initKernelStack(void* entryPoint, void* esp); }; struct AllocTracker { - void* page_base; + void* page_base; uint32_t page_size; uint32_t alloc_count; + AllocTracker(); AllocTracker(void* base, uint32_t size, uint32_t count); }; @@ -41,16 +78,15 @@ private: uint32_t last_page_pointer; uint32_t page_remaining; - // List of pages this process has allocated - xnoe::linkedlist allocations; - xnoe::maybe*> get_alloc_tracker(uint32_t address); - xnoe::dynarray* file_handlers; - Path currentWorkingDirectory; + static uint32_t currentPID; + public: + xnoe::dynarray* file_handlers; + uint32_t PID; uint32_t esp; @@ -59,12 +95,18 @@ public: xnoe::linkedlist threads; - Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base); - Process(uint32_t PID); - Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc=0, char** argv=0); + // List of pages this process has allocated + xnoe::linkedlist allocations; + + Process(void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base); + Process(); + Process(PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc=0, char** argv=0, uint32_t envc=0, char** envp=0); + + Process(Process* p); ~Process(); // Iterate through allocations and free those; delete stack + void* allocate(uint32_t size, uint32_t alloc_count); void* allocate(uint32_t size) override; void deallocate(uint32_t virt_addr) override; diff --git a/src/kernel/stdio/circularrwbuffer.cpp b/src/kernel/stdio/circularrwbuffer.cpp index 8167c70..3b3f498 100644 --- a/src/kernel/stdio/circularrwbuffer.cpp +++ b/src/kernel/stdio/circularrwbuffer.cpp @@ -1,16 +1,16 @@ #include "circularrwbuffer.h" -CircularRWBuffer::CircularRWBuffer(uint32_t reader, uint32_t writer) -: ReadWriter(0) { - this->giveReadPerm(reader); - this->giveWritePerm(writer); - +CircularRWBuffer::CircularRWBuffer() { this->bufferSize = 3072; this->buffer = new uint8_t[this->bufferSize]; this->readPtr = 0; this->writePtr = 0; } +CircularRWBuffer::~CircularRWBuffer() { + delete this->buffer; +} + uint32_t CircularRWBuffer::write(uint32_t count, uint8_t* buffer) { int i=0; while (i < count) { diff --git a/src/kernel/stdio/circularrwbuffer.h b/src/kernel/stdio/circularrwbuffer.h index 52bb153..3aafe82 100644 --- a/src/kernel/stdio/circularrwbuffer.h +++ b/src/kernel/stdio/circularrwbuffer.h @@ -10,7 +10,8 @@ private: uint32_t writePtr; uint32_t bufferSize; public: - CircularRWBuffer(uint32_t reader, uint32_t writer); + CircularRWBuffer(); + ~CircularRWBuffer(); uint32_t read(uint32_t count, uint8_t* buffer) override; uint32_t write(uint32_t count, uint8_t* buffer) override; diff --git a/src/kernel/stdio/oneshotreadwriter.cpp b/src/kernel/stdio/oneshotreadwriter.cpp index b7191e1..c7563a8 100644 --- a/src/kernel/stdio/oneshotreadwriter.cpp +++ b/src/kernel/stdio/oneshotreadwriter.cpp @@ -1,6 +1,6 @@ #include "oneshotreadwriter.h" -OneShotReadWriter::OneShotReadWriter(uint32_t owner, uint8_t* toRead) : ReadWriter(owner) { +OneShotReadWriter::OneShotReadWriter(uint8_t* toRead) { this->length = strlen(toRead); this->buffer = new uint8_t[this->length]; diff --git a/src/kernel/stdio/oneshotreadwriter.h b/src/kernel/stdio/oneshotreadwriter.h index 5dbf490..977cbe2 100644 --- a/src/kernel/stdio/oneshotreadwriter.h +++ b/src/kernel/stdio/oneshotreadwriter.h @@ -12,7 +12,7 @@ private: uint32_t index=0; public: - OneShotReadWriter(uint32_t owner, uint8_t* toRead); + OneShotReadWriter(uint8_t* toRead); uint32_t read(uint32_t count, uint8_t* buffer) override; uint32_t size() override; diff --git a/src/kernel/stdio/readwriter.cpp b/src/kernel/stdio/readwriter.cpp index c553248..78c09ee 100644 --- a/src/kernel/stdio/readwriter.cpp +++ b/src/kernel/stdio/readwriter.cpp @@ -1,38 +1,16 @@ #include "readwriter.h" -ReadWriter::ReadWriter(uint32_t owner) { - this->owner = owner; +uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){return;} +uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){return;} +uint32_t ReadWriter::seek(uint32_t position){return;} +uint32_t ReadWriter::size(){return;} + +void ReadWriter::open() { + this->opens++; } -void ReadWriter::giveReadPerm(uint32_t PID) { - this->allowedRead.append(PID); +void ReadWriter::close() { + this->opens--; + if (this->opens == 0) + delete this; } - -void ReadWriter::giveWritePerm(uint32_t PID) { - this->allowedWrite.append(PID); -} - -uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){} -uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){} -uint32_t ReadWriter::seek(uint32_t position){} -uint32_t ReadWriter::size(){} - -bool ReadWriter::canRead(uint32_t PID) { - if (this->owner == PID) - return true; - - if (this->allowedRead.has(PID)) - return true; - - return false; -} - -bool ReadWriter::canWrite(uint32_t PID) { - if (this->owner == PID) - return true; - - if (this->allowedWrite.has(PID)) - return true; - - return false; -} \ No newline at end of file diff --git a/src/kernel/stdio/readwriter.h b/src/kernel/stdio/readwriter.h index 4ba43f9..21e9937 100644 --- a/src/kernel/stdio/readwriter.h +++ b/src/kernel/stdio/readwriter.h @@ -6,22 +6,17 @@ class ReadWriter { private: - uint32_t owner; - xnoe::linkedlist allowedRead; - xnoe::linkedlist allowedWrite; + uint32_t opens=1; public: - ReadWriter(uint32_t owner); - void giveReadPerm(uint32_t PID); - void giveWritePerm(uint32_t PID); - virtual uint32_t read(uint32_t count, uint8_t* buffer); virtual uint32_t write(uint32_t count, uint8_t* buffer); virtual uint32_t size(); virtual uint32_t seek(uint32_t position); uint32_t getOwner(); - bool canRead(uint32_t PID); - bool canWrite(uint32_t PID); + + void open(); + void close(); }; -#endif \ No newline at end of file +#endif diff --git a/src/kernel/terminal.cpp b/src/kernel/terminal.cpp index 33625d1..c838fe1 100644 --- a/src/kernel/terminal.cpp +++ b/src/kernel/terminal.cpp @@ -215,8 +215,7 @@ void Terminal::update(){} void Terminal::update_cur(){} void Terminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {} -Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) -: ReadWriter(0) { +Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) { this->width = width; this->height = height; this->pages = pages; @@ -297,9 +296,10 @@ uint32_t Terminal::write(uint32_t count, uint8_t* string) { this->putchar(string[index]); this->set_curpos(this->cur_x, this->cur_y); + return count; } -uint32_t Terminal::read(uint32_t count, uint8_t* buffer) {} +uint32_t Terminal::read(uint32_t count, uint8_t* buffer) {return;} void Terminal::clear_screen() { for (int i=0; i < width * height * pages; i++) { @@ -444,14 +444,14 @@ void VGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) { } } -static void VGAModeTerminal::bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal) { - uint32_t count4 = (terminal->pixelWidth * terminal->pixelHeight) / 8 / 4; +void VGAModeTerminal::bufferToVRAM() { + uint32_t count4 = (this->pixelWidth * this->pixelHeight) / 8 / 4; for (int i=0; i<4; i++) { outb(0x3c4, 2); outb(0x3c5, 1<vga_pointer)[c] = ((uint32_t*)terminal->planes[i])[c]; + ((uint32_t*)this->vga_pointer)[c] = ((uint32_t*)this->planes[i])[c]; } } } @@ -526,7 +526,7 @@ for (int i=0; i<4; i++) { } } - Timer::register_event(16, &VGAModeTerminal::bufferToVRAM, this); + Timer::register_event(16, (void(*)(void*))&VGAModeTerminal::bufferToVRAM, this); } void BGAModeTerminal::update() { @@ -576,8 +576,8 @@ void BGAModeTerminal::put_pixel(uint32_t x, uint32_t y, uint8_t color) { this->fb[pixel] = color_map[color]; } -static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal) { - uint32_t c = terminal->pixelWidth * terminal->pixelHeight; +void BGAModeTerminal::bufferToVRAM() { + uint32_t c = this->pixelWidth * this->pixelHeight; uint32_t bank=0; uint32_t ctr=0; for (int i=0; ivga_pointer)[i%16384] = ((uint32_t*)terminal->fb)[i]; + ((uint32_t*)this->vga_pointer)[i%16384] = ((uint32_t*)this->fb)[i]; } } @@ -607,5 +607,5 @@ BGAModeTerminal::BGAModeTerminal(uint8_t* vga_pointer): Terminal(0, 0, 1) { outw(0x1ce, 4); outw(0x1cf, 1); - Timer::register_event(16, &BGAModeTerminal::bufferToVRAM, this); -} \ No newline at end of file + Timer::register_event(16, (void(*)(void*))&BGAModeTerminal::bufferToVRAM, this); +} diff --git a/src/kernel/terminal.h b/src/kernel/terminal.h index a894ae6..658114a 100644 --- a/src/kernel/terminal.h +++ b/src/kernel/terminal.h @@ -14,7 +14,7 @@ struct frame_struct; namespace Timer { - void register_event(uint32_t milliseconds, void(*function)(frame_struct*, void*), void* auxiliary, bool oneshot=false); + void register_event(uint32_t milliseconds, void(*function)(void*), void* auxiliary, bool oneshot=false); } enum TerminalState { @@ -99,10 +99,10 @@ private: void put_pixel(uint32_t x, uint32_t y, uint8_t color); void put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte); - - static void bufferToVRAM(frame_struct* frame, VGAModeTerminal* terminal); public: + void bufferToVRAM(); + uint32_t pixelWidth = 720; uint32_t pixelHeight = 480; @@ -120,10 +120,10 @@ private: void put_pixel(uint32_t x, uint32_t y, uint8_t color); void put_pixels_byte(uint32_t x, uint32_t y, uint8_t color, uint8_t pixel_byte); - - static void bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal); public: + void bufferToVRAM(); + uint32_t pixelWidth = 720; uint32_t pixelHeight = 480; diff --git a/src/programs/cat/main.c b/src/programs/cat/main.c new file mode 100644 index 0000000..af07c65 --- /dev/null +++ b/src/programs/cat/main.c @@ -0,0 +1,17 @@ +#include "common/common.h" + +int main(int argc, char** argv) { + for (int i=1; i>> "); - readline(32, buffer); - print("You said: "); - print(buffer); - print("\n\n"); - } -} \ No newline at end of file diff --git a/src/programs/init/main.c b/src/programs/init/main.c new file mode 100644 index 0000000..d501a4c --- /dev/null +++ b/src/programs/init/main.c @@ -0,0 +1,21 @@ +#include "common/common.h" + +int main() { + // The job of init will be to load the system configuration, mount devices, etc + + bindToKeyboard(); + + char* fn = "/xosh.bin"; + uint8_t* argv[] = { + fn, + 0 + }; + uint8_t* envp[] = { + "PATH=/", + 0 + }; + uint32_t xosh_fh = fopen(fn); + uint32_t xosh = execve(xosh_fh, argv, envp); + + while (1); +} \ No newline at end of file diff --git a/src/programs/listenvp/main.c b/src/programs/listenvp/main.c new file mode 100644 index 0000000..2b9762c --- /dev/null +++ b/src/programs/listenvp/main.c @@ -0,0 +1,8 @@ +#include "common/common.h" + +int main(uint32_t argc, char** argv, char** envp) { + printf("Environment: \n"); + for (int i=0; envp[i]; i++) + printf("- %s\n", envp[i]); + printf("\n"); +} \ No newline at end of file diff --git a/src/programs/ls/main.c b/src/programs/ls/main.c new file mode 100644 index 0000000..4a8e10e --- /dev/null +++ b/src/programs/ls/main.c @@ -0,0 +1,35 @@ +#include "common/common.h" + +char* filetype(FSType t) { + switch (t) { + case File: + return "File"; + case Directory: + return "Directory"; + case CharacterDev: + return "CharacterDev"; + case BlockDev: + return "BlockDev"; + case NoExist: + return "NoExist"; + } + return ""; +} + +int main(int argc, char** argv) { + if (argc != 2) { + printf("Usage: %s ", argv[0]); + return 1; + } + + char* directory = argv[1]; + + uint32_t dentsSize = getDentsSize(directory); + FSDirectoryListing* dents = (FSDirectoryListing*)malloc(dentsSize); + getDents(directory, (uint8_t*)dents); + + for (int i=0; icount; i++) { + FSDirectoryEntry e = dents->entries[i]; + printf("%.s %d %s\n", e.path.length, e.path.path, e.sizeBytes, filetype(e.type)); + } +} \ No newline at end of file diff --git a/src/programs/timer/timer.c b/src/programs/timer/timer.c deleted file mode 100644 index 3020a41..0000000 --- a/src/programs/timer/timer.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "common/common.h" - -int main() { - uint32_t crashBin = fopen("/crash.bin"); - uint32_t pid = getPID(); - while (1) { - printf("Time Elapsed: %dms\n", getMillisecondsElapsed()); - printf("Init. Pages: %d\nRemaining Pages: %d\n", getInitPages(), getRemainingPages()); - - printf("PID 2 State: %s\n", (!getProcessState(2))?"Running":"Suspended"); - printf("I am PID %d\n", pid); - - //exec(crashBin); - sleep(1000); - } -} \ No newline at end of file diff --git a/src/programs/world/world.c b/src/programs/world/world.c deleted file mode 100644 index a1b8dda..0000000 --- a/src/programs/world/world.c +++ /dev/null @@ -1,340 +0,0 @@ -#include "common/common.h" -#include - -typedef struct { - char* buffer; - int x; - int y; - uint32_t process; - uint32_t stdin; - uint32_t stdout; - uint32_t width; - uint32_t height; -} procbuffer; - -void scrollBuffer(procbuffer* buf) { - for (int y=0; yheight; y++) - for (int x=0; xwidth; x++) - if (y != buf->height-1) - buf->buffer[y*buf->width+x] = buf->buffer[(y+1)*buf->width+x]; - else - buf->buffer[y*buf->width+x] = ' '; -} - -void writeToBuf(char c, procbuffer* buf) { - switch (c) { - case '\n': - buf->x = 0; - buf->y++; - break; - - case '\b': - if (buf->x > 0) - buf->x--; - else if (buf->y > 0) { - buf->x = buf->width-1; - buf->y--; - } - buf->buffer[buf->y*buf->width+buf->x] = ' '; - break; - - default: - buf->buffer[buf->y*buf->width+buf->x++] = c; - } - if (buf->x == buf->width) { - buf->x = 0; - buf->y++; - } - if (buf->y == buf->height) { - buf->y--; - scrollBuffer(buf); - } -} - -void writeCountToBuf(int count, char* c, procbuffer* buf) { - while (count--) { - writeToBuf(*(c++), buf); - } -} - -void clearBuf(procbuffer* buf) { - for (int i=0; iheight*buf->width;i++) { - buf->buffer[i] = ' '; - } - buf->x = 0; - buf->y = 0; -} - -void writeStrToBuf(char* c, procbuffer* b) { - char* s = c; - while(*s) - writeToBuf(*(s++), b); -} - -void setCurPos(int x, int y) { - char pset[11] = "\x1b[000;000H"; - for (int i=0; iheight; i++) { - setCurPos(dx, dy++); - write(b->width, 0, b->buffer+(b->width*i)); - } -} - -void readline(int count, char* buffer) { - int index = 0; - char c; - while (index < count) { - if (read(1, 1, &c)) { - if (c == '\n') - break; - if (c == '\b') { - if (index == 0) - continue; - else { - index--; - buffer[index] = 0; - write(1, 0, &c); - continue; - } - } - - buffer[index++] = c; - write(1, 0, &c); - } - } -} - -bool strcmp(char* a, char* b) { - int index=0; - while (a[index]) - if (a[index] == b[index]) - index++; - else - return false; - return true; -} - -bool strcmpcnt(int count, char* a, char* b) { - int index=0; - while (index < count) - if (a[index] == b[index]) - index++; - else - return false; - return true; -} - -procbuffer b1; -procbuffer b2; - -int bufferWidth; - -void displayBuffer1() { - char c[128]; - int succ=0; - while (1) { - if (b1.process) - if (succ = read(128, b1.stdout, c)) - writeCountToBuf(succ, c, &b1); - displayBuf(&b1, 2, 2); - } -} - -void displayBuffer2() { - char c[128]; - int succ=0; - while (1) { - if (b2.process) - if (succ = read(128, b2.stdout, c)) - writeCountToBuf(succ, c, &b2); - displayBuf(&b2, bufferWidth+4, 2); - } -} - -int main() { - int width = getCurrentTerminalWidth(); - int height = getCurrentTerminalHeight(); - - bufferWidth = (width - 4) / 2; - int bufferHeight = (height - 4); - - bindToKeyboard(); - - char space = ' '; - char plus = '+'; - - print("\x1b[1;1H"); - for (int i=0; i < 1000; i++) - write(1, 0, &space); - print("\x1b[1;1H"); - print("\x1b[45;33;1m"); - - for (int i=0; i\n", selectedBuf); - writeStrToBuf(" Loads and executes the program \n", selectedBuf); - writeStrToBuf(":ls \n", selectedBuf); - writeStrToBuf(" Lists the files in directory \n", selectedBuf); - writeStrToBuf(":clear\n", selectedBuf); - writeStrToBuf(" Clears the buffer\n", selectedBuf); - writeStrToBuf(":type \n", selectedBuf); - writeStrToBuf(" Writes out the contents of the file \n", selectedBuf); - - writeStrToBuf("--------\n", selectedBuf); - } else if (strcmpcnt(4, buf, "kill")) { - if (selectedBuf->process) { - kill(selectedBuf->process); - clearBuf(selectedBuf); - selectedBuf->process = 0; - selectedBuf->stdin = 0; - selectedBuf->stdout = 0; - } - } else if (strcmpcnt(4, buf, "load")) { - if (!selectedBuf->process) { - char* potFn = buf+5; - uint32_t fh = fopen(potFn); - selectedBuf->process = exec(fh); - selectedBuf->stdout = bindStdout(selectedBuf->process); - selectedBuf->stdin = bindStdin(selectedBuf->process); - fclose(fh); - } - } else if (strcmpcnt(2, buf, "ls")) { - uint32_t size = getDentsSize((char*)(buf+3)); - FSDirectoryListing* listing = (FSDirectoryListing*)malloc(size); - getDents((char*)(buf+3), listing); - writeStrToBuf("\n", selectedBuf); - for (int i=0; icount; i++) { - writeCountToBuf(listing->entries[i].path.length, listing->entries[i].path.path, selectedBuf); - writeStrToBuf("\n", selectedBuf); - } - free(listing); - } else if (strcmpcnt(5, buf, "clear")) { - clearBuf(selectedBuf); - } else if (strcmpcnt(4, buf, "type")) { - uint32_t f = fopen(buf+5); - char c; - while (read(1, f, &c)) - writeCountToBuf(1, &c, selectedBuf); - fclose(f); - } - } else { - if (selectedBuf->process) - write(1, selectedBuf->stdin, c); - } - } - } -} \ No newline at end of file diff --git a/src/programs/xosh/main.c b/src/programs/xosh/main.c new file mode 100644 index 0000000..3b00a3b --- /dev/null +++ b/src/programs/xosh/main.c @@ -0,0 +1,107 @@ +#include "common/common.h" + +void readline(char* buf, uint32_t lim) { + uint32_t idx = 0; + while (1) { + char c; + if (idx == lim) { + printf("\n"); + break; + } + if (read(1, 1, &c)) { + if (c == '\n') { + write(1, 0, &c); + break; + } else if (c == '\b') { + if (idx > 0) { + buf[--idx] = 0; + write(1, 0, &c); + } + } else if (c == 0) { + continue; + } else { + buf[idx++] = c; + write(1, 0, &c); + } + } + } +} + +typedef enum { + Normal, + StringLiteral, + Escaped +} ParseState; + +int main(int argc, char** argv, char** envp) { + // XOSH - The XnoeOS Shell + // XoSH is going to be a simple shell that can be used to execute programs. + + printf("Welcome to %s!\n\n", argv[0]); + + printf("Environment:\n"); + for (int i=0; envp[i]; i++) + printf("- %s\n", envp[i]); + printf("\n"); + + while (1) { + printf("\x1b[0m# "); + char input[128]; + memset(input, 0, 128); + readline(input, 128); + + // Parse the input + char* result[32]; + uint32_t ridx=0; + memset(result, 0, 128); + char c; + uint32_t idx=0; + char* lp = input; + ParseState s = Normal; + while (c=input[idx++]) { + switch (s) { + case Normal: + switch (c) { + case '"': + s = StringLiteral; + break; + case '\\': + s = Escaped; + break; + case ' ': + input[idx-1] = 0; + result[ridx++] = lp; + lp = (char*)(input+idx); + break; + default: + break; + } + break; + case StringLiteral: + if (c == '"') { + s = Normal; + } + break; + case Escaped: + break; + default: + break; + } + } + result[ridx++] = lp; + + if (ridx > 0) { + char* programName = result[0]; + if (exists(programName)) { + char** argv = result; + uint32_t program = fopen(programName); + uint32_t e = execv(program, argv); + printf("\nExit code: %d\n\n", e); + } else if (strcmp(result[0], "set")) { + setenv(result[1], result[2]); + } else { + printf("No such executable file: `%s`\n\n", programName); + } + } + } +} \ No newline at end of file