Added file reading via filehandlers. Added support for directories. Processes are now created using filehandlers.

This commit is contained in:
Xnoe 2022-01-19 16:51:37 +00:00
parent 2bbc81955d
commit 2f2a7a3e45
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
21 changed files with 323 additions and 96 deletions

View File

@ -2,7 +2,7 @@ CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exce
CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -I.
LDFLAGS =
DISK_IMG_FILES = build/kernel/kernel.bin build/world/world.bin hello.txt alpha.txt \
DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt \
build/hello/hello.bin
KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp)
@ -39,12 +39,14 @@ run: disk.img
debug: disk.img
qemu-system-i386 -s -S -no-reboot -no-shutdown disk.img & gdb --command=gdbscript
disk.img: clean prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES)
disk.img: clean prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES) build/world/world.bin
dd if=/dev/zero of=disk.img count=43 bs=100k
dd if=build/boot/boot.bin of=disk.img conv=notrunc
dd obs=512 seek=1 if=build/boot_stage2/boot.bin of=disk.img conv=notrunc
mount disk.img img.d
mkdir img.d/etc/
cp $(DISK_IMG_FILES) img.d/
cp build/world/world.bin img.d/etc/world.bin
sleep 0.1
umount img.d
chmod 777 disk.img

View File

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

View File

@ -9,7 +9,7 @@ void* localalloc(uint32_t size);
void localdelete(void* ptr);
uint32_t filesize(char* filename);
uint32_t fork(char* filename);
uint32_t fork(uint32_t fh);
uint32_t bindStdout(uint32_t PID);
uint32_t bindStdin(uint32_t PID);
@ -19,6 +19,9 @@ int read(uint32_t count, void* filehandler, uint8_t* buffer);
int write(uint32_t count, void* filehandler, uint8_t* buffer);
void bindToKeyboard();
int fopen(char* filename);
void fclose(uint32_t fh);
int int_to_decimal(unsigned int number, char* string_buffer);
int int_to_hex(unsigned int number, char* string_buffer);

View File

