Various additions
This commit is contained in:
parent
b00f6d6217
commit
5a70976f5d
@ -3,6 +3,7 @@
|
|||||||
_start:
|
_start:
|
||||||
mov ax, 10h
|
mov ax, 10h
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov esp, 90000h
|
mov esp, 90000h
|
||||||
|
|
||||||
|
@ -19,6 +19,63 @@
|
|||||||
|
|
||||||
#include "syscalls.h"
|
#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) {
|
void print(char* string) {
|
||||||
char* c = string;
|
char* c = string;
|
||||||
int i=0;
|
int i=0;
|
||||||
@ -59,6 +116,10 @@ int int_to_hex(unsigned int number, char* string_buffer) {
|
|||||||
return (index+1);
|
return (index+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isnum(char c) {
|
||||||
|
return c >= 0x30 && c <= 0x39;
|
||||||
|
}
|
||||||
|
|
||||||
void printf(const char* string, ...) {
|
void printf(const char* string, ...) {
|
||||||
va_list ptr;
|
va_list ptr;
|
||||||
va_start(ptr, string);
|
va_start(ptr, string);
|
||||||
@ -68,23 +129,48 @@ void printf(const char* string, ...) {
|
|||||||
|
|
||||||
while (current=string[index++]) {
|
while (current=string[index++]) {
|
||||||
if (current == '%') {
|
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 type = string[index++];
|
||||||
int offset;
|
int offset;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'd': {
|
case 'd': {
|
||||||
char decimal_buffer[11];
|
char decimal_buffer[11];
|
||||||
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
|
offset = int_to_decimal(va_arg(ptr, int), decimal_buffer);
|
||||||
printf(decimal_buffer + offset);
|
print(decimal_buffer + offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'x': {
|
case 'x': {
|
||||||
char hex_buffer[8];
|
char hex_buffer[8];
|
||||||
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
|
offset = int_to_hex(va_arg(ptr, int), hex_buffer);
|
||||||
printf(hex_buffer);
|
print(hex_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 's': {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
@ -103,3 +189,23 @@ void printf(const char* string, ...) {
|
|||||||
|
|
||||||
va_end(ptr);
|
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) {
|
||||||
|
char* zero = 0;
|
||||||
|
return execve(fh, &zero, environ);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t execv(uint32_t fh, char** argv) {
|
||||||
|
char* zero = 0;
|
||||||
|
return execve(fh, argv, environ);
|
||||||
|
}
|
@ -40,9 +40,19 @@ typedef struct {
|
|||||||
|
|
||||||
#include "syscalls.h"
|
#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);
|
void print(char* string);
|
||||||
int int_to_decimal(unsigned int number, char* string_buffer);
|
int int_to_decimal(unsigned int number, char* string_buffer);
|
||||||
int int_to_hex(unsigned int number, char* string_buffer);
|
int int_to_hex(unsigned int number, char* string_buffer);
|
||||||
void printf(const char* string, ...);
|
void printf(const char* string, ...);
|
||||||
|
|
||||||
|
uint32_t exec(uint32_t fh);
|
||||||
|
uint32_t execv(uint32_t fh, char** argv);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -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*, malloc, "4", uint32_t, size);
|
||||||
syscall_hdlr_1(void, free, "5", void*, ptr);
|
syscall_hdlr_1(void, free, "5", void*, ptr);
|
||||||
syscall_hdlr_0(uint32_t, getMillisecondsElapsed, "6");
|
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(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, 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_3(int, write, "11", uint32_t, count, uint32_t, filehandler, const uint8_t*, buffer);
|
||||||
syscall_hdlr_0(void, bindToKeyboard, "12");
|
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, getRemainingPages, "19");
|
||||||
syscall_hdlr_0(uint32_t, getInitPages, "20");
|
syscall_hdlr_0(uint32_t, getInitPages, "20");
|
||||||
|
|
||||||
syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
|
syscall_hdlr_0(uint32_t, getCurrentTerminalWidth, "21");
|
||||||
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");
|
syscall_hdlr_0(uint32_t, getCurrentTerminalHeight, "22");
|
||||||
|
|
||||||
syscall_hdlr_1(uint32_t, getProcessState, "23", uint32_t, PID);
|
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);
|
||||||
|
@ -102,9 +102,8 @@ void ATA::ATAWrite(uint32_t sector, uint8_t* buffer) {
|
|||||||
driveLock.unlock();
|
driveLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
ATAReadWriter::ATAReadWriter(uint32_t owner, uint32_t bus):
|
ATAReadWriter::ATAReadWriter(uint32_t bus):
|
||||||
ATA(bus),
|
ATA(bus) {
|
||||||
ReadWriter(owner) {
|
|
||||||
this->currentPosition = 0;
|
this->currentPosition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,4 +165,5 @@ uint32_t ATAReadWriter::size() {
|
|||||||
}
|
}
|
||||||
uint32_t ATAReadWriter::seek(uint32_t position) {
|
uint32_t ATAReadWriter::seek(uint32_t position) {
|
||||||
this->currentPosition = position;
|
this->currentPosition = position;
|
||||||
|
return position;
|
||||||
}
|
}
|
@ -99,7 +99,7 @@ private:
|
|||||||
Spinlock driveLock;
|
Spinlock driveLock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ATAReadWriter(uint32_t owner, uint32_t bus);
|
ATAReadWriter(uint32_t bus);
|
||||||
|
|
||||||
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
||||||
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
||||||
|
@ -21,6 +21,14 @@ namespace xnoe {
|
|||||||
this->index = this->start_index = start_index;
|
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) {
|
void push(T t) {
|
||||||
if (index == size) {
|
if (index == size) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
@ -59,11 +59,12 @@ namespace xnoe {
|
|||||||
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
|
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
|
||||||
if (current) {
|
if (current) {
|
||||||
while (current) {
|
while (current) {
|
||||||
|
xnoe::linkedlistelem<xnoe::tuple<key, value>>* next = current->next;
|
||||||
if (xnoe::get<0>(current->elem) == k) {
|
if (xnoe::get<0>(current->elem) == k) {
|
||||||
list->remove(current);
|
list->remove(current);
|
||||||
delete current;
|
delete current;
|
||||||
}
|
}
|
||||||
current = current->next;
|
current = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "devfs.h"
|
#include "devfs.h"
|
||||||
|
|
||||||
DevFS::DevFS() {
|
DevFS::DevFS() {
|
||||||
addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0,0);});
|
addEntry(createPathFromString("ata"), [](){return new ATAReadWriter(0);});
|
||||||
}
|
}
|
@ -11,8 +11,7 @@ uint32_t FAT16FileReadWriter::offsetBytesToCluster(uint32_t offset) {
|
|||||||
return cluster;
|
return cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
FAT16FileReadWriter::FAT16FileReadWriter(uint32_t owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS)
|
FAT16FileReadWriter::FAT16FileReadWriter(uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS) {
|
||||||
: ReadWriter(owner) {
|
|
||||||
this->firstCluster = firstCluster;
|
this->firstCluster = firstCluster;
|
||||||
this->sizeBytes = sizeBytes;
|
this->sizeBytes = sizeBytes;
|
||||||
this->currentPosition = 0;
|
this->currentPosition = 0;
|
||||||
@ -55,7 +54,7 @@ uint32_t FAT16FileReadWriter::read(uint32_t count, uint8_t* buffer) {
|
|||||||
return index;
|
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() {
|
uint32_t FAT16FileReadWriter::size() {
|
||||||
return this->sizeBytes;
|
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;
|
uint32_t maxSize = pe.length;
|
||||||
uint8_t* data = pe.path;
|
uint8_t* data = pe.path;
|
||||||
|
|
||||||
@ -244,7 +243,8 @@ bool FAT16FS::exists(Path p) {
|
|||||||
if (!end)
|
if (!end)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char name83[11] = {' '};
|
char name83[12] = " ";
|
||||||
|
name83[11] = 0;
|
||||||
pathEntryTo83(end->elem, name83);
|
pathEntryTo83(end->elem, name83);
|
||||||
for (int i=0; i<count; i++) {
|
for (int i=0; i<count; i++) {
|
||||||
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
||||||
@ -271,7 +271,7 @@ FSType FAT16FS::type(Path p) {
|
|||||||
if (!end)
|
if (!end)
|
||||||
return NoExist;
|
return NoExist;
|
||||||
|
|
||||||
char name83[11] = {' '};
|
char name83[12] = " ";
|
||||||
pathEntryTo83(end->elem, name83);
|
pathEntryTo83(end->elem, name83);
|
||||||
for (int i=0; i<count; i++) {
|
for (int i=0; i<count; i++) {
|
||||||
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
||||||
@ -307,7 +307,7 @@ ReadWriter* FAT16FS::open(Path p) {
|
|||||||
for (int i=0; i<count; i++) {
|
for (int i=0; i<count; i++) {
|
||||||
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
if (strcmp(directoryEntries[i].name, name83, 11)) {
|
||||||
if (!directoryEntries[i].directory)
|
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;
|
delete directoryEntries;
|
||||||
|
@ -74,7 +74,7 @@ private:
|
|||||||
|
|
||||||
FAT16FS* backingFS;
|
FAT16FS* backingFS;
|
||||||
public:
|
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 read(uint32_t count, uint8_t* buffer) override;
|
||||||
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
||||||
@ -96,7 +96,7 @@ public:
|
|||||||
|
|
||||||
ReadWriter* backingDevice;
|
ReadWriter* backingDevice;
|
||||||
|
|
||||||
bool pathEntryTo83(PathEntry pe, char* buffer);
|
void pathEntryTo83(PathEntry pe, char* buffer);
|
||||||
|
|
||||||
uint32_t clusterToSector(uint32_t cluster);
|
uint32_t clusterToSector(uint32_t cluster);
|
||||||
void load_file(uint32_t location, uint8_t* destination);
|
void load_file(uint32_t location, uint8_t* destination);
|
||||||
|
@ -16,11 +16,11 @@ bool operator!=(const PathEntry& lhs, const PathEntry& rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FS Tree Skeleton
|
// FS Tree Skeleton
|
||||||
bool FSTree::exists(Path p){}
|
bool FSTree::exists(Path p){return;}
|
||||||
FSType FSTree::type(Path p){}
|
FSType FSTree::type(Path p){return;}
|
||||||
ReadWriter* FSTree::open(Path p){}
|
ReadWriter* FSTree::open(Path p){return;}
|
||||||
uint32_t FSTree::getDentsSize(Path p){}
|
uint32_t FSTree::getDentsSize(Path p){return;}
|
||||||
void FSTree::getDents(Path p, FSDirectoryListing* buffer){}
|
void FSTree::getDents(Path p, FSDirectoryListing* buffer){return;}
|
||||||
|
|
||||||
// RootFSTree
|
// RootFSTree
|
||||||
|
|
||||||
|
@ -5,24 +5,24 @@ SysFS::SysFS() {
|
|||||||
uint32_t remainingPages = Global::kernel->phys->remainingPages;
|
uint32_t remainingPages = Global::kernel->phys->remainingPages;
|
||||||
char str[11];
|
char str[11];
|
||||||
uint32_t offset = int_to_decimal(remainingPages, str);
|
uint32_t offset = int_to_decimal(remainingPages, str);
|
||||||
return new OneShotReadWriter(0, str+offset);
|
return new OneShotReadWriter(str+offset);
|
||||||
});
|
});
|
||||||
addEntry(createPathFromString("initPages"), [](){
|
addEntry(createPathFromString("initPages"), [](){
|
||||||
uint32_t initPages = Global::kernel->phys->initPages;
|
uint32_t initPages = Global::kernel->phys->initPages;
|
||||||
char str[11];
|
char str[11];
|
||||||
uint32_t offset = int_to_decimal(initPages, str);
|
uint32_t offset = int_to_decimal(initPages, str);
|
||||||
return new OneShotReadWriter(0, str+offset);
|
return new OneShotReadWriter(str+offset);
|
||||||
});
|
});
|
||||||
addEntry(createPathFromString("terminalWidth"), [](){
|
addEntry(createPathFromString("terminalWidth"), [](){
|
||||||
uint32_t termWidth = Global::kernel->terminal->width;
|
uint32_t termWidth = Global::kernel->terminal->width;
|
||||||
char str[11];
|
char str[11];
|
||||||
uint32_t offset = int_to_decimal(termWidth, str);
|
uint32_t offset = int_to_decimal(termWidth, str);
|
||||||
return new OneShotReadWriter(0, str+offset);
|
return new OneShotReadWriter(str+offset);
|
||||||
});
|
});
|
||||||
addEntry(createPathFromString("terminalHeight"), [](){
|
addEntry(createPathFromString("terminalHeight"), [](){
|
||||||
uint32_t termHeight = Global::kernel->terminal->height;
|
uint32_t termHeight = Global::kernel->terminal->height;
|
||||||
char str[11];
|
char str[11];
|
||||||
uint32_t offset = int_to_decimal(termHeight, str);
|
uint32_t offset = int_to_decimal(termHeight, str);
|
||||||
return new OneShotReadWriter(0, str+offset);
|
return new OneShotReadWriter(str+offset);
|
||||||
});
|
});
|
||||||
}
|
}
|
@ -80,7 +80,7 @@ nextPE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VFS::exists(Path p) {
|
bool VFS::exists(Path p) {
|
||||||
return false;
|
return getEntry(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadWriter* VFS::open(Path p) {
|
ReadWriter* VFS::open(Path p) {
|
||||||
|
@ -22,35 +22,37 @@ void set_entry(uint8_t interrupt_number, uint16_t code_segment, void(*handler)()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handle_fault(frame_struct* frame) {
|
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.
|
// 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("\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) {
|
switch (frame->gate) {
|
||||||
case 0: // Divide by zero
|
case 0: // Divide by zero
|
||||||
//Global::kernel->terminal->printf("Divide by Zero");
|
Global::kernel->terminal->printf("Divide by Zero");
|
||||||
break;
|
break;
|
||||||
case 6: // Invalid Opcode
|
case 6: // Invalid Opcode
|
||||||
//Global::kernel->terminal->printf("Invalid Opcode");
|
Global::kernel->terminal->printf("Invalid Opcode");
|
||||||
break;
|
break;
|
||||||
case 13: // GPF
|
case 13: // GPF
|
||||||
//Global::kernel->terminal->printf("General Protection Fault!");
|
Global::kernel->terminal->printf("General Protection Fault!");
|
||||||
if (frame->eflags & 0x00020000) {
|
if (frame->eflags & 0x00020000) {
|
||||||
v86_monitor((v8086_frame_struct*)frame);
|
v86_monitor((v8086_frame_struct*)frame);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14: // Page Fault
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
//Global::kernel->terminal->printf("Unkown Fault!");
|
Global::kernel->terminal->printf("Unkown Fault! Gate: %d", frame->gate);
|
||||||
break;
|
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)) {
|
if (!(frame->cs & 3)) {
|
||||||
Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n");
|
Global::kernel->terminal->printf("[FATAL] Kernel Fault!!!\n");
|
||||||
|
((VGAModeTerminal*)Global::kernel->terminal)->bufferToVRAM();
|
||||||
while (1) asm("hlt");
|
while (1) asm("hlt");
|
||||||
} else {
|
} else {
|
||||||
// Print an error message.
|
// Print an error message.
|
||||||
@ -62,13 +64,14 @@ void handle_fault(frame_struct* frame) {
|
|||||||
Global::kernel->destroyProcess(Global::currentProc);
|
Global::kernel->destroyProcess(Global::currentProc);
|
||||||
|
|
||||||
Global::currentProcValid = false;
|
Global::currentProcValid = false;
|
||||||
context_switch(frame);
|
context_switch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignore_interrupt(frame_struct* frame) {}
|
void ignore_interrupt() {}
|
||||||
|
|
||||||
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
|
// 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
|
||||||
//
|
//
|
||||||
@ -91,9 +94,6 @@ void context_switch(frame_struct* frame) {
|
|||||||
while (1) asm ("hlt");
|
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
|
// 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
|
||||||
@ -128,11 +128,8 @@ void context_switch(frame_struct* frame) {
|
|||||||
Global::currentProc = threads->start->elem->parent;
|
Global::currentProc = threads->start->elem->parent;
|
||||||
} while (Global::currentThread->state != Running);
|
} while (Global::currentThread->state != Running);
|
||||||
|
|
||||||
|
|
||||||
// Select the next processes page directory
|
// Select the next processes page directory
|
||||||
frame->new_cr3 = Global::currentThread->parent->PD->phys_addr;
|
Global::currentThread->frame.new_cr3 = Global::currentThread->parent->PD->phys_addr;
|
||||||
// Restore kernelStackPtr of the new process.
|
|
||||||
frame->new_esp = Global::currentThread->kernelStackPtr;
|
|
||||||
|
|
||||||
Global::tss->esp0 = Global::currentThread->kernelStackPtrDefault;
|
Global::tss->esp0 = Global::currentThread->kernelStackPtrDefault;
|
||||||
|
|
||||||
@ -142,15 +139,15 @@ void context_switch(frame_struct* frame) {
|
|||||||
|
|
||||||
namespace Timer {
|
namespace Timer {
|
||||||
// counter, default count, function, argument, oneshot
|
// 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;
|
xnoe::linkedlist<TimedEvent> timed_events;
|
||||||
void tick(frame_struct* frame) {
|
void tick() {
|
||||||
xnoe::linkedlistelem<TimedEvent>* current = timed_events.start;
|
xnoe::linkedlistelem<TimedEvent>* current = timed_events.start;
|
||||||
while (current) {
|
while (current) {
|
||||||
TimedEvent t = current->elem;
|
TimedEvent t = current->elem;
|
||||||
uint32_t count = xnoe::get<0>(t);
|
uint32_t count = xnoe::get<0>(t);
|
||||||
if (--count == 0) {
|
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);
|
count = xnoe::get<1>(t);
|
||||||
|
|
||||||
if (xnoe::get<4>(t)) {
|
if (xnoe::get<4>(t)) {
|
||||||
@ -167,16 +164,16 @@ namespace Timer {
|
|||||||
Global::milliseconds_elapsed++;
|
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));
|
timed_events.append(TimedEvent(milliseconds, milliseconds, function, auxiliary, oneshot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void awaken(frame_struct* frame, Thread* t) {
|
void awaken(Thread* t) {
|
||||||
t->state = Running;
|
t->state = Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void syscall(frame_struct* frame) {
|
void syscall() {
|
||||||
// Syscall ABI:
|
// Syscall ABI:
|
||||||
// 0: getDentsSize :: char* path -> uint32_t size
|
// 0: getDentsSize :: char* path -> uint32_t size
|
||||||
// 1: getDents :: char* path -> uint8_t* buffer -> void
|
// 1: getDents :: char* path -> uint8_t* buffer -> void
|
||||||
@ -214,87 +211,93 @@ void syscall(frame_struct* frame) {
|
|||||||
// 2..7: Reserved
|
// 2..7: Reserved
|
||||||
// _: General use
|
// _: General use
|
||||||
|
|
||||||
uint32_t rval = frame->eax;
|
frame_struct* frame = &Global::currentThread->frame;
|
||||||
|
|
||||||
Process* currentProc = Global::currentProc;
|
Process* currentProc = Global::currentProc;
|
||||||
|
|
||||||
switch (frame->eax) {
|
switch (frame->eax) {
|
||||||
case 0: // getDentsSize
|
case 0: // getDentsSize
|
||||||
rval = Global::kernel->rootfs->getDentsSize(createPathFromString(frame->ebx));
|
frame->eax = Global::kernel->rootfs->getDentsSize(createPathFromString(frame->ebx));
|
||||||
break;
|
break;
|
||||||
case 1: // getDents
|
case 1: // getDents
|
||||||
Global::kernel->rootfs->getDents(createPathFromString(frame->ebx), frame->ecx);
|
Global::kernel->rootfs->getDents(createPathFromString(frame->ebx), frame->ecx);
|
||||||
break;
|
break;
|
||||||
case 2: // exists
|
case 2: // exists
|
||||||
rval = Global::kernel->rootfs->exists(createPathFromString(frame->ebx));
|
frame->eax = Global::kernel->rootfs->exists(createPathFromString(frame->ebx));
|
||||||
break;
|
break;
|
||||||
case 3: // type
|
case 3: // type
|
||||||
rval = Global::kernel->rootfs->type(createPathFromString(frame->ebx));
|
frame->eax = Global::kernel->rootfs->type(createPathFromString(frame->ebx));
|
||||||
break;
|
break;
|
||||||
case 4: // malloc
|
case 4: // malloc
|
||||||
rval = currentProc->allocate(frame->ebx);
|
frame->eax = currentProc->allocate(frame->ebx);
|
||||||
break;
|
break;
|
||||||
case 5: // free
|
case 5: // free
|
||||||
currentProc->deallocate(frame->ebx);
|
currentProc->deallocate(frame->ebx);
|
||||||
break;
|
break;
|
||||||
case 6: // getMillisecondsElapsed
|
case 6: // getMillisecondsElapsed
|
||||||
rval = Global::milliseconds_elapsed;
|
frame->eax = Global::milliseconds_elapsed;
|
||||||
break;
|
break;
|
||||||
case 7: { // exec
|
|
||||||
|
case 7: {// execve
|
||||||
asm("cli");
|
asm("cli");
|
||||||
xnoe::maybe<ReadWriter*> file = Global::currentProc->getFH(frame->ebx);
|
xnoe::maybe<ReadWriter*> file = Global::currentProc->getFH(frame->ebx);
|
||||||
if (file.is_ok()) {
|
if (file.is_ok()) {
|
||||||
Process* p = Global::kernel->createProcess(file.get());
|
Process* p = Global::kernel->createProcess(file.get(), (uint8_t**)frame->ecx, (uint8_t**)frame->edx);
|
||||||
rval = p->PID;
|
|
||||||
|
// 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 {
|
} else {
|
||||||
rval = 0;
|
frame->eax = 0;
|
||||||
}
|
}
|
||||||
asm("sti");
|
asm("sti");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: // getPID
|
case 8: // getPID
|
||||||
rval = currentProc->PID;
|
frame->eax = currentProc->PID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9: // die
|
case 9: { // die
|
||||||
Global::kernel->PD->select();
|
Global::kernel->PD->select();
|
||||||
|
Global::kernel->destroyProcess(Global::currentProc, frame->ebx);
|
||||||
// We can now safely delete the current process
|
|
||||||
Global::kernel->destroyProcess(Global::currentProc);
|
|
||||||
|
|
||||||
Global::currentProcValid = false;
|
Global::currentProcValid = false;
|
||||||
context_switch(frame);
|
context_switch();
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case 10: { // read
|
case 10: { // read
|
||||||
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
|
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
|
||||||
if (!fh.is_ok()) {
|
if (!fh.is_ok()) {
|
||||||
rval = 0;
|
frame->eax = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadWriter* rw = fh.get();
|
ReadWriter* rw = fh.get();
|
||||||
rval = rw->read(frame->ebx, frame->edx);
|
frame->eax = rw->read(frame->ebx, frame->edx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 11: { // write
|
case 11: { // write
|
||||||
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
|
xnoe::maybe<ReadWriter*> fh = Global::currentProc->getFH(frame->ecx);
|
||||||
if (!fh.is_ok()) {
|
if (!fh.is_ok()) {
|
||||||
rval = 0;
|
frame->eax = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadWriter* rw = fh.get();
|
ReadWriter* rw = fh.get();
|
||||||
rval = rw->write(frame->ebx, frame->edx);
|
frame->eax = rw->write(frame->ebx, frame->edx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 12: // bindToKeyboard
|
case 12: // bindToKeyboard
|
||||||
if (currentProc->stdin)
|
if (currentProc->stdin)
|
||||||
break;
|
currentProc->stdin->close();
|
||||||
|
|
||||||
currentProc->stdin = new CircularRWBuffer(currentProc->PID, 0);
|
currentProc->stdin = new CircularRWBuffer();
|
||||||
Global::kernel->KBListeners.append(currentProc);
|
Global::kernel->KBListeners.append(currentProc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -303,11 +306,12 @@ void syscall(frame_struct* frame) {
|
|||||||
if (!pm.is_ok())
|
if (!pm.is_ok())
|
||||||
break;
|
break;
|
||||||
Process* p = pm.get();
|
Process* p = pm.get();
|
||||||
if (!p->stdout) {
|
//if (!p->stdout) {
|
||||||
ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx);
|
//ReadWriter* buffer = new CircularRWBuffer(currentProc->PID, frame->ebx);
|
||||||
p->stdout = buffer;
|
//p->stdout = buffer;
|
||||||
rval = Global::currentProc->mapFH(buffer);
|
p->stdout->open();
|
||||||
}
|
frame->eax = Global::currentProc->mapFH(p->stdout);
|
||||||
|
//}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,25 +320,26 @@ void syscall(frame_struct* frame) {
|
|||||||
if (!pm.is_ok())
|
if (!pm.is_ok())
|
||||||
break;
|
break;
|
||||||
Process* p = pm.get();
|
Process* p = pm.get();
|
||||||
if (!p->stdin) {
|
//if (!p->stdin) {
|
||||||
ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID);
|
//ReadWriter* buffer = new CircularRWBuffer(frame->ebx, currentProc->PID);
|
||||||
p->stdin = buffer;
|
//p->stdin = buffer;
|
||||||
rval = Global::currentProc->mapFH(buffer);
|
p->stdin->open();
|
||||||
}
|
frame->eax = Global::currentProc->mapFH(p->stdin);
|
||||||
|
//}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 15: { // fopen
|
case 15: { // fopen
|
||||||
ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(frame->ebx));
|
ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(frame->ebx));
|
||||||
if (file)
|
if (file)
|
||||||
rval = Global::currentProc->mapFH(file);
|
frame->eax = Global::currentProc->mapFH(file);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 16: { // fclose
|
case 16: { // fclose
|
||||||
xnoe::maybe<ReadWriter*> f = Global::currentProc->getFH(frame->ebx);
|
xnoe::maybe<ReadWriter*> f = Global::currentProc->getFH(frame->ebx);
|
||||||
if (f.is_ok()) {
|
if (f.is_ok()) {
|
||||||
delete f.get();
|
f.get()->close();
|
||||||
Global::currentProc->unmapFH(frame->ebx);
|
Global::currentProc->unmapFH(frame->ebx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -354,45 +359,61 @@ void syscall(frame_struct* frame) {
|
|||||||
case 18: { // sleep
|
case 18: { // sleep
|
||||||
Global::currentThread->state = Suspended;
|
Global::currentThread->state = Suspended;
|
||||||
Timer::register_event(frame->ebx, &awaken, (void*)Global::currentThread, true);
|
Timer::register_event(frame->ebx, &awaken, (void*)Global::currentThread, true);
|
||||||
context_switch(frame);
|
context_switch();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 19: // getRemainingPages
|
case 19: // getRemainingPages
|
||||||
rval = Global::kernel->phys->remainingPages;
|
frame->eax = Global::kernel->phys->remainingPages;
|
||||||
break;
|
break;
|
||||||
case 20: // getInitPages
|
case 20: // getInitPages
|
||||||
rval = Global::kernel->phys->initPages;
|
frame->eax = Global::kernel->phys->initPages;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 21: // getTerminalWidth
|
case 21: // getTerminalWidth
|
||||||
rval = Global::kernel->terminal->width;
|
frame->eax = Global::kernel->terminal->width;
|
||||||
break;
|
break;
|
||||||
case 22: // getTerminalHeight
|
case 22: // getTerminalHeight
|
||||||
rval = Global::kernel->terminal->height;
|
frame->eax = Global::kernel->terminal->height;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 23: { // getProcessState
|
case 23: { // getProcessState
|
||||||
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
|
xnoe::maybe<Process*> p = Global::kernel->pid_map->get(frame->ebx);
|
||||||
if (p.is_ok()) {
|
if (p.is_ok()) {
|
||||||
Process* proc = p.get();
|
Process* proc = p.get();
|
||||||
//rval = proc->state;
|
//frame->eax = proc->state;
|
||||||
}
|
}
|
||||||
break;
|
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* thread = new Thread(Global::currentProc);
|
||||||
thread->initKernelStack(frame->ebx, thread->stack);
|
thread->initKernelStack(frame->ebx, thread->stack);
|
||||||
Global::kernel->threads.append(thread);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->eax = rval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void v86_monitor(v8086_frame_struct* frame) {
|
void v86_monitor(v8086_frame_struct* frame) {
|
||||||
|
@ -7,32 +7,6 @@
|
|||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "stdio/circularrwbuffer.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 {
|
struct __attribute__((packed)) v8086_frame_struct {
|
||||||
uint32_t new_cr3;
|
uint32_t new_cr3;
|
||||||
uint32_t new_esp;
|
uint32_t new_esp;
|
||||||
@ -90,10 +64,10 @@ struct __attribute__((packed)) idt_desc {
|
|||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void context_switch(frame_struct* frame);
|
void context_switch();
|
||||||
void handle_fault(frame_struct* frame);
|
void handle_fault(frame_struct* frame);
|
||||||
void syscall(frame_struct* frame);
|
void syscall();
|
||||||
void ignore_interrupt(frame_struct* frame);
|
void ignore_interrupt();
|
||||||
void v86_monitor(v8086_frame_struct* frame);
|
void v86_monitor(v8086_frame_struct* frame);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -6,64 +6,72 @@ global catchall_return
|
|||||||
|
|
||||||
catchall: ; At this point the gate number has been pushed to the stack
|
catchall: ; At this point the gate number has been pushed to the stack
|
||||||
pushad
|
pushad
|
||||||
|
|
||||||
push esp
|
|
||||||
sub esp, 4
|
|
||||||
push eax
|
|
||||||
mov eax, cr3
|
mov eax, cr3
|
||||||
mov [esp+4], eax
|
push eax
|
||||||
pop eax
|
push 0
|
||||||
|
|
||||||
; Pushed 40 bytes
|
; Pushed 40 bytes
|
||||||
mov eax, [esp+40]
|
mov eax, [esp+40]
|
||||||
mov ebx, gates
|
mov ebx, gates
|
||||||
mov eax, [ebx+4*eax]
|
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
|
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
|
call eax
|
||||||
|
|
||||||
catchall_return:
|
catchall_return:
|
||||||
add esp, 4
|
add esp, 4
|
||||||
|
|
||||||
push 0x20
|
push 0x20
|
||||||
push 0x20
|
push 0x20
|
||||||
call outb
|
call outb
|
||||||
add esp, 8
|
add esp, 8
|
||||||
|
|
||||||
push eax
|
; Decrement and check the current thread's count
|
||||||
mov eax, [esp+4]
|
|
||||||
mov cr3, eax
|
mov ecx, [_ZN6Global13currentThreadE]
|
||||||
pop eax
|
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
|
add esp, 4
|
||||||
pop esp
|
pop eax
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
popad
|
popad
|
||||||
|
add esp, 8
|
||||||
mov esp, ebp
|
|
||||||
pop ebp
|
pop ebp
|
||||||
iret
|
iret
|
||||||
|
|
||||||
extern gates ; (void(*)(frame_struct))*
|
extern gates ; (void(*)(frame_struct))*
|
||||||
extern outb
|
extern outb
|
||||||
|
extern _ZN6Global13currentThreadE
|
||||||
; 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;
|
|
||||||
; }
|
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack)
|
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::allocator = this;
|
||||||
Global::kernel = this;
|
Global::kernel = this;
|
||||||
|
|
||||||
Global::currentProc = 0;
|
Global::currentProc = this;
|
||||||
|
|
||||||
this->stack = stack;
|
this->stack = stack;
|
||||||
|
|
||||||
@ -16,38 +15,117 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint
|
|||||||
|
|
||||||
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->tid_map = new xnoe::hashtable<uint32_t, Thread*>();
|
||||||
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
|
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
|
||||||
|
Global::currentThread = new Thread(this);
|
||||||
|
Global::currentThread->frame.count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* Kernel::createProcess(ReadWriter* file) {
|
Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp) {
|
||||||
char* name = "test";
|
// argv is currently stored on the stack of the calling process
|
||||||
Process* p = new Process(currentPID, this->PD, 0xc0000000, file, 1, &name);
|
// We need to create a copy of it in the kernel stack for createProcess
|
||||||
this->pid_map->set(currentPID, p);
|
|
||||||
currentPID++;
|
|
||||||
|
|
||||||
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* Kernel::createProcess(ReadWriter* file, ReadWriter* stdout) {
|
Process* Kernel::createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout) {
|
||||||
Process* p = this->createProcess(file);
|
char* zero = 0;
|
||||||
|
Process* p = this->createProcess(file, argv, &zero);
|
||||||
p->stdout = stdout;
|
p->stdout = stdout;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::destroyProcess(Process* p) {
|
void Kernel::registerProcess(Process* p) {
|
||||||
if (Global::currentProc == p)
|
this->pid_map->set(p->PID, p);
|
||||||
Global::currentProcValid = false;
|
}
|
||||||
|
|
||||||
|
void Kernel::destroyProcess(Process* p, uint32_t exit_code) {
|
||||||
xnoe::linkedlistelem<Thread*>* currentThread = p->threads.start;
|
xnoe::linkedlistelem<Thread*>* currentThread = p->threads.start;
|
||||||
while (currentThread) {
|
while (currentThread) {
|
||||||
this->threads.remove(currentThread->elem);
|
destroyThread(currentThread->elem, exit_code);
|
||||||
currentThread = currentThread->next;
|
currentThread = currentThread->next;
|
||||||
}
|
}
|
||||||
this->pid_map->remove(p->PID);
|
this->pid_map->remove(p->PID);
|
||||||
delete p;
|
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) {
|
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.
|
// Create the payload to perform an interrupt.
|
||||||
uint8_t payload[21] = {
|
uint8_t payload[21] = {
|
||||||
|
@ -12,12 +12,12 @@ class Kernel : public Process {
|
|||||||
private:
|
private:
|
||||||
int lastFH;
|
int lastFH;
|
||||||
public:
|
public:
|
||||||
uint32_t currentPID;
|
|
||||||
uint32_t stack;
|
uint32_t stack;
|
||||||
uint32_t globalISRStack;
|
uint32_t globalISRStack;
|
||||||
Terminal* terminal;
|
Terminal* terminal;
|
||||||
|
|
||||||
xnoe::hashtable<uint32_t, Process*>* pid_map; // Map of PIDs -> Process*s
|
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*> processes;
|
||||||
xnoe::linkedlist<Process*> KBListeners;
|
xnoe::linkedlist<Process*> KBListeners;
|
||||||
@ -28,9 +28,13 @@ public:
|
|||||||
|
|
||||||
void init_kernel();
|
void init_kernel();
|
||||||
|
|
||||||
Process* createProcess(ReadWriter* file);
|
Process* createProcess(ReadWriter* file, uint8_t** argv, uint8_t** envp);
|
||||||
Process* createProcess(ReadWriter* file, ReadWriter* stdout);
|
Process* createProcess(ReadWriter* file, uint8_t** argv, ReadWriter* stdout);
|
||||||
void destroyProcess(Process* p);
|
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);
|
void v86(uint16_t ax, uint16_t bx, uint16_t cx, uint16_t es, uint16_t di, uint8_t intn);
|
||||||
};
|
};
|
||||||
|
@ -55,15 +55,14 @@ int main(KernelInformationStruct kstruct) {
|
|||||||
|
|
||||||
term->printf("KERNEL OK!\n");
|
term->printf("KERNEL OK!\n");
|
||||||
|
|
||||||
ReadWriter* atareadwriter = new ATAReadWriter(0, 0);
|
|
||||||
|
|
||||||
kernel.rootfs = new RootFSTree();
|
kernel.rootfs = new RootFSTree();
|
||||||
kernel.rootfs->mount(createPathFromString("/dev"), new DevFS());
|
kernel.rootfs->mount(createPathFromString("/dev"), new DevFS());
|
||||||
kernel.rootfs->mount(createPathFromString("/sys"), new SysFS());
|
kernel.rootfs->mount(createPathFromString("/sys"), new SysFS());
|
||||||
kernel.rootfs->mount(createPathFromString("/"), new FAT16FS(kernel.rootfs->open(createPathFromString("/dev/ata"))));
|
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;
|
Global::tss->esp0 = (new uint8_t[8192]) + 8192;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
extern void(*catchall_return)();
|
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(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::maybe<xnoe::linkedlistelem<AllocTracker>*> Process::get_alloc_tracker(uint32_t address) {
|
||||||
xnoe::linkedlistelem<AllocTracker>* current = this->allocations.start;
|
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>*>();
|
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) {
|
: Allocator(page_directory, phys, virt, virt_alloc_base) {
|
||||||
this->PID = PID;
|
this->PID = this->currentPID++;
|
||||||
this->page_remaining = 0;
|
this->page_remaining = 0;
|
||||||
this->last_page_pointer = virt_alloc_base;
|
this->last_page_pointer = virt_alloc_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process::Process(uint32_t PID)
|
Process::Process()
|
||||||
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
|
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
|
||||||
this->PID = PID;
|
this->PID = 0;
|
||||||
this->page_remaining = 0;
|
this->page_remaining = 0;
|
||||||
this->last_page_pointer = 0;
|
this->last_page_pointer = 0;
|
||||||
this->file_handlers = new xnoe::dynarray<ReadWriter*>(8);
|
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) {
|
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
|
||||||
this->stdout = 0;
|
this->stdout = 0;
|
||||||
this->stdin = 0;
|
this->stdin = 0;
|
||||||
|
|
||||||
this->PID = PID;
|
this->PID = this->currentPID++;
|
||||||
this->page_remaining = 0;
|
this->page_remaining = 0;
|
||||||
this->last_page_pointer = 0;
|
this->last_page_pointer = 0;
|
||||||
|
|
||||||
@ -55,17 +58,30 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
|
|||||||
this->PD->select();
|
this->PD->select();
|
||||||
|
|
||||||
uint32_t* stack = thread->stack + 0x8000;
|
uint32_t* stack = thread->stack + 0x8000;
|
||||||
uint8_t* argenvarea = this->allocate(0x2000);
|
uint8_t* argenvarea = this->allocate(0x2000) + 0x2000;
|
||||||
uint32_t argenv = argenvarea + 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--) {
|
for (int i=argc; i>0; i--) {
|
||||||
char* s = argv[i-1];
|
char* s = argv[i-1];
|
||||||
uint32_t c = 0;
|
uint32_t c = strlen(s);
|
||||||
while (*(c++, s++));
|
memcpy((uint8_t*)(argenvarea -= c), (uint8_t*)argv[i-1], c);
|
||||||
memcpy((uint8_t*)(argenv -= c), (uint8_t*)argv[i-1], c);
|
*(--stack) = argenvarea;
|
||||||
*(--stack) = argenv;
|
|
||||||
}
|
}
|
||||||
*(--stack) = ((uint32_t)stack);
|
uint32_t argv_p = ((uint32_t)stack);
|
||||||
|
|
||||||
|
*(--stack) = envp_p;
|
||||||
|
*(--stack) = argv_p;
|
||||||
*(--stack) = argc;
|
*(--stack) = argc;
|
||||||
|
|
||||||
filereader->seek(0);
|
filereader->seek(0);
|
||||||
@ -78,16 +94,91 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, Rea
|
|||||||
this->threads.append(thread);
|
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) {
|
Thread::Thread(Process* parent) {
|
||||||
|
this->TID = this->currentTID++;
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
|
|
||||||
this->stack = this->parent->allocate(0x8000);
|
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;
|
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() {
|
Thread::~Thread() {
|
||||||
delete kernelStackPtr;
|
//delete kernelStackPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::initKernelStack(void* entryPoint, void* esp) {
|
void Thread::initKernelStack(void* entryPoint, void* esp) {
|
||||||
@ -100,19 +191,24 @@ void Thread::initKernelStack(void* entryPoint, void* esp) {
|
|||||||
*(--stack32) = 0x200; // EFLAGS
|
*(--stack32) = 0x200; // EFLAGS
|
||||||
*(--stack32) = 27; // CS
|
*(--stack32) = 27; // CS
|
||||||
*(--stack32) = (uint32_t)entryPoint; // EIP
|
*(--stack32) = (uint32_t)entryPoint; // EIP
|
||||||
*(--stack32) = ((uint32_t)esp); // EBP
|
*(--stack32);
|
||||||
|
*(--stack32);
|
||||||
uint32_t rEBP = stack32;
|
*(--stack32);
|
||||||
|
|
||||||
*(--stack32) = 0; // EAX
|
*(--stack32) = 0; // EAX
|
||||||
*(--stack32) = 0; // ECX
|
*(--stack32) = 0; // ECX
|
||||||
*(--stack32) = 0; // EDX
|
*(--stack32) = 0; // EDX
|
||||||
*(--stack32) = 0; // EBX
|
*(--stack32) = 0; // EBX
|
||||||
*(--stack32) = 0; // ESP
|
*(--stack32) = 0; // ESP
|
||||||
*(--stack32) = rEBP; // EBP
|
*(--stack32) = 0; // EBP
|
||||||
*(--stack32) = 0; // ESI
|
*(--stack32) = 0; // ESI
|
||||||
*(--stack32) = 0; // EDI
|
*(--stack32) = 0; // EDI
|
||||||
|
|
||||||
|
*(--stack32) = 0; // CR3
|
||||||
|
*(--stack32) = 1;
|
||||||
|
|
||||||
|
memcpy((uint8_t*)&this->frame, (uint8_t*)stack32, 72);
|
||||||
|
|
||||||
this->kernelStackPtr = stack32;
|
this->kernelStackPtr = stack32;
|
||||||
asm ("mov %0, %%cr3" : : "r" (pCR3));
|
asm ("mov %0, %%cr3" : : "r" (pCR3));
|
||||||
}
|
}
|
||||||
@ -134,14 +230,52 @@ Process::~Process() {
|
|||||||
xnoe::maybe<ReadWriter*> r;
|
xnoe::maybe<ReadWriter*> r;
|
||||||
if ((r=file_handlers->get(i)).is_ok())
|
if ((r=file_handlers->get(i)).is_ok())
|
||||||
if (r.get())
|
if (r.get())
|
||||||
delete r.get();
|
r.get()->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
|
/*xnoe::linkedlistelem<Thread*>* currentThread = threads.start;
|
||||||
while (currentThread) {
|
while (currentThread) {
|
||||||
delete currentThread->elem;
|
delete currentThread->elem;
|
||||||
currentThread = currentThread->next;
|
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) {
|
void* Process::allocate(uint32_t size) {
|
||||||
@ -163,7 +297,7 @@ void* Process::allocate(uint32_t size) {
|
|||||||
uint32_t elem_size = sizeof(xnoe::linkedlistelem<AllocTracker>);
|
uint32_t elem_size = sizeof(xnoe::linkedlistelem<AllocTracker>);
|
||||||
size += elem_size;
|
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 pages = size / 4096;
|
||||||
uint32_t remainder = 4096 - (size % 4096);
|
uint32_t remainder = 4096 - (size % 4096);
|
||||||
|
|
||||||
|
@ -11,18 +11,54 @@
|
|||||||
#include "stdio/readwriter.h"
|
#include "stdio/readwriter.h"
|
||||||
#include "datatypes/dynarray.h"
|
#include "datatypes/dynarray.h"
|
||||||
#include "filesystem/fstree.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 Process;
|
||||||
class Thread {
|
class Thread {
|
||||||
|
private:
|
||||||
|
static uint32_t currentTID;
|
||||||
public:
|
public:
|
||||||
|
frame_struct frame;
|
||||||
|
uint32_t TID;
|
||||||
|
|
||||||
void* stack;
|
void* stack;
|
||||||
|
void* kspRaw;
|
||||||
void* kernelStackPtr;
|
void* kernelStackPtr;
|
||||||
void* kernelStackPtrDefault;
|
void* kernelStackPtrDefault;
|
||||||
Process* parent;
|
Process* parent;
|
||||||
ProcessState state;
|
ProcessState state;
|
||||||
bool firstRun;
|
bool firstRun;
|
||||||
|
|
||||||
|
uint32_t suspending=0;
|
||||||
|
|
||||||
Thread(Process* parent);
|
Thread(Process* parent);
|
||||||
|
Thread(Thread* t, Process* parent);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
void Thread::initKernelStack(void* entryPoint, void* esp);
|
void Thread::initKernelStack(void* entryPoint, void* esp);
|
||||||
@ -33,6 +69,7 @@ struct AllocTracker {
|
|||||||
uint32_t page_size;
|
uint32_t page_size;
|
||||||
uint32_t alloc_count;
|
uint32_t alloc_count;
|
||||||
|
|
||||||
|
AllocTracker();
|
||||||
AllocTracker(void* base, uint32_t size, uint32_t count);
|
AllocTracker(void* base, uint32_t size, uint32_t count);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,16 +78,15 @@ private:
|
|||||||
uint32_t last_page_pointer;
|
uint32_t last_page_pointer;
|
||||||
uint32_t page_remaining;
|
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::maybe<xnoe::linkedlistelem<AllocTracker>*> get_alloc_tracker(uint32_t address);
|
||||||
|
|
||||||
xnoe::dynarray<ReadWriter*>* file_handlers;
|
|
||||||
|
|
||||||
Path currentWorkingDirectory;
|
Path currentWorkingDirectory;
|
||||||
|
|
||||||
|
static uint32_t currentPID;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
xnoe::dynarray<ReadWriter*>* file_handlers;
|
||||||
|
|
||||||
uint32_t PID;
|
uint32_t PID;
|
||||||
uint32_t esp;
|
uint32_t esp;
|
||||||
|
|
||||||
@ -59,12 +95,18 @@ public:
|
|||||||
|
|
||||||
xnoe::linkedlist<Thread*> threads;
|
xnoe::linkedlist<Thread*> threads;
|
||||||
|
|
||||||
Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
|
// List of pages this process has allocated
|
||||||
Process(uint32_t PID);
|
xnoe::linkedlist<AllocTracker> allocations;
|
||||||
Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, ReadWriter* filereader, uint32_t argc=0, char** argv=0);
|
|
||||||
|
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
|
~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* allocate(uint32_t size) override;
|
||||||
void deallocate(uint32_t virt_addr) override;
|
void deallocate(uint32_t virt_addr) override;
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#include "circularrwbuffer.h"
|
#include "circularrwbuffer.h"
|
||||||
|
|
||||||
CircularRWBuffer::CircularRWBuffer(uint32_t reader, uint32_t writer)
|
CircularRWBuffer::CircularRWBuffer() {
|
||||||
: ReadWriter(0) {
|
|
||||||
this->giveReadPerm(reader);
|
|
||||||
this->giveWritePerm(writer);
|
|
||||||
|
|
||||||
this->bufferSize = 3072;
|
this->bufferSize = 3072;
|
||||||
this->buffer = new uint8_t[this->bufferSize];
|
this->buffer = new uint8_t[this->bufferSize];
|
||||||
this->readPtr = 0;
|
this->readPtr = 0;
|
||||||
this->writePtr = 0;
|
this->writePtr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CircularRWBuffer::~CircularRWBuffer() {
|
||||||
|
delete this->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
|
uint32_t CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
|
||||||
int i=0;
|
int i=0;
|
||||||
while (i < count) {
|
while (i < count) {
|
||||||
|
@ -10,7 +10,8 @@ private:
|
|||||||
uint32_t writePtr;
|
uint32_t writePtr;
|
||||||
uint32_t bufferSize;
|
uint32_t bufferSize;
|
||||||
public:
|
public:
|
||||||
CircularRWBuffer(uint32_t reader, uint32_t writer);
|
CircularRWBuffer();
|
||||||
|
~CircularRWBuffer();
|
||||||
|
|
||||||
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
||||||
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
uint32_t write(uint32_t count, uint8_t* buffer) override;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "oneshotreadwriter.h"
|
#include "oneshotreadwriter.h"
|
||||||
|
|
||||||
OneShotReadWriter::OneShotReadWriter(uint32_t owner, uint8_t* toRead) : ReadWriter(owner) {
|
OneShotReadWriter::OneShotReadWriter(uint8_t* toRead) {
|
||||||
this->length = strlen(toRead);
|
this->length = strlen(toRead);
|
||||||
|
|
||||||
this->buffer = new uint8_t[this->length];
|
this->buffer = new uint8_t[this->length];
|
||||||
|
@ -12,7 +12,7 @@ private:
|
|||||||
uint32_t index=0;
|
uint32_t index=0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OneShotReadWriter(uint32_t owner, uint8_t* toRead);
|
OneShotReadWriter(uint8_t* toRead);
|
||||||
|
|
||||||
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
uint32_t read(uint32_t count, uint8_t* buffer) override;
|
||||||
uint32_t size() override;
|
uint32_t size() override;
|
||||||
|
@ -1,38 +1,16 @@
|
|||||||
#include "readwriter.h"
|
#include "readwriter.h"
|
||||||
|
|
||||||
ReadWriter::ReadWriter(uint32_t owner) {
|
uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){return;}
|
||||||
this->owner = owner;
|
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) {
|
void ReadWriter::close() {
|
||||||
this->allowedRead.append(PID);
|
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;
|
|
||||||
}
|
}
|
@ -6,22 +6,17 @@
|
|||||||
|
|
||||||
class ReadWriter {
|
class ReadWriter {
|
||||||
private:
|
private:
|
||||||
uint32_t owner;
|
uint32_t opens=1;
|
||||||
xnoe::linkedlist<uint32_t> allowedRead;
|
|
||||||
xnoe::linkedlist<uint32_t> allowedWrite;
|
|
||||||
|
|
||||||
public:
|
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 read(uint32_t count, uint8_t* buffer);
|
||||||
virtual uint32_t write(uint32_t count, uint8_t* buffer);
|
virtual uint32_t write(uint32_t count, uint8_t* buffer);
|
||||||
virtual uint32_t size();
|
virtual uint32_t size();
|
||||||
virtual uint32_t seek(uint32_t position);
|
virtual uint32_t seek(uint32_t position);
|
||||||
uint32_t getOwner();
|
uint32_t getOwner();
|
||||||
bool canRead(uint32_t PID);
|
|
||||||
bool canWrite(uint32_t PID);
|
void open();
|
||||||
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -215,8 +215,7 @@ void Terminal::update(){}
|
|||||||
void Terminal::update_cur(){}
|
void Terminal::update_cur(){}
|
||||||
void Terminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {}
|
void Terminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {}
|
||||||
|
|
||||||
Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages)
|
Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) {
|
||||||
: ReadWriter(0) {
|
|
||||||
this->width = width;
|
this->width = width;
|
||||||
this->height = height;
|
this->height = height;
|
||||||
this->pages = pages;
|
this->pages = pages;
|
||||||
@ -297,9 +296,10 @@ uint32_t Terminal::write(uint32_t count, uint8_t* string) {
|
|||||||
this->putchar(string[index]);
|
this->putchar(string[index]);
|
||||||
|
|
||||||
this->set_curpos(this->cur_x, this->cur_y);
|
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() {
|
void Terminal::clear_screen() {
|
||||||
for (int i=0; i < width * height * pages; i++) {
|
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) {
|
void VGAModeTerminal::bufferToVRAM() {
|
||||||
uint32_t count4 = (terminal->pixelWidth * terminal->pixelHeight) / 8 / 4;
|
uint32_t count4 = (this->pixelWidth * this->pixelHeight) / 8 / 4;
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
outb(0x3c4, 2);
|
outb(0x3c4, 2);
|
||||||
outb(0x3c5, 1<<i);
|
outb(0x3c5, 1<<i);
|
||||||
|
|
||||||
for (int c=0; c<count4; c++) {
|
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() {
|
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];
|
this->fb[pixel] = color_map[color];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal* terminal) {
|
void BGAModeTerminal::bufferToVRAM() {
|
||||||
uint32_t c = terminal->pixelWidth * terminal->pixelHeight;
|
uint32_t c = this->pixelWidth * this->pixelHeight;
|
||||||
uint32_t bank=0;
|
uint32_t bank=0;
|
||||||
uint32_t ctr=0;
|
uint32_t ctr=0;
|
||||||
for (int i=0; i<c; i++) {
|
for (int i=0; i<c; i++) {
|
||||||
@ -585,7 +585,7 @@ static void BGAModeTerminal::bufferToVRAM(frame_struct* frame, BGAModeTerminal*
|
|||||||
outw(0x1ce, 5);
|
outw(0x1ce, 5);
|
||||||
outw(0x1cf, bank++);
|
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(0x1ce, 4);
|
||||||
outw(0x1cf, 1);
|
outw(0x1cf, 1);
|
||||||
|
|
||||||
Timer::register_event(16, &BGAModeTerminal::bufferToVRAM, this);
|
Timer::register_event(16, (void(*)(void*))&BGAModeTerminal::bufferToVRAM, this);
|
||||||
}
|
}
|
@ -14,7 +14,7 @@
|
|||||||
struct frame_struct;
|
struct frame_struct;
|
||||||
|
|
||||||
namespace Timer {
|
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 {
|
enum TerminalState {
|
||||||
@ -100,9 +100,9 @@ private:
|
|||||||
void put_pixel(uint32_t x, uint32_t y, uint8_t color);
|
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);
|
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:
|
public:
|
||||||
|
void bufferToVRAM();
|
||||||
|
|
||||||
uint32_t pixelWidth = 720;
|
uint32_t pixelWidth = 720;
|
||||||
uint32_t pixelHeight = 480;
|
uint32_t pixelHeight = 480;
|
||||||
|
|
||||||
@ -121,9 +121,9 @@ private:
|
|||||||
void put_pixel(uint32_t x, uint32_t y, uint8_t color);
|
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);
|
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:
|
public:
|
||||||
|
void bufferToVRAM();
|
||||||
|
|
||||||
uint32_t pixelWidth = 720;
|
uint32_t pixelWidth = 720;
|
||||||
uint32_t pixelHeight = 480;
|
uint32_t pixelHeight = 480;
|
||||||
|
|
||||||
|
17
src/programs/cat/main.c
Normal file
17
src/programs/cat/main.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
7
src/programs/echo/main.c
Normal 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":" ");
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
[BITS 32]
|
[BITS 32]
|
||||||
|
|
||||||
_start:
|
_start:
|
||||||
|
call __setup
|
||||||
call main
|
call main
|
||||||
|
push eax
|
||||||
call die
|
call die
|
||||||
|
|
||||||
extern die
|
extern die
|
||||||
extern main
|
extern main
|
||||||
|
extern __setup
|
10
src/programs/forktest/main.c
Normal file
10
src/programs/forktest/main.c
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
@ -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
21
src/programs/init/main.c
Normal 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";
|
||||||
|
char* argv[] = {
|
||||||
|
fn,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
char* envp[] = {
|
||||||
|
"PATH=/",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
uint32_t xosh_fh = fopen(fn);
|
||||||
|
uint32_t xosh = execve(xosh_fh, argv, envp);
|
||||||
|
|
||||||
|
while (1);
|
||||||
|
}
|
8
src/programs/listenvp/main.c
Normal file
8
src/programs/listenvp/main.c
Normal 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
35
src/programs/ls/main.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* directory = argv[1];
|
||||||
|
|
||||||
|
uint32_t dentsSize = getDentsSize(directory);
|
||||||
|
FSDirectoryListing* dents = (FSDirectoryListing*)malloc(dentsSize);
|
||||||
|
getDents(directory, 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));
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
107
src/programs/xosh/main.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user