Add ability for other processes to bind to eachother's stdin and stdout. Add PoC for this functionality

This commit is contained in:
Xnoe 2022-01-17 19:43:13 +00:00
parent 55a5bea35a
commit 73c0fe429f
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
14 changed files with 498 additions and 140 deletions

View File

@ -2,7 +2,8 @@ CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exce
CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -I. CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -I.
LDFLAGS = LDFLAGS =
DISK_IMG_FILES = build/kernel/kernel.bin build/world/world.bin hello.txt alpha.txt DISK_IMG_FILES = build/kernel/kernel.bin build/world/world.bin hello.txt alpha.txt \
build/hello/hello.bin
KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp) KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp)
KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm) KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm)
@ -44,6 +45,7 @@ disk.img: clean prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IM
dd obs=512 seek=1 if=build/boot_stage2/boot.bin of=disk.img conv=notrunc dd obs=512 seek=1 if=build/boot_stage2/boot.bin of=disk.img conv=notrunc
mount disk.img img.d mount disk.img img.d
cp $(DISK_IMG_FILES) img.d/ cp $(DISK_IMG_FILES) img.d/
sleep 0.1
umount img.d umount img.d
chmod 777 disk.img chmod 777 disk.img

View File

@ -28,6 +28,18 @@ int write(uint32_t count, void* filehanlder, uint8_t* buffer) {
asm volatile ("mov $11, %%eax; mov %0, %%ebx; mov %1, %%esi; mov %2, %%edi; int $0x7f" : : "m" (count), "m" (filehanlder), "m" (buffer): "ebx", "esi", "edi"); asm volatile ("mov $11, %%eax; mov %0, %%ebx; mov %1, %%esi; mov %2, %%edi; int $0x7f" : : "m" (count), "m" (filehanlder), "m" (buffer): "ebx", "esi", "edi");
} }
uint32_t fork(char* filename) {
asm volatile("mov $7, %%eax; mov %0, %%esi; int $0x7f" : : "m" (filename) : "esi");
}
uint32_t bindStdout(uint32_t PID) {
asm volatile("mov $13, %%eax; mov %0, %%esi; int $0x7f" : : "m" (PID) : "esi");
}
uint32_t bindStdin(uint32_t PID) {
asm volatile("mov $14, %%eax; mov %0, %%esi; int $0x7f" : : "m" (PID) : "esi");
}
void bindToKeyboard() { void bindToKeyboard() {
asm volatile ("mov $12, %%eax; int $0x7f" : : :); asm volatile ("mov $12, %%eax; int $0x7f" : : :);
} }

View File

@ -9,6 +9,10 @@ void* localalloc(uint32_t size);
void localdelete(void* ptr); void localdelete(void* ptr);
uint32_t filesize(char* filename); uint32_t filesize(char* filename);
uint32_t fork(char* filename);
uint32_t bindStdout(uint32_t PID);
uint32_t bindStdin(uint32_t PID);
uint32_t getPID(); uint32_t getPID();
int read(uint32_t count, void* filehandler, uint8_t* buffer); int read(uint32_t count, void* filehandler, uint8_t* buffer);

View File

@ -1,16 +1,40 @@
#include "../common/common.h" #include "../common/common.h"
int main() { void readline(int count, char* buffer) {
uint32_t counter = 0; int index = 0;
uint32_t PID = getPID(); char c;
char intbuffer[32]; while (index < count) {
uint32_t index = int_to_decimal(PID, intbuffer); if (read(1, 1, &c)) {
while (1) { if (c == '\n')
counter++; break;
if (counter == 312500) { if (c == '\b') {
print(intbuffer+index); if (index == 0)
print(" "); continue;
counter = 0; else {
index--;
buffer[index] = 0;
write(1, 0, &c);
continue;
}
}
buffer[index++] = c;
write(1, 0, &c);
} }
} }
print("\n");
}
int main() {
print("Hello, World!\n");
char buffer[32];
while (1) {
for (int i=0; i<32; i++)
buffer[i] = 0;
print(">>> ");
readline(32, buffer);
print("You said: ");
print(buffer);
print("\n\n");
}
} }

View File

