Miscellaneous changes and fixed (I think?) virtual 8086 mode

This commit is contained in:
Xnoe 2025-01-08 18:46:58 +00:00
parent b00f6d6217
commit fafae757e1
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
47 changed files with 908 additions and 727 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"random": "cpp"
}
}

View File

@ -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 $^
ld -o $@ -T $^

View File

@ -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<countRDEs; i++) {
bool found = strcmp(rootDirEntries+(i*32), filename, 11);
if (found) {
uint16_t* correctEntry = (rootDirEntries+(i*32));
uint16_t* correctEntry = (uint16_t*)(rootDirEntries+(i*32));
return correctEntry[13];
}
}

View File

@ -10,7 +10,7 @@ typedef struct {
uint32_t acpi3_extended;
}__attribute__((packed)) e820entry;
uint8_t* bitmap = 0x100000;
uint8_t* bitmap = (uint8_t*)0x100000;
void set_bit(uint32_t offset, uint8_t* buffer) {
uint32_t index = offset / 8;
@ -61,7 +61,7 @@ void main() {
init_atapio();
// e820 memory map exists at 0x20000
e820entry* e820_entries = 0x20000;
e820entry* e820_entries = (e820entry*)0x20000;
// Zero out the bitmap.
memset(bitmap, 0x20000, 0);
@ -93,11 +93,11 @@ void main() {
}
}
mark_unavailble(bitmap, 0x20000, bitmap);
mark_unavailble((uint32_t)bitmap, 0x20000, bitmap);
mark_unavailble(0, 0xFFFFF, bitmap);
// Page Directory
PDE* kernel_page_directory = bitmap + 0x20000;
PDE* kernel_page_directory = (PDE*)(bitmap + 0x20000);
// Clear the PD
memset((uint8_t*)kernel_page_directory, 4096, 0);
@ -110,7 +110,7 @@ void main() {
((uint32_t*)0x521000)[i] = 0x121000 + 0x1000*i;
}
PTE** kernel_page_tables = 0x521000;
PTE** kernel_page_tables = (PTE**)0x521000;
for (int i = 0; i < 1023; i++) {
kernel_page_directory[i] = (PDE){
@ -130,15 +130,15 @@ void main() {
}
// Mark unavailable bitmap to 0x522000
mark_unavailble(bitmap, 0x4000000, bitmap);
mark_unavailble((uint32_t)bitmap, 0x4000000, bitmap);
// Now we want to map some stuff.
// But first, we should load the kernel somewhere
uint8_t* kernel_location = 0x542000; // Just load it at 0x524000 for now
mark_unavailble(kernel_location, 0x20000, bitmap); // Just treat the kernel as not growing beyond 128k for now.
uint8_t* kernel_location = (uint8_t*)0x542000; // Just load it at 0x524000 for now
mark_unavailble((uint32_t)kernel_location, 0x20000, bitmap); // Just treat the kernel as not growing beyond 128k for now.
map_many_4k_phys_to_virt(kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 pages from 0x522000 to 0xc0000000;
map_many_4k_phys_to_virt((uint32_t)kernel_location, 0xc0000000, kernel_page_directory, kernel_page_tables, 0x20); // Map 32 pages from 0x522000 to 0xc0000000;
map_4k_phys_to_virt((uint32_t)kernel_page_directory, 0xc0100000, kernel_page_directory, kernel_page_tables); // Map the page directory to 0xc0100000
map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000
map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000
@ -148,8 +148,8 @@ void main() {
mark_unavailble(0xa0000, 0x20000, bitmap);
uint8_t* vm_bitmap = 0x522000;
mark_unavailble(vm_bitmap, 0x20000, bitmap);
uint8_t* vm_bitmap = (uint8_t*)0x522000;
mark_unavailble((uint32_t)vm_bitmap, 0x20000, bitmap);
memset(vm_bitmap, 0x20000, 0xff);
mark_unavailble(0xc07a0000, 0x20000, vm_bitmap);
@ -189,8 +189,8 @@ void main() {
asm volatile ("mov %0, %%esp":: "r"(0xc1000000 + 16*0x1000));
KernelInformationStruct kstruct= (KernelInformationStruct){
.pde = 0xc0100000,
.page_directory_phys_addr = kernel_page_directory,
.pde = (PDE*)0xc0100000,
.page_directory_phys_addr = (uint32_t)kernel_page_directory,
.page_directory_phys_offset = 0xc0100000 - (uint32_t)kernel_page_directory,
.page_bitmap_phys = 0xc0600000,
.page_bitmap_virt = 0xc0620000,

View File

@ -34,4 +34,5 @@ typedef struct {
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables);
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
void map_many_4k_phys_to_virt_pl3(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
#endif

View File

@ -3,6 +3,7 @@
_start:
mov ax, 10h
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 90000h

View File

@ -19,6 +19,63 @@
#include "syscalls.h"
char** environ = 0;
uint32_t strcmpc(char* a, char* b, char c) {
for (int i=0; a[i] && b[i]; i++) {
if (a[i] == c)
return i;
}
return 0;
}
void __setup(uint32_t argc, char** argv, char** envp) {
environ = envp;
}
char* getenv(char* key) {
for (int i=0; environ[i]; i++) {
uint32_t pos;
if (pos = strcmpc(environ[i], key, '=')) {
return key+pos+1;
}
}
return 0;
}
void setenv(char* key, char* value) {
uint32_t environ_count = 0;
for (int i=0; environ[i]; i++)
environ_count += 1;
char** new_environ = (char**)malloc((environ_count+2)*sizeof(char*));
for (int i=0; i<environ_count; i++)
new_environ[i] = environ[i];
uint32_t key_size = strlen(key);
uint32_t value_size = strlen(value);
char* new_entry = (char*)malloc(key_size + value_size + 2);
memcpy(new_entry, key, key_size);
new_entry[key_size] = '=';
memcpy(new_entry+key_size+1, value, value_size);
new_entry[key_size+1+value_size] = 0;
new_environ[environ_count] = new_entry;
new_environ[environ_count+1] = 0;
environ = new_environ;
}
uint32_t strlen(char* s) {
uint32_t i=0;
while (s[i]) i++;
return i;
}
bool strcmp(char* a, char* b) {
for (int i=0; a[i] && b[i]; i++)
if (a[i] != b[i])
return false;
return true;
}
void print(char* string) {
char* c = string;
int i=0;
@ -59,6 +116,10 @@ int int_to_hex(unsigned int number, char* string_buffer) {
return (index+1);
}
bool isnum(char c) {
return c >= 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; i<count; i++) {
((char*)ptr)[i] = c;
}
}
void memcpy(void* dst, void* src, uint32_t count) {
for (int i=0; i<count; i++)
((char*)dst)[i] = ((char*)src)[i];
}
uint32_t exec(uint32_t fh) {
uint8_t* zero = 0;
return execve(fh, &zero, (uint8_t**)environ);
}
uint32_t execv(uint32_t fh, char** argv) {
return execve(fh, (uint8_t**)argv, (uint8_t**)environ);
}

View File

@ -40,9 +40,19 @@ typedef struct {
#include "syscalls.h"
char* getenv(char* key);
void setenv(char* key, char* value);
uint32_t strlen(char* s);
bool strcmp(char* a, char* b);
void memset(void* ptr, char c, uint32_t count);
void memcpy(void* dst, void* src, uint32_t count);
void print(char* string);
int int_to_decimal(unsigned int number, char* string_buffer);
int int_to_hex(unsigned int number, char* string_buffer);
void printf(const char* string, ...);
uint32_t exec(uint32_t fh);
uint32_t execv(uint32_t fh, char** argv);
#endif

View File

@ -7,9 +7,9 @@ syscall_hdlr_1(FSType, type, "3", char*, path);
syscall_hdlr_1(void*, malloc, "4", uint32_t, size);
syscall_hdlr_1(void, free, "5", void*, ptr);
syscall_hdlr_0(uint32_t, getMillisecondsElapsed, "6");
syscall_hdlr_1(uint32_t, exec, "7", uint32_t, filehandler);
syscall_hdlr_3(uint32_t, execve, "7", uint32_t, fh, uint8_t**, argv, uint8_t**, envp);
syscall_hdlr_0(uint32_t, getPID, "8");
syscall_hdlr_0(void, die, "9");
syscall_hdlr_1(void, die, "9", uint32_t, exit);
syscall_hdlr_3(int, read, "10", uint32_t, count, uint32_t, filehandler, uint8_t*, buffer);
syscall_hdlr_3(int, write, "11", uint32_t, count, uint32_t, filehandler, const uint8_t*, buffer);
syscall_hdlr_0(void, bindToKeyboard, "12");
@ -22,10 +22,10 @@ syscall_hdlr_1(void, sleep, "18", uint32_t, time);
syscall_hdlr_0(uint32_t, getRemainingPages, "19");
syscall_hdlr_0(uint32_t, getInitPages, "20");
syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");
syscall_hdlr_1(uint32_t, getProcessState, "23", uint32_t, PID);
syscall_hdlr_1(void, spawnThread, "24", uint32_t, functionPointer);
syscall_hdlr_1(void, spawnThread, "24", uint32_t, functionPointer);
syscall_hdlr_0(uint32_t, fork, "25");
syscall_hdlr_1(bool, programRunning, "26", uint32_t, pid);

View File

@ -102,9 +102,8 @@ void ATA::ATAWrite(uint32_t sector, uint8_t* buffer) {
driveLock.unlock();
}
ATAReadWriter::ATAReadWriter(uint32_t owner, uint32_t bus):
ATA(bus),
ReadWriter(owner) {
ATAReadWriter::ATAReadWriter(uint32_t bus):
ATA(bus) {
this->currentPosition = 0;
}
@ -166,4 +165,5 @@ uint32_t ATAReadWriter::size() {
}
uint32_t ATAReadWriter::seek(uint32_t position) {
this->currentPosition = position;
}
return position;
}

View File

@ -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
#endif

View File

@ -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();

View File

@ -59,11 +59,12 @@ namespace xnoe {
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
if (current) {
while (current) {
xnoe::linkedlistelem<xnoe::tuple<key, value>>* next = current->next;
if (xnoe::get<0>(current->elem) == k) {
list->remove(current);
delete current;
}
current = current->next;
current = next;
}
}
}

View File

@ -1,5 +1,5 @@
#include "devfs.h"
DevFS::DevFS() {
addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0,0);});
addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0);});
}

View File

@ -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; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
@ -271,7 +271,7 @@ FSType FAT16FS::type(Path p) {
if (!end)
return NoExist;
char name83[11] = {' '};
char name83[12] = " ";
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
@ -307,7 +307,7 @@ ReadWriter* FAT16FS::open(Path p) {
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
if (!directoryEntries[i].directory)
return new FAT16FileReadWriter(0, ((uint32_t)directoryEntries[i].firstClusterHigh << 16) | directoryEntries[i].firstClusterLow, directoryEntries[i].size, this);
return new FAT16FileReadWriter(((uint32_t)directoryEntries[i].firstClusterHigh << 16) | directoryEntries[i].firstClusterLow, directoryEntries[i].size, this);
}
}
delete directoryEntries;
@ -398,4 +398,4 @@ void FAT16FS::getDents(Path p, FSDirectoryListing* buffer) {
}
delete directoryEntries;
}
}

View File

@ -74,7 +74,7 @@ private:
FAT16FS* backingFS;
public:
FAT16FileReadWriter(uint32_t owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS);
FAT16FileReadWriter(uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
@ -96,7 +96,7 @@ public:
ReadWriter* backingDevice;
bool pathEntryTo83(PathEntry pe, char* buffer);
void pathEntryTo83(PathEntry pe, char* buffer);
uint32_t clusterToSector(uint32_t cluster);
void load_file(uint32_t location, uint8_t* destination);
@ -116,4 +116,4 @@ public:
void getDents(Path p, FSDirectoryListing* buffer) override;
};
#endif
#endif

View File

@ -16,11 +16,11 @@ bool operator!=(const PathEntry& lhs, const PathEntry& rhs) {
}
// FS Tree Skeleton
bool FSTree::exists(Path p){}
FSType FSTree::type(Path p){}
ReadWriter* FSTree::open(Path p){}
uint32_t FSTree::getDentsSize(Path p){}
void FSTree::getDents(Path p, FSDirectoryListing* buffer){}
bool FSTree::exists(Path p){return;}
FSType FSTree::type(Path p){return;}
ReadWriter* FSTree::open(Path p){return;}
uint32_t FSTree::getDentsSize(Path p){return;}
void FSTree::getDents(Path p, FSDirectoryListing* buffer){return;}
// RootFSTree
@ -267,4 +267,4 @@ Path createPathFromString(char* s) {
if (length)
p.append(PathEntry{length, lastPtr});
return p;
}
}

