Shellscript improvement plus FAT driver implementations

- Improved the run bash script to exit when an error occurs in one of the sub tasks
- Wrote basic FAT16 functions that should give enough information to properly implement the rest of the driver
- FAT structure namings are now in accordence with the microsoft spec of March 2005
This commit is contained in:
2023-02-23 23:54:02 +01:00
parent 50bf952a49
commit a77621faf5
20 changed files with 760 additions and 495 deletions

View File

@ -1,41 +0,0 @@
//
// Created by nigel on 21/02/23.
//
#include "FileSystem.h"
void FileSystem::WriteFile(int file, unsigned char* buffer, unsigned int length) {
}
void FileSystem::ReadFile(int file, unsigned char* buffer, unsigned int length) {
}
FILE FileSystem::OpenFile(const char* fname){
if(fname){
unsigned char device = 'a';
char* filename = (char*) fname;
if(fname[1]== ':'){
device = fname[0];
filename += 2; // strip the volume component from the path
}
if(_filesystems[device - 'a']){
FILE file = _filesystems[device-'a']->Open(filename);
file.device = device;
return file;
}
}
FILE file;
file.flags = FS_INVALID;
return file;
}
void FileSystem::CloseFile(PFILE file) {
if(file->device < DEVICE_MAX){
// _filesystems[file->device]->Close(file);
}
}

View File

@ -1,18 +0,0 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
#include "StorageTypes.h"
class FileSystem {
public:
static void WriteFile(PFILE file, unsigned char* beffer, unsigned int length);
static void ReadFile(PFILE file, unsigned char* buffer, unsigned int length);
static FILE OpenFile(const char* fname);
static void CloseFile(PFILE file);
};

View File

@ -1,5 +0,0 @@
//
// Created by nigel on 21/02/23.
//
#include "Inode.h"

View File

@ -1,24 +0,0 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
enum struct NODE_TYPE {
FILESYSTEM,
FILE,
DIRECTORY
};
enum struct PERMISSIONS {
READ,
WRITE,
EXECUTE
};
struct Inode {
NODE_TYPE type;
PERMISSIONS permissions;
Inode* Parent;
Inode* sibling;
};

View File

@ -1,40 +0,0 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
#include <stdint-gcc.h>
enum FS_TYPES {
FS_FILE =0,
FS_DIRECTORY =1,
FS_INVALID=2
};
typedef struct _FILE {
char name [32];
uint32_t flags;
uint32_t filelength;
uint32_t id;
uint32_t eof;
uint32_t position;
uint32_t currentCluster;
uint32_t device;
}FILE, *PFILE;
typedef struct _FILE_SYSTEM{
char name[8];
FILE (*Directory) (const char* Directoryname);
void (*Mount) ();
void (*Read) (PFILE file, unsigned char* buffer, unsigned int length);
void (*Write)(PFILE file, unsigned char* buffer, unsigned int length);
void (*Close) (PFILE);
FILE (*Open) (char* filename);
}FILESYSTEM, *PFS;
typedef struct _PARTITION {
uint32_t Disk;
uint32_t StartAddress;
uint32_t Sectors;
uint8_t Fs_hint;
uint8_t Attributes;
}PARTITION, *PTR_PARTITION;

View File

