From a0d0454e322ed6497c80d5a078c0c23f65c1d556 Mon Sep 17 00:00:00 2001 From: Xnoe Date: Wed, 6 Apr 2022 14:46:47 +0100 Subject: [PATCH] Moved to a new Filesystem, ATA and FAT16 driver. --- Makefile | 73 +++--- src/kernel/ata.cpp | 161 ++++++++++++ src/kernel/ata.h | 110 +++++++++ src/kernel/atapio.cpp | 255 ------------------- src/kernel/atapio.h | 77 ------ src/kernel/datatypes/linkedlist.h | 10 + src/kernel/filesystem/devfs.cpp | 27 ++ src/kernel/filesystem/devfs.h | 18 ++ src/kernel/filesystem/fat16.cpp | 394 ++++++++++++++++++++++++++++++ src/kernel/filesystem/fat16.h | 118 +++++++++ src/kernel/filesystem/fstree.cpp | 204 ++++++++++++++++ src/kernel/filesystem/fstree.h | 85 +++++++ src/kernel/idt.cpp | 5 +- src/kernel/ioport.cpp | 19 ++ src/kernel/ioport.h | 19 ++ src/kernel/kernel.h | 3 + src/kernel/kmain.cpp | 28 ++- src/kernel/process.h | 2 +- src/kernel/stdio/readwriter.cpp | 1 + src/kernel/stdio/readwriter.h | 1 + src/programs/entry.asm | 8 + src/programs/hello/hello.c | 40 +++ src/programs/userspace.ld | 11 + src/programs/world/world.c | 283 +++++++++++++++++++++ 24 files changed, 1569 insertions(+), 383 deletions(-) create mode 100644 src/kernel/ata.cpp create mode 100644 src/kernel/ata.h delete mode 100644 src/kernel/atapio.cpp delete mode 100644 src/kernel/atapio.h create mode 100644 src/kernel/filesystem/devfs.cpp create mode 100644 src/kernel/filesystem/devfs.h create mode 100644 src/kernel/filesystem/fat16.cpp create mode 100644 src/kernel/filesystem/fat16.h create mode 100644 src/kernel/filesystem/fstree.cpp create mode 100644 src/kernel/filesystem/fstree.h create mode 100644 src/kernel/ioport.cpp create mode 100644 src/kernel/ioport.h create mode 100644 src/programs/entry.asm create mode 100644 src/programs/hello/hello.c create mode 100644 src/programs/userspace.ld create mode 100644 src/programs/world/world.c diff --git a/Makefile b/Makefile index 661d128..a698177 100644 --- a/Makefile +++ b/Makefile @@ -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 -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. +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 -Isrc/ LDFLAGS = -DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt \ - build/hello/hello.bin +DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt -KERNEL_CPP_SRCS = $(wildcard src/kernel/*.cpp) $(wildcard src/kernel/*/*.cpp) -KERNEL_ASM_SRCS = $(wildcard src/kernel/*.asm) +KERNEL_CPP_SRCS = $(shell find src/kernel/ -name '*.cpp') +KERNEL_ASM_SRCS = $(shell find src/kernel/ -name '*.asm') KERNEL_CPP_OBJS = $(patsubst src/%.cpp,build/%.o,$(KERNEL_CPP_SRCS)) KERNEL_ASM_OBJS = $(patsubst src/%.asm,build/%.o,$(KERNEL_ASM_SRCS)) 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_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) -PROGRAM_C_OBJS = $(patsubst src/%.c,build/%.o,$(PROGRAM_C_SRCS)) -PROGRAM_OBJS = $(PROGRAM_COMMON) $(PROGRAM_C_OBJS) +SRC_DIRS = $(shell find src/ -type d) +BUILD_DIRS = $(subst src/,build/,$(SRC_DIRS)) -HELLO_C_SRCS = $(wildcard src/hello/*.c) -HELLO_C_OBJS = $(patsubst src/%.c,build/%.o,$(HELLO_C_SRCS)) -HELLO_OBJS = $(PROGRAM_COMMON) $(HELLO_C_OBJS) +PROGRAMS = $(shell find src/programs/* -type d) +$(foreach program,$(PROGRAMS),\ + $(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) -WORLD_C_OBJS = $(patsubst src/%.c,build/%.o,$(WORLD_C_SRCS)) -WORLD_OBJS = $(PROGRAM_COMMON) $(WORLD_C_OBJS) - -.PHONY: run debug prepare clean +.PHONY: run debug prepare clean cleanbuild run: 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 -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=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 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 prepare: mkdir -p img.d - mkdir -p build/boot - 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 + mkdir -p $(BUILD_DIRS) mountpoint img.d | grep not || umount img.d clean: @@ -71,10 +64,10 @@ build/boot/boot.bin: src/boot/boot.asm nasm $< -o $@ # 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) -build/boot_stage2/%.o: src/boot_stage2/%.c +build/bootstage2/%.o: src/bootstage2/%.c gcc $(CFLAGS) -o $@ -c $< # Kernel @@ -101,12 +94,6 @@ src/kernel/isr.S: src/kernel/isr.S.base src/kernel/gen_isr_asm.sh # Program -build/program/program.bin: src/program/program.ld $(PROGRAM_OBJS) - echo $(PROGRAM_OBJS) - ld $(LDFLAGS) -T $< $(PROGRAM_OBJS) - -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) \ No newline at end of file +.SECONDEXPANSION: +build/programs/%.bin: src/programs/userspace.ld build/programs/entry.o $$(src/programs/$$(basename $$(notdir $$*))_OBJS) $(PROGRAM_COMMON) + ld -o $@ -T $^ \ No newline at end of file diff --git a/src/kernel/ata.cpp b/src/kernel/ata.cpp new file mode 100644 index 0000000..a132603 --- /dev/null +++ b/src/kernel/ata.cpp @@ -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; +} \ No newline at end of file diff --git a/src/kernel/ata.h b/src/kernel/ata.h new file mode 100644 index 0000000..e2fc608 --- /dev/null +++ b/src/kernel/ata.h @@ -0,0 +1,110 @@ +#ifndef ATA_PIO +#define ATA_PIO + +#include + +#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 \ No newline at end of file diff --git a/src/kernel/atapio.cpp b/src/kernel/atapio.cpp deleted file mode 100644 index b906969..0000000 --- a/src/kernel/atapio.cpp +++ /dev/null @@ -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; ifirstClusterLow); - 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; ifirstClusterLow; - return 0; -} - -uint32_t file_size(char* filename) { - for (int i=0; ifirstClusterLow, 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; -} diff --git a/src/kernel/atapio.h b/src/kernel/atapio.h deleted file mode 100644 index 52f509f..0000000 --- a/src/kernel/atapio.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef ATA_PIO -#define ATA_PIO - -#include - -#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 \ No newline at end of file diff --git a/src/kernel/datatypes/linkedlist.h b/src/kernel/datatypes/linkedlist.h index a2d977f..7ea98de 100644 --- a/src/kernel/datatypes/linkedlist.h +++ b/src/kernel/datatypes/linkedlist.h @@ -27,11 +27,21 @@ namespace xnoe { while (start) { if (start->elem == t) return true; + //current = current->next; } return false; } + void destroy() { + xnoe::linkedlistelem* current = this->start; + while (current) { + xnoe::linkedlistelem* c = current; + current = current->next; + delete c; + } + } + void append(T t) { xnoe::linkedlistelem* llelem = new xnoe::linkedlistelem(t); append(llelem); diff --git a/src/kernel/filesystem/devfs.cpp b/src/kernel/filesystem/devfs.cpp new file mode 100644 index 0000000..e481cba --- /dev/null +++ b/src/kernel/filesystem/devfs.cpp @@ -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) {} \ No newline at end of file diff --git a/src/kernel/filesystem/devfs.h b/src/kernel/filesystem/devfs.h new file mode 100644 index 0000000..761632a --- /dev/null +++ b/src/kernel/filesystem/devfs.h @@ -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 \ No newline at end of file diff --git a/src/kernel/filesystem/fat16.cpp b/src/kernel/filesystem/fat16.cpp new file mode 100644 index 0000000..8cdf839 --- /dev/null +++ b/src/kernel/filesystem/fat16.cpp @@ -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 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(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(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(currentDirectory, 0, false); + } + + return xnoe::tuple(currentDirectory, count, true); +} + +xnoe::tuple 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(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(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(currentDirectory, 0, false); + } + + return xnoe::tuple(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 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 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 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 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 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 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; ientries[written] = FSDirectoryEntry { + name83ToPathEntry(directoryEntries[i].name, nameBuffer + 13*written), + directoryEntries[i].directory ? Directory : File, + directoryEntries[i].size + }; + written++; + } + } + + delete directoryEntries; +} \ No newline at end of file diff --git a/src/kernel/filesystem/fat16.h b/src/kernel/filesystem/fat16.h new file mode 100644 index 0000000..957202d --- /dev/null +++ b/src/kernel/filesystem/fat16.h @@ -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 getDirectoryEntry(Path p); + xnoe::tuple 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 \ No newline at end of file diff --git a/src/kernel/filesystem/fstree.cpp b/src/kernel/filesystem/fstree.cpp new file mode 100644 index 0000000..7473b0c --- /dev/null +++ b/src/kernel/filesystem/fstree.cpp @@ -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(), + 0 + }; +} + +bool pathEntryInFSTreeNode(PathEntry p, FSTreeNode* n) { + xnoe::linkedlistelem* 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* 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* 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(), 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 +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(&FSTree::exists, p, false); +} +FSType RootFSTree::type(Path p){ + return attempt(&FSTree::type, p, Directory); +} +ReadWriter* RootFSTree::open(Path p){ + return attempt(&FSTree::open, p, 0); +} +uint32_t RootFSTree::getDentsSize(Path p){ + return attempt(&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; +} \ No newline at end of file diff --git a/src/kernel/filesystem/fstree.h b/src/kernel/filesystem/fstree.h new file mode 100644 index 0000000..ed5b614 --- /dev/null +++ b/src/kernel/filesystem/fstree.h @@ -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; +using PathElement = xnoe::linkedlistelem; + +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 children; + FSTree* mountpoint; +}; + +class RootFSTree: public FSTree { +private: + FSTree* getLongestMatchingUnder(Path p); + Path* getRemainingPath(Path p); + + FSTreeNode* makeNodeIfNotExist(Path p); + + template + 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 \ No newline at end of file diff --git a/src/kernel/idt.cpp b/src/kernel/idt.cpp index cf38ebb..eff988c 100644 --- a/src/kernel/idt.cpp +++ b/src/kernel/idt.cpp @@ -298,8 +298,9 @@ void syscall(frame_struct* frame) { } case 15: { - ReadWriter* file = new FATFileReadWriter(0, esi); - rval = Global::kernel->mapFH(file); + ReadWriter* file = Global::kernel->rootfs->open(createPathFromString(esi)); + if (file) + rval = Global::kernel->mapFH(file); break; } diff --git a/src/kernel/ioport.cpp b/src/kernel/ioport.cpp new file mode 100644 index 0000000..20553c1 --- /dev/null +++ b/src/kernel/ioport.cpp @@ -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); +} \ No newline at end of file diff --git a/src/kernel/ioport.h b/src/kernel/ioport.h new file mode 100644 index 0000000..fcee08d --- /dev/null +++ b/src/kernel/ioport.h @@ -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 \ No newline at end of file diff --git a/src/kernel/kernel.h b/src/kernel/kernel.h index 12af0af..3d72b4d 100644 --- a/src/kernel/kernel.h +++ b/src/kernel/kernel.h @@ -5,6 +5,7 @@ #include "datatypes/hashtable.h" #include "global.h" #include "terminal.h" +#include "filesystem/fstree.h" class Kernel : public Process { private: @@ -20,6 +21,8 @@ public: xnoe::linkedlist processes; xnoe::linkedlist KBListeners; + RootFSTree* rootfs; + Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint32_t virt_alloc_base, uint32_t stack); void init_kernel(); diff --git a/src/kernel/kmain.cpp b/src/kernel/kmain.cpp index 2121f93..78544ba 100644 --- a/src/kernel/kmain.cpp +++ b/src/kernel/kmain.cpp @@ -4,7 +4,7 @@ #include "idt.h" #include "keyboard.h" #include "strings.h" -#include "atapio.h" +#include "ata.h" #include "gdt.h" #include "paging.h" #include "allocate.h" @@ -14,6 +14,9 @@ #include "datatypes/hashtable.h" #include "terminal.h" #include "kernel.h" +#include "filesystem/fstree.h" +#include "filesystem/fat16.h" +#include "filesystem/devfs.h" int main() { init_gdt(); @@ -29,7 +32,6 @@ int main() { Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xc0000000, 0xc1006000); kernel.init_kernel(); - init_atapio(); VGAModeTerminal* term = new VGAModeTerminal(0xc07a0000); @@ -44,14 +46,30 @@ int main() { 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); Process* p1 = kernel.createProcess(fh, term); init_keyboard(); - - enable_idt(); + if (worldbin) { + worldbin->seek(0); + worldbin->read(512, buffer); + worldbin->seek(0); + enable_idt(); + } while (1) asm ("hlt"); } \ No newline at end of file diff --git a/src/kernel/process.h b/src/kernel/process.h index c056d0f..65075a5 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -8,7 +8,7 @@ #include "datatypes/maybe.h" #include "screenstuff.h" #include "global.h" -#include "atapio.h" +#include "ata.h" #include "stdio/readwriter.h" diff --git a/src/kernel/stdio/readwriter.cpp b/src/kernel/stdio/readwriter.cpp index c2c1043..c553248 100644 --- a/src/kernel/stdio/readwriter.cpp +++ b/src/kernel/stdio/readwriter.cpp @@ -14,6 +14,7 @@ void ReadWriter::giveWritePerm(uint32_t 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) { diff --git a/src/kernel/stdio/readwriter.h b/src/kernel/stdio/readwriter.h index d32738c..4ba43f9 100644 --- a/src/kernel/stdio/readwriter.h +++ b/src/kernel/stdio/readwriter.h @@ -18,6 +18,7 @@ public: virtual uint32_t read(uint32_t count, uint8_t* buffer); virtual uint32_t write(uint32_t count, uint8_t* buffer); virtual uint32_t size(); + virtual uint32_t seek(uint32_t position); uint32_t getOwner(); bool canRead(uint32_t PID); bool canWrite(uint32_t PID); diff --git a/src/programs/entry.asm b/src/programs/entry.asm new file mode 100644 index 0000000..eee6c14 --- /dev/null +++ b/src/programs/entry.asm @@ -0,0 +1,8 @@ +[BITS 32] + +_start: + call main +_loop: + jmp _loop + +extern main \ No newline at end of file diff --git a/src/programs/hello/hello.c b/src/programs/hello/hello.c new file mode 100644 index 0000000..c2db5d2 --- /dev/null +++ b/src/programs/hello/hello.c @@ -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"); + } +} \ No newline at end of file diff --git a/src/programs/userspace.ld b/src/programs/userspace.ld new file mode 100644 index 0000000..843ecd5 --- /dev/null +++ b/src/programs/userspace.ld @@ -0,0 +1,11 @@ +OUTPUT_FORMAT(binary) +OUTPUT_ARCH(i386:i386) + +SECTIONS { + . = 0x20; + + .text : { + build/programs/entry.o(.text) + build/common/common.o(.text) + } +} \ No newline at end of file diff --git a/src/programs/world/world.c b/src/programs/world/world.c new file mode 100644 index 0000000..231fb30 --- /dev/null +++ b/src/programs/world/world.c @@ -0,0 +1,283 @@ +#include "common/common.h" +#include + +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; ibuffer+(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\n", selectedBuf); + writeStrToBuf(" Loads and executes the program \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); + } +} \ No newline at end of file