@ -5,7 +5,7 @@ namespace Global {
Kernel* kernel = 0; Kernel* kernel = 0;
Process* currentProc = 0; Process* currentProc = 0;
tss_struct* tss = 0; tss_struct* tss = 0;
bool currentProcValid = true; bool currentProcValid = false;
} }
void* operator new (uint32_t size) { void* operator new (uint32_t size) {

View File

@ -21,18 +21,36 @@ void set_entry(uint8_t interrupt_number, uint16_t code_segment, void(*handler)()
}; };
} }
void page_fault(frame_struct* frame) { void handle_fault(frame_struct* frame) {
// Clear interrupts, we don't want to perform a context switch during a page fault. // Clear interrupts, we don't want to perform a context switch whilst handling a fault.
asm ("cli"); asm ("cli");
uint32_t problem_address; uint32_t problem_address;
asm("mov %%cr2, %0" : "=a" (problem_address) :); asm ("mov %%cr2, %0" : "=a" (problem_address):);
Global::kernel->terminal->printf("(CS %x EIP %x): Page Fault at %x Error Code: %x Gate: %d\n", frame->cs, frame->eip, problem_address, frame->errcode, frame->gate); Global::kernel->terminal->printf("(CS %x EIP %x): ", frame->cs, frame->eip);
switch (frame->gate) {
case 0: // Divide by zero
Global::kernel->terminal->printf("Divide by Zero");
break;
case 6: // Invalid Opcode
Global::kernel->terminal->printf("Invalid Opcode");
break;
case 13: // GPF
Global::kernel->terminal->printf("General Protection Fault!");
break;
case 14: // Page Fault
Global::kernel->terminal->printf("Page Fault at %x", problem_address);
break;
default:
Global::kernel->terminal->printf("Unkown Fault!");
break;
}
Global::kernel->terminal->printf(" Error Code: %x\n", frame->errcode);
if (!(frame->cs & 3)) { if (!(frame->cs & 3)) {
Global::kernel->terminal->printf("[FATAL] Kernel Page Fault!!!\n"); Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n");
while (1) asm("hlt"); while (1) asm("hlt");
} else { } else {
// Print an error message. // Print an error message.
Global::kernel->terminal->printf("PID %d Terminated due to page 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)); asm volatile ("mov %0, %%esp" ::"m"(Global::kernel->globalISRStack));
Global::kernel->PD->select(); Global::kernel->PD->select();
@ -49,11 +67,6 @@ void page_fault(frame_struct* frame) {
void ignore_interrupt(frame_struct* frame) {} void ignore_interrupt(frame_struct* frame) {}
void gpf(frame_struct* frame) {
printf("(EIP %x) General Protection Fault %x\n", frame->eip, frame->errcode);
while (1) asm("hlt");
}
void context_switch(frame_struct* frame) { void context_switch(frame_struct* frame) {
// When any interrupt occurs (including context_switch), SS:ESP is set to // When any interrupt occurs (including context_switch), SS:ESP is set to
// the values of SS0:ESP0 in Global::tss // the values of SS0:ESP0 in Global::tss
@ -70,77 +83,65 @@ void context_switch(frame_struct* frame) {
asm ("cli"); // Disable interrupts whilst handling the context switch. asm ("cli"); // Disable interrupts whilst handling the context switch.
// Restore eax xnoe::linkedlist<Process*>* processes = &Global::kernel->processes;
asm ("mov %0, %%eax"::"r"(frame->eax));
Process* currentProc = 0; if (!processes->start) {
Process* nextProc = 0; Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n");
while (1) asm ("hlt");
if (Global::currentProcValid) {
currentProc = Global::currentProc;
// Write current esp to currentProc->kernelStackPtr
asm ("mov %%esp, %0" : "=a" (currentProc->kernelStackPtr):);
} }
if (currentProc || !Global::currentProcValid) { if (Global::currentProcValid)
xnoe::linkedlist<Process*>* processes = &Global::kernel->processes; asm ("mov %%esp, %0" : "=a" (Global::currentProc->kernelStackPtr):);
// This cursed bit of code first determines if the processes list is longer than 1 and if it is // 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 // - Determines if it has 2 or more elements
// - If it has two, swap the first and last, update prev and next of each to be null or the other item // - If it has two, swap the first and last, update prev and next of each to be null or the other item
// - If it has more than two, add the start to the end then set start to the second element // - If it has more than two, add the start to the end then set start to the second element
if (processes->start) { if (Global::currentProc) {
if (processes->start->next != 0) { if (processes->start->next != 0) {
if (processes->end->prev == processes->start) { if (processes->end->prev == processes->start) {
xnoe::linkedlistelem<Process*>* tmp = processes->start; xnoe::linkedlistelem<Process*>* tmp = processes->start;
processes->start = processes->end; processes->start = processes->end;
processes->end = tmp; processes->end = tmp;
processes->start->prev = 0; processes->start->prev = 0;
processes->end->next = 0; processes->end->next = 0;
processes->end->prev = processes->start; processes->end->prev = processes->start;
processes->start->next = processes->end; processes->start->next = processes->end;
} else { } else {
processes->end->next = processes->start; processes->end->next = processes->start;
processes->start = processes->start->next; processes->start = processes->start->next;
processes->start->prev = 0; processes->start->prev = 0;
xnoe::linkedlistelem<Process*>* tmp = processes->end; xnoe::linkedlistelem<Process*>* tmp = processes->end;
processes->end = processes->end->next; processes->end = processes->end->next;
processes->end->next = 0; processes->end->next = 0;
processes->end->prev = tmp; processes->end->prev = tmp;
}
} }
} }
}
// Get the next process. Global::currentProc = processes->start->elem;
if (processes->start)
nextProc = processes->start->elem;
if (nextProc == 0) { // Select the next processes page directory
Global::kernel->terminal->printf("[FATAL] No more processes! Halting!\n"); asm volatile ("mov %0, %%cr3" : : "r" (Global::currentProc->PD->phys_addr));
while (1) asm ("hlt"); // Restore kernelStackPtr of the new process.
} asm volatile ("mov %0, %%esp" : : "m" (Global::currentProc->kernelStackPtr));
Global::currentProc = nextProc; // At this point interrupts are disabled till iret so we can safely set
// Global::tss->esp0 to the new Process's kernelStackPtrDefault
// Select the next processes page directory Global::tss->esp0 = Global::currentProc->kernelStackPtrDefault;
asm volatile ("mov %0, %%cr3" : : "r" (nextProc->PD->phys_addr));
// Restore kernelStackPtr of the new process.
asm volatile ("mov %0, %%esp" : : "m" (Global::kernel->processes.start->elem->kernelStackPtr));
// At this point interrupts are disabled till iret so we can safely set // Set the current proc to valid
// Global::tss->esp0 to the new Process's kernelStackPtrDefault Global::currentProcValid = true;
Global::tss->esp0 = Global::kernel->processes.start->elem->kernelStackPtrDefault; if (Global::currentProc->firstRun) {
Global::currentProc->firstRun = false;
// Set the current proc to valid asm("add $4, %esp");
Global::currentProcValid = true; asm("ret");
} else {
if (Global::currentProc->firstRun) { asm("add $28, %esp");
Global::currentProc->firstRun = false; asm("ret");
asm("add $4, %esp");
asm("ret");
}
} }
} }
@ -153,13 +154,16 @@ void syscall(frame_struct* frame) {
// 4: localalloc: LocalAlloc: Allocate under current process (in esi: size; out eax void* ptr) // 4: localalloc: LocalAlloc: Allocate under current process (in esi: size; out eax void* ptr)
// 5: localdelete: LocalDelete: Deallocate under current process (in esi: pointer) // 5: localdelete: LocalDelete: Deallocate under current process (in esi: pointer)
// 6: X // 6: X
// 7: X // 7: fork :: char* filename esi -> int PID // Spawns a process and returns its PID.
// 8: getPID: returns the current process's PID (out eax: uint32_t) // 8: getPID: returns the current process's PID (out eax: uint32_t)
// 9: getFileHandler :: char* path esi -> void* eax // Returns a file handlers for a specific file // 9: getFileHandler :: char* path esi -> void* eax // Returns a file handlers for a specific file
// 10: read :: uint32_t count ebx -> void* filehandler esi -> uint8_t* outputbuffer edi -> int read // Reads from a file handler in to a buffer, returns successful read // 10: read :: uint32_t count ebx -> void* filehandler esi -> uint8_t* outputbuffer edi -> int read // Reads from a file handler in to a buffer, returns successful read
// 11: write :: uint32_t count ebx -> void* filehandler esi -> uint8_t* inputbuffer edi -> int written // Reads from a buffer in to a file, returns successful written // 11: write :: uint32_t count ebx -> void* filehandler esi -> uint8_t* inputbuffer edi -> int written // Reads from a buffer in to a file, returns successful written
// 12: bindToKeyboard :: void -> void // Binds the current process's stdout to the keyboard. // 12: bindToKeyboard :: void -> void // Binds the current process's stdout to the keyboard.
// 13: bindStdout :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdout of another process.
// 14: bindStdin :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdin of another process.
// File handlers: // File handlers:
// 0: Stdout // 0: Stdout
// 1: Stdin // 1: Stdin
@ -190,8 +194,16 @@ void syscall(frame_struct* frame) {
break; break;
case 6: case 6:
break; break;
case 7: case 7: {
asm("cli");
char filename[12];
for (int i=0; i<12; i++)
filename[i] = ((char*)(frame->esi))[i];
Process* p = Global::kernel->createProcess(filename);
rval = p->PID;
asm("sti");
break; break;
}
case 8: case 8:
rval = currentProc->PID; rval = currentProc->PID;
break; break;
@ -208,8 +220,10 @@ void syscall(frame_struct* frame) {
rval = stdin->read(frame->ebx, edi); rval = stdin->read(frame->ebx, edi);
} else { } else {
xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi); xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi);
if (!fh.is_ok()) if (!fh.is_ok()) {
rval = 0;
break; break;
}
ReadWriter* rw = fh.get(); ReadWriter* rw = fh.get();
rval = rw->read(frame->ebx, edi); rval = rw->read(frame->ebx, edi);
@ -226,8 +240,10 @@ void syscall(frame_struct* frame) {
rval = stdout->write(frame->ebx, edi); rval = stdout->write(frame->ebx, edi);
} else { } else {
xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi); xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi);
if (!fh.is_ok()) if (!fh.is_ok()) {
rval = 0;
break; break;
}
ReadWriter* rw = fh.get(); ReadWriter* rw = fh.get();
rval = rw->write(frame->ebx, edi); rval = rw->write(frame->ebx, edi);
@ -241,6 +257,33 @@ void syscall(frame_struct* frame) {
currentProc->stdin = new CircularRWBuffer(currentProc->PID, 0); currentProc->stdin = new CircularRWBuffer(currentProc->PID, 0);
Global::kernel->KBListeners.append(currentProc); Global::kernel->KBListeners.append(currentProc);
break;
case 13: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
if (!pm.is_ok())
break;
Process* p = pm.get();
if (!p->stdout) {
ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, esi);
p->stdout = buffer;
rval = Global::kernel->mapFH(buffer);
}
break;
}
case 14: {
xnoe::Maybe<Process*> pm = Global::kernel->pid_map->get(esi);
if (!pm.is_ok())
break;
Process* p = pm.get();
if (!p->stdin) {
ReadWriter* buffer = new CircularRWBuffer(esi, currentProc->PID);
p->stdin = buffer;
rval = Global::kernel->mapFH(buffer);
}
break;
}
default: default:
break; break;
@ -259,12 +302,28 @@ void init_idt() {
for (int i=0; i<256; i++) for (int i=0; i<256; i++)
gates[i] = &ignore_interrupt; gates[i] = &ignore_interrupt;
gates[0x20] = &context_switch; gates[32] = &context_switch;
gates[0xd] = &gpf; gates[0] = &handle_fault;
gates[0xe] = &page_fault; gates[5] = &handle_fault;
gates[0x7f] = &syscall; gates[6] = &handle_fault;
gates[7] = &handle_fault;
gates[9] = &handle_fault;
gates[10] = &handle_fault;
gates[11] = &handle_fault;
gates[12] = &handle_fault;
gates[13] = &handle_fault;
gates[14] = &handle_fault;
gates[16] = &handle_fault;
gates[17] = &handle_fault;
gates[19] = &handle_fault;
gates[20] = &handle_fault;
gates[21] = &handle_fault;
gates[29] = &handle_fault;
gates[30] = &handle_fault;
gates[31] = &handle_fault;
gates[127] = &syscall;
idt[0x7f].privilege = 3; idt[127].privilege = 3;
outb(0x20, 0x11); outb(0x20, 0x11);
outb(0xA0, 0x11); outb(0xA0, 0x11);

View File

@ -11,11 +11,14 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint
this->stack = stack; this->stack = stack;
this->lastFH = 8;
//this->processes.append(this); //this->processes.append(this);
} }
void Kernel::init_kernel() { void Kernel::init_kernel() {
this->pid_map = new xnoe::hashtable<uint32_t, Process*>(); this->pid_map = new xnoe::hashtable<uint32_t, Process*>();
this->FH = new xnoe::hashtable<void*, ReadWriter*>();
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000; this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
} }
@ -41,6 +44,11 @@ void Kernel::destroyProcess(Process* p) {
delete p; delete p;
} }
int Kernel::mapFH(ReadWriter* fh) {
this->FH->set(this->lastFH++, fh);
return this->lastFH - 1;
}
//void Kernel::loadPrimaryStack() { //void Kernel::loadPrimaryStack() {
// asm volatile("mov %0, %%esp"::"m"(this->stack - 64)); // asm volatile("mov %0, %%esp"::"m"(this->stack - 64));
//} //}

View File

@ -7,6 +7,8 @@
#include "terminal.h" #include "terminal.h"
class Kernel : public Process { class Kernel : public Process {
private:
int lastFH;
public: public:
uint32_t currentPID; uint32_t currentPID;
uint32_t stack; uint32_t stack;
@ -26,6 +28,8 @@ public:
Process* createProcess(char* filename); Process* createProcess(char* filename);
Process* createProcess(char* filename, ReadWriter* stdout); Process* createProcess(char* filename, ReadWriter* stdout);
void destroyProcess(Process* p); void destroyProcess(Process* p);
int mapFH(ReadWriter* fh);
//void loadPrimaryStack(); //void loadPrimaryStack();
}; };

View File

@ -36,12 +36,15 @@ bool shift_on = false;
void keyboard_interrupt(frame_struct* frame) { void keyboard_interrupt(frame_struct* frame) {
uint8_t decoded = 0; uint8_t decoded = 0;
uint8_t current_scancode = inb(0x60); uint8_t current_scancode = inb(0x60);
outb(0x20, 0x21); if ((current_scancode&0x7f) == 0x2a) {
if ((current_scancode&0x7f) == 0x2a)
shift_on = !(current_scancode&0x80); shift_on = !(current_scancode&0x80);
return;
}
if (current_scancode == 0x3a) if (current_scancode == 0x3a) {
caps_on ^= 1; caps_on ^= 1;
return;
}
if (shift_on) if (shift_on)
decoded = key_to_char_shift[current_scancode&0x7f]; decoded = key_to_char_shift[current_scancode&0x7f];

View File

@ -44,10 +44,7 @@ int main() {
term->printf("KERNEL OK!\n"); term->printf("KERNEL OK!\n");
Global::currentProc = &kernel;
Process* p1 = kernel.createProcess("WORLD BIN", term); Process* p1 = kernel.createProcess("WORLD BIN", term);
//kernel.createProcess("HELLO BIN");
init_keyboard(); init_keyboard();

View File

@ -244,6 +244,9 @@ void* Allocator::allocate(uint32_t size) {
this->PD->map(phys_addr, virt_addr + 4096 * i, this->privilege); this->PD->map(phys_addr, virt_addr + 4096 * i, this->privilege);
} }
for (int i=0; i<4096; i++)
((uint8_t*)virt_addr)[i] = 0;
return virt_addr; return virt_addr;
} }

View File

@ -59,44 +59,26 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha
// We also need to initialise ESP and the stack // We also need to initialise ESP and the stack
uint32_t* stack32 = ((uint32_t)this->kernelStackPtr); uint32_t* stack32 = ((uint32_t)this->kernelStackPtr);
stack32--; *(--stack32) = 0x23; // SS
*stack32 = 0x23; // SS *(--stack32) = ((uint32_t)this->stack + 0x8000); // ESP
stack32--; *(--stack32) = 0x200; // EFLAGS
*stack32 = ((uint32_t)this->stack + 0x8000); // ESP *(--stack32) = 27; // CS
stack32--; *(--stack32) = (uint32_t)program_data; // EIP
*stack32 = 0x200; // EFLAGS *(--stack32) = ((uint32_t)this->stack + 0x8000); // EBP
stack32--;
*stack32 = 27; // CS 0x08
stack32--;
*stack32 = (uint32_t)program_data; // EIP
stack32--;
*stack32 = ((uint32_t)this->stack + 0x8000); // EBP
uint32_t rEBP = stack32; uint32_t rEBP = stack32;
//stack32--;
*(--stack32) = 0; // EAX
*(--stack32) = 0; // ECX
*(--stack32) = 0; // EDX
*(--stack32) = 0; // EBX
*(--stack32) = 0; // ESP
*(--stack32) = rEBP; // EBP
*(--stack32) = 0; // ESI
*(--stack32) = 0; // EDI
stack32--; stack32--;
*stack32 = 0; // EAX *(--stack32) = &catchall_return; // cachall_return
stack32--;
*stack32 = 0; // ECX
stack32--;
*stack32 = 0; // EDX
stack32--;
*stack32 = 0; // EBX
stack32--;
*stack32 = 0; // ESP
stack32--;
*stack32 = rEBP; // EBP
stack32--;
*stack32 = 0; // ESI
stack32--;
*stack32 = 0; // EDI
stack32--;
stack32--;
*stack32 = &catchall_return; // cachall_return
stack32--; stack32--;
this->kernelStackPtr = stack32; this->kernelStackPtr = stack32;

View File

@ -46,6 +46,23 @@ Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages)
this->active = false; this->active = false;
} }
int strToInt(char* str) {
int r=0;
while (*str >= 0x30 && *str <= 0x39) {
r *= 10;
r += *(str++) - 0x30;
}
return r;
}
int clamp(int a, int b, int c) {
if (a < b)
return b;
if (a > c)
return c;
return a;
}
void Terminal::printf(const char* string, ...) { void Terminal::printf(const char* string, ...) {
va_list ptr; va_list ptr;
va_start(ptr, string); va_start(ptr, string);
@ -59,10 +76,50 @@ void Terminal::printf(const char* string, ...) {
this->cur_y++; this->cur_y++;
} }
if (current == 0x1b && string[index] == '[') {
index++;
char* parameterStart = (string+index);
while (string[index] >= 0x30 && string[index] <= 0x3F)
index++;
char* parameterEnd = (string+index);
char* intermediateStart = (string+index);
while (string[index] >= 0x20 && string[index] <= 0x2F)
index++;
char final = *(string+(index++));
switch (final) {
case 'A':
this->cur_y -= clamp(strToInt(parameterStart), 0, this->cur_y);
break;
case 'B':
this->cur_y += clamp(strToInt(parameterStart), 0, this->height - this->cur_y);
break;
case 'C':
this->cur_x += clamp(strToInt(parameterStart), 0, this->width - this->cur_x);
break;
case 'D':
this->cur_x -= clamp(strToInt(parameterStart), 0, this->cur_x);
break;
case 'H': {
char* s=parameterStart;
while (*s != ';' && s < parameterEnd)
s++;
s++;
this->cur_y = clamp(strToInt(parameterStart), 1, this->height) - 1;
this->cur_x = clamp(strToInt(s), 1, this->width) - 1;
break;
}
}
continue;
}
if (current == '\b') { if (current == '\b') {
if (this->cur_x > 0) { if (this->cur_x > 0) {
this->cur_x--; this->cur_x--;
} else { } else if (this->cur_y > 0) {
this->cur_y--; this->cur_y--;
this->cur_x = this->width-1; this->cur_x = this->width-1;
} }
@ -125,14 +182,94 @@ void Terminal::printf(const char* string, ...) {
va_end(ptr); va_end(ptr);
} }
int Terminal::write(uint32_t count, uint8_t* buffer) { int Terminal::write(uint32_t count, uint8_t* string) {
char* buf = new char[count+1]; /*char* buf = new char[count+1];
for (int i=0;i<count;i++) { for (int i=0;i<count;i++) {
buf[i] = buffer[i]; buf[i] = buffer[i];
} }
buf[count] = 0; buf[count] = 0x00;
printf(buf); printf(buf);
delete buf; delete buf;*/
int index = 0;
char current;
while (index < count) {
current=string[index++];
if (current == '\n') {
this->cur_x = 0;
this->cur_y++;
}
if (current == 0x1b && string[index] == '[') {
index++;
char* parameterStart = (string+index);
while (string[index] >= 0x30 && string[index] <= 0x3F)
index++;
char* parameterEnd = (string+index);
char* intermediateStart = (string+index);
while (string[index] >= 0x20 && string[index] <= 0x2F)
index++;
char final = *(string+(index++));
switch (final) {
case 'A':
this->cur_y -= clamp(strToInt(parameterStart), 0, this->cur_y);
break;
case 'B':
this->cur_y += clamp(strToInt(parameterStart), 0, this->height - this->cur_y);
break;
case 'C':
this->cur_x += clamp(strToInt(parameterStart), 0, this->width - this->cur_x);
break;
case 'D':
this->cur_x -= clamp(strToInt(parameterStart), 0, this->cur_x);
break;
case 'H': {
char* s=parameterStart;
while (*s != ';' && s < parameterEnd)
s++;
s++;
this->cur_y = clamp(strToInt(parameterStart), 1, this->height) - 1;
this->cur_x = clamp(strToInt(s), 1, this->width) - 1;
break;
}
}
continue;
}
if (current == '\b') {
if (this->cur_x > 0) {
this->cur_x--;
} else if (this->cur_y > 0) {
this->cur_y--;
this->cur_x = this->width-1;
}
int mem_pos = this->cur_y * this->width + this->cur_x;
this->putchar(mem_pos, ' ');
continue;
}
if (this->cur_x == this->width) {
this->cur_x = 0;
this->cur_y++;
}
if (this->cur_y == this->height)
this->scroll_up();
if (current != '\n') {
int mem_pos = this->cur_y * this->width + this->cur_x++;
this->putchar(mem_pos, current);
}
}
this->set_curpos(this->cur_x, this->cur_y);
} }
int Terminal::read(uint32_t count, uint8_t* buffer) {} int Terminal::read(uint32_t count, uint8_t* buffer) {}

View File

@ -1,14 +1,137 @@
#include "../common/common.h" #include "../common/common.h"
#include <stdbool.h> #include <stdbool.h>
void scrollBuffer(char* buf) {
for (int y=0; y<21; y++)
for (int x=0; x<38; x++)
if (y != 20)
buf[y*38+x] = buf[(y+1)*38+x];
else
buf[y*38+x] = ' ';
}
void writeToBuf(char c, char* buf, int* cx, int* cy) {
switch (c) {
case '\n':
*cx = 0;
(*cy)++;
break;
case '\b':
if (*cx > 0)
(*cx)--;
else if (*cy > 0) {
*cx = 37;
(*cy)--;
}
buf[(*cy)*38+(*cx)] = ' ';
break;
default:
buf[(*cy)*38+(*cx)++] = c;
}
if (*cx == 38) {
*cx = 0;
(*cy)++;
}
if (*cy == 21) {
(*cy)--;
scrollBuffer(buf);
}
}
void writeStrToBuf(char* c, char* buf, int* cx, int* cy) {
char* s = c;
while(*s)
writeToBuf(*(s++), buf, cx, cy);
}
void displayBuf(char* buf, int dx, int dy) {
char pset[9] = "\x1b[00;00H";
for (int i=0; i<dy;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<dx;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
for (int i=0; i<21; i++) {
print(pset);
write(38, 0, buf+(38*i));
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
}
int main() { int main() {
bindToKeyboard(); bindToKeyboard();
print("Hello from Ring 3!\n"); char space = ' ';
char plus = '+';
print("\x1b[1;1H");
for (int i=0; i < 1000; i++)
write(1, 0, &space);
print("\x1b[1;1H");
char* mid = "+ ++ +";
char* bottom = "+ +";
for (int i=0; i<80;i++)
write(1, 0, &plus);
for (int i=0; i<21;i++)
write(80, 0, mid);
for (int i=0; i<80;i++)
write(1, 0, &plus);
write(80, 0, bottom);
for (int i=0; i<80;i++)
write(1, 0, &plus);
char* hello_bin = "HELLO BIN";
uint32_t p1 = fork(hello_bin);
uint32_t p2 = fork(hello_bin);
uint32_t p1out = bindStdout(p1);
uint32_t p1in = bindStdin(p1);
uint32_t p2out = bindStdout(p2);
uint32_t p2in = bindStdin(p2);
char* buf1 = localalloc(21 * 38);
char* buf2 = localalloc(21 * 38);
int b1cx = 0;
int b1cy = 0;
int b2cx = 0;
int b2cy = 0;
char* selectedBuf = buf1;
uint32_t selectedOut = p1out;
uint32_t selectedIn = p1in;
while (1) { while (1) {
char c; char c;
if (read(1, 1, &c)) if (read(1, selectedOut, &c))
write(1, 0, &c); writeToBuf(c, selectedBuf, &b1cx, &b1cy);
if (read(1, p2out, &c))
writeToBuf(c, buf2, &b2cx, &b2cy);
if (read(1, 1, &c)) {
write(1, selectedIn, &c);
write(1, p2in, &c);
}
displayBuf(selectedBuf, 2, 2);
displayBuf(buf2, 42, 2);
} }
} }