@ -4,127 +4,183 @@
#include "../ata pio/ATAPIO.h"
#include "../partitiontables/mbr/MasterBootRecord.h"
#include "../filesystems/FAT/FAT.h"
#include "StorageTypes.h"
#include "vfs_types.h"
#include "../../../CoreLib/Memory.h"
#include <CoreLib/Memory.h>
PFS VirtualFileSystem::_filesystems[VirtualFileSystem::DEVICE_MAX];
PTR_PARTITION VirtualFileSystem::_partitions [VirtualFileSystem::PARTITION_MAX];
unsigned int VirtualFileSystem::num_partitions = 0;
vfsmount* VirtualFileSystem::rootfs;
int VirtualFileSystem::mount_number = 0;
int VirtualFileSystem::superblock_number =0;
int VirtualFileSystem::filesystem_number =0;
filesystem* VirtualFileSystem::filesystems[4];
superblock* 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);
mounts[mount_number++] = mnt_point;
superblocks[superblock_number++] = sb;
rootfs = mnt_point;
}
void VirtualFileSystem::initialize()
{
// TODO: setup memory pools etc to speed things up
// a bit
// TODO: Add a devfs, procfs etc...
// Mount the boot disk
// NOTE: we assume for now that it is the only disk in the system
// This information could possibly be had from the bootloader (GRUB)
// We als assume it is the primary device on the Master port.
ATAPIO::Soft_Reset(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
bool isAvailable = ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
if(!isAvailable){
// PANIC!!!
printf("Failed to mount root filesystem!\n");
return;
}
auto masterbootrecord = GetPartitions(false);
for (auto partition : masterbootrecord->TableEntries)
{
if(partition.PartitionType == 0x0) continue; // Consider marked as free
PTR_PARTITION found_partition = (PARTITION*) malloc(sizeof(PARTITION));
found_partition->Disk = ATAPIO_PORT::Primary | ( DEVICE_DRIVE::MASTER << 16);
printf("Disk Identifier: 0x%x\n", found_partition->Disk);
found_partition->Attributes = partition.driveAttribute;
found_partition->StartAddress = partition.LBA_partition_start;
found_partition->Sectors = partition.Number_sectors_inPartition;
found_partition->Fs_hint = partition.PartitionType;
VirtualFileSystem::RegisterPartition(found_partition);
}
printf("Found %d partitions on disk!\n", num_partitions);
for (int i = 0; i < num_partitions; i++)
{
auto* partition = _partitions[i];
// Check the fs_hint for a proper driver
if ( partition->Fs_hint != 0x06){
printf("Assumed Unkown filesystem!\n");
continue;
}
// Check if filesystem OK
printf("Partition Start Address (LBA): 0x%x\n", partition->StartAddress);
bool valid = FAT::Validate(partition);
if(!valid)
{
printf("Not a valid FAT fs!\n");
continue;
}
// setup FileSystem Description before mounting
PFS FS_FAT = (PFS)malloc(sizeof(FILESYSTEM));
FAT::Info(partition, FS_FAT);
// Mount the partition/filesystem
Mount(FS_FAT , i);
}
filesystem* fat_fs = (filesystem*) malloc(sizeof (filesystem));
fat_fs->name = "fat";
fat_fs->mount = FAT::Mount;
//register_filesystem(fat_fs);
// Mount the bootdrive
// NOTE: for now will hardcode this
Mount(fat_fs, "/");
};
void VirtualFileSystem::RegisterPartition(PTR_PARTITION partition) {
_partitions[num_partitions] = partition;
num_partitions++;
int VirtualFileSystem::register_filesystem(struct filesystem* fs) {
// register the filesystem to the kernel.
filesystems[filesystem_number] = fs;
filesystem_number++;
}
FILE VirtualFileSystem::OpenFile(const char* path)
{
struct 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.
// 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
unsigned char device = 'a';
char* filename = (char*)path;
char* cpy = filename;
if(filename[1] == ':'){
device = filename[0];
filename += 2;
// FILE file = ->Open(filename);
if(pathname[0] != '/'){
printf("We won't handle relative paths yet!");
file file;
file.flags = 1;
return &file;
}
if ( _filesystems[device - 'a']){
// Unfortunately this way the FAT Driver doesn't know which device and which partition to read from
// leaving us hopeless of finding the file.
FILE file = _filesystems[device-'a']->Open(filename);
file.device = device;
free(cpy);
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;
}
free(cpy);
FILE file;
file.flags = FS_INVALID;
return file;
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);
}
}
file file;
file.flags = 1;
return &file;
}
void VirtualFileSystem::Mount(PFS filesystemDescriptor, unsigned int DeviceID)
{
if(DeviceID < DEVICE_MAX)
if(filesystemDescriptor)
_filesystems[DeviceID] = filesystemDescriptor;
int VirtualFileSystem::close (struct file* file){
// 1. release the file descriptor
}
int VirtualFileSystem::write(struct file* file, const void* buf, size_t 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){
// 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
}
void VirtualFileSystem::Unmount(unsigned int DeviceID) {
if(DeviceID < DEVICE_MAX)
_filesystems[DeviceID] = nullptr;
/*
void fs_discovery(){
// Mount the boot disk
// NOTE: we assume for now that it is the only disk in the system
// This information could possibly be had from the bootloader (GRUB)
// We als assume it is the primary device on the Master port.
ATAPIO::Soft_Reset(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
bool isAvailable = ATAPIO::Identify(ATAPIO_PORT::Primary, DEVICE_DRIVE::MASTER);
if(!isAvailable){
// PANIC!!!
printf("Failed to mount root filesystem!\n");
return;
}
auto masterbootrecord = GetPartitions(false);
for (auto partition : masterbootrecord->TableEntries)
{
if(partition.PartitionType == 0x0) continue; // Consider marked as free
PTR_PARTITION found_partition = (PARTITION*) malloc(sizeof(PARTITION));
found_partition->Disk = ATAPIO_PORT::Primary | ( DEVICE_DRIVE::MASTER << 16);
printf("Disk Identifier: 0x%x\n", found_partition->Disk);
found_partition->Attributes = partition.driveAttribute;
found_partition->StartAddress = partition.LBA_partition_start;
found_partition->Sectors = partition.Number_sectors_inPartition;
found_partition->Fs_hint = partition.PartitionType;
}
printf("Found %d partitions on disk!\n", num_partitions);
for (int i = 0; i < num_partitions; i++)
{
auto* partition = _partitions[i];
// Check the fs_hint for a proper driver
if ( partition->Fs_hint != 0x06){
printf("Assumed Unkown filesystem!\n");
continue;
}
// Check if filesystem OK
printf("Partition Start Address (LBA): 0x%x\n", partition->StartAddress);
bool valid = FAT::Validate(partition);
if(!valid)
{
printf("Not a valid FAT fs!\n");
continue;
}
// setup FileSystem Description before mounting
PFS FS_FAT = (PFS)malloc(sizeof(FILESYSTEM));
FAT::Info(partition, FS_FAT);
// Mount the partition/filesystem
}
}
*/

View File

@ -1,20 +1,32 @@
#pragma once
#include <stdint-gcc.h>
#include "../../../CoreLib/Path.h"
#include "StorageTypes.h"
#include "vfs_types.h"
#include "vfs_types.h"
class VirtualFileSystem
{
public:
static void initialize();
static void Mount(PFS fs, unsigned int DeviceID);
static void Unmount(unsigned int DeviceID);
static FILE OpenFile(const char* path);
static void RegisterPartition(PTR_PARTITION partition);
static void Mount(filesystem* fs, const char* name);
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);
private:
static const unsigned int DEVICE_MAX = 26;
static const unsigned int PARTITION_MAX = 4 * DEVICE_MAX;
static PFS _filesystems[DEVICE_MAX];
static unsigned int num_partitions;
static PTR_PARTITION _partitions [PARTITION_MAX];
};
static vfsmount* rootfs;
static int mount_number;
static int superblock_number;
static int filesystem_number;
static filesystem* filesystems[];
static superblock* superblocks[];
static vfsmount* mounts[];
};

