Add ability for other processes to bind to eachother's stdin and stdout. Add PoC for this functionality
This commit is contained in:
parent
55a5bea35a
commit
73c0fe429f
4
Makefile
4
Makefile
@ -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
|
||||||
|
|
||||||
|
@ -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" : : :);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
@ -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) {
|
||||||
|
@ -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,12 +154,15 @@ 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
|
||||||
@ -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);
|
||||||
|
@ -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));
|
||||||
//}
|
//}
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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) {}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user