View File

@ -5,24 +5,24 @@ SysFS::SysFS() {
uint32_t remainingPages = Global::kernel->phys->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);
});
}

View File

@ -80,7 +80,7 @@ nextPE:
}
bool VFS::exists(Path p) {
return false;
return getEntry(p);
}
ReadWriter* VFS::open(Path p) {

View File

@ -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<uint32_t, uint32_t, void(*)(frame_struct*, void*), void*, bool>;
using TimedEvent = xnoe::tuple<uint32_t, uint32_t, void(*)(void*), void*, bool>;
xnoe::linkedlist<TimedEvent> timed_events;
void tick(frame_struct* frame) {
void tick(frame_struct* _) {
xnoe::linkedlistelem<TimedEvent>* 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<ReadWriter*> 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<ReadWriter*> 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<ReadWriter*> 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<ReadWriter*> 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<Process*> 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<Process*> 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() {

View File

@ -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

View File

@ -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

View File

@ -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<uint32_t, Process*>();
this->tid_map = new xnoe::hashtable<uint32_t, Thread*>();
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; i<argc; i++)
argv_strings_length += strlen(argv[i]);
// Allocate space for the strings + new argv
char argv_strings[argv_strings_length];
char* argv_new[argc];
// Copy the strings, fill argv_new
for (int i=0, string_index=0; argv[i]; string_index+=strlen(argv[i++])) {
memcpy(&argv_strings[string_index], argv[i], strlen(argv[i]));
argv_new[i] = &argv_strings[string_index];
}
// envp is currently stored on the stack of the calling process
// We need to create a copy of it in the kernel stack for createProcess
// Determine the length of envp (null terminated)
uint32_t envc = 0;
if (envp)
for (int i=0; envp[i]; i++)
envc++;
// Determine the length of all stings under envp
uint32_t envp_strings_length = 0;
for (int i=0; i<envc; i++)
envp_strings_length += strlen(envp[i]);
// Allocate space for the strings + new envp
char envp_strings[envp_strings_length];
char* envp_new[envc];
// Copy the strings, fill envp_new
if (envc) {
for (int i=0, string_index=0; envp[i]; string_index+=strlen(envp[i++])) {
memcpy(&envp_strings[string_index], envp[i], strlen(envp[i]));
envp_new[i] = &envp_strings[string_index];
}
}
Process* p = new Process(this->PD, 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<Thread*>* 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<Thread*> 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] = {

View File

@ -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<uint32_t, Process*>* pid_map; // Map of PIDs -> Process*s
xnoe::hashtable<uint32_t, Thread*>* tid_map; // Map of TIDs -> Thread*s
xnoe::linkedlist<Process*> processes;
xnoe::linkedlist<Process*> 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);
};

View File

@ -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");
}
}

