diff --git a/src/bootloader/stage1/boot.asm b/src/bootloader/stage1/boot.asm index df87676..e3b9ebf 100644 --- a/src/bootloader/stage1/boot.asm +++ b/src/bootloader/stage1/boot.asm @@ -367,7 +367,7 @@ disk_reset: ret -msg_loading: db 'Loading Nanite...', ENDL, 0 +msg_loading: db '', ENDL, 0 msg_read_failed: db 'Cant Read Disk!', ENDL, 0 msg_no_stage2: db 'Cant Find Stage 2!', ENDL, 0 file_stage2_bin: db 'STAGE2 BIN' diff --git a/src/bootloader/stage2/fat.c b/src/bootloader/stage2/fat.c index 5e9ccf2..9f35d02 100644 --- a/src/bootloader/stage2/fat.c +++ b/src/bootloader/stage2/fat.c @@ -9,6 +9,7 @@ #include "utility.h" #include "string.h" #include "memory.h" +#include "ctype.h" #define SECTOR_SIZE 512 #define MAX_PATH_SIZE 256 @@ -126,6 +127,8 @@ bool FAT_Initialize(DISK* disk) { // reset opened files for (int i = 0; i < MAX_FILE_HANDLES; i++) g_Data->OpenedFiles[i].Opened = false; + + return true; } uint32_t FAT_ClusterToLba(uint32_t cluster) { @@ -164,122 +167,155 @@ FAT_File far* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) { return &fd->Public; } -FAT_File* FAT_Open(DISK* disk, const char* path) { - char buffer[MAX_PATH_SIZE]; +uint32_t FAT_NextCluster(uint32_t currentCluster) { + uint32_t fatIndex = currentCluster * 3 / 2; + if (currentCluster % 2 == 0) + return (*(uint16_t*)(g_Fat + fatIndex)) & 0x0FFF; + else + return (*(uint16_t*)(g_Fat + fatIndex)) >> 4; + +} + +uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* dataOut) { + // get file data + FAT_FileData far* fd = (file->Handle == ROOT_DIRECTORY_HANDLE) + ? &g_Data->RootDirectory + : &g_Data->OpenedFiles[file->Handle]; + + uint8_t* u8DataOut = (uint8_t*)dataOut; + + // don't read past EOF + byteCount = min(byteCount, fd->Public.Size - fd->Public.Position); + + while (byteCount > 0) { + uint32_t leftInBuffer = SECTOR_SIZE - (fd->Public.Position % SECTOR_SIZE); + uint32_t take = min(byteCount, leftInBuffer); + + memcpy(u8DataOut, fd->Buffer + fd->Public.Position % SECTOR_SIZE, take); + u8DataOut += take; + fd->Public.Position += take; + byteCount -= take; + + // see if we need to read more data + if (byteCount > 0) { + // root dir handler + if (fd->Public.Handle == ROOT_DIRECTORY_HANDLE) { + ++fd->CurrentCluster; + // read next sect. + if (!DISK_ReadSectors(disk, fd->CurrentCluster, 1, fd->Buffer)) { + printf("FAT: Read Error!\r\n"); + break; + } + } + else { + // read next sect. + if (++fd->CurrentSectorInCluster >= g_Data->BS.BootSector.SectorsPerCluster) { + // calc next cluster & sect. to read + fd->CurrentSectorInCluster = 0; + fd->CurrentCluster = FAT_NextCluster; + } + if (fd->CurrentCluster >= 0x0FF8) { + printf("FAT: Read Error, Invalid Next Cluster!\r\n"); + break; + + } + + // read next sect. + if (!DISK_ReadSectors(disk, FAT_ClusterToLba(fd->CurrentCluster) + fd->CurrentSectorInCluster, 1, fd->Buffer)) { + printf("FAT: Read Error!\r\n"); + break; + } + } + } + } + + return u8DataOut - (uint8_t*)dataOut; +} +bool FAT_ReadEntry(DISK* disk, FAT_File far* file, FAT_DirectoryEntry* dirEntry) { + return FAT_Read(disk, file, sizeof(FAT_DirectoryEntry), dirEntry) == sizeof(FAT_DirectoryEntry); + +} +void FAT_Close(FAT_File far* file) { + if (file->Handle == ROOT_DIRECTORY_HANDLE) { + file->Position = 0; + g_Data->RootDirectory.CurrentCluster = g_Data->RootDirectory.FirstCluster; + } + else { + g_Data->OpenedFiles[file->Handle].Opened = false; + } +} + +bool FAT_FindFile(DISK* disk, FAT_File far* file, const char* name, FAT_DirectoryEntry* entryOut) { + char fatName[11]; + FAT_DirectoryEntry entry; + + // convert from name to fat name + memset(fatName, ' ', sizeof(fatName)); + const char* ext = strchr(name, '.'); + if (ext == NULL) + ext = name + 11; + for (int i = 0; i < 8 && name + i < ext; i++) + fatName[i] = toupper(name[i]); + if (ext != NULL) { + for (int i = 0; i < 3 && ext[i + 1]; i++) + fatName[i + 8] = toupper(ext[i + 1]); + } + while (FAT_ReadEntry(disk, file, &entry)) { + if (memcmp(fatName, entry.Name, 11) == 0) { + *entryOut = entry; + return true; + } + } + + return false; +} + +FAT_File far* FAT_Open(DISK* disk, const char* path) { + char name[MAX_PATH_SIZE]; // ignore leading slash if (path[0] == '/') path++; - FAT_File far* parent = NULL; - FAT_File far* current = g_Data->RootDirectory.Public; + FAT_File far* current = &g_Data->RootDirectory.Public; while (*path) { // extract next file name from path - const char * delim = strchr(path, '/'); + bool isLast = false; + const char* delim = strchr(path, '/'); if (delim != NULL) { memcpy(name, path, delim - path); name[delim - path + 1] = '\0'; - path = delim + 1 + path = delim + 1; } else { unsigned len = strlen(path); memcpy(name, path, len); name[len + 1] = '\0'; path += len; + bool isLast = true; + } + // find directory entry in current dir + FAT_DirectoryEntry entry; + if (FAT_FindFile(disk, current, name, &entry)) { + FAT_Close(current); + + // check if DIR + if (!isLast && entry.Attributes & FAT_ATTRIBUTE_DIRECTORY == 0) { + printf("FAT: %s is NOT a Directory!\r\n", name); + return NULL; + } + + // open new DIR entry + current = FAT_OpenEntry(disk, &entry); + } + else { + FAT_Close(current); + printf("FAT: %s NOT Found!", name); + return NULL; } - } -} -DirectoryEntry* findFile(const char* name) -{ - for (uint32_t i = 0; i < g_BootSector.DirEntryCount; i++) - { - if (memcmp(name, g_RootDirectory[i].Name, 11) == 0) - return &g_RootDirectory[i]; - } - return NULL; -} - -bool readFile(DirectoryEntry* fileEntry, FILE* disk, uint8_t* outputBuffer) -{ - bool ok = true; - uint16_t currentCluster = fileEntry->FirstClusterLow; - - do { - uint32_t lba = g_RootDirectoryEnd + (currentCluster - 2) * g_BootSector.SectorsPerCluster; - ok = ok && readSectors(disk, lba, g_BootSector.SectorsPerCluster, outputBuffer); - outputBuffer += g_BootSector.SectorsPerCluster * g_BootSector.BytesPerSector; - - uint32_t fatIndex = currentCluster * 3 / 2; - if (currentCluster % 2 == 0) - currentCluster = (*(uint16_t*)(g_Fat + fatIndex)) & 0x0FFF; - else - currentCluster = (*(uint16_t*)(g_Fat + fatIndex)) >> 4; - - } while (ok && currentCluster < 0x0FF8); - - return ok; -} - -int main(int argc, char** argv) -{ - if (argc < 3){ - printf("Syntax: %s \n", argv[0]); - return -1; - } - - FILE* disk = fopen(argv[1], "rb"); - if (!disk) { - fprintf(stderr, "Cannot open disk image %s!\n", argv[1]); - return -1; - } - - if (!readBootSector(disk)) { - fprintf(stderr, "Could not read boot sector!\n"); - return -2; - } - - if (!readFat(disk)) { - fprintf(stderr, "Could not read FAT!\n"); - free(g_Fat); - return -3; - } - - if (!readRootDirectory(disk)) { - fprintf(stderr, "Could not read root!\n"); - free(g_Fat); - free(g_RootDirectory); - return -4; - } - - DirectoryEntry* fileEntry = findFile(argv[2]); - if (!fileEntry) { - fprintf(stderr, "Could not locate file %s!\n", argv[2]); - free(g_Fat); - free(g_RootDirectory); - return -5; - } - - uint8_t* buffer = (uint8_t*) malloc(fileEntry->Size + g_BootSector.BytesPerSector); - if (!readFile(fileEntry, disk, buffer)) { - fprintf(stderr, "Could not read file %s!\n", argv[2]); - free(g_Fat); - free(g_RootDirectory); - free(buffer); - return -5; - } - - for (size_t i = 0; i < fileEntry->Size; i++) - { - if (isprint(buffer[i])) fputc(buffer[i], stdout); - //else printf("<%02x>", buffer[i]); - } - printf("\n"); - - free(g_Fat); - free(g_RootDirectory); - return 0; -} + return current; +} \ No newline at end of file diff --git a/src/bootloader/stage2/fat.h b/src/bootloader/stage2/fat.h index 915b6d5..8f10869 100644 --- a/src/bootloader/stage2/fat.h +++ b/src/bootloader/stage2/fat.h @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #pragma once #include "stdint.h" #include "disk.h" diff --git a/src/bootloader/stage2/main.c b/src/bootloader/stage2/main.c index 916e41e..0064fd8 100644 --- a/src/bootloader/stage2/main.c +++ b/src/bootloader/stage2/main.c @@ -5,8 +5,41 @@ \*----------------*/ #include "stdint.h" #include "stdio.h" +#include "disk.h" +#include "fat.h" + +#define VERSION "v0.0.1" void _cdecl cstart_(uint16_t bootDrive) { - puts("Loading Main System\r\n"); + + printf("Loading NANITE %s\r\n\r\n", VERSION); + + printf("Initializing FAT Driver..."); + DISK disk; + if (!DISK_Initialize(&disk, bootDrive)) { + printf("Failed!\r\nDisk Init Error!"); + goto end; + } + else { + printf("Done!\r\n"); + } + + // list files in root DIR + printf("Listing Files in Root Directory..."); + FAT_File far* fd = FAT_Open(&disk, "/"); + FAT_DirectoryEntry entry; + while (FAT_ReadEntry(&disk, fd, &entry)) { + printf(" "); + for (int i = 0; i < 11; i++) + putc(entry.Name[i]); + printf("\r\n"); + } + FAT_Close(fd); printf("Done!\r\n"); + + +end: + for (;;); } + + diff --git a/src/bootloader/stage2/memory.c b/src/bootloader/stage2/memory.c index 34c42bc..094a26c 100644 --- a/src/bootloader/stage2/memory.c +++ b/src/bootloader/stage2/memory.c @@ -11,4 +11,26 @@ int memcpy(void far* dst, const void far* src, uint16_t num) { for (uint16_t i = 0; i < num; i++) u8Dst[i] = u8Src[i]; -} \ No newline at end of file + + return dst; +} + +void far* memset (void far * ptr, int value, uint16_t num) { + uint8_t far* u8Ptr = (uint8_t far *)ptr; + + for (uint16_t i = 0; i < num; i++) + u8Ptr[i] = (uint8_t)value; + + return ptr; +} + +int memcmp(const void far* ptr1, const void far * ptr2, uint16_t num) { + const uint8_t far* u8Ptr1 = (const uint8_t far *)ptr1; + const uint8_t far* u8Ptr2 = (const uint8_t far *)ptr2; + + for (uint16_t i = 0; i < num; i++) + if (u8Ptr1[i] != u8Ptr2[i]) + return 1; + + return 0; +} diff --git a/src/bootloader/stage2/memory.h b/src/bootloader/stage2/memory.h index be97639..80c2a52 100644 --- a/src/bootloader/stage2/memory.h +++ b/src/bootloader/stage2/memory.h @@ -6,4 +6,6 @@ #pragma once #include "stdint.h" -int memcpy(void far* dst, const void far* src, uint16_t num); \ No newline at end of file +int memcpy(void far* dst, const void far* src, uint16_t num); +void far* memset(void far* ptr, int value, uint16_t num); +int memcmp(const void far* ptr1, const void far * ptr2, uint16_t num); diff --git a/src/bootloader/stage2/stdint.h b/src/bootloader/stage2/stdint.h index 6894554..4ff2be2 100644 --- a/src/bootloader/stage2/stdint.h +++ b/src/bootloader/stage2/stdint.h @@ -16,7 +16,9 @@ typedef unsigned long long int uint64_t; typedef uint8_t bool; -#define true 1 -#define false 0 +#define true 1 +#define false 0 -#define NULL ((void*)0) +#define NULL ((void*)0) +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define max(a,b) ((a) > (b) ? (a) : (b)) diff --git a/src/bootloader/stage2/stdio.c b/src/bootloader/stage2/stdio.c index 123e41c..9ae959f 100644 --- a/src/bootloader/stage2/stdio.c +++ b/src/bootloader/stage2/stdio.c @@ -51,7 +51,7 @@ void _cdecl printf(const char* fmt, ...) { case PRINTF_STATE_NORMAL: switch (*fmt) { - case '%': state = PRINTF_STATE_NORMAL; + case '%': state = PRINTF_STATE_LENGTH; break; default: putc(*fmt); break; diff --git a/src/bootloader/stage2/string.c b/src/bootloader/stage2/string.c index 8a86be8..8361098 100644 --- a/src/bootloader/stage2/string.c +++ b/src/bootloader/stage2/string.c @@ -46,4 +46,4 @@ unsigned strlen(const char* 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 63974fc..4f36582 100644 --- a/src/bootloader/stage2/string.h +++ b/src/bootloader/stage2/string.h @@ -7,4 +7,4 @@ const char* strchr(const char* str, char chr); char* strcpy(char* dst, const char* src); -unsigned strlen(const char* str); \ No newline at end of file +unsigned strlen(const char* str); diff --git a/src/bootloader/stage2/utility.c b/src/bootloader/stage2/utility.c index d170209..00e44b9 100644 --- a/src/bootloader/stage2/utility.c +++ b/src/bootloader/stage2/utility.c @@ -1,3 +1,8 @@ +/*----------------*\ +|Nanite OS | +|Copyright (C) 2024| +|Tyler McGurrin | +\*----------------*/ #include "utility.h" uint32_t align(uint32_t number, uint32_t alignTo) { diff --git a/src/bootloader/stage2/x86.asm b/src/bootloader/stage2/x86.asm index 91b0988..dae2362 100644 --- a/src/bootloader/stage2/x86.asm +++ b/src/bootloader/stage2/x86.asm @@ -36,6 +36,31 @@ __U4D: shr edx, 16 ret +; +; U4M +; +; Operation: Interger 4 Byte Multiplication +; Inputs: DX;AX INT M1 +; CX;BX INT M2 +; Outputs: DX;AX Product +; Volatile: CX;BX Destroyed +; +global __U4M +__U4M: + shl edx, 16 ;DX to upper 1/2 of EDX + mov dx, ax + mov eax, edx + + shl ecx, 16 + mov cx, bx + + mul ecx + mov edx, eax + shr edx, 16 + + ret + + ; ;void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotentOut, uint32_t* remainderOut); diff --git a/write.sh b/write.sh old mode 100644 new mode 100755 index ab54ab6..d307b57 --- a/write.sh +++ b/write.sh @@ -7,7 +7,7 @@ sudo make echo --------- echo Finished! echo --------- -read -p "Do you want to write the IMG to Floppy? (/dev/sdb) (Y/n) " yn +read -p "Do you want to write the IMG to Floppy? (/dev/sdc) (y/n) " yn case $yn in y ) @@ -15,7 +15,7 @@ case $yn in echo Writing IMG to Floppy echo --------------------- - sudo dd if=./build/main_floppy.img of=/dev/sdb + sudo dd if=./build/main_floppy.img of=/dev/sdc status=progress echo --------- echo Finished!