Finish and Fix FAT Driver

This commit is contained in:
Tyler McGurrin 2024-12-16 09:24:22 -05:00
parent 473dac80f2
commit ebaffb85ad
15 changed files with 254 additions and 208 deletions

View File

@ -18,11 +18,12 @@ floppy_image: $(BUILD_DIR)/main_floppy.img
$(BUILD_DIR)/main_floppy.img: bootloader kernel $(BUILD_DIR)/main_floppy.img: bootloader kernel
dd if=/dev/zero of=$(BUILD_DIR)/main_floppy.img bs=512 count=2880 dd if=/dev/zero of=$(BUILD_DIR)/main_floppy.img bs=512 count=2880
mkfs.fat -F 12 -n "Nanite" $(BUILD_DIR)/main_floppy.img mkfs.fat -F 12 -n "NANITE" $(BUILD_DIR)/main_floppy.img
dd if=$(BUILD_DIR)/stage1.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc dd if=$(BUILD_DIR)/stage1.bin of=$(BUILD_DIR)/main_floppy.img conv=notrunc
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin" mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/stage2.bin "::stage2.bin"
mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin" mcopy -i $(BUILD_DIR)/main_floppy.img $(BUILD_DIR)/kernel.bin "::kernel.bin"
mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::test.txt" mmd -i $(BUILD_DIR)/main_floppy.img "::misc"
mcopy -i $(BUILD_DIR)/main_floppy.img test.txt "::misc/test.txt"
# #
# Bootloader # Bootloader

View File

@ -19,8 +19,8 @@ isLittleEndian = TRUE
DefaultAsmLines = 512 DefaultAsmLines = 512
DumpWSIndex = 0 DumpWSIndex = 0
DockOrder = 0x123 DockOrder = 0x123
ListWidthPix[0] = 179 ListWidthPix[0] = 486
ListWidthPix[1] = 248 ListWidthPix[1] = 667
ListWidthPix[2] = 283 ListWidthPix[2] = 763
MainWindow = 0, 0, 714, 500 MainWindow = 0, 0, 1280, 500
FontName = Normal FontName = Normal

0
debug.sh Normal file → Executable file
View File

View File

@ -1,9 +1,9 @@
BUILD_DIR?=build/ BUILD_DIR?=build/
ASM?=nasm ASM?=nasm
ASMFLAGS?=-f obj ASMFLAGS?=-f obj
CC16?=/opt/watcom/binl/wcc CC16?=/usr/bin/watcom/binl/wcc
CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq -za99 # -oneatxzh CFLAGS16?=-4 -d3 -s -wx -ms -zl -zq -za99 # -oneatxzh
LD16?=/opt/watcom/binl/wlink LD16?=/usr/bin/watcom/binl/wlink
SOURCES_C=$(wildcard *.c) SOURCES_C=$(wildcard *.c)
SOURCES_ASM=$(wildcard *.asm) SOURCES_ASM=$(wildcard *.asm)

View File