View File

@ -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<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint32_t address) {
xnoe::linkedlistelem<AllocTracker>* current = this->allocations.start;
@ -16,27 +17,29 @@ xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint
return xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*>();
}
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<ReadWriter*>(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<ReadWriter*>(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<xnoe::tuple<AllocTracker, void*>> allocations;
xnoe::linkedlistelem<AllocTracker>* current_old = p->allocations.start;
while (current_old) {
allocations.append(xnoe::tuple<AllocTracker, void*>(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<xnoe::tuple<AllocTracker, void*>>* 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<ReadWriter*> r;
if ((r=file_handlers->get(i)).is_ok())
if (r.get())
delete r.get();
r.get()->close();
}
xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
/*xnoe::linkedlistelem<Thread*>* 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<AllocTracker>);
// 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<AllocTracker>* elem = (xnoe::linkedlistelem<AllocTracker>*)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<AllocTracker>);
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);

View File

@ -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<AllocTracker> allocations;
xnoe::maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
xnoe::dynarray<ReadWriter*>* file_handlers;
Path currentWorkingDirectory;
static uint32_t currentPID;
public:
xnoe::dynarray<ReadWriter*>* file_handlers;
uint32_t PID;
uint32_t esp;
@ -59,12 +95,18 @@ public:
xnoe::linkedlist<Thread*> 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<AllocTracker> 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;

View File

@ -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) {

View File

@ -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;

View File

@ -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];

View File

@ -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;

View File

@ -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;
}

View File

@ -6,22 +6,17 @@
class ReadWriter {
private:
uint32_t owner;
xnoe::linkedlist<uint32_t> allowedRead;
xnoe::linkedlist<uint32_t> 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
#endif

View File

@ -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<<i);
for (int c=0; c<count4; c++) {
((uint32_t*)terminal->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; i<c; i++) {
@ -585,7 +585,7 @@ static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal*
outw(0x1ce, 5);
outw(0x1cf, bank++);
}
((uint32_t*)terminal->vga_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);
}
Timer::register_event(16, (void(*)(void*))&BGAModeTerminal::bufferToVRAM, this);
}

View File

@ -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;

17
src/programs/cat/main.c Normal file
View File

@ -0,0 +1,17 @@
#include "common/common.h"
int main(int argc, char** argv) {
for (int i=1; i<argc; i++) {
if (exists(argv[i])) {
uint32_t fh = fopen(argv[i]);
char buf[128];
uint32_t count;
while (count=read(128, fh, buf))
write(count, 0, buf);
fclose(fh);
} else {
printf("No such file or directory: %s", argv[i]);
break;
}
}
}

View File

@ -1,4 +0,0 @@
int main() {
// Cause a Division by zero by trying to divide by zero.
int x = 1 / 0;
}

7
src/programs/echo/main.c Normal file
View File

@ -0,0 +1,7 @@
#include "common/common.h"
int main(int argc, char** argv) {
for (int i=1; i<argc; i++) {
printf("%s%s", argv[i], (i==argc-1)?"\n":" ");
}
}

View File

@ -1,8 +1,11 @@
[BITS 32]
_start:
call __setup
call main
push eax
call die
extern die
extern main
extern main
extern __setup

View File

@ -0,0 +1,10 @@
#include "common/common.h"
int main() {
uint32_t pid = fork();
if (pid) {
printf("Parent PID: %d\nChild PID: %d\n", getPID(), pid);
} else {
printf("CHILD: Hello!\n");
}
}

View File

@ -1,42 +0,0 @@
#include "common/common.h"
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);
}
}
print("\n");
}
int main(int argc, char** argv) {
printf("Hi, I am %s, running with PID %d!\n", argv[0], getPID());
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");
}
}

21
src/programs/init/main.c Normal file
View File

@ -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);
}

View File

@ -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");
}

35
src/programs/ls/main.c Normal file
View File

@ -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 <directory>", 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; i<dents->count; i++) {
FSDirectoryEntry e = dents->entries[i];
printf("%.s %d %s\n", e.path.length, e.path.path, e.sizeBytes, filetype(e.type));
}
}

View File

@ -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);
}
}

View File

@ -1,340 +0,0 @@
#include "common/common.h"
#include <stdbool.h>
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; y<buf->height; y++)
for (int x=0; x<buf->width; 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; i<buf->height*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; i<y;i++) {
pset[4]++;
if (pset[4] == 0x3a) {
pset[4] = 0x30;
pset[3]++;
}
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<x;i++) {
pset[8]++;
if (pset[8] == 0x3a) {
pset[8] = 0x30;
pset[7]++;
}
if (pset[7] == 0x3a) {
pset[7] = 0x30;
pset[6]++;
}
}
print(pset);
}
void displayBuf(procbuffer* b, int dx, int dy) {
print("\x1b[42;36;1m");
char pset[9] = "\x1b[000;000H";
for (int i=0; i<b->height; 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<width;i++)
write(1, 0, &plus);
for (int i=0; i<bufferHeight;i++) {
write(1, 0, &plus);
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
write(1, 0, &plus);
for (int j=0; j<bufferWidth; j++)
write(1, 0, &space);
write(1, 0, &plus);
}
for (int i=0; i<width;i++)
write(1, 0, &plus);
write(1, 0, &plus);
for (int i=0; i< width - 2; i++)
write(1, 0, &space);
write(1, 0, &plus);
for (int i=0; i<width;i++)
write(1, 0, &plus);
uint32_t program = fopen("/hello.bin");
uint32_t p1 = exec(program);
uint32_t p1out = bindStdout(p1);
uint32_t p1in = bindStdin(p1);
fclose(program);
program = fopen("/timer.bin");
uint32_t p2 = exec(program);
uint32_t p2out = bindStdout(p2);
uint32_t p2in = bindStdin(p2);
fclose(program);
b1 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p1,
.stdin = p1in,
.stdout = p1out,
.width = bufferWidth,
.height = bufferHeight
};
b2 = (procbuffer) {
.buffer = malloc(bufferWidth * bufferHeight),
.x = 0,
.y = 0,
.process = p2,
.stdin = p2in,
.stdout = p2out,
.width = bufferWidth,
.height = bufferHeight
};
spawnThread(&displayBuffer1);
spawnThread(&displayBuffer2);
procbuffer* selectedBuf = &b1;
writeStrToBuf("XoSH (XOS SHell) v0.0.1\nPress : to use commands.\n :help for help.\n", &b1);
while (1) {
char c[128];
int succ = 0;
if (b2.process)
if (succ = read(128, b2.stdout, c))
writeCountToBuf(succ, c, &b2);
if (read(1, 1, c)) {
if (c[0] == ':') {
char buf[32] = {0};
print("\x1b[45;33;1m");
setCurPos(2, height-1);
print(": ");
setCurPos(3, height-1);
readline(32, buf);
if (strcmpcnt(6, buf, "switch")) {
if (selectedBuf == &b1) {
selectedBuf = &b2;
} else {
selectedBuf = &b1;
}
} else if (strcmpcnt(4, buf, "help")) {
writeStrToBuf("\n--------\n", selectedBuf);
writeStrToBuf(":help\n", selectedBuf);
writeStrToBuf(" Displays this message.\n", selectedBuf);
writeStrToBuf(":switch\n", selectedBuf);
writeStrToBuf(" Switches which process you're using\n", selectedBuf);
writeStrToBuf(":kill\n", selectedBuf);
writeStrToBuf(" Kills the current process\n", selectedBuf);
writeStrToBuf(":load <filename>\n", selectedBuf);
writeStrToBuf(" Loads and executes the program <filename>\n", selectedBuf);
writeStrToBuf(":ls <path>\n", selectedBuf);
writeStrToBuf(" Lists the files in directory <path>\n", selectedBuf);
writeStrToBuf(":clear\n", selectedBuf);
writeStrToBuf(" Clears the buffer\n", selectedBuf);
writeStrToBuf(":type <filename>\n", selectedBuf);
writeStrToBuf(" Writes out the contents of the file <filename>\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; i<listing->count; 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);
}
}
}
}

107
src/programs/xosh/main.c Normal file
View File

@ -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);
}
}
}
}