summaryrefslogtreecommitdiff
path: root/Source/Kernel
diff options
context:
space:
mode:
authorAlexis211 <alexis211@gmail.com>2009-11-15 17:42:07 +0100
committerAlexis211 <alexis211@gmail.com>2009-11-15 17:42:07 +0100
commitca1b573ef87498595a30b757d6d9c66d12d14ae6 (patch)
tree6fa043fd75c83910737c3701c0147bde782fefdf /Source/Kernel
parent21bfca4ad4b84768f05eb4fa2bc0ad7a76b6c536 (diff)
downloadMelon-ca1b573ef87498595a30b757d6d9c66d12d14ae6.tar.gz
Melon-ca1b573ef87498595a30b757d6d9c66d12d14ae6.zip
Reading from the FAT12-formatted floppy works \o
Diffstat (limited to 'Source/Kernel')
-rw-r--r--Source/Kernel/Core/Sys.ns.h3
-rw-r--r--Source/Kernel/Core/kmain.wtf.cpp7
-rw-r--r--Source/Kernel/FileSystems/FAT/FATDirectoryNode.class.h16
-rw-r--r--Source/Kernel/FileSystems/FAT/FATFS.class.cpp201
-rw-r--r--Source/Kernel/FileSystems/FAT/FATFS.class.h130
-rw-r--r--Source/Kernel/FileSystems/FAT/FATFileNode.class.h16
-rw-r--r--Source/Kernel/Makefile1
-rw-r--r--Source/Kernel/Shell/KernelShell.class.cpp3
8 files changed, 374 insertions, 3 deletions
diff --git a/Source/Kernel/Core/Sys.ns.h b/Source/Kernel/Core/Sys.ns.h
index 4d15676..9b34dbf 100644
--- a/Source/Kernel/Core/Sys.ns.h
+++ b/Source/Kernel/Core/Sys.ns.h
@@ -18,9 +18,12 @@
//This file contains system-relative functions
class String;
+class SimpleVT;
class VirtualTerminal;
struct registers_t;
+extern SimpleVT* kvt;
+
namespace Sys {
void outb(u16int port, u8int value);
u8int inb(u16int port);
diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp
index d0751d1..bb77eeb 100644
--- a/Source/Kernel/Core/kmain.wtf.cpp
+++ b/Source/Kernel/Core/kmain.wtf.cpp
@@ -25,6 +25,7 @@
#include <Rand.ns.h>
#include <VFS/Part.ns.h>
#include <FileSystems/RamFS/RamFS.class.h>
+#include <FileSystems/FAT/FATFS.class.h>
#include <VFS/FileNode.class.h>
#include <VFS/VFS.ns.h>
#include <VFS/DirectoryNode.class.h>
@@ -37,6 +38,8 @@ extern u32int end; //Placement address
extern "C" void kmain(multiboot_info_t* mbd, u32int magic);
+SimpleVT* kvt;
+
u32int logoAnimation(void* p) {
SimpleVT& vt = *((SimpleVT*)p);
vt.setColor(8);
@@ -140,7 +143,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
Disp::setText(vgaout);
//Create a VT for logging what kernel does
- SimpleVT *kvt = new ScrollableVT(25, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR);
+ kvt = new ScrollableVT(25, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR);
kvt->map(0, 0);
*kvt << "Melon is loading...";
@@ -187,6 +190,8 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
cwd = VFS::getRootNode();
Task::currProcess()->setCwd(cwd);
+ FATFS::mount(Part::partitions[0], (DirectoryNode*)VFS::createDirectory("/Mount"));
+
if (keymap != "builtin") {
if (!Kbd::loadKeymap(keymap)) *kvt << "\nWARNING : Could not load keymap " << keymap << ", using built-in keymap instead.";
}
diff --git a/Source/Kernel/FileSystems/FAT/FATDirectoryNode.class.h b/Source/Kernel/FileSystems/FAT/FATDirectoryNode.class.h
new file mode 100644
index 0000000..c2f55e1
--- /dev/null
+++ b/Source/Kernel/FileSystems/FAT/FATDirectoryNode.class.h
@@ -0,0 +1,16 @@
+#ifndef DEF_FATDIRECTORYNODE_CLASS_H
+#define DEF_FATDIRECTORYNODE_CLASS_H
+
+#include <VFS/DirectoryNode.class.h>
+
+class FATDirectoryNode : public DirectoryNode {
+ friend class FATFS;
+ FATDirectoryNode(String name, FileSystem* fs, FSNode* parent, u32int permissions = 0777,
+ u32int uid = 0, u32int gid = 0) :
+ DirectoryNode(name, fs, parent, permissions, uid, gid) {}
+
+ u32int m_firstCluster;
+ u32int m_firstDirEntryID; //id of the first directory entry corresponding to this file in parent directory
+};
+
+#endif
diff --git a/Source/Kernel/FileSystems/FAT/FATFS.class.cpp b/Source/Kernel/FileSystems/FAT/FATFS.class.cpp
new file mode 100644
index 0000000..2590785
--- /dev/null
+++ b/Source/Kernel/FileSystems/FAT/FATFS.class.cpp
@@ -0,0 +1,201 @@
+#include "FATFS.class.h"
+#include <VTManager/SimpleVT.class.h>
+#include "FATFileNode.class.h"
+#include "FATDirectoryNode.class.h"
+#include <VFS/VFS.ns.h>
+
+#define FIRSTCLUS(node) ((u32int&)(node->type() == NT_DIRECTORY ? \
+ ((FATDirectoryNode*)(node))->m_firstCluster : \
+ ((FATFileNode*)(node))->m_firstCluster))
+#define FIRSTDEID(node) ((u32int&)(node->type() == NT_DIRECTORY ? \
+ ((FATDirectoryNode*)(node))->m_firstDirEntryID : \
+ ((FATFileNode*)(node))->m_firstDirEntryID))
+
+FATFS* FATFS::mount(Partition* p, DirectoryNode* mountpoint) {
+ if (mountpoint != 0 and !mountpoint->mountpointable()) return 0;
+ // *** READ BOOT SECTOR ***
+ union {
+ fat_BS_t s;
+ u8int c[512];
+ } bs;
+ p->readBlocks(0, 1, bs.c);
+ // *** CHECK FILESYSTEM TYPE ***
+ if (bs.s.extBS_16.boot_signature != 0x28 and bs.s.extBS_16.boot_signature != 0x29
+ and bs.s.extBS_32.boot_signature != 0x28 and bs.s.extBS_32.boot_signature != 0x29) return 0;
+ // *** DO SOME CALCULATIONS ***
+ FATFS* fs = new FATFS();
+ fs->m_fatSize = (bs.s.table_size_16 == 0 ? bs.s.extBS_32.table_size_32 : bs.s.table_size_16);
+ fs->m_totalSectors = (bs.s.total_sectors_16 == 0 ? bs.s.total_sectors_32 : bs.s.total_sectors_16);
+ fs->m_rootDirSectors = ((bs.s.root_entry_count * 32) + (bs.s.bytes_per_sector - 1)) / bs.s.bytes_per_sector;
+ fs->m_firstDataSector = bs.s.reserved_sector_count + (fs->m_fatSize * bs.s.table_count);
+ fs->m_clusterSize = bs.s.bytes_per_sector * bs.s.sectors_per_cluster;
+ u32int dataSectors = fs->m_totalSectors - (fs->m_firstDataSector + fs->m_rootDirSectors);
+ fs->m_countOfClusters = dataSectors / bs.s.sectors_per_cluster;
+ if (fs->m_countOfClusters < 4085) { //Find out FAT type
+ fs->m_fatType = 12;
+ } else if (fs->m_countOfClusters < 65525) {
+ fs->m_fatType = 16;
+ } else {
+ fs->m_fatType = 32;
+ }
+ fs->m_readOnly = true;
+ fs->m_bs = bs.s;
+ fs->m_part = p;
+ // *** CREATE ROOT DIRECTORY NODE ***
+ fs->m_rootNode = new FATDirectoryNode("/", fs, mountpoint);
+ FIRSTCLUS(fs->m_rootNode) = 2;
+ if (fs->m_fatType == 32) FIRSTCLUS(fs->m_rootNode) = bs.s.extBS_32.root_cluster;
+ if (mountpoint != 0) mountpoint->mount(fs->m_rootNode);
+ VFS::registerFilesystem(fs);
+ *kvt << "\nDetected a FAT" << (s64int)fs->m_fatType << " filesystem.\n" <<
+ "root_dir_sectors:" << fs->m_rootDirSectors << " fat_size:" << fs->m_fatSize << " total_sectors:" <<
+ fs->m_totalSectors << " data_sectors:" << dataSectors << " count_of_clusters:" << fs->m_countOfClusters <<
+ " sizeof(fat_dir_entry_t):" << sizeof(fat_dir_entry_t) << " first_data_sector:" << fs->m_firstDataSector;
+ return 0;
+}
+
+u32int FATFS::nextCluster(u32int cluster) {
+ u8int fat_table[m_part->getBlockSize()];
+ u32int val;
+ if (m_fatType == 12) {
+ u32int fat_offset = cluster + (cluster / 2);
+ u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize());
+ u32int ent_offset = fat_offset % m_part->getBlockSize();
+ m_part->readBlocks(fat_sector, 1, fat_table);
+ u16int tblval = *(u16int*)&fat_table[ent_offset];
+ if (cluster & 1) val = tblval >> 4;
+ else val = tblval & 0x0FFF;
+ if (val >= 0xFF7) val = 0;
+ } else if (m_fatType == 16) {
+ u32int fat_offset = cluster * 2;
+ u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize());
+ u32int ent_offset = fat_offset % m_part->getBlockSize();
+ m_part->readBlocks(fat_sector, 1, fat_table);
+ u16int tblval = *(u16int*)&fat_table[ent_offset];
+ val = tblval;
+ if (tblval >= 0xFFF7) val = 0;
+ } else if (m_fatType == 32) {
+ u32int fat_offset = cluster * 4;
+ u32int fat_sector = m_bs.reserved_sector_count + (fat_offset / m_part->getBlockSize());
+ u32int ent_offset = fat_offset % m_part->getBlockSize();
+ m_part->readBlocks(fat_sector, 1, fat_table);
+ val = *(u32int*)&fat_table[ent_offset] & 0x0FFFFFFF;
+ if (val >= 0x0FFFFFF7) val = 0;
+ }
+ return val;
+}
+
+void FATFS::readCluster(u32int cluster, u8int* data) {
+ u32int firstSector = ((cluster - 2) * m_bs.sectors_per_cluster) + m_firstDataSector;
+ if (cluster > 2 and m_fatType != 32) firstSector += m_rootDirSectors;
+ m_part->readBlocks(firstSector, m_bs.sectors_per_cluster, data);
+}
+
+bool FATFS::unmount() {
+ if (m_readOnly) return true;
+ return false;
+}
+
+bool FATFS::setName(FSNode* node, String name) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::setPermissions(FSNode* node, u32int permissions) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::setUid(FSNode* node, u32int uid) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::setGid(FSNode* node, u32int gid) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::setParent(FSNode* node, FSNode* parent) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+u32int FATFS::read(FileNode* file, u64int position, u32int max_length, u8int *data) {
+ return 0;
+}
+
+bool FATFS::write(FileNode* file, u64int position, u32int length, u8int* data) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::truncate(FileNode* file) {
+ if (m_readOnly) return false;
+ return false;
+}
+
+bool FATFS::loadContents(DirectoryNode* dir) {
+ u32int cluster = FIRSTCLUS(dir);
+ union {
+ u8int *c;
+ fat_dir_entry_t *e;
+ } e;
+
+ u32int entries = m_clusterSize / sizeof(fat_dir_entry_t);
+ if (cluster == 2 and m_fatType != 32) { //This is the value we use for the root directory
+ e.c = (u8int*)Mem::alloc(m_rootDirSectors * m_part->getBlockSize());
+ m_part->readBlocks(m_firstDataSector, m_rootDirSectors, e.c);
+ } else {
+ e.c = (u8int*)Mem::alloc(m_clusterSize);
+ }
+
+ while (cluster != 0) {
+ if (cluster != 2 or m_fatType == 32) readCluster(cluster, e.c);
+ for (u32int i = 0; i < entries; i++) {
+ if (e.e[i].name[0] == 0 or e.e[i].name[0] == 0xE5) continue; //Nothing intresting here.
+ if (e.e[i].attributes == FA_LFN) continue; //Long file name entry, nothing intresting
+ if (e.e[i].attributes & FA_VOLUMEID) continue;
+ String name;
+ for (int j = 0; j < 8; j++) {
+ if (e.e[i].name[j] == ' ') break;
+ name += WChar(e.e[i].name[j]);
+ }
+ for (int j = 0; j < 3; j++) {
+ if (e.e[i].extension[j] == ' ') break;
+ if (j == 0) name += ".";
+ name += WChar(e.e[i].extension[j]);
+ }
+ u32int first_clus = (e.e[i].first_clust_high << 16) + e.e[i].first_clust_low;
+ FSNode* n;
+ if (e.e[i].attributes & FA_DIRECTORY) {
+ if (name == "." or name == "..") continue;
+ n = new FATDirectoryNode(name, this, dir);
+ } else {
+ n = new FATFileNode(name, this, dir, e.e[i].size);
+ }
+ FIRSTCLUS(n) = first_clus;
+ dir->getChildren().push(n);
+ }
+ if (cluster == 2 && m_fatType != 32) break; //We are in a FAT12/16 root directory
+ cluster = nextCluster(cluster);
+ }
+
+ Mem::free(e.c);
+ return true;
+}
+
+FileNode* FATFS::createFile(DirectoryNode* parent, String name) {
+ if (m_readOnly) return false;
+ return 0;
+}
+
+DirectoryNode* FATFS::createDirectory(DirectoryNode* parent, String name) {
+ if (m_readOnly) return false;
+ return 0;
+}
+
+bool FATFS::remove(DirectoryNode* parent, FSNode* node) {
+ if (m_readOnly) return false;
+ return false;
+}
diff --git a/Source/Kernel/FileSystems/FAT/FATFS.class.h b/Source/Kernel/FileSystems/FAT/FATFS.class.h
new file mode 100644
index 0000000..50ff479
--- /dev/null
+++ b/Source/Kernel/FileSystems/FAT/FATFS.class.h
@@ -0,0 +1,130 @@
+#ifndef DEF_FATFS_CLASS_H
+#define DEF_FATFS_CLASS_H
+
+#include <VFS/FileSystem.proto.h>
+#include <VFS/Part.ns.h>
+
+struct fat_extBS_32_t { //Extended boot sector for FAT32
+ unsigned int table_size_32;
+ unsigned short extended_flags;
+ unsigned short fat_version;
+ unsigned int root_cluster;
+ unsigned short fat_info;
+ unsigned short backup_BS_sector;
+ unsigned char reserved_0[12];
+ unsigned char drive_number;
+ unsigned char reserved_1;
+ unsigned char boot_signature;
+ unsigned int volume_id;
+ unsigned char volume_label[11];
+ unsigned char fat_type_label[8];
+}__attribute__((packed));
+
+struct fat_extBS_16_t { //Extended boot sector for FAT12 and FAT16
+ unsigned char bios_drive_num;
+ unsigned char reserved1;
+ unsigned char boot_signature;
+ unsigned int volume_id;
+ unsigned char volume_label[11];
+ unsigned char fat_type_label[8];
+}__attribute__((packed));
+
+struct fat_BS_t { //Boot sector
+ unsigned char bootjmp[3];
+ unsigned char oem_name[8];
+ unsigned short bytes_per_sector;
+ unsigned char sectors_per_cluster;
+ unsigned short reserved_sector_count;
+ unsigned char table_count;
+ unsigned short root_entry_count;
+ unsigned short total_sectors_16;
+ unsigned char media_type;
+ unsigned short table_size_16;
+ unsigned short sectors_per_track;
+ unsigned short head_side_count;
+ unsigned int hidden_sector_count;
+ unsigned int total_sectors_32;
+ union {
+ fat_extBS_32_t extBS_32;
+ fat_extBS_16_t extBS_16;
+ };
+}__attribute__((packed));
+
+struct fat_date_t {
+ u16int year : 7;
+ u16int month : 4;
+ u16int day : 5;
+}__attribute__((packed));
+
+struct fat_time_t {
+ u16int hour : 5;
+ u16int minutes : 6;
+ u16int seconds : 5;
+}__attribute__((packed));
+
+struct fat_dir_entry_t {
+ char name[8];
+ char extension[3];
+ u8int attributes;
+ u8int reserved;
+ u8int createtenthsofseconds;
+ fat_time_t created_time;
+ fat_date_t created_date;
+ fat_date_t accessed_date;
+ u16int first_clust_high; //always 0 on FAT12/16
+ fat_time_t modified_time;
+ fat_date_t modified_date;
+ u16int first_clust_low;
+ u32int size;
+}__attribute__((packed));
+
+#define FA_READONLY 0x01
+#define FA_HIDDEN 0x02
+#define FA_SYSTEM 0x04
+#define FA_VOLUMEID 0x08
+#define FA_DIRECTORY 0x10
+#define FA_ARCHIVE 0x20
+#define FA_LFN 0x0F
+
+class FATFS : public FileSystem {
+ private:
+ FATFS() {}
+ ~FATFS() {}
+
+ fat_BS_t m_bs;
+ bool m_readOnly;
+ u32int m_fatSize; //Size of one FAT, in sectors
+ u32int m_totalSectors; //Total sectors used by the FAT
+ u32int m_rootDirSectors; //Sectors used by the root directory
+ u32int m_firstDataSector; //First data sector, start of cluster 2
+ u32int m_countOfClusters; //Count of usable clusters, EXCLUDING the ones used by the root directory
+ u32int m_clusterSize; //size of a cluster in bytes
+ u32int m_fatType; //12, 16 or 32
+ Partition* m_part;
+
+ u32int nextCluster(u32int cluster); //Get the next cluster number in the chain (0 = EOF)
+ void readCluster(u32int cluster, u8int* data); //Read the content of a cluster to a buffer
+
+ public:
+ static FATFS* mount(Partition* p, DirectoryNode* mountpoint);
+
+ bool unmount();
+
+ bool setName(FSNode* node, String name);
+ bool setPermissions(FSNode* node, u32int permissions);
+ bool setUid(FSNode* node, u32int uid);
+ bool setGid(FSNode* node, u32int gid);
+ bool setParent(FSNode* node, FSNode* parent);
+
+ u32int read(FileNode* file, u64int position, u32int max_length, u8int *data);
+ bool write(FileNode* file, u64int position, u32int length, u8int *data);
+ bool truncate(FileNode* file);
+
+ bool loadContents(DirectoryNode* dir);
+ FileNode* createFile(DirectoryNode* parent, String name);
+ DirectoryNode* createDirectory(DirectoryNode* parent, String name);
+ bool remove(DirectoryNode* parent, FSNode* node);
+};
+
+#endif
+
diff --git a/Source/Kernel/FileSystems/FAT/FATFileNode.class.h b/Source/Kernel/FileSystems/FAT/FATFileNode.class.h
new file mode 100644
index 0000000..b64f911
--- /dev/null
+++ b/Source/Kernel/FileSystems/FAT/FATFileNode.class.h
@@ -0,0 +1,16 @@
+#ifndef DEF_FATFILENODE_CLASS_H
+#define DEF_FATFILENODE_CLASS_H
+
+#include <VFS/FileNode.class.h>
+
+class FATFileNode : public FileNode {
+ friend class FATFS;
+ FATFileNode (String name, FileSystem* fs, FSNode* parent, u32int size, u32int permissions = 0777,
+ u32int uid = 0, u32int gid = 0) :
+ FileNode(name, fs, parent, size, permissions, uid, gid){}
+
+ u32int m_firstCluster;
+ u32int m_firstDirEntryID; //id of the first directory entry corresponding to this file in parent directory
+};
+
+#endif
diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile
index a70c8c5..2005cd2 100644
--- a/Source/Kernel/Makefile
+++ b/Source/Kernel/Makefile
@@ -66,6 +66,7 @@ Objects = Core/loader.wtf.o \
VFS/DirectoryNode.class.o \
UserManager/Usr.ns.o \
FileSystems/RamFS/RamFS.class.o \
+ FileSystems/FAT/FATFS.class.o \
SyscallManager/IDT.ns.o \
SyscallManager/Ressource.class.o \
SyscallManager/Res.ns.o \
diff --git a/Source/Kernel/Shell/KernelShell.class.cpp b/Source/Kernel/Shell/KernelShell.class.cpp
index 8f71b9f..7f57f8b 100644
--- a/Source/Kernel/Shell/KernelShell.class.cpp
+++ b/Source/Kernel/Shell/KernelShell.class.cpp
@@ -128,8 +128,7 @@ u32int KernelShell::run() {
String p = VFS::path(n);
for (u32int i = 0; i < VFS::filesystems.size(); i++) {
if (VFS::path(VFS::filesystems[i]->getRootNode()) == p) {
- VFS::unmount(VFS::filesystems[i]);
- ok = true;
+ ok = VFS::unmount(VFS::filesystems[i]);
break;
}
}