Moved to a new Filesystem, ATA and FAT16 driver.

This commit is contained in:
Xnoe 2022-04-06 14:46:47 +01:00
parent ed34174d68
commit a0d0454e32
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
24 changed files with 1569 additions and 383 deletions

View File

@ -1,67 +1,60 @@
CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast CFLAGS = -g -std=gnu11 -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-leading-underscore -fno-pie -fno-stack-protector -Wno-pointer-to-int-cast -Isrc/
CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -I. CXXFLAGS = -g -m32 -fno-use-cxa-atexit -mgeneral-regs-only -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -fpermissive -fno-pie -fno-stack-protector -Isrc/
LDFLAGS = LDFLAGS =
DISK_IMG_FILES = build/kernel/kernel.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) KERNEL_CPP_SRCS = $(shell find src/kernel/ -name '*.cpp')
KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm) KERNEL_ASM_SRCS = $(shell find src/kernel/ -name '*.asm')
KERNEL_CPP_OBJS = $(patsubst src/%.cpp,build/%.o,$(KERNEL_CPP_SRCS)) KERNEL_CPP_OBJS = $(patsubst src/%.cpp,build/%.o,$(KERNEL_CPP_SRCS))
KERNEL_ASM_OBJS = $(patsubst src/%.asm,build/%.o,$(KERNEL_ASM_SRCS)) KERNEL_ASM_OBJS = $(patsubst src/%.asm,build/%.o,$(KERNEL_ASM_SRCS))
KERNEL_OBJS = build/kernel/isr.o $(KERNEL_CPP_OBJS) $(KERNEL_ASM_OBJS) KERNEL_OBJS = build/kernel/isr.o $(KERNEL_CPP_OBJS) $(KERNEL_ASM_OBJS)
STAGE2_C_SRCS = $(wildcard src/boot_stage2/*.c) STAGE2_C_SRCS = $(wildcard src/bootstage2/*.c)
STAGE2_C_OBJS = $(patsubst src/%.c,build/%.o,$(STAGE2_C_SRCS)) STAGE2_C_OBJS = $(patsubst src/%.c,build/%.o,$(STAGE2_C_SRCS))
STAGE2_OBJS = build/c_code_entry.o $(STAGE2_C_OBJS) STAGE2_OBJS = build/c_code_entry.o $(STAGE2_C_OBJS)
PROGRAM_COMMON = build/program_code_entry.o build/common/common.o PROGRAM_COMMON = build/programs/entry.o build/common/common.o
PROGRAM_C_SRCS = $(wildcard src/program/*.c) SRC_DIRS = $(shell find src/ -type d)
PROGRAM_C_OBJS = $(patsubst src/%.c,build/%.o,$(PROGRAM_C_SRCS)) BUILD_DIRS = $(subst src/,build/,$(SRC_DIRS))
PROGRAM_OBJS = $(PROGRAM_COMMON) $(PROGRAM_C_OBJS)
HELLO_C_SRCS = $(wildcard src/hello/*.c) PROGRAMS = $(shell find src/programs/* -type d)
HELLO_C_OBJS = $(patsubst src/%.c,build/%.o,$(HELLO_C_SRCS)) $(foreach program,$(PROGRAMS),\
HELLO_OBJS = $(PROGRAM_COMMON) $(HELLO_C_OBJS) $(eval $(program)_C_SRCS := $(shell find $(program) -name '*.c')) \
$(eval $(program)_CPP_SRCS := $(shell find $(program) -name '*.cpp')) \
$(eval $(program)_OBJS := $(patsubst src/%.c,build/%.o,$($(program)_C_SRCS)) \
$(patsubst src/%.cpp,build/%.o,$($(program)_CPP_SRCS))) \
$(eval DISK_IMG_FILES += $(subst src/,build/,$(program))/$(shell basename $(program).bin)) \
)
WORLD_C_SRCS = $(wildcard src/world/*.c) .PHONY: run debug prepare clean cleanbuild
WORLD_C_OBJS = $(patsubst src/%.c,build/%.o,$(WORLD_C_SRCS))
WORLD_OBJS = $(PROGRAM_COMMON) $(WORLD_C_OBJS)
.PHONY: run debug prepare clean
run: disk.img run: disk.img
qemu-system-i386 disk.img qemu-system-i386 disk.img
debug: disk.img cleanbuild: clean disk.img
qemu-system-i386 disk.img
debug: clean disk.img
qemu-system-i386 -s -S -no-reboot -no-shutdown disk.img & gdb --command=gdbscript qemu-system-i386 -s -S -no-reboot -no-shutdown disk.img & gdb --command=gdbscript
disk.img: prepare build/boot/boot.bin build/boot_stage2/boot.bin $(DISK_IMG_FILES) build/world/world.bin disk.img: prepare build/boot/boot.bin build/bootstage2/boot.bin $(DISK_IMG_FILES)
dd if=/dev/zero of=disk.img count=43 bs=100k dd if=/dev/zero of=disk.img count=43 bs=100k
dd if=build/boot/boot.bin of=disk.img conv=notrunc 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 dd obs=512 seek=1 if=build/bootstage2/boot.bin of=disk.img conv=notrunc
mount disk.img img.d mount disk.img img.d
mkdir img.d/etc/ mkdir img.d/etc/
cp $(DISK_IMG_FILES) img.d/ cp $(DISK_IMG_FILES) img.d/
cp build/world/world.bin img.d/etc/world.bin
sleep 0.1 sleep 0.1
umount img.d umount img.d
chmod 777 disk.img chmod 777 disk.img
prepare: prepare:
mkdir -p img.d mkdir -p img.d
mkdir -p build/boot mkdir -p $(BUILD_DIRS)
mkdir -p build/boot_stage2
mkdir -p build/kernel
mkdir -p build/kernel/datatypes
mkdir -p build/kernel/stdio
mkdir -p build/program
mkdir -p build/hello
mkdir -p build/world
mkdir -p build/common
mountpoint img.d | grep not || umount img.d mountpoint img.d | grep not || umount img.d
clean: clean:
@ -71,10 +64,10 @@ build/boot/boot.bin: src/boot/boot.asm
nasm $< -o $@ nasm $< -o $@
# Boot Stage 2 # Boot Stage 2
build/boot_stage2/boot.bin: src/boot_stage2/boot_stage2.ld $(STAGE2_OBJS) build/bootstage2/boot.bin: src/bootstage2/bootstage2.ld $(STAGE2_OBJS)
ld $(LDFLAGS) -T $< $(STAGE2_OBJS) ld $(LDFLAGS) -T $< $(STAGE2_OBJS)
build/boot_stage2/%.o: src/boot_stage2/%.c build/bootstage2/%.o: src/bootstage2/%.c
gcc $(CFLAGS) -o $@ -c $< gcc $(CFLAGS) -o $@ -c $<
# Kernel # Kernel
@ -101,12 +94,6 @@ src/kernel/isr.S: src/kernel/isr.S.base src/kernel/gen_isr_asm.sh
# Program # Program
build/program/program.bin: src/program/program.ld $(PROGRAM_OBJS) .SECONDEXPANSION:
echo $(PROGRAM_OBJS) build/programs/%.bin: src/programs/userspace.ld build/programs/entry.o $$(src/programs/$$(basename $$(notdir $$*))_OBJS) $(PROGRAM_COMMON)
ld $(LDFLAGS) -T $< $(PROGRAM_OBJS) ld -o $@ -T $^
build/hello/hello.bin: src/hello/hello.ld $(HELLO_OBJS)
ld $(LDFLAGS) -T $< $(HELLO_OBJS)
build/world/world.bin: src/world/world.ld $(WORLD_OBJS)
ld $(LDFLAGS) -T $< $(WORLD_OBJS)

161
src/kernel/ata.cpp Normal file
View File

@ -0,0 +1,161 @@
#include "ata.h"
uint16_t controlBase[4] = {0x1f0, 0x170, 0x1e8, 0x168};
uint16_t dcrBase[4] = {0x3f6, 0x376, 0x3e6, 0x366};
uint8_t ATA::readStatus() {
uint8_t status;
for (int i=0; i<15; i++)
status=StatusRegister.readb();
return status;
}
uint8_t ATA::pollTillNotBSY() {
uint8_t lastStatus;
while (((lastStatus=StatusRegister.readb()) & 0x80))
if (lastStatus&0x1)
return lastStatus;
return 0;
}
uint8_t ATA::pollTillDRQ() {
uint8_t lastStatus;
while (!((lastStatus=StatusRegister.readb()) & 0x8))
if (lastStatus&0x1)
return lastStatus;
return 0;
}
ATA::ATA(uint32_t bus) :
DataRegister(controlBase[bus]+0),
ErrorRegister(controlBase[bus]+1),
FeaturesRegister(controlBase[bus]+1),
SectorCountRegister(controlBase[bus]+2),
LBOLo(controlBase[bus]+3),
LBOMid(controlBase[bus]+4),
LBOHi(controlBase[bus]+5),
DriveSelectRegister(controlBase[bus]+6),
StatusRegister(controlBase[bus]+7),
CommandRegister(controlBase[bus]+7) {
this->isValid = 0;
DriveSelectRegister.writeb(0xA0);
LBOLo.writeb(0);
LBOMid.writeb(0);
LBOHi.writeb(0);
CommandRegister.writeb(0xEC);
if (!readStatus()) {
this->isValid = false;
} else {
pollTillNotBSY();
uint8_t lbomid;
uint8_t lbohi;
if ((lbomid = LBOMid.readb()) || (lbohi = LBOHi.readb())) {
this->isValid = false;
} else {
uint8_t status = pollTillDRQ();
if (!(status&0x1)) {
for (int i=0; i<256; i++)
((uint16_t*)identifyResult)[i] = DataRegister.readw();
this->isValid = true;
}
}
}
if (this->isValid) {
this->totalLBA28Sectors = *((uint32_t*)(identifyResult+60));
this->diskSize = this->totalLBA28Sectors * 512;
}
}
bool ATA::validDevice() {
return this->isValid;
}
void ATA::ATARead(uint32_t sector, uint8_t* buffer) {
DriveSelectRegister.writeb(0xE0 | ((sector >> 24) & 0xf));
SectorCountRegister.writeb(1);
LBOLo.writeb((uint8_t)sector);
LBOMid.writeb((uint8_t)(sector>>8));
LBOHi.writeb((uint8_t)(sector>>16));
CommandRegister.writeb(0x20);
pollTillNotBSY();
for (int i=0; i<256; i++)
((uint16_t*)buffer)[i] = DataRegister.readw();
}
void ATA::ATAWrite(uint32_t sector, uint8_t* buffer) {
DriveSelectRegister.writeb(0xE0 | ((sector >> 24) & 0xf));
SectorCountRegister.writeb(1);
LBOLo.writeb((uint8_t)sector);
LBOMid.writeb((uint8_t)(sector>>8));
LBOHi.writeb((uint8_t)(sector>>16));
CommandRegister.writeb(0x30);
pollTillNotBSY();
for (int i=0; i<256; i++)
DataRegister.writew(((uint16_t*)buffer)[i]);
CommandRegister.writeb(0xe7);
}
ATAReadWriter::ATAReadWriter(uint32_t owner, uint32_t bus):
ATA(bus),
ReadWriter(owner) {
this->currentPosition = 0;
}
uint32_t ATAReadWriter::read(uint32_t count, uint8_t* buffer) {
uint32_t remainingBytes = count;
uint32_t inThisSector = currentPosition % 512;
uint32_t index=0;
uint32_t c=0;
ATARead(currentPosition / 512, sectorBuffer);
while (remainingBytes) {
if (currentPosition >= diskSize)
break;
buffer[index++] = sectorBuffer[inThisSector++];
remainingBytes--;
currentPosition++;
if (inThisSector == 512) {
ATARead(currentPosition / 512, sectorBuffer);
inThisSector = 0;
}
c++;
}
return c;
}
uint32_t ATAReadWriter::write(uint32_t count, uint8_t* buffer) {
uint32_t remainingBytes = count;
uint32_t inThisSector = currentPosition % 512;
uint32_t index=0;
uint32_t c=0;
ATARead(currentPosition / 512, sectorBuffer);
while (remainingBytes) {
if (currentPosition >= diskSize)
break;
sectorBuffer[inThisSector++] = buffer[index++];
remainingBytes--;
currentPosition++;
if (inThisSector == 512) {
ATAWrite((currentPosition / 512) - 1, sectorBuffer);
ATARead(currentPosition / 512, sectorBuffer);
inThisSector = 0;
}
c++;
}
// Perform a final write to ensure that we've written everything to disk.
ATAWrite((currentPosition / 512), sectorBuffer);
return c;
}
uint32_t ATAReadWriter::size() {
return this->diskSize;
}
uint32_t ATAReadWriter::seek(uint32_t position) {
this->currentPosition = position;
}

110
src/kernel/ata.h Normal file
View File

@ -0,0 +1,110 @@
#ifndef ATA_PIO
#define ATA_PIO
#include <stdbool.h>
#include "io.h"
#include "types.h"
#include "strings.h"
#include "allocate.h"
#include "global.h"
#include "ioport.h"
#include "stdio/readwriter.h"
// Bus 0
// Control Ports: 1F0-1F7
// DCR / Alt Status: 3F6
// IRQ: 14
// Bus 1
// Control Ports: 170-177
// DCR / Alt Status: 376
// IRQ: 15
// Bus 2
// Control Ports: 1E8-1EF
// DCR / Alt Status: 3E6
// IRQ: Determine via PCI
// Bus 3
// Control Ports: 168-16F
// DCR / Alt Status: 366
// IRQ: Determine via PCI
// Control Port Map
// Name | RW | Offset | Size28 | Size48
// Data Register RW 0 2 2
// Error Register R 1 1 2
// Features Reg. W 1 1 2
// Sector Count Reg. RW 2 1 2
// LBOlo RW 3 1 2
// LBOmid RW 4 1 2
// LBOhi RW 5 1 2
// Drive Select RW 6 1 1
// Status Reg R 7 1 1
// Command Reg W 7 1 1
// DCR Port Map
// Name | RW | Offset | Size28 | Size48
// Alt. Status R 0 1 1
// Device Control W 1 1 1
// Device Address R 1 1 1
enum ATADriveType {
ATA,
ATAPI,
SATA
};
class ATA {
private:
ATADriveType type;
protected:
uint32_t bus;
uint32_t totalLBA28Sectors;
uint32_t diskSize;
uint8_t identifyResult[512];
Port DataRegister;
Port ErrorRegister;
Port FeaturesRegister;
Port SectorCountRegister;
Port LBOLo;
Port LBOMid;
Port LBOHi;
Port DriveSelectRegister;
Port StatusRegister;
Port CommandRegister;
bool isValid;
uint8_t readStatus();
uint8_t pollTillNotBSY();
uint8_t pollTillDRQ();
public:
ATA(uint32_t bus);
bool validDevice();
void ATARead(uint32_t sector, uint8_t* buffer);
void ATAWrite(uint32_t sector, uint8_t* buffer);
};
class ATAReadWriter: public ReadWriter, public ATA {
private:
uint8_t sectorBuffer[512];
uint32_t currentPosition;
public:
ATAReadWriter(uint32_t owner, uint32_t bus);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
uint32_t seek(uint32_t position) override;
};
#endif

View File

@ -1,255 +0,0 @@
#include "atapio.h"
// Disk code
// Primary ATA Bus: 0x1f0 to 0x1f7
// Device Control Register: 0x3f6
// Secondary ATA Bus: 0x170 to 0x177
// Device Control Register: 0x376
uint16_t identify_result[256];
uint32_t total_28_lbas = 0;
DirectoryEntry* rootDirEntries;
uint16_t* FAT1;
uint16_t countReserved;
uint8_t countFATs;
uint16_t countRDEs;
uint16_t sectorsPerFAT;
void init_atapio() {
rootDirEntries = (DirectoryEntry*)new uint8_t[8192];
FAT1 = (uint16_t*)(new uint8_t[512 * 34]);
uint32_t boot_sector = new uint32_t[1024];
read_sectors(0, 1, (uint8_t*)boot_sector);
countReserved = *((uint16_t*)(boot_sector + 0x0e));
countFATs = *((uint8_t*)(boot_sector + 0x10));
countRDEs = *((uint16_t*)(boot_sector + 0x11));
sectorsPerFAT = *((uint16_t*)(boot_sector + 0x16));
// Select Drive 0 on the Primary Bus
outb(0x1f6, 0xa0);
// Set sector count to 0 for IDENTIFY
outb(0x1f2, 0);
// Set LBAlo to 0
outb(0x1f3, 0);
// Set LBAmid to 0
outb(0x1f4, 0);
// Set LBAhi to 0
outb(0x1f5, 0);
// Send IDENTIFY command
outb(0x1f7, 0xec);
uint8_t status = inb(0x1f7);
if (status) {
while ((status = inb(0x1f7)) & 0x80);
if ( !(inb(0x1f4) || inb(0x1f5)) ) {
while ( !(status & 8 || status & 1) )
status = inb(0x1f7);
if (!(status & 1)) {
for (int index=0; index<256; index++)
identify_result[index] = inw(0x1f0);
}
}
}
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, (uint8_t*)rootDirEntries);
read_sectors(countReserved, sectorsPerFAT, (uint8_t*)FAT1);
}
void read_sector(uint32_t address, uint8_t* buffer) {
outb(0x1f6, 0xe0 | ((address>>24)&0x0f));
// Read a single sector
outb(0x1f2, 1);
// Set LBAlo, LBAmid and LBAhi
outb(0x1f3, address);
outb(0x1f4, address>>8);
outb(0x1f5, address>>16);
// Send read command
outb(0x1f7, 0x20);
// Poll
uint8_t status = inb(0x1f7);
while ( (status & 0x80) && !(status & 8) )
status = inb(0x1f7);
for (int index=0; index<256; index++)
((uint16_t*)buffer)[index] = inw(0x1f0);
}
void read_sectors(uint32_t address, int count, uint8_t* buffer) {
for (int i=0; i<count; i++) {
read_sector(address+i, buffer+512*i);
for (int i=0; i<15; i++)
inb(0x1f7);
}
}
uint32_t clusterToSector(uint32_t cluster) {
return cluster + (sectorsPerFAT * countFATs) + (countRDEs / 16) + (countReserved - 1) - 1;
}
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 = clusterToSector(location);
read_sector(fromSector, destination+offset);
offset += 512;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
}
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) {
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

@ -1,77 +0,0 @@
#ifndef ATA_PIO
#define ATA_PIO
#include <stdbool.h>
#include "io.h"
#include "types.h"
#include "strings.h"
#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);
uint16_t file_exists(char* filename);
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

@ -27,11 +27,21 @@ namespace xnoe {
while (start) { while (start) {
if (start->elem == t) if (start->elem == t)
return true; return true;
//current = current->next;
} }
return false; return false;
} }
void destroy() {
xnoe::linkedlistelem<T>* current = this->start;
while (current) {
xnoe::linkedlistelem<T>* c = current;
current = current->next;
delete c;
}
}
void append(T t) { void append(T t) {
xnoe::linkedlistelem<T>* llelem = new xnoe::linkedlistelem<T>(t); xnoe::linkedlistelem<T>* llelem = new xnoe::linkedlistelem<T>(t);
append(llelem); append(llelem);

View File

@ -0,0 +1,27 @@
#include "devfs.h"
bool DevFS::exists(Path p) {
if (p.start->elem == PathEntry{3, "ata"})
return true;
return false;
}
FSType DevFS::type(Path p) {
if (p.start->elem == PathEntry{3, "ata"})
return BlockDev;
}
ReadWriter* DevFS::open(Path p) {
if (p.start->elem == PathEntry{3, "ata"}) {
return new ATAReadWriter(0, 0);
}
return 0;
}
uint32_t DevFS::getDentsSize(Path p) {
return 0;
}
void DevFS::getDents(Path p, FSDirectoryListing* buffer) {}

View File

@ -0,0 +1,18 @@
#ifndef DEVFS_H
#define DEVFS_H
#include "fstree.h"
#include "../ata.h"
#include "../kernel.h"
class DevFS: public FSTree {
bool exists(Path p) override;
FSType type(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
#endif

View File

@ -0,0 +1,394 @@
#include "fat16.h"
uint32_t FAT16FileReadWriter::offsetBytesToCluster(uint32_t offset) {
uint32_t cluster = this->firstCluster;
uint32_t remaining = offset;
while (remaining > 512) {
cluster = this->backingFS->FAT1[this->firstCluster];
remaining -= 512;
}
return cluster;
}
FAT16FileReadWriter::FAT16FileReadWriter(uint32_t owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS)
: ReadWriter(owner) {
this->firstCluster = firstCluster;
this->sizeBytes = sizeBytes;
this->currentPosition = 0;
this->backingFS = backingFS;
}
uint32_t FAT16FileReadWriter::read(uint32_t count, uint8_t* buffer) {
uint8_t* clusterBuffer = new uint8_t[512];
uint32_t clusterToRead = offsetBytesToCluster(this->currentPosition);
uint32_t sectorToRead = this->backingFS->clusterToSector(clusterToRead);
this->backingFS->backingDevice->seek(sectorToRead * 512);
this->backingFS->backingDevice->read(512, clusterBuffer);
uint32_t currentClusterIndex = this->currentPosition % 512;
uint32_t remaining = count;
uint32_t index = 0;
while (remaining) {
if (currentClusterIndex == 512) {
clusterToRead = this->backingFS->FAT1[clusterToRead];
if (clusterToRead == 0xffff)
break;
sectorToRead = this->backingFS->clusterToSector(clusterToRead);
this->backingFS->backingDevice->seek(sectorToRead * 512);
this->backingFS->backingDevice->read(512, clusterBuffer);
currentClusterIndex = 0;
}
buffer[index++] = clusterBuffer[currentClusterIndex++];
remaining--;
}
delete[] clusterBuffer;
return index;
}
uint32_t FAT16FileReadWriter::write(uint32_t count, uint8_t* buffer) {}
uint32_t FAT16FileReadWriter::size() {
return this->sizeBytes;
}
uint32_t FAT16FileReadWriter::seek(uint32_t position) {
if (position < this->sizeBytes) {
this->currentPosition = position;
return position;
}
return 0;
}
char safeUppercase(char c) {
switch (c) {
case 'a'...'z':
return c & ~32;
default:
return c;
}
}
bool FAT16FS::pathEntryTo83(PathEntry pe, char* buffer) {
uint32_t maxSize = pe.length;
uint8_t* data = pe.path;
uint32_t readIndex=0;
uint32_t writeIndex=0;
while (writeIndex<11 && readIndex < maxSize) {
char c;
if ((c=data[readIndex++]) == '.') {
writeIndex = 8;
continue;
}
buffer[writeIndex++] = safeUppercase(c);
}
}
uint32_t FAT16FS::clusterToSector(uint32_t cluster) {
return cluster + (*sectorsPerFAT * *countFATs) + (*countRDEs / 16) + (*countReserved - 1) - 1;
}
void FAT16FS::load_file(uint32_t location, uint8_t* destination) {
int offset = 0;
bool loaded = false;
while (!loaded) {
uint16_t fromSector = clusterToSector(location);
this->backingDevice->seek(fromSector * 512);
this->backingDevice->read(512, destination+offset);
offset += 512;
location = FAT1[location++];
if (location == 0xffff)
loaded = true;
}
}
uint32_t FAT16FS::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;
}
xnoe::tuple<DirectoryEntry*, uint32_t, bool> FAT16FS::getDirectoryEntry(Path p) {
PathElement* current = p.start;
DirectoryEntry* currentDirectory = new DirectoryEntry[*countRDEs];
for (int i=0; i < *countRDEs; i++)
currentDirectory[i] = rootDirEntries[i];
uint32_t count = *countRDEs;
if (!current)
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
escape_for:
while (current != p.end) {
char name83[12] = " ";
pathEntryTo83(current->elem, name83);
for (int i=0; i < count; i++) {
if (strcmp(currentDirectory[i].name, name83, 11)) {
DirectoryEntry found = currentDirectory[i];
if (!(found.directory))
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
delete currentDirectory;
uint32_t sizeBytes = calc_size(found.firstClusterLow);
currentDirectory = (DirectoryEntry*)(new uint8_t[sizeBytes]);
load_file(found.firstClusterLow, (uint8_t*)currentDirectory);
i=0;
count = sizeBytes / sizeof(DirectoryEntry);
current = current->next;
goto escape_for;
}
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, 0, false);
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
}
xnoe::tuple<DirectoryEntry*, uint32_t, bool> FAT16FS::getDirectoryEntryFull(Path p) {
PathElement* current = p.start;
DirectoryEntry* currentDirectory = new DirectoryEntry[*countRDEs];
for (int i=0; i < *countRDEs; i++)
currentDirectory[i] = rootDirEntries[i];
uint32_t count = *countRDEs;
if (!current)
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
escape_for:
while (current) {
char name83[12] = " ";
pathEntryTo83(current->elem, name83);
for (int i=0; i < count; i++) {
if (strcmp(currentDirectory[i].name, name83, 11)) {
DirectoryEntry found = currentDirectory[i];
if (!(found.directory))
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
delete currentDirectory;
uint32_t sizeBytes = calc_size(found.firstClusterLow);
currentDirectory = (DirectoryEntry*)(new uint8_t[sizeBytes]);
load_file(found.firstClusterLow, (uint8_t*)currentDirectory);
i=0;
count = sizeBytes / sizeof(DirectoryEntry);
current = current->next;
goto escape_for;
}
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, 0, false);
}
return xnoe::tuple<DirectoryEntry*, uint32_t, bool>(currentDirectory, count, true);
}
FAT16FS::FAT16FS(ReadWriter* disk) {
this->backingDevice = disk;
this->backingDevice->seek(0);
this->backingDevice->read(512, sectorOne);
this->rootDirEntries = new DirectoryEntry[*countRDEs];
this->backingDevice->seek(((*sectorsPerFAT) * (*countFATs) + (*countReserved)) * 512);
this->backingDevice->read((*countRDEs) * sizeof(DirectoryEntry), (uint8_t*)this->rootDirEntries);
this->FAT1 = new uint16_t[(*sectorsPerFAT) * 256];
this->backingDevice->seek((*countReserved) * 512);
this->backingDevice->read((*sectorsPerFAT) * 512, (uint8_t*)FAT1);
}
bool FAT16FS::exists(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return false;
bool found = false;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return false;
char name83[11] = {' '};
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
found = true;
break;
}
}
delete directoryEntries;
return found;
}
FSType FAT16FS::type(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return NoExist;
FSType found = NoExist;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return NoExist;
char name83[11] = {' '};
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
if (directoryEntries[i].directory)
found = Directory;
else
found = File;
}
}
delete directoryEntries;
return found;
}
ReadWriter* FAT16FS::open(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntry(p);
if (!xnoe::get<2>(directory))
return 0;
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
uint32_t count = xnoe::get<1>(directory);
PathElement* end = p.end;
if (!end)
return 0;
uint32_t written=0;
char name83[12] = " ";
name83[11] = 0;
pathEntryTo83(end->elem, name83);
for (int i=0; i<count; i++) {
if (strcmp(directoryEntries[i].name, name83, 11)) {
if (!directoryEntries[i].directory)
return new FAT16FileReadWriter(0, ((uint32_t)directoryEntries[i].firstClusterHigh << 16) | directoryEntries[i].firstClusterLow, directoryEntries[i].size, this);
}
}
delete directoryEntries;
return 0;
}
PathEntry name83ToPathEntry(char* name83, char* text) {
uint32_t mainLength = 8;
uint32_t index = 7;
while (name83[index] == ' ' && index--)
mainLength--;
uint32_t extLength = 3;
index = 10;
while (name83[index] == ' ' && index-- > 7)
extLength--;
memcpy(name83, text, mainLength);
if (name83[8] != ' ') {
text[mainLength] = '.';
memcpy(name83+8, text+mainLength+1, extLength);
}
text[mainLength+extLength+1] = 0;
return PathEntry{mainLength+extLength+1, text};
}
uint32_t getRealCount(DirectoryEntry* directoryEntries, uint32_t c) {
uint32_t r = 0;
for (int i = 0; i < c; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid)
r++;
}
return r;
}
uint32_t FAT16FS::getDentsSize(Path p) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntryFull(p);
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
if (!xnoe::get<2>(directory)) {
delete directoryEntries;
return 0;
}
uint32_t found = 0;
uint32_t count = xnoe::get<1>(directory);
found += 4;
for (int i=0; i<count; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid) {
found += sizeof(FSDirectoryEntry);
found += 13;
}
}
delete directoryEntries;
return found;
}
void FAT16FS::getDents(Path p, FSDirectoryListing* buffer) {
xnoe::tuple<DirectoryEntry*, uint32_t, bool> directory = getDirectoryEntryFull(p);
DirectoryEntry* directoryEntries = xnoe::get<0>(directory);
if (!xnoe::get<2>(directory)) {
delete directoryEntries;
return 0;
}
uint32_t count = xnoe::get<1>(directory);
uint32_t written=0;
buffer->count = getRealCount(directoryEntries, count);
char* nameBuffer = ((char*)buffer);
nameBuffer += sizeof(FSDirectoryEntry)*buffer->count + 4;
for (int i=0; i<count; i++) {
if (directoryEntries[i].name[0] != 0 && directoryEntries[i].name[0] != 0xE5 && !directoryEntries[i].volumeid) {
buffer->entries[written] = FSDirectoryEntry {
name83ToPathEntry(directoryEntries[i].name, nameBuffer + 13*written),
directoryEntries[i].directory ? Directory : File,
directoryEntries[i].size
};
written++;
}
}
delete directoryEntries;
}

View File

@ -0,0 +1,118 @@
#ifndef FAT16_H
#define FAT16_H
#include "fstree.h"
#include "strings.h"
#include "../memory.h"
#include "../stdio/readwriter.h"
#include "../datatypes/tuple.h"
struct __attribute__((packed)) DirectoryEntry {
char name[11];
uint8_t readonly : 1;
uint8_t hidden : 1;
uint8_t system : 1;
uint8_t volumeid : 1;
uint8_t directory : 1;
uint8_t archive : 1;
uint8_t device : 1;
uint8_t _ignored0 : 1;
uint8_t f1 : 1;
uint8_t f2 : 1;
uint8_t f3 : 1;
uint8_t f4 : 1;
uint8_t _ignored1 : 1;
uint8_t deleteRequiresPassword : 1;
uint8_t writeRequiresPassword : 1;
uint8_t readRequiresPassword : 1;
uint8_t createTime10ms;
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;
};
class FAT16FS;
class FAT16FileReadWriter: public ReadWriter {
private:
uint32_t firstCluster;
uint32_t sizeBytes;
uint32_t currentPosition;
uint32_t offsetBytesToCluster(uint32_t offset);
FAT16FS* backingFS;
public:
FAT16FileReadWriter(uint32_t owner, uint32_t firstCluster, uint32_t sizeBytes, FAT16FS* backingFS);
uint32_t read(uint32_t count, uint8_t* buffer) override;
uint32_t write(uint32_t count, uint8_t* buffer) override;
uint32_t size() override;
uint32_t seek(uint32_t position) override;
};
class FAT16FS: public FSTree {
public:
DirectoryEntry* rootDirEntries;
uint16_t* FAT1;
uint8_t sectorOne[512];
uint16_t* countReserved = ((uint16_t*)(sectorOne + 0x0e));
uint8_t* countFATs = ((uint8_t*)(sectorOne + 0x10));
uint16_t* countRDEs = ((uint16_t*)(sectorOne + 0x11));
uint16_t* sectorsPerFAT = ((uint16_t*)(sectorOne + 0x16));
ReadWriter* backingDevice;
bool pathEntryTo83(PathEntry pe, char* buffer);
uint32_t clusterToSector(uint32_t cluster);
void load_file(uint32_t location, uint8_t* destination);
uint32_t calc_size(uint32_t location);
xnoe::tuple<DirectoryEntry*, uint32_t, bool> getDirectoryEntry(Path p);
xnoe::tuple<DirectoryEntry*, uint32_t, bool> getDirectoryEntryFull(Path p);
FAT16FS(ReadWriter* disk);
bool exists(Path p) override;
FSType type(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
#endif

View File

@ -0,0 +1,204 @@
#include "fstree.h"
bool operator==(const PathEntry& lhs, const PathEntry& rhs) {
if (lhs.length == rhs.length)
if (lhs.length == 0)
return true;
else
return strcmp(lhs.path, rhs.path, lhs.length);
return false;
}
// FS Tree Skeleton
bool FSTree::exists(Path p){}
FSType FSTree::type(Path p){}
ReadWriter* FSTree::open(Path p){}
uint32_t FSTree::getDentsSize(Path p){}
void FSTree::getDents(Path p, FSDirectoryListing* buffer){}
// RootFSTree
RootFSTree::RootFSTree() {
this->node = new FSTreeNode{
PathEntry{0,0},
xnoe::linkedlist<FSTreeNode*>(),
0
};
}
bool pathEntryInFSTreeNode(PathEntry p, FSTreeNode* n) {
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
if (current->elem->self == p)
return true;
current = current->next;
}
return false;
}
FSTreeNode* getNodeFromPathEntry(PathEntry p, FSTreeNode* n) {
if (!n)
return 0;
xnoe::linkedlistelem<FSTreeNode*>* current = n->children.start;
while (current) {
if (current->elem->self == p)
return current->elem;
current = current->next;
}
return 0;
}
FSTreeNode* RootFSTree::makeNodeIfNotExist(Path p) {
PathElement* currentPathElement = p.start;
FSTreeNode* currentNode = this->node;
if (!currentPathElement || currentPathElement == p.end)
return currentNode;
nextPE:
while (currentPathElement) {
xnoe::linkedlistelem<FSTreeNode*>* currentChild = currentNode->children.start;
while (currentChild) {
if (currentChild->elem->self == currentPathElement->elem) {
currentNode = currentChild->elem;
currentPathElement = currentPathElement->next;
goto nextPE;
}
currentChild = currentChild->next;
}
currentNode->children.append(new FSTreeNode{currentPathElement->elem, xnoe::linkedlist<FSTreeNode*>(), 0});
currentNode = currentNode->children.end->elem;
currentPathElement = currentPathElement->next;
}
return currentNode;
}
FSTree* RootFSTree::getLongestMatchingUnder(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
FSTree* lastMountpoint = 0;
while (currentPath && currentNode) {
if ((currentPath->elem == currentNode->self) && currentNode->mountpoint)
lastMountpoint = currentNode->mountpoint;
currentNode = getNodeFromPathEntry(currentPath->elem, currentNode);
if (currentNode && currentNode->mountpoint)
lastMountpoint = currentNode->mountpoint;
currentPath = currentPath->next;
}
return lastMountpoint;
}
Path* RootFSTree::getRemainingPath(Path p) {
PathElement* currentPath = p.start;
FSTreeNode* currentNode = this->node;
PathElement* lastMountpoint = 0;
while (currentPath && currentNode) {
if (currentPath->elem == currentNode->self && currentNode->mountpoint)
lastMountpoint = currentPath;
currentNode = getNodeFromPathEntry(currentPath->elem, currentNode);
if (currentNode && currentNode->mountpoint)
lastMountpoint = currentPath;
currentPath = currentPath->next;
}
lastMountpoint = lastMountpoint->next;
if (lastMountpoint) {
Path* np = new Path;
PathElement* current = lastMountpoint;
while (current) {
np->append(current->elem);
current = current->next;
}
return np;
}
return 0;
}
template<typename T>
T RootFSTree::attempt(T(FSTree::*fn)(Path), Path p, T fallback) {
FSTree* mp = getLongestMatchingUnder(p);
if (mp) {
Path* rp = getRemainingPath(p);
T r;
if (rp) {
r = (mp->*fn)(*rp);
rp->destroy();
} else {
r = (mp->*fn)(Path());
}
return r;
}
return fallback;
}
void RootFSTree::attempt(void(FSTree::*fn)(Path, FSDirectoryListing*), Path p, FSDirectoryListing* b) {
FSTree* mp = getLongestMatchingUnder(p);
if (mp) {
Path* rp = getRemainingPath(p);
if (rp) {
(mp->*fn)(*rp, b);
rp->destroy();
} else {
(mp->*fn)(Path(), b);
}
}
}
bool RootFSTree::exists(Path p) {
return attempt<bool>(&FSTree::exists, p, false);
}
FSType RootFSTree::type(Path p){
return attempt<FSType>(&FSTree::type, p, Directory);
}
ReadWriter* RootFSTree::open(Path p){
return attempt<ReadWriter*>(&FSTree::open, p, 0);
}
uint32_t RootFSTree::getDentsSize(Path p){
return attempt<uint32_t>(&FSTree::getDentsSize, p, 0);
}
void RootFSTree::getDents(Path p, FSDirectoryListing* buffer){
attempt(&FSTree::getDents, p, buffer);
}
bool RootFSTree::isMountpoint(Path p) {
Path* mp = getRemainingPath(p);
if (mp->start->next)
return false;
else
return true;
}
void RootFSTree::mount(Path p, FSTree* f) {
FSTreeNode* fstn = makeNodeIfNotExist(p);
fstn->mountpoint = f;
}
void RootFSTree::unmount(Path p) {
}
Path createPathFromString(char* s) {
Path p;
p.start = 0;
p.end = 0;
char* lastPtr = s;
uint32_t length = 0;
char c;
while (c=*(s++)) {
if (c == '/') {
if (length == 0)
p.append(PathEntry{length, 0});
else
p.append(PathEntry{length, lastPtr});
lastPtr = s;
length = 0;
continue;
}
length += 1;
}
if (length)
p.append(PathEntry{length, lastPtr});
return p;
}

View File

@ -0,0 +1,85 @@
#ifndef FSTREE_H
#define FSTREE_H
#include "../datatypes/linkedlist.h"
#include "strings.h"
#include "../stdio/readwriter.h"
struct PathEntry {
uint16_t length;
uint8_t* path;
};
bool operator==(const PathEntry& lhs, const PathEntry& rhs);
using Path = xnoe::linkedlist<PathEntry>;
using PathElement = xnoe::linkedlistelem<PathEntry>;
enum FSType {
File,
Directory,
CharacterDev,
BlockDev,
NoExist
};
struct FSDirectoryEntry {
PathEntry path;
FSType type;
uint32_t sizeBytes;
};
struct FSDirectoryListing {
uint32_t count;
FSDirectoryEntry entries[];
};
class FSTreeNode;
class FSTree {
public:
virtual bool exists(Path p);
virtual FSType type(Path p);
virtual ReadWriter* open(Path p);
virtual uint32_t getDentsSize(Path p);
virtual void getDents(Path p, FSDirectoryListing* buffer);
};
struct FSTreeNode {
PathEntry self;
xnoe::linkedlist<FSTreeNode*> children;
FSTree* mountpoint;
};
class RootFSTree: public FSTree {
private:
FSTree* getLongestMatchingUnder(Path p);
Path* getRemainingPath(Path p);
FSTreeNode* makeNodeIfNotExist(Path p);
template<typename T>
T attempt(T(FSTree::*fn)(Path), Path p, T fallback);
void attempt(void(FSTree::*fn)(Path, FSDirectoryListing*), Path p, FSDirectoryListing* b);
public:
RootFSTree();
FSTreeNode* node;
bool isMountpoint(Path p);
void mount(Path p, FSTree* f);
void unmount(Path p);
bool exists(Path p) override;
FSType type(Path p) override;
ReadWriter* open(Path p) override;
uint32_t getDentsSize(Path p) override;
void getDents(Path p, FSDirectoryListing* buffer) override;
};
Path createPathFromString(char* s);
#endif

View File

@ -298,8 +298,9 @@ void syscall(frame_struct* frame) {
} }
case 15: { case 15: {
ReadWriter* file = new FATFileReadWriter(0, esi); ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(esi));
rval = Global::kernel->mapFH(file); if (file)
rval = Global::kernel->mapFH(file);
break; break;
} }

19
src/kernel/ioport.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "ioport.h"
Port::Port(uint16_t a) {
this->addr = a;
}
uint8_t Port::readb() {
return inb(this->addr);
}
uint16_t Port::readw() {
return inw(this->addr);
}
void Port::writeb(uint8_t d) {
outb(this->addr, d);
}
void Port::writew(uint16_t d) {
outw(this->addr, d);
}

19
src/kernel/ioport.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef IOPORT_H
#define IOPORT_H
#include "io.h"
class Port {
private:
uint16_t addr;
public:
Port(uint16_t a);
uint8_t readb();
uint16_t readw();
void writeb(uint8_t d);
void writew(uint16_t d);
};
#endif

View File

@ -5,6 +5,7 @@
#include "datatypes/hashtable.h" #include "datatypes/hashtable.h"
#include "global.h" #include "global.h"
#include "terminal.h" #include "terminal.h"
#include "filesystem/fstree.h"
class Kernel : public Process { class Kernel : public Process {
private: private:
@ -20,6 +21,8 @@ public:
xnoe::linkedlist<Process*> processes; xnoe::linkedlist<Process*> processes;
xnoe::linkedlist<Process*> KBListeners; xnoe::linkedlist<Process*> KBListeners;
RootFSTree* rootfs;
Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack); Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack);
void init_kernel(); void init_kernel();

View File

@ -4,7 +4,7 @@
#include "idt.h" #include "idt.h"
#include "keyboard.h" #include "keyboard.h"
#include "strings.h" #include "strings.h"
#include "atapio.h" #include "ata.h"
#include "gdt.h" #include "gdt.h"
#include "paging.h" #include "paging.h"
#include "allocate.h" #include "allocate.h"
@ -14,6 +14,9 @@
#include "datatypes/hashtable.h" #include "datatypes/hashtable.h"
#include "terminal.h" #include "terminal.h"
#include "kernel.h" #include "kernel.h"
#include "filesystem/fstree.h"
#include "filesystem/fat16.h"
#include "filesystem/devfs.h"
int main() { int main() {
init_gdt(); init_gdt();
@ -29,7 +32,6 @@ int main() {
Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, 0xc1006000); Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, 0xc1006000);
kernel.init_kernel(); kernel.init_kernel();
init_atapio();
VGAModeTerminal* term = new VGAModeTerminal(0xc07a0000); VGAModeTerminal* term = new VGAModeTerminal(0xc07a0000);
@ -44,14 +46,30 @@ int main() {
term->printf("KERNEL OK!\n"); term->printf("KERNEL OK!\n");
ReadWriter* worldbin = new FATFileReadWriter(0, "etc/world.bin"); ReadWriter* atareadwriter = new ATAReadWriter(0, 0);
uint8_t* buffer = new uint8_t[512];
for (int i=0;i<512;i++)
buffer[i]=0;
uint32_t size = atareadwriter->size();
atareadwriter->seek(268*512);
atareadwriter->read(512, buffer);
kernel.rootfs = new RootFSTree();
kernel.rootfs->mount(createPathFromString("/dev"), new DevFS());
kernel.rootfs->mount(createPathFromString("/"), new FAT16FS(kernel.rootfs->open(createPathFromString("/dev/ata"))));
ReadWriter* worldbin = kernel.rootfs->open(createPathFromString("/world.bin"));
uint32_t fh = kernel.mapFH(worldbin); uint32_t fh = kernel.mapFH(worldbin);
Process* p1 = kernel.createProcess(fh, term); Process* p1 = kernel.createProcess(fh, term);
init_keyboard(); init_keyboard();
if (worldbin) {
enable_idt(); worldbin->seek(0);
worldbin->read(512, buffer);
worldbin->seek(0);
enable_idt();
}
while (1) asm ("hlt"); while (1) asm ("hlt");
} }

View File

@ -8,7 +8,7 @@
#include "datatypes/maybe.h" #include "datatypes/maybe.h"
#include "screenstuff.h" #include "screenstuff.h"
#include "global.h" #include "global.h"
#include "atapio.h" #include "ata.h"
#include "stdio/readwriter.h" #include "stdio/readwriter.h"

View File

@ -14,6 +14,7 @@ void ReadWriter::giveWritePerm(uint32_t PID) {
uint32_t ReadWriter::read(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::write(uint32_t count, uint8_t* buffer){}
uint32_t ReadWriter::seek(uint32_t position){}
uint32_t ReadWriter::size(){} uint32_t ReadWriter::size(){}
bool ReadWriter::canRead(uint32_t PID) { bool ReadWriter::canRead(uint32_t PID) {

View File

@ -18,6 +18,7 @@ public:
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);
uint32_t getOwner(); uint32_t getOwner();
bool canRead(uint32_t PID); bool canRead(uint32_t PID);
bool canWrite(uint32_t PID); bool canWrite(uint32_t PID);

8
src/programs/entry.asm Normal file
View File

@ -0,0 +1,8 @@
[BITS 32]
_start:
call main
_loop:
jmp _loop
extern main

View File

@ -0,0 +1,40 @@
#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() {
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");
}
}

11
src/programs/userspace.ld Normal file
View File

@ -0,0 +1,11 @@
OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i386:i386)
SECTIONS {
. = 0x20;
.text : {
build/programs/entry.o(.text)
build/common/common.o(.text)
}
}

283
src/programs/world/world.c Normal file
View File

@ -0,0 +1,283 @@
#include "common/common.h"
#include <stdbool.h>
typedef struct {
char* buffer;
int x;
int y;
uint32_t process;
uint32_t stdin;
uint32_t stdout;
} procbuffer;
void scrollBuffer(char* buf) {
for (int y=0; y<56; y++)
for (int x=0; x<43; x++)
if (y != 55)
buf[y*43+x] = buf[(y+1)*43+x];
else
buf[y*43+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 = 42;
buf->y--;
}
buf->buffer[buf->y*43+buf->x] = ' ';
break;
default:
buf->buffer[buf->y*43+buf->x++] = c;
}
if (buf->x == 43) {
buf->x = 0;
buf->y++;
}
if (buf->y == 56) {
buf->y--;
scrollBuffer(buf->buffer);
}
}
void writeCountToBuf(int count, char* c, procbuffer* buf) {
while (count--) {
writeToBuf(*(c++), buf);
}
}
void clearBuf(procbuffer* buf) {
for (int i=0; i<56*43;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 displayBuf(procbuffer* b, int dx, int dy) {
char pset[9] = "\x1b[00;00H";
for (int i=0; i<dy;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<dx;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
for (int i=0; i<56; i++) {
print(pset);
write(43, 0, b->buffer+(43*i));
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
}
void setCurPos(int x, int y) {
char pset[9] = "\x1b[00;00H";
for (int i=0; i<y;i++) {
pset[3]++;
if (pset[3] == 0x3a) {
pset[3] = 0x30;
pset[2]++;
}
}
for (int i=0; i<x;i++) {
pset[6]++;
if (pset[6] == 0x3a) {
pset[6] = 0x30;
pset[5]++;
}
}
print(pset);
}
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;
}
int main() {
bindToKeyboard();
char space = ' ';
char plus = '+';
print("\x1b[1;1H");
for (int i=0; i < 1000; i++)
write(1, 0, &space);
print("\x1b[1;1H");
char* mid = "+ ++ +";
char* bottom = "+ +";
for (int i=0; i<90;i++)
write(1, 0, &plus);
for (int i=0; i<56;i++)
write(90, 0, mid);
for (int i=0; i<90;i++)
write(1, 0, &plus);
write(90, 0, bottom);
for (int i=0; i<90;i++)
write(1, 0, &plus);
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(56 * 43),
.x = 0,
.y = 0,
.process = p1,
.stdin = p1in,
.stdout = p1out
};
procbuffer b2 = {
.buffer = localalloc(56 * 43),
.x = 0,
.y = 0,
.process = p2,
.stdin = p2in,
.stdout = p2out
};
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 (b1.process)
if (succ = read(128, b1.stdout, c))
writeCountToBuf(succ, c, &b1);
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[59;2H");
print(": ");
print("\x1b[59;3H");
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("--------\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;
if (selectedBuf == &b1) {
selectedBuf = &b2;
} else {
selectedBuf = &b1;
}
}
} else if (strcmpcnt(4, buf, "load")) {
if (!selectedBuf->process) {
char* potFn = buf+5;
uint32_t fh = fopen(potFn);
selectedBuf->process = fork(fh);
selectedBuf->stdout = bindStdout(selectedBuf->process);
selectedBuf->stdin = bindStdin(selectedBuf->process);
fclose(fh);
}
}
} else {
if (selectedBuf->process)
write(1, selectedBuf->stdin, c);
}
}
displayBuf(&b1, 2, 2);
displayBuf(&b2, 47, 2);
}
}