diff --git a/src/bootloader/stage2/disk.c b/src/bootloader/stage2/disk.c index a795783..059e6b0 100644 --- a/src/bootloader/stage2/disk.c +++ b/src/bootloader/stage2/disk.c @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #include "disk.h" #include "x86.h" #include "stdio.h" diff --git a/src/bootloader/stage2/fat.c b/src/bootloader/stage2/fat.c index f7cba59..5e9ccf2 100644 --- a/src/bootloader/stage2/fat.c +++ b/src/bootloader/stage2/fat.c @@ -1,9 +1,19 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #include "fat.h" #include "stdio.h" #include "memdefs.h" #include "utility.h" +#include "string.h" +#include "memory.h" -#define SECTOR_SIZE 512 +#define SECTOR_SIZE 512 +#define MAX_PATH_SIZE 256 +#define MAX_FILE_HANDLES 10 +#define ROOT_DIRECTORY_HANDLE -1 #pragma pack(push,1) typedef struct @@ -34,36 +44,40 @@ typedef struct } FAT_BootSector; #pragma pack(pop) +typedef struct { + FAT_File Public; + bool Opened; + uint32_t FirstCluster; + uint32_t CurrentCluster; + uint32_t CurrentSectorInCluster; + uint8_t Buffer[SECTOR_SIZE]; + +} FAT_FileData; + + typedef struct { union { - FAT_BootSector Bootsector; - uint8_t BootsectorBytes[SECTOR_SIZE]; + FAT_BootSector BootSector; + uint8_t BootSectorBytes[SECTOR_SIZE]; } BS; + FAT_FileData RootDirectory; + + FAT_FileData OpenedFiles[MAX_FILE_HANDLES]; + } FAT_Data; static FAT_Data far* g_Data; static uint8_t far* g_Fat = NULL; -static FAT_DirectoryEntry far* g_RootDirectory = NULL; -static uint32_t g_RootDirectoryEnd; +static uint32_t g_DataSectionLba; -bool FAT_ReadBootSector(FILE* disk) { +bool FAT_ReadBootSector(DISK* disk) { return DISK_ReadSectors(disk, 0, 1, &g_Data->BS.BootSectorBytes); } bool FAT_ReadFat(DISK* disk) { - return DISK_ReadSectors(disk, g_Data->g_BootSector.ReservedSectors, g_Data->g_BootSector.SectorsPerFat, g_Fat); -} - -bool FAT_ReadRootDirectory(DISK* disk) -{ - uint32_t lba = g_Data->g_BootSector.ReservedSectors + g_Data->g_BootSector.SectorsPerFat * g_Data->g_BootSector.FatCount; - uint32_t size = sizeof(FAT_DirectoryEntry) * g_Data->g_BootSector.DirEntryCount; - uint32_t sectors = (size + g_Data->g_BootSector.BytesPerSector - 1) / g_Data->g_BootSector.BytesPerSector; - - g_RootDirectoryEnd = lba + sectors; - return DISK_ReadSectors(disk, lba, sectors, g_RootDirectory); + return DISK_ReadSectors(disk, g_Data->BS.BootSector.ReservedSectors, g_Data->BS.BootSector.SectorsPerFat, g_Fat); } bool FAT_Initialize(DISK* disk) { @@ -77,7 +91,7 @@ bool FAT_Initialize(DISK* disk) { // read FAT g_Fat = (uint8_t far*)(g_Data + sizeof(FAT_Data)); - uint32_t fatSize = g_Data->BS.Bootsector.BytesPerSector * g_Data->BS.BootSector.SectorsPerFat; + uint32_t fatSize = g_Data->BS.BootSector.BytesPerSector * g_Data->BS.BootSector.SectorsPerFat; if(sizeof(FAT_Data) + fatSize >= MEMORY_FAT_SIZE) { printf("FAT: Not Enough Memory to Read FAT!\r\nNeeded %u, Only Have %u\r\n", sizeof(FAT_Data) + fatSize, MEMORY_FAT_SIZE); return false; @@ -87,24 +101,94 @@ bool FAT_Initialize(DISK* disk) { printf("FAT: Failed to Read FAT!\r\n"); return false; } - // read root dir (/) - g_RootDirectory = (FAT_DirectoryEntry far*)(g_Fat + fatSize); + + // open root dir + uint32_t rootDirLba = g_Data->BS.BootSector.ReservedSectors + g_Data->BS.BootSector.SectorsPerFat * g_Data->BS.BootSector.FatCount; uint32_t rootDirSize = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount; - rootDirSize = align(rootDirSize, g_Data->BS.BootSector.BytesPerSector); - if (sizeof(FAT_Data) + fatSize + rootDirSize >= MEMORY_FAT_SIZE) { - printf("FAT: Not Enough Memory to Read Root Directory!\r\nNeeded %u, Only Have %u\r\n", sizeof(FAT_Data) + fatSize + rootDirSize, MEMORY_FAT_SIZE); - return false; - } + g_Data->RootDirectory.Public.Handle = ROOT_DIRECTORY_HANDLE; + g_Data->RootDirectory.Public.IsDirectory = true; + g_Data->RootDirectory.Public.Position = 0; + g_Data->RootDirectory.Public.Size = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount; + g_Data->RootDirectory.Opened = true; + g_Data->RootDirectory.FirstCluster = 0; + g_Data->RootDirectory.CurrentCluster = 0; + g_Data->RootDirectory.CurrentSectorInCluster = 0; - if(!FAT_ReadRootDirectory(disk)) { + if (!DISK_ReadSectors(disk, rootDirLba, 1, g_Data->RootDirectory.Buffer)) { printf("FAT: Failed to Read Root Directory!\r\n"); return false; } + //calculate data + uint32_t rootDirSectors = (rootDirSize + g_Data->BS.BootSector.BytesPerSector - 1) / g_Data->BS.BootSector.BytesPerSector; + g_DataSectionLba = rootDirLba + rootDirSectors; + + // reset opened files + for (int i = 0; i < MAX_FILE_HANDLES; i++) + g_Data->OpenedFiles[i].Opened = false; } -FAT_File far* FAT_Open(DISK* disk, const char* path) { +uint32_t FAT_ClusterToLba(uint32_t cluster) { + return g_DataSectionLba + (cluster -2) * g_Data->BS.BootSector.SectorsPerCluster; +} + +FAT_File far* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) { + // find empty handle + int handle = -1; + for (int i = 0; i < MAX_FILE_HANDLES && handle < 0; i++) { + if (!g_Data->OpenedFiles[i].Opened) + handle = i; + } + // out of handles + if (handle < 0) { + printf("FAT: Out of File Handles!\r\n"); + return false; + } + + // setup vars + FAT_FileData far* fd = &g_Data->OpenedFiles[handle]; + fd->Public.Handle = handle; + fd->Public.IsDirectory = (entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0;\ + fd->Public.Position = 0; + fd->Public.Size = 0; + fd->FirstCluster = entry->FirstClusterLow + ((uint32_t)entry->FirstClusterHigh << 16); + fd->CurrentCluster = fd->FirstCluster; + fd->CurrentSectorInCluster = 0; + + if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster), 1, fd->Buffer)) { + printf("FAT: Read Error!\r\n"); + return false; + } + + fd->Opened = true; + return &fd->Public; +} + +FAT_File* FAT_Open(DISK* disk, const char* path) { + char buffer[MAX_PATH_SIZE]; + // ignore leading slash + if (path[0] == '/') + path++; + + FAT_File far* parent = NULL; + FAT_File far* current = g_Data->RootDirectory.Public; + + while (*path) { + // extract next file name from path + const char * delim = strchr(path, '/'); + if (delim != NULL) { + memcpy(name, path, delim - path); + name[delim - path + 1] = '\0'; + path = delim + 1 + } + else { + unsigned len = strlen(path); + memcpy(name, path, len); + name[len + 1] = '\0'; + path += len; + } + } } DirectoryEntry* findFile(const char* name) diff --git a/src/bootloader/stage2/fat.h b/src/bootloader/stage2/fat.h index 2c75eae..915b6d5 100644 --- a/src/bootloader/stage2/fat.h +++ b/src/bootloader/stage2/fat.h @@ -21,7 +21,7 @@ typedef struct } FAT_DirectoryEntry; #pragma pack(pop) -typdef struct { +typedef struct { int Handle; bool IsDirectory; uint32_t Position; @@ -39,7 +39,6 @@ enum FAT_Attributes { }; - bool FAT_Initialize(DISK* disk); FAT_File far* FAT_Open(DISK* disk, const char* path); uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* dataOut); diff --git a/src/bootloader/stage2/memdefs.h b/src/bootloader/stage2/memdefs.h index c3fe589..f4b2452 100644 --- a/src/bootloader/stage2/memdefs.h +++ b/src/bootloader/stage2/memdefs.h @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #pragma once // 0x00000000 - 0x000003FF - int vector table diff --git a/src/bootloader/stage2/memory.c b/src/bootloader/stage2/memory.c new file mode 100644 index 0000000..34c42bc --- /dev/null +++ b/src/bootloader/stage2/memory.c @@ -0,0 +1,14 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#include "memory.h" + +int memcpy(void far* dst, const void far* src, uint16_t num) { + uint8_t far* u8Dst = (uint8_t far *)dst; + const uint8_t far* u8Src = (const uint8_t far *)src; + + for (uint16_t i = 0; i < num; i++) + u8Dst[i] = u8Src[i]; +} \ No newline at end of file diff --git a/src/bootloader/stage2/memory.h b/src/bootloader/stage2/memory.h new file mode 100644 index 0000000..be97639 --- /dev/null +++ b/src/bootloader/stage2/memory.h @@ -0,0 +1,9 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ +#pragma once +#include "stdint.h" + +int memcpy(void far* dst, const void far* src, uint16_t num); \ No newline at end of file diff --git a/src/bootloader/stage2/stdint.h b/src/bootloader/stage2/stdint.h index ca0d7f9..6894554 100644 --- a/src/bootloader/stage2/stdint.h +++ b/src/bootloader/stage2/stdint.h @@ -19,4 +19,4 @@ typedef uint8_t bool; #define true 1 #define false 0 -#define NULL ((void*)0) \ No newline at end of file +#define NULL ((void*)0) diff --git a/src/bootloader/stage2/string.c b/src/bootloader/stage2/string.c index adcacfd..8a86be8 100644 --- a/src/bootloader/stage2/string.c +++ b/src/bootloader/stage2/string.c @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #include "string.h" #include "stdint.h" @@ -33,4 +38,12 @@ char* strcpy(char* dst, const char* src) { *dst = '\0'; return origDst; +} + +unsigned strlen(const char* str) { + unsigned len = 0; + while (*str) { + ++len; ++str; + } + return len; } \ No newline at end of file diff --git a/src/bootloader/stage2/string.h b/src/bootloader/stage2/string.h index d7318b8..63974fc 100644 --- a/src/bootloader/stage2/string.h +++ b/src/bootloader/stage2/string.h @@ -1,4 +1,10 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #pragma once const char* strchr(const char* str, char chr); -char* strcpy(char* dst, const char* src); \ No newline at end of file +char* strcpy(char* dst, const char* src); +unsigned strlen(const char* str); \ No newline at end of file diff --git a/src/bootloader/stage2/utility.h b/src/bootloader/stage2/utility.h index dc170b8..741bc59 100644 --- a/src/bootloader/stage2/utility.h +++ b/src/bootloader/stage2/utility.h @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #pragma once #include "stdint.h"