@ -11,7 +11,7 @@
uint16_t identify_result[256];
uint32_t total_28_lbas = 0;
uint8_t* rootDirEntries;
DirectoryEntry* rootDirEntries;
uint16_t* FAT1;
uint16_t countReserved;
@ -21,7 +21,7 @@ uint16_t sectorsPerFAT;
void init_atapio() {
rootDirEntries = new uint8_t[8192];
rootDirEntries = (DirectoryEntry*)new uint8_t[8192];
FAT1 = (uint16_t*)(new uint8_t[512 * 34]);
uint32_t boot_sector = new uint32_t[1024];
@ -65,7 +65,7 @@ void init_atapio() {
total_28_lbas = *(uint32_t*)(identify_result+60);
// We've initialised now, let's load the FAT and RootDirEntries.
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, rootDirEntries);
read_sectors(sectorsPerFAT * countFATs + countReserved, countRDEs / 16, (uint8_t*)rootDirEntries);
read_sectors(countReserved, sectorsPerFAT, (uint8_t*)FAT1);
}
@ -97,27 +97,46 @@ void read_sectors(uint32_t address, int count, uint8_t* buffer) {
}
}
uint16_t file_exists(char* filename) {
for (int i=0; i<countRDEs; i++) {
bool found = strcmp(rootDirEntries+(i*32), filename, 11);
if (found) {
uint16_t* correctEntry = (uint16_t*)(rootDirEntries+(i*32));
return correctEntry[13];
}
}
return 0;
uint32_t clusterToSector(uint32_t cluster) {
return cluster + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
}
void load_file(char* filename, uint8_t* destination) {
uint16_t location = file_exists(filename);
if (!location)
return;
int split_on_char(char c, char* str, char** split) {
char* cstr = str;
char* last = str;
uint32_t count = 0;
while (*cstr) {
if (*cstr == c) {
*cstr = 0;
split[count++] = last;
last = cstr+1;
}
cstr++;
}
split[count++] = last;
return count;
}
void to83(char* filename, char* buf83) {
char* c = filename;
for (int i=0;i<11;i++)
buf83[i] = ' ';
uint32_t bufpos = 0;
while (*c && bufpos != 11) {
if (*c == '.')
bufpos = 8;
else
buf83[bufpos++] = *c & 223;
c++;
}
}
void load_file(uint32_t location, uint8_t* destination) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = location + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
uint16_t fromSector = clusterToSector(location);
read_sector(fromSector, destination+offset);
offset += 512;
@ -127,13 +146,110 @@ void load_file(char* filename, uint8_t* destination) {
}
}
uint32_t file_size(char* filename) {
for (int i=0; i<countRDEs; i++) {
bool found = strcmp(rootDirEntries+(i*32), filename, 11);
int calc_size(uint32_t location) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
offset += 512;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
return offset;
}
DirectoryEntry* get_DE(char* filename) {
DirectoryEntry* dirbuf;
Directory dir = {
.entry = rootDirEntries,
.entries = countRDEs
};
char* levels[8];
int count = split_on_char('/', filename, levels);
for (int i=0; i<(count-1); i++) {
char normalname[11] = {' '};
to83(levels[i], normalname);
for (int e=0; e<dir.entries; e++) {
bool found=strcmp(dir.entry[e].name, normalname, 11);
if (found) {
uint32_t* correctEntry = (uint32_t*)(rootDirEntries+(i*32));
return correctEntry[7];
DirectoryEntry* de = &dir.entry[e];
uint32_t size = calc_size(de->firstClusterLow);
dirbuf = (DirectoryEntry*)(new uint8_t[size]);
uint32_t cluster = de->firstClusterLow;
load_file(cluster, (uint8_t*)dirbuf);
dir.entry = dirbuf;
dir.entries = size / 32;
break;
}
}
}
char normalname[11];
to83(levels[count-1], normalname);
for (int i=0; i<dir.entries; i++) {
bool found = strcmp(dir.entry[i].name, normalname, 11);
if (found) {
return &dir.entry[i];
}
}
return 0;
}
uint16_t file_exists(char* filename) {
DirectoryEntry* de = get_DE(filename);
if (de)
return de->firstClusterLow;
return 0;
}
uint32_t file_size(char* filename) {
for (int i=0; i<countRDEs; i++) {
bool found = strcmp(rootDirEntries[i].name, filename, 11);
if (found) {
if (rootDirEntries[i].size % 512)
return ((rootDirEntries[i].size / 512) + 1) * 512;
else
return rootDirEntries[i].size;
}
}
return 0;
}
void load_file(char* filename, uint8_t* location) {
DirectoryEntry* de = get_DE(filename);
load_file(de->firstClusterLow, location);
}
FATFileReadWriter::FATFileReadWriter(uint32_t owner, char* filename)
: ReadWriter(owner) {
this->bytesRead = 0;
DirectoryEntry* de = get_DE(filename);
this->sizeBytes = de->size;
this->currentCluster = de->firstClusterLow;
this->read_buffer = new uint8_t[512];
read_sector(clusterToSector(this->currentCluster), this->read_buffer);
}
uint32_t FATFileReadWriter::read(uint32_t count, uint8_t* buffer) {
int index = 0;
while (count) {
buffer[index] = this->read_buffer[this->bytesRead++];
if (this->bytesRead == 512) {
this->currentCluster = FAT1[this->currentCluster++];
read_sector(clusterToSector(this->currentCluster), this->read_buffer);
this->bytesRead = 0;
}
count--;
index++;
}
}
uint32_t FATFileReadWriter::write(uint32_t count, uint8_t* buffer) {}
uint32_t FATFileReadWriter::size() {
return this->sizeBytes;
}

View File

@ -9,6 +9,49 @@
#include "allocate.h"
#include "global.h"
#include "stdio/readwriter.h"
struct __attribute__((packed)) DirectoryEntry {
char name[11];
uint8_t _ignored0 : 3;
uint8_t archive : 1;
uint8_t directory : 1;
uint8_t volumeid : 1;
uint8_t system : 1;
uint8_t hidden : 1;
uint8_t readonly : 1;
uint8_t _ignored1;
uint16_t createdHour : 5;
uint16_t createdMinute : 6;
uint16_t createdSecond : 5;
uint16_t createdYear : 7;
uint16_t createdMonth : 4;
uint16_t createdDay : 5;
uint16_t lastAccessYear : 7;
uint16_t lastAccessMonth : 4;
uint16_t lastAccessDay : 5;
uint16_t firstClusterHigh;
uint16_t modifiedHour : 5;
uint16_t modifiedMinute : 6;
uint16_t modifiedSecond : 5;
uint16_t modifiedYear : 7;
uint16_t modifiedMonth : 4;
uint16_t modifiedDay : 5;
uint16_t firstClusterLow;
uint32_t size;
};
struct Directory {
DirectoryEntry* entry;
uint32_t entries;
};
void init_atapio();
void read_sector(uint32_t address, uint8_t* buffer);
void read_sectors(uint32_t address, int count, uint8_t* buffer);
@ -17,4 +60,18 @@ void load_file(char* filename, uint8_t* location);
uint32_t file_size(char* filename);
class FATFileReadWriter : public ReadWriter {
private:
uint32_t sizeBytes;
uint32_t bytesRead;
uint32_t currentCluster;
uint8_t* read_buffer;
public:
FATFileReadWriter(uint32_t owner, char* filename);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
};
#endif

View File

@ -55,7 +55,7 @@ namespace xnoe {
return xnoe::Maybe<value>();
}
void remove(key k, value v) {
void remove(key k) {
xnoe::linkedlist<xnoe::tuple<key, value>>* list = &table[xnoe::hash<key>(k) % 4096];
xnoe::linkedlistelem<xnoe::tuple<key, value>>* current = list->start;
if (current) {

View File

@ -6,6 +6,7 @@ namespace Global {
Process* currentProc = 0;
tss_struct* tss = 0;
bool currentProcValid = false;
xnoe::hashtable<void*, ReadWriter*>* FH; // Map of File Handlers -> Read Writer
}
void* operator new (uint32_t size) {

View File

@ -7,6 +7,11 @@ class Kernel;
class Allocator;
class Process;
struct tss_struct;
class ReadWriter;
namespace xnoe {
template<class, class>
class hashtable;
}
namespace Global {
extern Allocator* allocator;
@ -14,6 +19,7 @@ namespace Global {
extern Process* currentProc;
extern tss_struct* tss;
extern bool currentProcValid;
extern xnoe::hashtable<void*, ReadWriter*>* FH;
}
void* operator new (uint32_t size);

View File

@ -164,6 +164,9 @@ void syscall(frame_struct* frame) {
// 13: bindStdout :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdout of another process.
// 14: bindStdin :: int PID esi -> int filehandler // Returns a filehandler for a CircularRWBuffer binding stdin of another process.
// 15: fopen :: char* path esi -> int filehandler // Returns a filehandler to the file.
// 16: fclose :: int filehandler esi -> void // Closes a file handler.
// File handlers:
// 0: Stdout
// 1: Stdin
@ -196,10 +199,7 @@ void syscall(frame_struct* frame) {
break;
case 7: {
asm("cli");
char filename[12];
for (int i=0; i<12; i++)
filename[i] = ((char*)(frame->esi))[i];
Process* p = Global::kernel->createProcess(filename);
Process* p = Global::kernel->createProcess(esi);
rval = p->PID;
asm("sti");
break;
@ -219,7 +219,7 @@ void syscall(frame_struct* frame) {
rval = stdin->read(frame->ebx, edi);
} else {
xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi);
xnoe::Maybe<ReadWriter*> fh = Global::FH->get(esi);
if (!fh.is_ok()) {
rval = 0;
break;
@ -239,7 +239,7 @@ void syscall(frame_struct* frame) {
rval = stdout->write(frame->ebx, edi);
} else {
xnoe::Maybe<ReadWriter*> fh = Global::kernel->FH->get(esi);
xnoe::Maybe<ReadWriter*> fh = Global::FH->get(esi);
if (!fh.is_ok()) {
rval = 0;
break;
@ -285,6 +285,19 @@ void syscall(frame_struct* frame) {
break;
}
case 15: {
ReadWriter* file = new FATFileReadWriter(0, esi);
rval = Global::kernel->mapFH(file);
}
case 16: {
xnoe::Maybe<ReadWriter*> f = Global::FH->get(esi);
if (f.is_ok()) {
delete f.get();
Global::kernel->unmapFH(esi);
}
}
default:
break;
}

View File

@ -18,12 +18,12 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint
void Kernel::init_kernel() {
this->pid_map = new xnoe::hashtable<uint32_t, Process*>();
this->FH = new xnoe::hashtable<void*, ReadWriter*>();
Global::FH = new xnoe::hashtable<void*, ReadWriter*>();
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
}
Process* Kernel::createProcess(char* filename) {
Process* p = new Process(currentPID, this->PD, 0xc0000000, filename);
Process* Kernel::createProcess(uint32_t fh) {
Process* p = new Process(currentPID, this->PD, 0xc0000000, fh);
this->pid_map->set(currentPID, p);
currentPID++;
@ -32,23 +32,27 @@ Process* Kernel::createProcess(char* filename) {
return p;
}
Process* Kernel::createProcess(char* filename, ReadWriter* stdout) {
Process* p = this->createProcess(filename);
Process* Kernel::createProcess(uint32_t fh, ReadWriter* stdout) {
Process* p = this->createProcess(fh);
p->stdout = stdout;
return p;
}
void Kernel::destroyProcess(Process* p) {
this->processes.remove(p);
this->pid_map->remove(p->PID, p);
this->pid_map->remove(p->PID);
delete p;
}
int Kernel::mapFH(ReadWriter* fh) {
this->FH->set(this->lastFH++, fh);
Global::FH->set(this->lastFH++, fh);
return this->lastFH - 1;
}
void Kernel::unmapFH(uint32_t fh) {
Global::FH->remove((void*)fh);
}
//void Kernel::loadPrimaryStack() {
// asm volatile("mov %0, %%esp"::"m"(this->stack - 64));
//}

View File

@ -16,7 +16,6 @@ public:
Terminal* terminal;
xnoe::hashtable<uint32_t, Process*>* pid_map; // Map of PIDs -> Process*s
xnoe::hashtable<void*, ReadWriter*>* FH; // Map of File Handlers -> Read Writer
xnoe::linkedlist<Process*> processes;
xnoe::linkedlist<Process*> KBListeners;
@ -25,11 +24,12 @@ public:
void init_kernel();
Process* createProcess(char* filename);
Process* createProcess(char* filename, ReadWriter* stdout);
Process* createProcess(uint32_t fh);
Process* createProcess(uint32_t fh, ReadWriter* stdout);
void destroyProcess(Process* p);
int mapFH(ReadWriter* fh);
void unmapFH(uint32_t fh);
//void loadPrimaryStack();
};

View File

@ -44,7 +44,10 @@ int main() {
term->printf("KERNEL OK!\n");
Process* p1 = kernel.createProcess("WORLD BIN", term);
ReadWriter* worldbin = new FATFileReadWriter(0, "etc/world.bin");
uint32_t fh = kernel.mapFH(worldbin);
Process* p1 = kernel.createProcess(fh, term);
init_keyboard();

View File

@ -33,7 +33,7 @@ Process::Process(uint32_t PID)
this->kernelStackPtr = (new uint8_t[0x1000]) + 0x1000;
}
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename)
Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh)
: Allocator(new PageDirectory, new PageMap, (uint32_t)0, 3) {
this->stdout = 0;
this->stdin = 0;
@ -47,7 +47,11 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha
for (int index = inheritBase >> 22; index < 1024; index++)
this->PD->page_directory[index] = inherit->page_directory[index];
uint8_t* program_data = this->allocate(file_size(filename) + 12) + 12;
xnoe::Maybe<ReadWriter*> file = Global::FH->get(fh);
if (file.is_ok()) {
ReadWriter* filereader = file.get();
uint32_t filesize = filereader->size();
uint8_t* program_data = this->allocate(filesize + 12) + 12;
this->stack = this->allocate(0x8000);
this->kernelStackPtr = (new uint8_t[0x1000]) + 0xffc;
@ -83,9 +87,11 @@ Process::Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, cha
this->kernelStackPtr = stack32;
load_file(filename, program_data);
//load_file(filename, program_data);
filereader->read(filesize, program_data);
asm ("mov %0, %%cr3" : : "r" (pCR3));
}
}
Process::~Process() {

View File

@ -46,7 +46,7 @@ public:
Process(uint32_t PID, void* stack, PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base);
Process(uint32_t PID);
Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, char* filename);
Process(uint32_t PID, PageDirectory* inherit, uint32_t inheritBase, uint32_t fh);
~Process(); // Iterate through allocations and free those; delete stack

View File

@ -11,7 +11,7 @@ CircularRWBuffer::CircularRWBuffer(uint32_t reader, uint32_t writer)
this->writePtr = 0;
}
int CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
uint32_t CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
int i=0;
while (i < count) {
this->buffer[this->writePtr] = buffer[i];
@ -24,7 +24,7 @@ int CircularRWBuffer::write(uint32_t count, uint8_t* buffer) {
return i;
}
int CircularRWBuffer::read(uint32_t count, uint8_t* buffer) {
uint32_t CircularRWBuffer::read(uint32_t count, uint8_t* buffer) {
int i=0;
while (i < count) {
if (this->readPtr == this->writePtr)
@ -38,3 +38,7 @@ int CircularRWBuffer::read(uint32_t count, uint8_t* buffer) {
}
return i;
}
uint32_t CircularRWBuffer::size() {
return 0;
}

View File

@ -12,8 +12,9 @@ private:
public:
CircularRWBuffer(uint32_t reader, uint32_t writer);
int read(uint32_t count, uint8_t* buffer) override;
int write(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 size() override;
};
#endif

View File

@ -12,8 +12,9 @@ void ReadWriter::giveWritePerm(uint32_t PID) {
this->allowedWrite.append(PID);
}
int ReadWriter::read(uint32_t count, uint8_t* buffer){}
int ReadWriter::write(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::read(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::write(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::size(){}
bool ReadWriter::canRead(uint32_t PID) {
if (this->owner == PID)

View File

@ -15,8 +15,9 @@ public:
void giveReadPerm(uint32_t PID);
void giveWritePerm(uint32_t PID);
virtual int read(uint32_t count, uint8_t* buffer);
virtual int write(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 size();
uint32_t getOwner();
bool canRead(uint32_t PID);
bool canWrite(uint32_t PID);

View File

@ -182,7 +182,7 @@ void Terminal::printf(const char* string, ...) {
va_end(ptr);
}
int Terminal::write(uint32_t count, uint8_t* string) {
uint32_t Terminal::write(uint32_t count, uint8_t* string) {
/*char* buf = new char[count+1];
for (int i=0;i<count;i++) {
buf[i] = buffer[i];
@ -272,7 +272,7 @@ int Terminal::write(uint32_t count, uint8_t* string) {
this->set_curpos(this->cur_x, this->cur_y);
}
int Terminal::read(uint32_t count, uint8_t* buffer) {}
uint32_t Terminal::read(uint32_t count, uint8_t* buffer) {}
void Terminal::clear_screen() {
for (int i=0; i < width * height * pages; i++) {

View File

@ -38,8 +38,8 @@ public:
void printf(const char* string, ...);
int write(uint32_t count, uint8_t* buffer) override;
int read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t read(uint32_t count, uint8_t* buffer) override;
void clear_screen();
void set_curpos(int x, int y);

View File

@ -168,15 +168,16 @@ int main() {
for (int i=0; i<80;i++)
write(1, 0, &plus);
char* hello_bin = "HELLO BIN";
uint32_t p1 = fork(hello_bin);
uint32_t p2 = fork(hello_bin);
uint32_t program = fopen("hello.bin");
uint32_t p1 = fork(program);
uint32_t p1out = bindStdout(p1);
uint32_t p1in = bindStdin(p1);
fclose(program);
program = fopen("hello.bin");
uint32_t p2 = fork(program);
uint32_t p2out = bindStdout(p2);
uint32_t p2in = bindStdin(p2);
fclose(program);
procbuffer b1 = {
.buffer = localalloc(21 * 38),