From e6901f05263a52cf0ff688c54ace9dceaccf2c60 Mon Sep 17 00:00:00 2001 From: Nigel Date: Sun, 26 Feb 2023 13:44:41 +0100 Subject: [PATCH] We can now open and read files on the harddisk through a messy virtual filesystem The uri has to contain 8.3 filenames for now as I have not yet figured out how to convert from that to regular filenaming for the name comparison. reading files is still limited to 1 sector --- CoreLib/List.h | 12 + CoreLib/Memory.cpp | 2 +- CoreLib/Memory.h | 2 +- README.md | 2 +- kernel/kernel.cpp | 95 ++---- kernel/storage/filesystems/FAT/FAT.cpp | 340 ++++++++++----------- kernel/storage/filesystems/FAT/FAT.h | 44 ++- kernel/storage/filesystems/FAT/msdosDate.h | 2 + kernel/storage/vfs/vfs.cpp | 94 +++--- kernel/storage/vfs/vfs.h | 10 +- kernel/storage/vfs/vfs_types.h | 90 +++--- todo.md | 2 +- 12 files changed, 310 insertions(+), 385 deletions(-) create mode 100644 CoreLib/List.h diff --git a/CoreLib/List.h b/CoreLib/List.h new file mode 100644 index 0000000..8d11e3b --- /dev/null +++ b/CoreLib/List.h @@ -0,0 +1,12 @@ +// +// Created by nigel on 25/02/23. +// +#pragma once + + +class List { +public: + List* next; + void* data; +}; + diff --git a/CoreLib/Memory.cpp b/CoreLib/Memory.cpp index 4559461..491ed38 100644 --- a/CoreLib/Memory.cpp +++ b/CoreLib/Memory.cpp @@ -32,7 +32,7 @@ int memcmp( const void* ptr1, const void* ptr2, size_t num) } -void memcpy (void* dest, const void* src, size_t count ){ +[[maybe_unused]] void memcpy (void* dest, const void* src, size_t count ){ for( int i = 0; i < count; i++){ ((char *)dest)[i] = ((const char*)src)[i]; } diff --git a/CoreLib/Memory.h b/CoreLib/Memory.h index e0a1d67..7482d65 100644 --- a/CoreLib/Memory.h +++ b/CoreLib/Memory.h @@ -7,7 +7,7 @@ void* memset (void* ptr, int value, size_t num); int memcmp( const void* ptr1, const void* ptr2, size_t num); -void memcpy (void* dest, const void* src, size_t count ); +[[maybe_unused]] void memcpy (void* dest, const void* src, size_t count ); size_t strlen(const char* str); diff --git a/README.md b/README.md index 2edcad6..9befc1a 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Enumerating the PCI bus Correctly identified our ATAPI device 🎉 ![Reading Files from FAT-16](screenshots/ReadingFilesFromFAT16.png) \ -Reading a file from a FAT-16 Formatted drive +Reading a FILE from a FAT-16 Formatted drive ________________________ diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index 48081dc..d705045 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -16,6 +16,7 @@ #include "serial.h" #include "storage/vfs/vfs.h" #include "storage/filesystems/FAT/FAT.h" +#include "../CoreLib/Memory.h" extern "C" void LoadGlobalDescriptorTable(); @@ -57,86 +58,26 @@ extern "C" void kernel () printf("Part1: %d, Part2: %d, Part3: %d\n", part1, part2 , part3); ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER); - auto* bpb = FAT::getBPB(false); - auto* mbr = GetPartitions(false); - auto fsType = FAT::determineFATType(bpb); - switch (fsType) { - case FAT_TYPE::FAT12: - printf("FAT12 Disk!\n"); - break; - case FAT_TYPE::FAT16: - printf("FAT16 Disk!\n"); - break; - case FAT_TYPE::FAT32: - printf("FAT32 Disk!\n"); - break; + + VirtualFileSystem::initialize(); + + printf("Lets open hello.txt\n"); + auto fontFile = VirtualFileSystem::open("/HELLO TXT", 0); + if(fontFile->flags == 0){ + uint16_t* contents = (uint16_t*) malloc(sizeof(uint16_t) * 256); + fontFile->read(fontFile, contents, 512); + + for(int i =0 ; i < fontFile->root->size; i++ ){ + kterm_put(contents[i] & 0x00ff); + kterm_put(contents[i] >> 8); + } + kterm_put('\n'); + free((void*)contents); + }else{ + printf("Could not find file\n"); } - // list files in root - int total_sectors = bpb->TotSec32; - int fat_size = bpb->FATSz16; - int root_dir_sectors = FAT::RootDirSize(bpb); - int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors ; - int data_sectors = bpb->TotSec32 - (bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors); - int total_clusters = data_sectors / bpb->SecPerClus; - - - int first_root_dir_sector = first_data_sector - root_dir_sectors; - //int first_sector_of_cluster = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; - uint16_t data[256]; - ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, first_root_dir_sector, data); - - auto* RootDirectory = (DIR*)data; - for(int i = 0; i < sizeof(data) / sizeof (DIR); i++) - { - DIR* entry = (DIR*)((uint32_t)RootDirectory + (i * sizeof(DIR))); - - - if(entry->Name[0] == FAT::FREE_DIR || entry->Name[0] == FAT::FREE_DIR_2 || entry->Name[0] == 0xE5){ - continue; - } - - - if(entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN){ - continue; - } - - if(entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM) - continue; - - - if(entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID){ - continue; - } - if (!(entry->ATTR & FAT::ATTRIBUTES::ATTR_LONG_NAME)){ - for(char n : entry->Name){ - if(n == 0x20) - continue; - kterm_put(n); - } - }else{ - printf("Long file name detected!"); - } - - printf(" [Size: %d bytes, Attributes: %d]\n", entry->ATTR, entry->FileSize); - if(entry->ATTR & FAT::ATTRIBUTES::ATTR_DIRECTORY ){ - FAT::OpenSubdir(entry, bpb); - } else { - FAT::readFile(entry, bpb); - } - - } - - - - - - - // VirtualFileSystem::initialize(); - - // VirtualFileSystem::open("/hello.txt", 0); - #ifdef USERMODE_RELEASE // Lets jump into user mode diff --git a/kernel/storage/filesystems/FAT/FAT.cpp b/kernel/storage/filesystems/FAT/FAT.cpp index 19619a0..80465b9 100644 --- a/kernel/storage/filesystems/FAT/FAT.cpp +++ b/kernel/storage/filesystems/FAT/FAT.cpp @@ -4,10 +4,14 @@ #include "FAT.h" #include "../../ata pio/ATAPIO.h" #include "../../../memory/KernelHeap.h" -#include "../../../../CoreLib/Memory.h" #include "../../partitiontables/mbr/MasterBootRecord.h" +#include "../../../../CoreLib/ctype.h" +#include "../../../../CoreLib/Memory.h" #include -superblock* FAT::Mount(filesystem *fs, const char* name ,vfsmount *mnt) +#include + +// exposed driver API +FS_SUPER* FAT::Mount(filesystem *fs, const char* name , vfsmount *mnt) { if( strncmp (fs->name, "fat", 3 ) != 0 ) @@ -15,58 +19,138 @@ superblock* FAT::Mount(filesystem *fs, const char* name ,vfsmount *mnt) printf("Can't mount filesystem with none fat type!\n"); return nullptr; } + auto* bpb = GetBiosParameterBlock(); + auto fat_type = DetermineFATType(bpb); - superblock* sb = (superblock*) malloc(sizeof(superblock)); - directoryEntry* root = (directoryEntry*) malloc(sizeof (directoryEntry)); + if(fat_type != FAT_TYPE::FAT16) + return nullptr; + + FS_SUPER* sb = (FS_SUPER*) malloc(sizeof(FS_SUPER)); + DirectoryNode* root = (DirectoryNode*) malloc(sizeof (DirectoryNode)); + inode* node = (inode*) malloc(sizeof(inode)); + + root->children = nullptr; + node->internal = (void*)FAT::GetSectorOfRootDirectory(bpb); //sector number; + node->lookup = FAT::Lookup; root->name = (char*) name; - root->node = nullptr; + root->node = node; root->parent = nullptr; - - dentry_operations* op = (dentry_operations*) malloc(sizeof(dentry_operations)); - op->compare = FAT::compare; - - - root->op = op; - - + root->compare = FAT::Compare; mnt->mnt_count =1; mnt->mnt_devname = "QEMU HDD"; mnt->mnt_flags = 0; mnt->mnt_parent = nullptr; - mnt->root = root; mnt->sb = sb; - sb->type = fs; sb->root = root; - //sb->fs_info = getBPB(); + sb->fs_info = bpb; return sb; } -int FAT::Read(file* file, void* buffer , int length) -{ - return 0; -} -int FAT::Write(file* file, const void* buffer, int length) -{ - return 0; -} -int FAT::compare (directoryEntry*, char* filename, char* filename2) -{ - // use the size of the smallest string - int a = strlen(filename); - int b = strlen(filename2); +FILE FAT::Open(char* filename){ - if( a == b ){ - return strncmp(filename, filename2, a); + return (FILE){nullptr, 0, nullptr, nullptr, 1} ; +} +int FAT::Read(FILE* file, void* buffer , unsigned int length) +{ + + if(file == nullptr) + { + printf("NO FILE!!\n"); + return -1; } - return a-b; + inode* node = file->root; + + if(node== nullptr) + { + printf("No INODE!\n"); + return -1; + } + + int cluster = (int)node->internal; + auto* bpb = FAT::GetBiosParameterBlock(); + + unsigned int FAT_entry = FAT::GetFATEntry(bpb, cluster); + unsigned int root_dir_sector = FAT::RootDirSize(bpb); + unsigned int fat_size = bpb->FATSz16; + unsigned int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sector; + unsigned int file_data_sector = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; + + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, file_data_sector, (uint16_t*)buffer); + + return 0; } -int FAT::create(inode* dir_node, inode** target, const char* component_name){} -int FAT::lookup (inode*, inode**, const char*){} + +int FAT::Write(FILE* file, const void* buffer, unsigned int length) +{ + return 0; +} + +int FAT::Compare (DirectoryNode*, char* filename, char* filename2) +{ + //TODO Implement proper compare method for 8.3 filenames + // printf("COMPARE: %s with %s\n", filename, filename2); + return memcmp(filename, filename2, 11); +} + +int FAT::Create(inode* dir_node, inode** target, const char* component_name){} + +DirectoryNode* FAT::Lookup (inode* currentDir , DirectoryNode* dir) +{ + + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, (int)currentDir->internal , data); + + List* lastAdded = nullptr; + auto* directory = (DIR*)data; + for(int i = 0; i < sizeof(data) / sizeof (DIR); i++) + { + DIR* entry = (DIR*)((uint32_t)directory + (i * sizeof(DIR))); + if( + entry->Name[0] == FAT::FREE_DIR || + entry->Name[0] == FAT::FREE_DIR_2 || + entry->Name[0] == 0xE5 || + entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID || + entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM || + entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN + ){ + continue; + } + + auto* dirNode = (DirectoryNode*) malloc(sizeof (DirectoryNode)); + + char* name = (char*)malloc(sizeof(char[11])); + memcpy(name, entry->Name, 11 ); + dirNode->name = name; + dirNode->compare = dir->compare; + dirNode->parent = dir; + + dirNode->node= (inode*) malloc(sizeof (inode)); + dirNode->node->internal = (void*)entry->FstClusLo; + + dirNode->node->read = currentDir->read; + dirNode->node->lookup = currentDir->lookup; + dirNode->node->sb = currentDir->sb; + dirNode->node->size = entry->FileSize; + + List* dirlist = (List*) malloc(sizeof (List)); + dirlist->data = dirNode; + dirlist->next = nullptr; + + lastAdded = dirlist; + auto* temp = dir->children; + dir->children = lastAdded; + lastAdded->next = temp; -FAT_TYPE FAT::determineFATType(BiosParameterBlock* bpb){ + } + + return (DirectoryNode*)dir; +} + +// internal functions +FAT_TYPE FAT::DetermineFATType(BiosParameterBlock* bpb){ int RootDirSector = ((bpb->RootEntCnt * 32) + (bpb->BytsPerSec -1)) / bpb->BytsPerSec; int FATSz = 0; if(bpb->FATSz16 != 0){ @@ -93,7 +177,7 @@ FAT_TYPE FAT::determineFATType(BiosParameterBlock* bpb){ return FAT_TYPE::FAT32; } }; -BiosParameterBlock* FAT::getBPB( bool DEBUG ){ +BiosParameterBlock* FAT::GetBiosParameterBlock(bool DEBUG ){ BiosParameterBlock* bpb = (BiosParameterBlock*) malloc(sizeof(BiosParameterBlock)); uint16_t StartAddress = 0x00 ; ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, StartAddress, (uint16_t*) bpb); @@ -114,24 +198,20 @@ BiosParameterBlock* FAT::getBPB( bool DEBUG ){ } uint16_t FAT::GetFATEntry (BiosParameterBlock* bpb, unsigned int cluster){ int FATSz = bpb->FATSz16; - int FATOffset = 0; - FAT_TYPE type = FAT::determineFATType(bpb); + FAT_TYPE type = FAT::DetermineFATType(bpb); if( type == FAT_TYPE::FAT16){ FATOffset = cluster *2; } else if( type == FAT_TYPE::FAT32){ FATOffset = cluster * 4; } - int thisFATSecNum = bpb->RsvdSecCnt + (FATOffset / bpb->BytsPerSec); // Sector number containing the entry for the cluster // For any other FAT other than the default // SectorNumber = (FATNumber * FATSz) + ThisFATSecNum uint16_t buff[bpb->BytsPerSec]; - ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, thisFATSecNum, buff ); - int thisFATEntOffset = FATOffset % bpb->BytsPerSec; // offset for the entry in the sector containing the entry for the cluster uint16_t ClusterEntryValue = 0; // Get the FATEntry @@ -145,7 +225,6 @@ uint16_t FAT::GetFATEntry (BiosParameterBlock* bpb, unsigned int cluster){ } } - uint16_t FAT::DetermineFreeSpace() { // Loop through all FAT entries in all FAT's @@ -166,35 +245,15 @@ the FAT entry for the last cluster) must be set to 0x0 during volume initializat } - int FAT::GetSectorOfRootDirectory (BiosParameterBlock* bpb) { return (bpb->RsvdSecCnt + (bpb->NumFATs * bpb->FATSz16)); } - unsigned int FAT::RootDirSize(BiosParameterBlock* bpb) { return ((bpb->RootEntCnt * 32) + (bpb->BytsPerSec -1)) /bpb->BytsPerSec; } - -uint16_t* ReadFAT (BiosParameterBlock& bpb , bool DEBUG = false ) { - uint32_t FATAddress = /*StartAddress*/ 0x00 + bpb.RsvdSecCnt ; - uint16_t* FAT = (uint16_t*)malloc(sizeof (uint16_t) * 256); - - ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, FATAddress, FAT ); - - // Show data in terminal - if(DEBUG){ - for( unsigned int i =0 ; i < 256 ; i++) { - printf("0x%x ", (unsigned short)FAT[i]); - } - kterm_put('\n'); - } - - return FAT; -} - void FAT::OpenSubdir(DIR* directory, BiosParameterBlock* bpb ){ unsigned int cluster = directory->FstClusLo; @@ -252,9 +311,9 @@ void FAT::OpenSubdir(DIR* directory, BiosParameterBlock* bpb ){ } } - -void FAT::readFile(DIR* fileEntry , BiosParameterBlock* bpb){ +void FAT::ReadFileContents(DIR* fileEntry , BiosParameterBlock* bpb){ unsigned int cluster = fileEntry->FstClusLo; + printf("cluster NR: %x\n", cluster); unsigned int FATEntry = FAT::GetFATEntry(bpb, cluster); unsigned int root_dir_sectors = FAT::RootDirSize(bpb); unsigned int fat_size = bpb->FATSz16; @@ -269,140 +328,63 @@ void FAT::readFile(DIR* fileEntry , BiosParameterBlock* bpb){ kterm_put(n & 0x00ff); kterm_put(n >> 8); } + kterm_put('\n'); } +void FAT::ListRootDirectoryContents(BiosParameterBlock* bpb){ + int total_sectors = bpb->TotSec32; + int fat_size = bpb->FATSz16; + int root_dir_sectors = FAT::RootDirSize(bpb); + int first_data_sector = bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors ; + int data_sectors = bpb->TotSec32 - (bpb->RsvdSecCnt + (bpb->NumFATs * fat_size) + root_dir_sectors); + int total_clusters = data_sectors / bpb->SecPerClus; -/* -file fsysFatDirectory (const char* DirectoryName){ - file file; - unsigned char* buf; - PDIRECTORY directory; - char DosFileName[11]; - //ToDosFileName(DirectoryName, DosFileName, 11); - DosFileName[11] =0; + int first_root_dir_sector = first_data_sector - root_dir_sectors; + //int first_sector_of_cluster = ((cluster - 2) * bpb->SecPerClus) + first_data_sector; + uint16_t data[256]; + ATAPIO::Read(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER, first_root_dir_sector, data); - for (int sector=0; sector <14 ; sector++){ - ATAPIO::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, mountInfo.rootOffset + sector, (uint16_t*)buf); - directory = (PDIRECTORY) buf; + auto* RootDirectory = (DIR*)data; + for(int i = 0; i < sizeof(data) / sizeof (DIR); i++) + { + DIR* entry = (DIR*)((uint32_t)RootDirectory + (i * sizeof(DIR))); - for (int i =0; i < 16; i++){ - char name[11]; - memcpy(name, directory->Filename, 11); - name[11]=0; - if(strncmp(DosFileName, name, 11) == 0){ - strcpy(file.name, DirectoryName); - file.id = 0; - file.currentCluster = directory->FirstCluster; - file.eof = 0; - file.filelength = directory->FileSize; - - if(directory->Attrib == 0x10){ - file.flags = 2; - } else { - file.flags = 1; - } - return file; - } - directory++; + if(entry->Name[0] == FAT::FREE_DIR || entry->Name[0] == FAT::FREE_DIR_2 || entry->Name[0] == 0xE5){ + continue; } - } - - // Can't find file - file.flags = -1; - return file; - -} -void fsysFATRead(PFILE file, unsigned char* buffer, unsigned int length){ - if(file){ - unsigned int physSector = 32 + (file->currentCluster - 1); - const unsigned int SECTOR_SIZE = 512; - // read sector - ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, physSector, (uint16_t*) buffer ); + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_HIDDEN){ + continue; + } - unsigned int FAT_Offset = file->currentCluster + (file->currentCluster /2); - unsigned int FAT_Sector = 1 + (FAT_Offset / SECTOR_SIZE); - unsigned int entryOffset =FAT_Offset % SECTOR_SIZE; + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_SYSTEM) + continue; - uint8_t FAT[SECTOR_SIZE*2]; - ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, FAT_Sector,(uint16_t*) FAT); // Read 1st FAT sector - ATA_DEVICE::Read(BUS_PORT::Primary, DEVICE_DRIVE::MASTER, FAT_Sector +1, (uint16_t*)FAT+SECTOR_SIZE); - - // read entry for next cluster - uint16_t nextCluster = *(uint16_t*) &FAT[entryOffset]; - - // test if entry is odd or even - if(file->currentCluster & 0x0001){ - nextCluster>>= 4; // grab the high 12 bits + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_VOLUME_ID){ + continue; + } + if (!(entry->ATTR & FAT::ATTRIBUTES::ATTR_LONG_NAME)){ + for(char n : entry->Name){ + if(n == 0x20) + continue; + kterm_put(n); + } }else{ - nextCluster &= 0x0FFF; // grab the low 12 bits + printf("Long file name detected!"); } - // test for end of file - if(nextCluster >= 0xff8){ - file->eof -1; - return; + printf(" [Size: %d bytes, Attributes: %d]\n", entry->ATTR, entry->FileSize); + if(entry->ATTR & FAT::ATTRIBUTES::ATTR_DIRECTORY ){ + FAT::OpenSubdir(entry, bpb); + } else { + FAT::ReadFileContents(entry, bpb); } - // test for file corruption - if(nextCluster == 0){ - file->eof =1; - return; - } - - // set next cluster - file->currentCluster = nextCluster; - - } } -FILE fsysFatOpenSubDir(FILE kFile, const char* filename){ - FILE file; - char DosFileName[11]; - ToDosFileName(filename, DosFileName, 11); - DosFileName[11] = 0; - - while(!kFile.eof){ - //read directory - unsigned char buf[512]; - fsysFATRead(&file, buf, 512); - - PDIRECTORY pkDir = (PDIRECTORY) buf; - - for (unsigned int i = 0; i < 16; i++){ - // get current filename - char name[11]; - memcpy(name, pkDir->Filename, 11); - name[11] = 0; - - if(strncmp(name, DosFileName, 11) == 0){ - strcpy(file.name, filename); - file.id = 0; - file.currentCluster = pkDir->FirstCluster; - file.filelength = pkDir->FileSize; - file.eof = 0; - - // set file type; - if(pkDir->Attrib == 0x10){ - file.flags = 2; - } else{ - file.flags = 1; - } - - return file; - } - // go to next entry - pkDir++; - } - } - // unable to find file - file.flags = -1; - return file; -} -*/ diff --git a/kernel/storage/filesystems/FAT/FAT.h b/kernel/storage/filesystems/FAT/FAT.h index 4d5ed59..3a29bc1 100644 --- a/kernel/storage/filesystems/FAT/FAT.h +++ b/kernel/storage/filesystems/FAT/FAT.h @@ -63,32 +63,18 @@ enum struct FAT_TYPE{ class FAT { public: - // Wanted API for vfs - static file Open(char* filename); - static int close(file* file); - static int Read(file* file, void* buffer , int length); - static int Write(file* file, const void* buffer, int length); - static int create(inode* dir_node, inode** target, const char* component_name); - static int lookup(inode* , inode**, const char*); - static int compare(directoryEntry* , char* , char*); - static superblock* Mount(filesystem* fs, const char* name ,vfsmount* mount); + static FILE Open(char* filename); + static int close(FILE* file); + static int Read(FILE* file, void* buffer , unsigned int length); + static int Write(FILE* file, const void* buffer, unsigned int length); + static int Create(inode* dir_node, inode** target, const char* component_name); + static DirectoryNode* Lookup(inode* , DirectoryNode*); + static int Compare(DirectoryNode* , char *filename, char *filename2); + static FS_SUPER* Mount(filesystem* fs, const char* name , vfsmount* mount); - // TEMP - static void listFilesInRoot(MBR* mbr, BiosParameterBlock* bpb ); - static BiosParameterBlock* getBPB( bool DEBUG =false ); - static FAT_TYPE determineFATType(BiosParameterBlock* bpb); - static uint16_t GetFATEntry(BiosParameterBlock*, unsigned int); - static uint16_t DetermineFreeSpace(); - static int GetSectorOfRootDirectory(BiosParameterBlock*); - static unsigned int RootDirSize(BiosParameterBlock*); - static void OpenSubdir (DIR*, BiosParameterBlock*); - static void readFile(DIR*, BiosParameterBlock*); - - - - static const int FREE = 0x0000; - static const int ALLOCATED = 0x0002; + static const int FREE = 0x0000; + static const int ALLOCATED = 0x0002; static const int BAD = 0xFFF7; static const int EOF = 0xFFFF; @@ -98,6 +84,9 @@ public: static const char DOS_TRAILING_SPACE = 0x20; static const char FREE_DIR = 0xE5; // If KANJI charset 0x05 static const char FREE_DIR_2 = 0x00; // All directories after this are free including this one + static void ListRootDirectoryContents(BiosParameterBlock* bpb ); + static BiosParameterBlock* GetBiosParameterBlock(bool DEBUG =false ); + enum ATTRIBUTES { ATTR_READ_ONLY = 0x01, @@ -111,6 +100,13 @@ public: private: + static FAT_TYPE DetermineFATType(BiosParameterBlock* bpb); + static uint16_t GetFATEntry(BiosParameterBlock*, unsigned int); + static uint16_t DetermineFreeSpace(); + static int GetSectorOfRootDirectory(BiosParameterBlock*); + static unsigned int RootDirSize(BiosParameterBlock*); + static void OpenSubdir (DIR*, BiosParameterBlock*); + static void ReadFileContents(DIR *fileEntry, BiosParameterBlock *bpb); enum ENTRY_SIZE { FAT12 = 12, diff --git a/kernel/storage/filesystems/FAT/msdosDate.h b/kernel/storage/filesystems/FAT/msdosDate.h index c1fff64..8eb2cc4 100644 --- a/kernel/storage/filesystems/FAT/msdosDate.h +++ b/kernel/storage/filesystems/FAT/msdosDate.h @@ -5,6 +5,8 @@ #pragma once #include "../../../terminal/kterm.h" +#include "../../../memory/KernelHeap.h" +#include "../../../../CoreLib/Memory.h" // Date Format // [0..4] Day diff --git a/kernel/storage/vfs/vfs.cpp b/kernel/storage/vfs/vfs.cpp index 7d67144..d432632 100644 --- a/kernel/storage/vfs/vfs.cpp +++ b/kernel/storage/vfs/vfs.cpp @@ -14,17 +14,21 @@ int VirtualFileSystem::superblock_number =0; int VirtualFileSystem::filesystem_number =0; filesystem* VirtualFileSystem::filesystems[4]; -superblock* VirtualFileSystem::superblocks[8]; +FS_SUPER* VirtualFileSystem::superblocks[8]; vfsmount* VirtualFileSystem::mounts[12]; void VirtualFileSystem::Mount(filesystem* fs, const char* name) { - vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount)); - superblock* sb = fs->mount(fs, name, mnt_point); + vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount)); + FS_SUPER* sb = fs->mount(fs, name, mnt_point); + if( sb == nullptr){ + printf("mount failed!\n"); + return; + } mounts[mount_number++] = mnt_point; superblocks[superblock_number++] = sb; - + mnt_point->mnt_count = 1; rootfs = mnt_point; } @@ -54,64 +58,58 @@ int VirtualFileSystem::register_filesystem(struct filesystem* fs) { } -struct file* VirtualFileSystem::open(const char* pathname, int flags){ +FILE* VirtualFileSystem::open(const char* pathname, int flags){ // 1. Lookup pathname from the root node - // 2. Create a new file descriptor for this v_node if found. + // 2. Create a new file descriptor for this inode if found. // 3. Create a new file if O_CREATE is specified in the flags. - - // See reference material (1) https://man7.org/linux/man-pages/man7/path_resolution.7.html - - // FILE file = ->Open(filename); - if(pathname[0] != '/'){ - printf("We won't handle relative paths yet!"); - file file; - file.flags = 1; - return &file; - } - - - - auto* dentry = rootfs->root; - - int result = dentry->op->compare(dentry, "/", dentry->name); - if(result != 0 ){ - printf("rootfs not called / \n"); - file file; - file.flags = 1; - return &file; - } - + FILE* file = (FILE*) malloc(sizeof (FILE)) ; + auto* rootentry = rootfs->root; char* tokstate = nullptr; auto nextdir = strtok ((char*)pathname, "/", &tokstate ); - while (nextdir) - { - printf("Look for dentry: %s\n", nextdir); - // look to its children - if (dentry->children ) { - printf("No children | children unknown!\n"); - break; - } - if (dentry->op->compare(dentry, nextdir, dentry->name)) - { - // file found - nextdir = strtok(nullptr, "/", &tokstate); - } + // look up children if not filled + if(rootentry->children == nullptr) + { + rootentry = rootentry->node->lookup(rootentry->node, rootentry); } - file file; - file.flags = 1; - return &file; + if(rootentry->children == nullptr) + { + file->flags =1; + return file; + } + + // let's just loop through the folder first + auto* child = rootentry->children; + while(child->next != nullptr){ + + auto* directory = (DirectoryNode*)child->data; + if( directory->compare(directory, directory->name, nextdir) == 0){ + nextdir = strtok(nullptr, "/", &tokstate); + if(nextdir == NULL){ + file->root = directory->node; + file->flags =0; + file->read = FAT::Read; + return file; + } + } + child = child->next; + } + + + + file->flags = 1; + return file; } -int VirtualFileSystem::close (struct file* file){ +int VirtualFileSystem::close (struct FILE* file){ // 1. release the file descriptor } -int VirtualFileSystem::write(struct file* file, const void* buf, size_t len){ +int VirtualFileSystem::write(struct FILE* file, const void* buf, unsigned int len){ // 1. Write len bytes from buf to the opened file. // 2. return written size or error code if an error occurs } -int VirtualFileSystem::read (struct file* file, void* buf, size_t len){ +int VirtualFileSystem::read (struct FILE* file, void* buf, unsigned int len){ // 1. read min(len, readable file data size) bytes ro buf from the opened file. // 2. return read size or error code if an error occurs } diff --git a/kernel/storage/vfs/vfs.h b/kernel/storage/vfs/vfs.h index 804f09a..821853d 100644 --- a/kernel/storage/vfs/vfs.h +++ b/kernel/storage/vfs/vfs.h @@ -11,10 +11,10 @@ static int register_filesystem(struct filesystem* fs); - static struct file* open(const char* pathname, int flags); - static int close(struct file* file); - static int write(struct file* file, const void* buf, size_t len); - static int read(struct file* file, void* buf, size_t len); + static FILE* open(const char* pathname, int flags); + static int close(struct FILE* file); + static int write(struct FILE* file, const void* buf, unsigned int len); + static int read(struct FILE* file, void* buf, unsigned int len); private: static vfsmount* rootfs; @@ -25,7 +25,7 @@ static int filesystem_number; static filesystem* filesystems[]; - static superblock* superblocks[]; + static FS_SUPER* superblocks[]; static vfsmount* mounts[]; }; diff --git a/kernel/storage/vfs/vfs_types.h b/kernel/storage/vfs/vfs_types.h index c989dbe..73744ca 100644 --- a/kernel/storage/vfs/vfs_types.h +++ b/kernel/storage/vfs/vfs_types.h @@ -5,55 +5,52 @@ // grasslab.github.io/osdi/en/labs/lab7.html #include #include +#include "../../../CoreLib/List.h" struct inode_operations; struct vfsmount; -struct superblock; +struct FS_SUPER; struct inode; struct dentry_operations; -struct directoryEntry; +struct DirectoryNode; struct filesystem; -struct superblock; -struct file; +struct FS_SUPER; +struct FILE; + -struct file_operations{ - int(*write) (file* file, const void* buf, size_t len); - int(*read) (file* file, void* buf, size_t len); -}; -struct inode_operations { - int (*create)(inode*, directoryEntry*, const char* ); - directoryEntry* (*lookup)(inode* , directoryEntry*); - int (*link)(directoryEntry*, inode* , directoryEntry*); - int (*unlink)(inode*, directoryEntry*); - int (*symlink)(inode*, directoryEntry*); - int (*mkdir)(inode*, directoryEntry*, const char*); - int (*rmdir)(inode*, directoryEntry*); - int (*rename)(inode*, directoryEntry*, inode*, directoryEntry*); - void (*truncate)(inode*); - int (*permission)(inode*, int); - int (*setattr)(directoryEntry, unsigned long*); - int (*getattr)(vfsmount* mnt, directoryEntry*, unsigned long*); -}; // Describes a mount struct vfsmount { vfsmount* mnt_parent; // fs we are mounted on - directoryEntry* mountpoint; // dentry of mount point - directoryEntry* root; // root of the mounted tree - superblock* sb; // pointer to the superblock + DirectoryNode* mountpoint; // dentry of mount point + DirectoryNode* root; // root of the mounted tree + FS_SUPER* sb; // pointer to the superblock unsigned int mnt_count; // keep track of users of this structure int mnt_flags; char* mnt_devname; // name of device eg /dev/dsk/hda1 }; -struct superblock; +struct FS_SUPER; // Represents a filesystem object (i.e. a file or directory or device) struct inode { unsigned long mode; // access permissions unsigned long uid; // user id owner unsigned long gid; // group id owner unsigned int flags; - inode_operations* i_op; // operations possible on inode - superblock* sb; + // operations possible on inode + int (*create)(inode*, DirectoryNode*, const char* ); + DirectoryNode* (*lookup)(inode* , DirectoryNode*); + int (*link)(DirectoryNode*, inode* , DirectoryNode*); + int (*unlink)(inode*, DirectoryNode*); + int (*symlink)(inode*, DirectoryNode*); + int (*mkdir)(inode*, DirectoryNode*, const char*); + int (*rmdir)(inode*, DirectoryNode*); + int (*rename)(inode*, DirectoryNode*, inode*, DirectoryNode*); + void (*truncate)(inode*); + int (*permission)(inode*, int); + int (*setattr)(DirectoryNode, unsigned long*); + int (*getattr)(vfsmount* mnt, DirectoryNode*, unsigned long*); + + FS_SUPER* sb; unsigned long ino; // unique number of this inode unsigned int links; // number of hard links void* device; @@ -62,43 +59,39 @@ struct inode { unsigned long mtime; // Modify time unsigned long ctime; // Creation time unsigned short bytes; // bytes consumed - file_operations* fop; + // File operations possible on Inode; + int(*write) (FILE* file, const void* buf, unsigned int len); + int(*read) (FILE* file, void* buf, unsigned int len); void* internal; // point to underlying representation of this virtual node (e.g. FAT entry or Directory Entry) }; -// Represents the possible operations on a directory entry -struct dentry_operations -{ - int (*compare)(directoryEntry*, char*, char* ); - int (*o_delete)(directoryEntry*); - void (*release)(directoryEntry*); - void (*iput)(directoryEntry*, inode* ); -}; // Represents the name of files in the filesystem // it identifies the file that an inode represents -struct directoryEntry { +struct DirectoryNode { char* name; // name of the file on the disk - directoryEntry* parent; // parent of the file + DirectoryNode* parent; // parent of the file inode* node; // node belongs to... - dentry_operations* op; - directoryEntry* children[]; - + int (*compare)(DirectoryNode*, char*, char* ); + int (*o_delete)(DirectoryNode*); + void (*release)(DirectoryNode*); + void (*iput)(DirectoryNode*, inode*); + List* children; }; // Represents a filesystem type struct filesystem { const char* name; - superblock* (*mount)(filesystem* self, const char* name, vfsmount* mnt); + FS_SUPER* (*mount)(filesystem* self, const char* name, vfsmount* mnt); }; // Represents a mounted filesystem -struct superblock { +struct FS_SUPER { void* device; // device associated with the filesystem unsigned long blocksize; unsigned long maxbytes; filesystem* type; unsigned long magic; // IDK - directoryEntry* root; // Root dentry + DirectoryNode* root; // Root dentry int count; // IDK void* fs_info; // pointer to raw filesystem info dentry_operations* d_op; @@ -106,10 +99,11 @@ struct superblock { }; // Represents an opened file -struct file { +struct FILE { inode* root; - size_t f_pos; // The next read/write position of this file descriptor; - file_operations* f_ops; + unsigned int f_pos; // The next read/write position of this file descriptor; + int(*write) (FILE* file, const void* buf, unsigned int len); + int(*read) (FILE* file, void* buf, unsigned int len); int flags; }; diff --git a/todo.md b/todo.md index cb71d04..b5556ea 100644 --- a/todo.md +++ b/todo.md @@ -4,7 +4,7 @@ This list keeps me focused and organised so I don't forget what -needs to be done. It is a expansion on the features markdown file which describes the features. Here I put things I need to remember +needs to be done. It is a expansion on the features markdown FILE which describes the features. Here I put things I need to remember to do on a more in depth level. ## --