View File

@ -0,0 +1,116 @@
//
// Created by nigel on 21/02/23.
//
#pragma once
// grasslab.github.io/osdi/en/labs/lab7.html
#include <stddef.h>
#include <stdint.h>
struct inode_operations;
struct vfsmount;
struct superblock;
struct inode;
struct dentry_operations;
struct directoryEntry;
struct filesystem;
struct superblock;
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
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;
// 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;
unsigned long ino; // unique number of this inode
unsigned int links; // number of hard links
void* device;
unsigned long size; // size of inode contents in bytes
unsigned long atime; // Access time
unsigned long mtime; // Modify time
unsigned long ctime; // Creation time
unsigned short bytes; // bytes consumed
file_operations* fop;
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 {
char* name; // name of the file on the disk
directoryEntry* parent; // parent of the file
inode* node; // node belongs to...
dentry_operations* op;
directoryEntry* children[];
};
// Represents a filesystem type
struct filesystem {
const char* name;
superblock* (*mount)(filesystem* self, const char* name, vfsmount* mnt);
};
// Represents a mounted filesystem
struct superblock {
void* device; // device associated with the filesystem
unsigned long blocksize;
unsigned long maxbytes;
filesystem* type;
unsigned long magic; // IDK
directoryEntry* root; // Root dentry
int count; // IDK
void* fs_info; // pointer to raw filesystem info
dentry_operations* d_op;
inode* inodes[];
};
// Represents an opened file
struct file {
inode* root;
size_t f_pos; // The next read/write position of this file descriptor;
file_operations* f_ops;
int flags;
};