Implemented custom filesystem and got it to compile. It seems that it isn't loading the 3rd stage bootloader though

This commit is contained in:
2024-08-12 16:30:45 +02:00
parent 044b1eceac
commit be6b65863f
7 changed files with 149 additions and 165 deletions
+20 -11
View File
@@ -4,28 +4,29 @@ Sector = 512 Bytes
Block = 4096 Bytes Block = 4096 Bytes
Reserved sectors: Reserved sectors:
Sector 0 - Bootsector, will be loaded by the Bios into memory and executed (512B) Sector 0..3 - Bootblock, will be loaded by the Bios into memory and executed (512B)
Sector 1..4 - Superblock, contains metadata about the filesystem itself (4KiB) Sector 4..7 - Superblock, contains metadata about the filesystem itself (4KiB)
Superblock structure: (4096B) Superblock structure: (4096B)
FS Name Device ID
FS Size (Sector) Max File Size
FS Size (Block)
INode Count INode Count
INodes per sector
INode Bitmap Block INode Bitmap Block
Data Bitmap Block
INodes Start INodes Start
INode Block Count
INodes per sector
Data Bitmap Block
Data Start Data Start
Root INode Number Data Block Count
Extents per indirect Root INode Pointer
First Unreserved INode
INode structure: (64B) INode structure: (64B)
Type Type
Size (bytes) Size (bytes)
Block Count (size in blocks) Sector Count (size in sectors)
Mode Mode
Extents[] Extent[4]
Single Indirect Single Indirect
Double Indirect? Double Indirect?
@@ -37,3 +38,11 @@ Directory Entry: (64B)
INode Number INode Number
Name (max length 60 Bytes) Name (max length 60 Bytes)
Filetypes:
File
Directory
#TODO
Link
Device
Stream?
+53 -60
View File
@@ -1,90 +1,83 @@
#ifndef FS_H #ifndef FS_H
#define FS_H #define FS_H
/*
* For info, read the fs-spec.txt document inside of docs/
*/
#include <stdint.h> #include <stdint.h>
#define FS_BLOCK_SIZE 4096 // FS Definitions
#define FS_SECTOR_SIZE 512 #define FS_SECTOR_SIZE 512
#define FS_BLOCK_SIZE 4096
#define FILETYPE_FILE 0 // Conversion Macros (beatiful)
#define FILETYPE_DIR 1 #define BYTES2BLOCKS(_n) ( (_n) == 0 ? 0 : \
(_n) <= (FS_BLOCK_SIZE) ? 1 : \
((_n) / FS_BLOCK_SIZE) + (((_n) % FS_BLOCK_SIZE) > 0 ? 1 : 0) )
// Filesystem structures #define BYTES2SECTORS(_n) ( (_n) == 0 ? 0 : \
typedef struct { (_n) <= (FS_SECTOR_SIZE) ? 1 : \
uint8_t second; ((_n) / FS_SECTOR_SIZE) + (((_n) % FS_SECTOR_SIZE) > 0 ? 1 : 0) )
uint8_t minute;
uint8_t hour; // Filetypes
uint8_t day; #define FT_FILE 0
uint8_t month; #define FT_DIR 1
uint16_t year;
uint8_t reserved; // FS Structures
} __attribute__ ((packed)) fsDatetime_t; // TODO: datetime_t?
typedef struct { typedef struct {
uint8_t sectors[FS_BLOCK_SIZE / FS_SECTOR_SIZE][FS_SECTOR_SIZE]; uint8_t sectors[FS_BLOCK_SIZE / FS_SECTOR_SIZE][FS_SECTOR_SIZE];
} __attribute__ ((packed)) bootBlock_t; } __attribute__ ((packed)) bootblock_t;
// Superblock - Padded to 4096 Bytes
typedef struct { typedef struct {
// Constant data
uint16_t deviceId;
uint16_t extentsPerIndirect;
uint32_t maxFileSize;
uint16_t inodesPerSector;
// INode data
uint32_t inodeCount; uint32_t inodeCount;
uint32_t inodeBitmapBlock;
uint32_t inodesStart;
uint32_t inodeBlockCount;
uint16_t firstINodeBitmapBlock; // Data data :)
uint16_t firstDataBitmapBlock; uint32_t dataBitmapBlock;
uint16_t inodeBitmapBlockCount; uint32_t dataStart;
uint16_t dataBitmapBlockCount; uint32_t dataBlockCount;
uint32_t firstINodeBlock;
uint32_t firstDataBlock;
uint16_t inodeBlockCount;
uint16_t dataBlockCount;
uint32_t maxFileSize; // in bytes // Other
uint16_t blockSize; // in bytes uint32_t rootInodePtr;
uint8_t inodeSize; // in bytes uint32_t firstUnreservedInode;
} __attribute__ ((packed)) superblock_t;
uint32_t rootINodePtr;
uint8_t inodesPerBlock;
uint8_t directExtentsPerINode;
uint16_t extentsPerIndirectBlock;
uint32_t firstFreeINodeBit;
uint32_t firstFreeDataBit;
uint16_t deviceNumber;
uint8_t firstUnreservedINode;
uint8_t reserved[14];
} __attribute__ ((packed)) superBlock_t;
// Extent - 8 Bytes
typedef struct { typedef struct {
uint32_t firstBlock; uint32_t block;
uint32_t length; uint32_t length;
} __attribute__ ((packed)) extent_t; } __attribute__ ((packed)) extent_t;
// INode - 64 Bytes
typedef struct { typedef struct {
uint32_t id; // Idetifier uint32_t id;
uint8_t filetype; uint8_t type;
uint32_t sizeBytes; uint32_t sizeBytes; // Size in bytes
uint32_t sizeSectors; uint32_t sizeSectors; // Size in sectors
fsDatetime_t timestamp; uint8_t mode; // Access permisions
extent_t extent[4]; extent_t extent[4];
uint32_t singleIndirectBlock; uint32_t singleIndirect;
uint32_t doubleIndirectBlock; uint32_t doubleIndirect;
uint8_t refCount;
uint8_t reserved[2]; uint8_t reserved[10];
} __attribute__ ((packed)) inode_t; } __attribute__ ((packed)) inode_t;
typedef struct { typedef struct {
uint32_t id; // Matching ID with INode
char name[60]; char name[60];
uint32_t id;
} __attribute__ ((packed)) dirEntry_t; } __attribute__ ((packed)) dirEntry_t;
// Utility functions
uint32_t bytesToBlocks(uint32_t bytes) {
if (bytes == 0) return 0;
if (bytes <= FS_BLOCK_SIZE) return 1;
return (bytes / FS_BLOCK_SIZE) + ((bytes % FS_BLOCK_SIZE) > 0 ? 1 : 0);
}
uint32_t bytesToSectors(uint32_t bytes) {
if (bytes == 0) return 0;
if (bytes <= FS_SECTOR_SIZE) return 1;
return (bytes / FS_SECTOR_SIZE) + ((bytes % FS_SECTOR_SIZE) > 0 ? 1 : 0);
}
#endif #endif
+12 -20
View File
@@ -1,44 +1,36 @@
#ifndef IMPL_H #ifndef IMPL_H
#define IMPL_H #define IMPL_H
#include <disk/disk.h>
#include <fs/fs.h> #include <fs/fs.h>
#include <memory/addresses.h> #include <memory/addresses.h>
#include <disk/disk.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
char* currentDir; char* currentDir;
inode_t currentDirINode;
char tempSector[FS_SECTOR_SIZE]; inode_t* getInode(char* path) {
char tempBlock[FS_BLOCK_SIZE]; dirEntry_t* dentry = (dirEntry_t*)SCRATCH_BLOCK_LOC;
inode_t rootINode; while (dentry->name[0] != '\0') {
if (strcmp(dentry->name, path)) break;
inode_t* getINode(char* path) { dentry++;
dirEntry_t* dirEntry = (dirEntry_t*)SCRATCH_BLOCK_LOC;
while (dirEntry->name[0] != '\0') {
if (strcmp(dirEntry->name, path) == 0) break;
dirEntry++;
} }
if (dirEntry->name[0] == '\0') return NULL; if (dentry->name[0] == '\0') return NULL;
inode_t* inode = (inode_t*)BOOT_FIRST_INODE_LOC; inode_t* inode = (inode_t*)BOOT_FIRST_INODE_LOC;
while (inode->id != dirEntry->id) { while (inode->id != dentry->id) { inode++; }
inode++;
}
return inode; return inode;
} }
uint8_t loadFile(inode_t* inode, void* dest) { uint8_t loadFile(inode_t* inode, void* dest) {
uint32_t totalBlocks = bytesToBlocks(inode->sizeBytes); uint32_t totalBlocks = BYTES2BLOCKS(inode->sizeBytes);
uint32_t addressOffset = 0; uint32_t offset = 0;
for (uint8_t i = 0; i < 4 && totalBlocks > 0; i++) { for (uint8_t i = 0; i < 4 && totalBlocks > 0; i++) {
diskRead(inode->extent[i].firstBlock * 8, inode->extent[i].length * 8, dest + addressOffset); diskRead(inode->extent[i].block * 8, inode->extent[i].length * 8, dest + offset);
addressOffset += inode->extent[i].length * FS_BLOCK_SIZE; offset += inode->extent[i].length * FS_BLOCK_SIZE;
totalBlocks -= inode->extent[i].length; totalBlocks -= inode->extent[i].length;
} }
+2 -1
View File
@@ -12,9 +12,10 @@
* 0x6000-0x6fff - VBE info area * 0x6000-0x6fff - VBE info area
* 0x7000-0x7bff - SMAP Area * 0x7000-0x7bff - SMAP Area
* 0x7c00-0x8bff - Bootblock * 0x7c00-0x8bff - Bootblock
* 0x8c00-0x9bff - Superblock (i think) * 0x8c00-0x9bff - Superblock
* 0x9c00-0xafff - Free * 0x9c00-0xafff - Free
* 0xb000-0xbfff - Bootloader first INode * 0xb000-0xbfff - Bootloader first INode
* 0xc000-0xcfff - Scratch INode block
*/ */
// Global Variables 0x1800-0x1fff // Global Variables 0x1800-0x1fff
+54 -65
View File
@@ -31,7 +31,7 @@ fileInfo_t files[] = { // TODO: Not have to list all of the files, loop through
{ BIN_DIR"editor.bin" }, { BIN_DIR"editor.bin" },
}; };
superBlock_t superblock = { 0 }; superblock_t superblock = { 0 };
FILE* imagePtr; FILE* imagePtr;
uint32_t diskSize = DISK_SIZE; uint32_t diskSize = DISK_SIZE;
@@ -63,11 +63,11 @@ int main(int argc, char** argv) {
fseek(files[i].fp, 0, SEEK_END); fseek(files[i].fp, 0, SEEK_END);
files[i].size = ftell(files[i].fp); files[i].size = ftell(files[i].fp);
rewind(files[i].fp); rewind(files[i].fp);
fileBlocks += bytesToBlocks(files[i].size); fileBlocks += BYTES2BLOCKS(files[i].size);
} }
printf("Building disk image %s...\n", IMAGE_NAME); printf("Building disk image %s...\n", IMAGE_NAME);
printf("Block size: %d Bytes, Total disk blocks: %d (%d Bytes)\n\n", FS_BLOCK_SIZE, bytesToBlocks(diskSize), diskSize); printf("Block size: %d Bytes, Total disk blocks: %d (%d Bytes)\n\n", FS_BLOCK_SIZE, BYTES2BLOCKS(diskSize), diskSize);
printf("%d files (2 hidden)\n", fileCount); // Stage 1 and 2 is hidden printf("%d files (2 hidden)\n", fileCount); // Stage 1 and 2 is hidden
@@ -79,12 +79,12 @@ int main(int argc, char** argv) {
writeINodeBlocks(); writeINodeBlocks();
writeDataBlocks(); writeDataBlocks();
uint32_t writtenBlocks = 2 + superblock.inodeBitmapBlockCount + superblock.dataBitmapBlockCount + superblock.inodeBlockCount + superblock.dataBlockCount; uint32_t writtenBlocks = 4 + superblock.inodeBlockCount + superblock.dataBlockCount;
printf("\nWritten blocks: %d (%d Bytes)\n", writtenBlocks, writtenBlocks * FS_BLOCK_SIZE); printf("\nWritten blocks: %d (%d Bytes)\n", writtenBlocks, writtenBlocks * FS_BLOCK_SIZE);
printf("Free blocks: %d (%d Bytes)\n", bytesToBlocks(diskSize) - writtenBlocks, diskSize - writtenBlocks * FS_BLOCK_SIZE); printf("Free blocks: %d (%d Bytes)\n", BYTES2BLOCKS(diskSize) - writtenBlocks, diskSize - writtenBlocks * FS_BLOCK_SIZE);
// Pad out to the whole disk size // Pad out to the whole disk size
for (uint32_t i = 0; i < bytesToBlocks(diskSize) - writtenBlocks; i++) { for (uint32_t i = 0; i < BYTES2BLOCKS(diskSize) - writtenBlocks; i++) {
assert(fwrite(nullBlock, FS_BLOCK_SIZE, 1, imagePtr) == 1); assert(fwrite(nullBlock, FS_BLOCK_SIZE, 1, imagePtr) == 1);
} }
@@ -98,10 +98,10 @@ int main(int argc, char** argv) {
} }
void writeBootblock() { void writeBootblock() {
bootBlock_t bootBlock = { 0 }; bootblock_t bootBlock = { 0 };
assert(fread(bootBlock.sectors[0], FS_SECTOR_SIZE, 1, files[0].fp) == 1); // File 0 - Stage 1 assert(fread(bootBlock.sectors[0], FS_SECTOR_SIZE, 1, files[0].fp) == 1); // File 0 - Stage 1
for (uint8_t i = 1; i < bytesToSectors(files[i].size); i++) { for (uint8_t i = 1; i < BYTES2SECTORS(files[i].size); i++) {
if (i > 7) { if (i > 7) {
fprintf(stderr, "%s is too large, maximum size of bootblock is 7 sectors (%d Bytes)\n", files[1].name, 7 * FS_SECTOR_SIZE); fprintf(stderr, "%s is too large, maximum size of bootblock is 7 sectors (%d Bytes)\n", files[1].name, 7 * FS_SECTOR_SIZE);
exit(1); exit(1);
@@ -117,33 +117,39 @@ void writeBootblock() {
} }
void writeSuperblock() { void writeSuperblock() {
superblock.inodeCount = fileCount; // 2 reserved INodes (0 - Invalid, 1 - Root) /* Block Layout
superblock.firstINodeBitmapBlock = 2; // Block 0 - Boot, Block 1 - Superblock * 0 - Boot
superblock.inodeBitmapBlockCount = superblock.inodeCount / (FS_BLOCK_SIZE * 8) + ((superblock.inodeCount % (FS_BLOCK_SIZE * 8) > 0) ? 1 : 0); * 1 - Super
superblock.firstDataBitmapBlock = superblock.firstINodeBitmapBlock + superblock.inodeBitmapBlockCount; * 2 - INode Bitmap
superblock.inodeBlockCount = bytesToBlocks(superblock.inodeCount * sizeof(inode_t)); * 3 - Data Bitmap
* 4 - First INode Block
*/
dataBlocks = bytesToBlocks(diskSize); // Constant
dataBitCount = (dataBlocks - superblock.firstDataBitmapBlock - superblock.inodeBlockCount); superblock.deviceId = 0x01;
superblock.extentsPerIndirect = FS_BLOCK_SIZE / sizeof(extent_t);
superblock.maxFileSize = 0xffffffff;
superblock.inodesPerSector = (FS_SECTOR_SIZE / sizeof(inode_t));
superblock.dataBitmapBlockCount = dataBitCount / (FS_BLOCK_SIZE * 8) + ((dataBitCount % (FS_BLOCK_SIZE * 8) > 0) ? 1 : 0); // INode
superblock.firstINodeBlock = superblock.firstDataBitmapBlock + superblock.dataBitmapBlockCount; superblock.inodeCount = fileCount + 2; // 2 reserved INodes (0 - Invalid, 1 - Root)
superblock.firstDataBlock = superblock.firstINodeBlock + superblock.inodeBlockCount; superblock.inodeBitmapBlock = 2;
superblock.dataBlockCount = (fileBlocks - 2) + 1; // 1 Block for root dir (-1 for boot block) superblock.inodesStart = 4;
superblock.maxFileSize = 0xffffffff; superblock.inodeBlockCount = BYTES2BLOCKS(superblock.inodeCount * sizeof(inode_t));
superblock.blockSize = FS_BLOCK_SIZE;
superblock.inodeSize = sizeof(inode_t); // Data
superblock.rootINodePtr = 0; // Gets setup at runtime dataBlocks = BYTES2BLOCKS(diskSize);
superblock.inodesPerBlock = FS_BLOCK_SIZE / sizeof(inode_t);
superblock.directExtentsPerINode = 4; superblock.dataBitmapBlock = 3;
superblock.extentsPerIndirectBlock = FS_BLOCK_SIZE / sizeof(extent_t); superblock.dataStart = superblock.inodesStart + superblock.inodeBlockCount;
superblock.firstFreeINodeBit = superblock.inodeCount; superblock.dataBlockCount = fileBlocks; // +1 for Root, -1 for Boot
superblock.firstFreeDataBit = (fileBlocks - 2) + 1; // +1 for root dir
superblock.deviceNumber = 0x01; // Other
superblock.firstUnreservedINode = 3; // 0 - Invalid; 1 - Root dir; 2 - Bootloader INode superblock.rootInodePtr = 0; // Will be filled at runtime
superblock.firstUnreservedInode = 3; // 0 - Invalid, 1 - Root, 2 - Bootloader
assert(fwrite(&superblock, sizeof(superBlock_t), 1, imagePtr) == 1);
assert(fwrite(nullBlock, paddingBytes(sizeof(superBlock_t), FS_BLOCK_SIZE), 1, imagePtr) == 1); // Padding assert(fwrite(&superblock, sizeof(superblock_t), 1, imagePtr) == 1);
assert(fwrite(nullBlock, paddingBytes(sizeof(superblock_t), FS_BLOCK_SIZE), 1, imagePtr) == 1); // Padding
} }
void writeINodeBitmapBlocks() { void writeINodeBitmapBlocks() {
@@ -178,50 +184,33 @@ void writeDataBitmapBlocks() {
void writeINodeBlocks() { void writeINodeBlocks() {
inode_t inode = { 0 }; inode_t inode = { 0 };
fsDatetime_t defaultTimestamp = {
.second = 12,
.minute = 12,
.hour = 12,
.day = 20,
.month = 4,
.year = 2024,
};
// INode 0 - Invalid // INode 0 - Invalid
assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1); assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1);
// INode 1 - Root directory // INode 1 - Root directory
inode = (inode_t) { // OOP In C??? inode.id = 1;
.id = 1, inode.type = FT_DIR;
.filetype = FILETYPE_DIR, inode.sizeBytes = sizeof(dirEntry_t) * fileCount;
.sizeBytes = sizeof(dirEntry_t) * fileCount, inode.sizeSectors = BYTES2SECTORS(inode.sizeBytes);
// .sizeSectors = bytesToSectors(inode.sizeBytes), Set below // TODO: Mode
.timestamp = defaultTimestamp,
.extent[0] = (extent_t) {
.firstBlock = superblock.firstDataBlock,
// .length = bytesToBlocks(inode.sizeBytes), Set below
},
};
inode.sizeSectors = bytesToSectors(inode.sizeBytes); inode.extent[0].block = superblock.dataStart;
inode.extent[0].length = bytesToBlocks(inode.sizeBytes); inode.extent[0].length = BYTES2BLOCKS(inode.sizeBytes);
assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1); assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1);
// INode 2 - Bootloader (stage 3) followed by other INodes // INode 2 - Bootloader (stage 3) followed by other INodes
uint32_t block = superblock.firstDataBlock + inode.extent[0].length; uint32_t block = superblock.dataStart + inode.extent[0].length;
for (uint32_t i = 2; i < fileCount; i++) { for (uint32_t i = 2; i < fileCount; i++) {
memset(&inode, 0, sizeof(inode)); memset(&inode, 0, sizeof(inode));
inode.id = i; inode.id = i;
inode.filetype = FILETYPE_FILE; inode.type = FT_FILE;
inode.sizeBytes = files[i].size; inode.sizeBytes = files[i].size;
inode.sizeSectors = bytesToSectors(inode.sizeBytes); inode.sizeSectors = BYTES2SECTORS(inode.sizeBytes);
inode.timestamp = defaultTimestamp;
inode.extent[0] = (extent_t) { inode.extent[0].block = block,
.firstBlock = block, inode.extent[0].length = BYTES2BLOCKS(inode.sizeBytes);
// .length = bytesToBlocks(inode.sizeBytes),
};
inode.extent[0].length = bytesToBlocks(inode.sizeBytes);
assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1); assert(fwrite(&inode, sizeof(inode), 1, imagePtr) == 1);
@@ -248,12 +237,12 @@ void writeDataBlocks() {
assert(fwrite(&dirEntry, sizeof(dirEntry), 1, imagePtr) == 1); assert(fwrite(&dirEntry, sizeof(dirEntry), 1, imagePtr) == 1);
} }
// Padd out // Pad out
assert(fwrite(nullBlock, paddingBytes(fileCount * sizeof(dirEntry_t), FS_BLOCK_SIZE), 1, imagePtr) == 1); assert(fwrite(nullBlock, paddingBytes(fileCount * sizeof(dirEntry_t), FS_BLOCK_SIZE), 1, imagePtr) == 1);
// Write actual file data // Write actual file data
for (uint32_t i = 2; i < fileCount; i++) { for (uint32_t i = 2; i < fileCount; i++) {
uint32_t blockCount = bytesToBlocks(files[i].size); uint32_t blockCount = BYTES2BLOCKS(files[i].size);
uint32_t bytesWritten = 0; uint32_t bytesWritten = 0;
printf("%s, %d Bytes -> %d Blocks\n", files[i].name, files[i].size, blockCount); printf("%s, %d Bytes -> %d Blocks\n", files[i].name, files[i].size, blockCount);
+3 -3
View File
@@ -2,9 +2,9 @@
[org 0x7c00] [org 0x7c00]
%define SUPERBLOCK 0x8c00 %define SUPERBLOCK 0x8c00
%define FIRST_INODE_BLOCK (SUPERBLOCK) + 12 %define FIRST_INODE_BLOCK (SUPERBLOCK) + 18
%define STAGE3_INODE 0xb000 + 128 %define STAGE3_INODE 0xb000 + (2 * 64)
%define EXTENT0 (STAGE3_INODE) + 21 ; Offset of extent[0] in inode_t %define EXTENT0 (STAGE3_INODE) + 14 ; Offset of extent[0] in inode_t
start: start:
xor ax, ax xor ax, ax
+5 -5
View File
@@ -27,16 +27,16 @@ void main() {
deinitMemoryRegion(MEMMAP_AREA, maxBlocks / BLOCKS_PER_BYTE); deinitMemoryRegion(MEMMAP_AREA, maxBlocks / BLOCKS_PER_BYTE);
// Load root dir, find kernel INode and parse it // Load root dir, find kernel INode and parse it
superBlock_t* superblock = (superBlock_t*)SUPERBLOCK_LOC; superblock_t* superblock = (superblock_t*)SUPERBLOCK_LOC;
superblock->rootINodePtr = BOOT_FIRST_INODE_LOC + sizeof(inode_t); superblock->rootInodePtr = BOOT_FIRST_INODE_LOC + sizeof(inode_t);
diskRead(superblock->firstDataBlock * 8, 8, (void*)SCRATCH_BLOCK_LOC); diskRead(superblock->dataStart * 8, 8, (void*)SCRATCH_BLOCK_LOC);
inode_t* inode; inode_t* inode;
if ((inode = getINode("kernel.bin")) == NULL) { if ((inode = getInode("kernel.bin")) == NULL) {
__asm__ volatile ("cli; hlt" : : "a"(0xDeadBeef)); __asm__ volatile ("cli; hlt" : : "a"(0xDeadBeef));
} else { loadFile(inode, (void*)KERNEL_LOC); } } else { loadFile(inode, (void*)KERNEL_LOC); }
if ((inode = getINode("term16n.fnt")) == NULL) { if ((inode = getInode("term16n.fnt")) == NULL) {
__asm__ volatile ("cli; hlt" : : "a"(0xDeadBeef)); __asm__ volatile ("cli; hlt" : : "a"(0xDeadBeef));
} else { loadFile(inode, (void*)FONT_LOC); } } else { loadFile(inode, (void*)FONT_LOC); }