@ -15,8 +15,8 @@ bool DISK_Initialize(DISK* disk, uint8_t driveNumber) {
return false; return false;
disk->id = driveNumber; disk->id = driveNumber;
disk->cylinders = cylinders; disk->cylinders = cylinders + 1;
disk->heads = heads; disk->heads = heads + 1;
disk->sectors = sectors; disk->sectors = sectors;
return true; return true;

View File

@ -112,7 +112,7 @@ bool FAT_Initialize(DISK* disk) {
g_Data->RootDirectory.Public.Position = 0; g_Data->RootDirectory.Public.Position = 0;
g_Data->RootDirectory.Public.Size = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount; g_Data->RootDirectory.Public.Size = sizeof(FAT_DirectoryEntry) * g_Data->BS.BootSector.DirEntryCount;
g_Data->RootDirectory.Opened = true; g_Data->RootDirectory.Opened = true;
g_Data->RootDirectory.FirstCluster = 0; g_Data->RootDirectory.FirstCluster = rootDirLba;
g_Data->RootDirectory.CurrentCluster = 0; g_Data->RootDirectory.CurrentCluster = 0;
g_Data->RootDirectory.CurrentSectorInCluster = 0; g_Data->RootDirectory.CurrentSectorInCluster = 0;
@ -151,9 +151,9 @@ FAT_File far* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) {
// setup vars // setup vars
FAT_FileData far* fd = &g_Data->OpenedFiles[handle]; FAT_FileData far* fd = &g_Data->OpenedFiles[handle];
fd->Public.Handle = handle; fd->Public.Handle = handle;
fd->Public.IsDirectory = (entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0;\ fd->Public.IsDirectory = (entry->Attributes & FAT_ATTRIBUTE_DIRECTORY) != 0;
fd->Public.Position = 0; fd->Public.Position = 0;
fd->Public.Size = 0; fd->Public.Size = entry->Size;
fd->FirstCluster = entry->FirstClusterLow + ((uint32_t)entry->FirstClusterHigh << 16); fd->FirstCluster = entry->FirstClusterLow + ((uint32_t)entry->FirstClusterHigh << 16);
fd->CurrentCluster = fd->FirstCluster; fd->CurrentCluster = fd->FirstCluster;
fd->CurrentSectorInCluster = 0; fd->CurrentSectorInCluster = 0;
@ -170,9 +170,9 @@ FAT_File far* FAT_OpenEntry(DISK* disk, FAT_DirectoryEntry* entry) {
uint32_t FAT_NextCluster(uint32_t currentCluster) { uint32_t FAT_NextCluster(uint32_t currentCluster) {
uint32_t fatIndex = currentCluster * 3 / 2; uint32_t fatIndex = currentCluster * 3 / 2;
if (currentCluster % 2 == 0) if (currentCluster % 2 == 0)
return (*(uint16_t*)(g_Fat + fatIndex)) & 0x0FFF; return (*(uint16_t far*)(g_Fat + fatIndex)) & 0x0FFF;
else else
return (*(uint16_t*)(g_Fat + fatIndex)) >> 4; return (*(uint16_t far*)(g_Fat + fatIndex)) >> 4;
} }
@ -185,19 +185,19 @@ uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* data
uint8_t* u8DataOut = (uint8_t*)dataOut; uint8_t* u8DataOut = (uint8_t*)dataOut;
// don't read past EOF // don't read past EOF
if (!fd->Public.IsDirectory)
byteCount = min(byteCount, fd->Public.Size - fd->Public.Position); byteCount = min(byteCount, fd->Public.Size - fd->Public.Position);
while (byteCount > 0) { while (byteCount > 0) {
uint32_t leftInBuffer = SECTOR_SIZE - (fd->Public.Position % SECTOR_SIZE); uint32_t leftInBuffer = SECTOR_SIZE - (fd->Public.Position % SECTOR_SIZE);
uint32_t take = min(byteCount, leftInBuffer); uint32_t take = min(byteCount, leftInBuffer);
memcpy(u8DataOut, fd->Buffer + fd->Public.Position % SECTOR_SIZE, take); memcpy(u8DataOut, fd->Buffer + fd->Public.Position % SECTOR_SIZE, take);
u8DataOut += take; u8DataOut += take;
fd->Public.Position += take; fd->Public.Position += take;
byteCount -= take; byteCount -= take;
// see if we need to read more data // see if we need to read more data
if (byteCount > 0) { if (leftInBuffer == take) {
// root dir handler // root dir handler
if (fd->Public.Handle == ROOT_DIRECTORY_HANDLE) { if (fd->Public.Handle == ROOT_DIRECTORY_HANDLE) {
++fd->CurrentCluster; ++fd->CurrentCluster;
@ -215,7 +215,8 @@ uint32_t FAT_Read(DISK* disk, FAT_File far* file, uint32_t byteCount, void* data
fd->CurrentCluster = FAT_NextCluster; fd->CurrentCluster = FAT_NextCluster;
} }
if (fd->CurrentCluster >= 0x0FF8) { if (fd->CurrentCluster >= 0x0FF8) {
printf("FAT: Read Error, Invalid Next Cluster!\r\n"); // mark EOF
fd->Public.Size = fd.Public.Position;
break; break;
} }
@ -254,7 +255,7 @@ bool FAT_FindFile(DISK* disk, FAT_File far* file, const char* name, FAT_Director
const char* ext = strchr(name, '.'); const char* ext = strchr(name, '.');
if (ext == NULL) if (ext == NULL)
ext = name + 11; ext = name + 11;
for (int i = 0; i < 8 && name + i < ext; i++) for (int i = 0; i < 8 && name[i] && name + i < ext; i++)
fatName[i] = toupper(name[i]); fatName[i] = toupper(name[i]);
if (ext != NULL) { if (ext != NULL) {
for (int i = 0; i < 3 && ext[i + 1]; i++) for (int i = 0; i < 3 && ext[i + 1]; i++)

View File

@ -8,35 +8,56 @@
#include "disk.h" #include "disk.h"
#include "fat.h" #include "fat.h"
void far* g_data = (void far*)0x00500200;
#define LOGO " _ _____ _ __________________\r\n / | / / | / | / / _/_ __/ ____/\r\n / |/ / /| | / |/ // / / / / __/ \r\n / /| / ___ |/ /| // / / / / /___ \r\n\\/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \r\n"
#define VERSION "v0.0.1" #define VERSION "v0.0.1"
void _cdecl cstart_(uint16_t bootDrive) { void _cdecl cstart_(uint16_t bootDrive) {
printf("%s", LOGO);
printf("Loading NANITE %s\r\n\r\n", VERSION); printf(" %s\r\n--------------------------------------\r\n", VERSION);
printf("Initializing FAT Driver..."); printf("Initializing FAT Driver...");
DISK disk; DISK disk;
if (!DISK_Initialize(&disk, bootDrive)) { if (!DISK_Initialize(&disk, bootDrive)) {
printf("Failed!\r\nDisk Init Error!"); printf("Failed!\r\nDisk Initialization Error\r\n");
goto end; goto end;
} }
else {
printf("Done!\r\n");
}
// list files in root DIR DISK_ReadSectors(&disk, 19, 1, g_data);
printf("Listing Files in Root Directory...");
if (!FAT_Initialize(&disk)) {
printf("Failed!\r\nDisk Initialization Error\r\n");
goto end;
}
printf("Done!\r\n");
// printf("Listing Root DIR...\r\n");
// // browse files in root
FAT_File far* fd = FAT_Open(&disk, "/"); FAT_File far* fd = FAT_Open(&disk, "/");
FAT_DirectoryEntry entry; FAT_DirectoryEntry entry;
while (FAT_ReadEntry(&disk, fd, &entry)) { int i = 0;
printf(" "); // while (FAT_ReadEntry(&disk, fd, &entry) && i++ < 5) {
for (int i = 0; i < 11; i++) // printf(" ");
putc(entry.Name[i]); // for (int i = 0; i < 11; i++)
printf("\r\n"); // putc(entry.Name[i]);
// printf("\r\n");
// }
// FAT_Close(fd);
printf("Testing FAT Driver...");
// read test.txt
char buffer[100];
uint32_t read;
fd = FAT_Open(&disk, "misc/test.txt");
while ((read = FAT_Read(&disk, fd, sizeof(buffer), buffer)))
{
for (uint32_t i = 0; i < read; i++)
{
if (buffer[i] == '\n')
putc('\r');
putc(buffer[i]);
}
} }
FAT_Close(fd); FAT_Close(fd);
printf("Done!\r\n");
end: end:
for (;;); for (;;);

View File

@ -5,15 +5,15 @@
\*----------------*/ \*----------------*/
#pragma once #pragma once
// 0x00000000 - 0x000003FF - int vector table // 0x00000000 - 0x000003FF - interrupt vector table
// 0x00000400 - 0x000004FF - Bios Data // 0x00000400 - 0x000004FF - BIOS data area
#define MEMORY_MIN 0x00000500 #define MEMORY_MIN 0x00000500
#define MEMORY_MAX 0x00080000 #define MEMORY_MAX 0x00080000
// 0x00000500 - 0x00010500 - FAT Driver // 0x00000500 - 0x00010500 - FAT driver
#define MEMORY_FAT_ADDR ((void far*)0x00500000) // segment:offset SSSS:OOOO #define MEMORY_FAT_ADDR ((void far*)0x00500000) // segment:offset (SSSSOOOO)
#define MEMORY_FAT_SIZE 0x00010500 #define MEMORY_FAT_SIZE 0x00010000
// 0x00020000 - 0x00030000 - stage2 // 0x00020000 - 0x00030000 - stage2

View File

@ -5,7 +5,7 @@
\*----------------*/ \*----------------*/
#include "memory.h" #include "memory.h"
int memcpy(void far* dst, const void far* src, uint16_t num) { void far* memcpy(void far* dst, const void far* src, uint16_t num) {
uint8_t far* u8Dst = (uint8_t far *)dst; uint8_t far* u8Dst = (uint8_t far *)dst;
const uint8_t far* u8Src = (const uint8_t far *)src; const uint8_t far* u8Src = (const uint8_t far *)src;

View File

@ -6,6 +6,6 @@
#pragma once #pragma once
#include "stdint.h" #include "stdint.h"
int memcpy(void far* dst, const void far* src, uint16_t num); void far* memcpy(void far* dst, const void far* src, uint16_t num);
void far* memset(void far* ptr, int value, 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); int memcmp(const void far* ptr1, const void far * ptr2, uint16_t num);

View File

@ -16,8 +16,8 @@ typedef unsigned long long int uint64_t;
typedef uint8_t bool; typedef uint8_t bool;
#define true 1
#define false 0 #define false 0
#define true 1
#define NULL ((void*)0) #define NULL ((void*)0)
#define min(a,b) ((a) < (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b))

View File

@ -7,6 +7,7 @@ bits 16
section _TEXT class=CODE section _TEXT class=CODE
; ;
; U4D ; U4D
; ;
@ -36,57 +37,56 @@ __U4D:
shr edx, 16 shr edx, 16
ret ret
; ;
; U4M ; U4M
; ; Operation: integer four byte multiply
; Operation: Interger 4 Byte Multiplication ; Inputs: DX;AX integer M1
; Inputs: DX;AX INT M1 ; CX;BX integer M2
; CX;BX INT M2 ; Outputs: DX;AX product
; Outputs: DX;AX Product ; Volatile: CX, BX destroyed
; Volatile: CX;BX Destroyed
; ;
global __U4M global __U4M
__U4M: __U4M:
shl edx, 16 ;DX to upper 1/2 of EDX shl edx, 16 ; dx to upper half of edx
mov dx, ax mov dx, ax ; m1 in edx
mov eax, edx mov eax, edx ; m1 in eax
shl ecx, 16 shl ecx, 16 ; cx to upper half of ecx
mov cx, bx mov cx, bx ; m2 in ecx
mul ecx mul ecx ; result in edx:eax (we only need eax)
mov edx, eax mov edx, eax ; move upper half to dx
shr edx, 16 shr edx, 16
ret ret
; ;
;void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotentOut, uint32_t* remainderOut); ; void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
; ;
global _x86_div64_32 global _x86_div64_32
_x86_div64_32: _x86_div64_32:
; make new call frame ; make new call frame
push bp ; save old call frame push bp ; save old call frame
mov bp, sp ;init new call frame mov bp, sp ; initialize new call frame
push bx push bx
; divide upper 32 bits ; divide upper 32 bits
mov eax, [bp + 4] ;eax is upper 32 bits of divedend mov eax, [bp + 8] ; eax <- upper 32 bits of dividend
mov ecx, [bp + 12] ;ecx is the divisor mov ecx, [bp + 12] ; ecx <- divisor
xor edx, edx xor edx, edx
div ecx ; eax - quot, edx - remainder div ecx ; eax - quot, edx - remainder
;store upper 32 bits ; store upper 32 bits of quotient
mov ebx, [bp + 16] mov bx, [bp + 16]
mov [bx + 4], eax mov [bx + 4], eax
; divide lower 32 bits ; divide lower 32 bits
mov eax, [bp + 4] ;eax is the lower 32 bits of the dividend mov eax, [bp + 4] ; eax <- lower 32 bits of dividend
;edx is old remainder ; edx <- old remainder
div ecx div ecx
; store results ; store results
@ -101,25 +101,35 @@ _x86_div64_32:
pop bp pop bp
ret ret
;
; int 10h ah=0Eh
; args: character, page
;
global _x86_Video_WriteCharTeletype global _x86_Video_WriteCharTeletype
_x86_Video_WriteCharTeletype: _x86_Video_WriteCharTeletype:
push bp ; make new call frame
mov bp,sp push bp ; save old call frame
mov bp, sp ; initialize new call frame
; save bx
push bx push bx
; [bp + 0] - old call frame
; [bp + 2] - return address (small memory model => 2 bytes)
; [bp + 4] - first argument (character)
; [bp + 6] - second argument (page)
; note: bytes are converted to words (you can't push a single byte on the stack)
mov ah, 0Eh mov ah, 0Eh
mov al, [bp + 4] mov al, [bp + 4]
mov bh, [bp + 6] mov bh, [bp + 6]
int 10h int 10h
; restore bx
pop bx pop bx
; restore old call frame
mov sp, bp mov sp, bp
pop bp pop bp
ret ret
@ -130,17 +140,18 @@ _x86_Video_WriteCharTeletype:
; ;
global _x86_Disk_Reset global _x86_Disk_Reset
_x86_Disk_Reset: _x86_Disk_Reset:
; make new call frame ; make new call frame
push bp ; save old call frame push bp ; save old call frame
mov bp, sp ;init new call frame mov bp, sp ; initialize new call frame
mov ah, 0 mov ah, 0
mov dl, [bp + 4] ; dl - drive mov dl, [bp + 4] ; dl - drive
std stc
int 13h int 13h
mov ax, 1 mov ax, 1
sbb ax, 0 ; 1 is true 0 is false sbb ax, 0 ; 1 on success, 0 on fail
; restore old call frame ; restore old call frame
mov sp, bp mov sp, bp
@ -151,43 +162,53 @@ _x86_Disk_Reset:
; ;
; bool _cdecl x86_Disk_Read(uint8_t drive, ; bool _cdecl x86_Disk_Read(uint8_t drive,
; uint16_t cylinder, ; uint16_t cylinder,
; uint16_t head,
; uint16_t sector, ; uint16_t sector,
; uint16_t head,
; uint8_t count, ; uint8_t count,
; uint8_t far * dataout); ; void far * dataOut);
; ;
global _x86_Disk_Read global _x86_Disk_Read
_x86_Disk_Read: _x86_Disk_Read:
; make new call frame ; make new call frame
push bp ; save old call frame push bp ; save old call frame
mov bp, sp ;init new call frame mov bp, sp ; initialize new call frame
; save modified regs
push bx
push es
; setup args ; setup args
mov dl, [bp + 4] ; dl - drive mov dl, [bp + 4] ; dl - drive
mov ch, [bp + 6] ; ch - cylinder (lower 8 bits) mov ch, [bp + 6] ; ch - cylinder (lower 8 bits)
mov cl, [bp + 7]; cl - cylinder to to bits 6-7 mov cl, [bp + 7] ; cl - cylinder to bits 6-7
shl cl, 6 shl cl, 6
mov dh, [bp + 10]; dh - head mov al, [bp + 8] ; cl - sector to bits 0-5
mov al, [bp + 8]; cl - sectory to bits 0-5
and al, 3Fh and al, 3Fh
or cl, al or cl, al
mov al, [bp + 12]; count mov dh, [bp + 10] ; dh - head
mov al, [bp + 12] ; al - count
mov bx, [bp + 16] ; es:bx - far pointer to data out mov bx, [bp + 16] ; es:bx - far pointer to data out
mov es, bx mov es, bx
mov bx, [bp + 14] mov bx, [bp + 14]
; call ; call int13h
mov al, 02h mov ah, 02h
std stc
int 13h int 13h
; set return value
mov ax, 1 mov ax, 1
sbb ax, 0 ; 1 is true 0 is false sbb ax, 0 ; 1 on success, 0 on fail
; restore regs
pop es
pop bx
; restore old call frame ; restore old call frame
mov sp, bp mov sp, bp
@ -195,17 +216,19 @@ _x86_Disk_Read:
ret ret
;
; bool _cdelc x86_Disk_GetDriveParams(uint8_t drive, ; bool _cdecl x86_Disk_GetDriveParams(uint8_t drive,
; uint8_t* driveTypeOut, ; uint8_t* driveTypeOut,
; uint16_t* cylindersOut, ; uint16_t* cylindersOut,
; uint16_t* sectorsOut, ; uint16_t* sectorsOut,
; uint16_t* headsOut); ; uint16_t* headsOut);
;
global _x86_Disk_GetDriveParams global _x86_Disk_GetDriveParams
_x86_Disk_GetDriveParams: _x86_Disk_GetDriveParams:
; make new call frame ; make new call frame
push bp ; save old frame push bp ; save old call frame
mov bp, sp ; init new frame mov bp, sp ; initialize new call frame
; save regs ; save regs
push es push es
@ -214,7 +237,7 @@ _x86_Disk_GetDriveParams:
push di push di
; call int13h ; call int13h
mov dl, [bp + 4] ;dl - drive mov dl, [bp + 4] ; dl - disk drive
mov ah, 08h mov ah, 08h
mov di, 0 ; es:di - 0000:0000 mov di, 0 ; es:di - 0000:0000
mov es, di mov es, di
@ -226,21 +249,21 @@ _x86_Disk_GetDriveParams:
sbb ax, 0 sbb ax, 0
; out params ; out params
mov si, [bp + 6] ; drive type mov si, [bp + 6] ; drive type from bl
mov [si], bl mov [si], bl
mov bl, ch ; cyl - lower bits in ch mov bl, ch ; cylinders - lower bits in ch
mov bh, cl ; cyl - upper bits in ch (6-7) mov bh, cl ; cylinders - upper bits in cl (6-7)
shr bh, 6 shr bh, 6
mov si, [bp + 8] mov si, [bp + 8]
mov [si], bx mov [si], bx
xor ch, ch ; sectors - lower 5 bits of cl xor ch, ch ; sectors - lower 5 bits in cl
and cl, 3Fh and cl, 3Fh
mov si, [bp + 10] mov si, [bp + 10]
mov [si], cx mov [si], cx
mov cl, dh mov cl, dh ; heads - dh
mov si, [bp + 12] mov si, [bp + 12]
mov [si], cx mov [si], cx

View File

@ -6,7 +6,7 @@
#pragma once #pragma once
#include "stdint.h" #include "stdint.h"
void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotentOut, uint32_t* remainderOut); void _cdecl x86_div64_32(uint64_t dividend, uint32_t divisor, uint64_t* quotientOut, uint32_t* remainderOut);
void _cdecl x86_Video_WriteCharTeletype(char c, uint8_t page); void _cdecl x86_Video_WriteCharTeletype(char c, uint8_t page);
@ -17,7 +17,7 @@ bool _cdecl x86_Disk_Read(uint8_t drive,
uint16_t sector, uint16_t sector,
uint16_t head, uint16_t head,
uint8_t count, uint8_t count,
void far * dataout); void far * dataOut);
bool _cdecl x86_Disk_GetDriveParams(uint8_t drive, bool _cdecl x86_Disk_GetDriveParams(uint8_t drive,
uint8_t* driveTypeOut, uint8_t* driveTypeOut,

View File

@ -1 +1 @@
this is text test har har har har *insert meme here* har har har Done!