diff --git a/doc/flatfs.md b/doc/flatfs.md index e99ed358..6c81f0f4 100644 --- a/doc/flatfs.md +++ b/doc/flatfs.md @@ -12,16 +12,14 @@ OEMName : array[0..7] of char; version : uint16 // numerical version of filesystem sectorCount : uint16; fileCount : uint16 -signature : uint32 = 0xABAB1F1E +signature : uint32 = 0x0B00B1E5 the Rest of the sector is reserved --- -Starting from sector 1 is the file table. Table size is determined by entry size (512) * fileCount - - +Starting from sector 1 is the file table. Table size is determined by entry size (64) * fileCount --- ####File entry @@ -30,4 +28,5 @@ name : array[0..59] of char //file name max 60 chars fileStart : 16bit // start sector of data fileSize : 16bit // data size in sectors ---- \ No newline at end of file +--- + diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index fb7b1153..1dec9787 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -446,7 +446,8 @@ var begin push_trace('IDE.dread'); for i:=0 to sectorCount-1 do begin - readPIO28(device^.controllerId0, LBA, puint8(@buffer[512*i])); + readPIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); + psleep(100) end; end; @@ -455,7 +456,8 @@ var i : uint16; begin for i:=0 to sectorCount-1 do begin - writePIO28(device^.controllerId0, LBA, puint8(@buffer[512*i])); + writePIO28(device^.controllerId0, LBA + i, puint8(@buffer[512*i])); + psleep(100) end; // writePIO28(device^.controllerId0, LBA, puint8(buffer)); end; diff --git a/src/driver/storage/drivemanager.pas b/src/driver/storage/drivemanager.pas index 3c0e496b..2286b881 100644 --- a/src/driver/storage/drivemanager.pas +++ b/src/driver/storage/drivemanager.pas @@ -95,18 +95,21 @@ var i : uint32 = 0; begin + push_trace('DriverManager.format_command'); //format spc:= puint32(kalloc(4)); spc^:= 1; + push_trace('DriverManager.format_command.0'); + //get drive from index/id driveIndex:= stringToInt( getParam(1, params) ); drive:= PStorage_Device(LL_Get(storageDevices, driveIndex)); filesystemString := getParam(2, params); - sectorCount := stringToInt( getParam(4, params) ); + sectorCount := stringToInt( getParam(3, params) ); // if sector count is 0, use full drive if sectorCount = 0 then begin @@ -114,11 +117,14 @@ begin end; //create MBR if none, and partition table - mb := PMaster_Boot_Record(kalloc(sizeof(TMaster_Boot_Record))); + mb := PMaster_Boot_Record(kalloc(sizeof(TMaster_Boot_Record)*2)); + memset(uint32(mb), 0, sizeof(TMaster_Boot_Record)); drive^.readCallback(drive, 0, 1, PuInt32(mb)); //check if MBR exists - if not mb^.boot_sector = $55AA then begin + if (mb^.boot_sector <> $55AA)then begin + + writestringlnWND('Creating MBR', getTerminalHWND()); //create MBR mb^.signature := $A570 + drive^.id; @@ -130,6 +136,20 @@ begin //write MBR drive^.writeCallback(drive, 0, 1, puint32(mb)); + end else begin + + writestringlnWND('MBR already exists', getTerminalHWND()); + + //write first partiton sectorStart and sectorCount + writeintlnWND(mb^.partition[0].LBA_start, getTerminalHWND()); + writeintlnWND(mb^.partition[0].sector_count, getTerminalHWND()); + + //create partition table + mbr.setup_partition(@mb^.partition[0], 2, sectorCount); + + //write MBR + drive^.writeCallback(drive, 0, 1, puint32(mb)); + end; kfree(puint32(mb)); @@ -176,19 +196,23 @@ var begin push_trace('DriverManager.drive_command'); subcmd:= getParam(0, params); + push_trace('DriverManager.drive_command.0'); if ((paramCount(params) = 0)) then begin console.writestringlnWnd('Please provide valid arguments.', getTerminalHWND()); console.writestringlnWnd(' ls - for listing all drives', getTerminalHWND()); console.writestringlnWnd(' info [drive] - display formation for specified drive', getTerminalHWND()); console.writestringlnWnd(' init [drive] - destructive, formats a drive with a blank partition', getTerminalHWND()); + console.writestringlnWnd(' format [drive] [filesystem] [size (0 for max)] - destructive, formats a drive with MBR and volume', getTerminalHWND()); exit; end; + push_trace('DriverManager.drive_command.1'); if( stringEquals(subcmd, 'ls') ) then begin list_drive_command(); exit; end; + push_trace('DriverManager.drive_command.2'); if( stringEquals(subcmd, 'info') ) then begin console.writestringWnd('Disk: ', getTerminalHWND()); @@ -196,14 +220,22 @@ begin console.writestringWnd('Capacity: ', getTerminalHWND()); console.writeintlnWND(1, getTerminalHWND()); - //TODO impliement - exit + //TODO impliment + exit; end; if( stringEquals(subcmd, 'init') ) then begin init_drive_command(stringToInt(getParam(1, params) ) ); - exit + exit; end; + push_trace('DriverManager.drive_command.3'); + + if( stringEquals(subcmd, 'format') ) then begin + format_command(params); + exit; + end; + push_trace('DriverManager.drive_command.4'); + end; { Initialise the drive manager } diff --git a/src/driver/storage/fat32.pas b/src/driver/storage/fat32.pas index 5f65475b..bd3c9e64 100644 --- a/src/driver/storage/fat32.pas +++ b/src/driver/storage/fat32.pas @@ -91,7 +91,7 @@ var filesystem : TFilesystem; procedure init; -procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32); +procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32); procedure detect_volumes(disk : PStorage_Device); //function writeDirectory(volume : PStorage_volume; directory : pchar; attributes : uint32) : uint8; // need to handle parent table cluster overflow, need to take attributes //function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error @@ -753,7 +753,7 @@ end; //TODO check directory commands for errors with a clean disk -procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32); +procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32); var buffer : puint32; bt: puint32; @@ -774,9 +774,18 @@ var programFileArray : byteArray8 = ('P','R','O','G','R','A','M','S'); rootCluster : uint32 = 1; + sysArray : byteArray8 = ('S','Y','S','T','E','M',' ',' '); + progArray : byteArray8 = ('P','R','O','G','R','A','M','S'); + userArray : byteArray8 = ('U','S','E','R',' ',' ',' ',' '); + + status : puint32; + disk : PStorage_device; + begin //maybe increase buffer size by one? push_trace('fat32.create_volume()'); + disk := volume^.device; + // zeroBuffer:= puint32(kalloc( disk^.sectorSize * 4 )); // memset(uint32(zeroBuffer), 0, disk^.sectorSize * 4); @@ -813,7 +822,7 @@ begin //maybe increase buffer size by one? bootRecord^.jmp2boot := $0; //TODO impliment boot jump bootRecord^.OEMName := asuroArray; bootRecord^.sectorSize := disk^.sectorsize; - bootRecord^.spc := config^; + bootRecord^.spc := 1; bootRecord^.rsvSectors := 32; //32 is standard bootRecord^.numFats := 1; bootRecord^.mediaDescp := $F8; @@ -875,8 +884,16 @@ begin //maybe increase buffer size by one? disk^.writecallback(disk, dataStart + (config^ * rootCluster), 1, buffer); + memset(uint32(buffer), 0, disk^.sectorsize); + + status := puint32(kalloc(sizeof(uint32))); + writeDirectory(volume, '', sysArray, $10, status, ''); + + kfree(buffer); + + end; procedure detect_volumes(disk : PStorage_Device); @@ -926,7 +943,6 @@ begin filesystem.detectcallback:= @detect_volumes; filesystem.writecallback:= @writeFile; filesystem.readcallback := @readFile; - // filesystem.formatVolumeCallback := @create_volume; volumemanager.register_filesystem(@filesystem); end; diff --git a/src/driver/storage/flatfs.pas b/src/driver/storage/flatfs.pas index eaba5305..848806bb 100644 --- a/src/driver/storage/flatfs.pas +++ b/src/driver/storage/flatfs.pas @@ -25,7 +25,13 @@ interface uses tracer, strings, - volumemanager; + volumemanager, + lists, + console, + terminal, + storagetypes, + lmemorymanager, + util; type @@ -35,14 +41,15 @@ type version: uint16; sectorCount : uint16; fileCount : uint16; - signature : uint32 = $0B00B1E5; + signature : uint32; end; PDisk_Info = ^TDisk_Info; - TFile_Entry = packed record - name: array[0..59] of char; - size: uint16; - start : uint16; + TFile_Entry = bitpacked record + attribues : uint8; // 0x00 = does not exsist, 0x01 = file, 0x02 = hidden, 0x04 = system/read only, 0x10 = directory, 0x20 = archive + name: array[0..54] of char; //max file name length is 55 + size: uint32; + start : uint32; end; PFile_Entry = ^TFile_Entry; @@ -51,11 +58,344 @@ var procedure init; -procedure create_volume(disk : PStorage_Device; sectors : uint32; start : uint32; config : puint32); +procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32); procedure detect_volumes(disk : PStorage_Device); - +function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase; + implementation +procedure create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : puint32); +var + info : PDisk_Info; + entryTable : PFile_Entry; + i : uint32; + + directories : PLinkedListBase; + status : PuInt32; + +const + asuroArray : array[0..7] of char = 'ASURO'; + systemArray : array[0..6] of char = '/system'; + programsArray : array[0..8] of char = '/programs'; + userArray : array[0..4] of char = '/user'; +begin + + info := PDisk_Info(Kalloc(512)); + memset(uint32(info), 0, 512); + + info^.jmp2boot := $0; + info^.OEMName := asuroArray; + info^.version := 1; + info^.sectorCount := sectors; + info^.fileCount := 1000; + info^.signature := $0B00B1E5; + + if config^ <> 0 then begin + info^.fileCount := config^; + end; + + volume^.device^.writeCallback(volume^.device, start, 1, PuInt32(info));// what happens if buffer is smaller than 512? + + // create file table + entryTable := PFile_Entry(Kalloc(126 * 512)); + memset(uint32(entryTable), 0, 126 * 512); + + //create system folders + entryTable[0].attribues := $10; + memcpy(uint32(@systemArray), uint32(@entryTable[0].name), 7); + entryTable[0].size := 0; + entryTable[0].start := 0; + + entryTable[1].attribues := $10; + memcpy(uint32(@programsArray), uint32(@entryTable[1].name), 9); + entryTable[1].size := 0; + entryTable[1].start := 0; + + entryTable[2].attribues := $10; + memcpy(uint32(@userArray), uint32(@entryTable[2].name), 5); + entryTable[2].size := 0; + entryTable[2].start := 0; + + //write file table + // volume^.device^.writeCallback(volume^.device, start + 1, ((sizeof(TFile_Entry) * info^.fileCount) div 512), puint32(entryTable)); + volume^.device^.writeCallback(volume^.device, start + 1, 1, puint32(entryTable)); + + //temp read + status := PuInt32(Kalloc(sizeof(uint32))); + directories := read_directory(volume, '/', status); +end; + +procedure write_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32); +var + directories : PLinkedListBase; + i : uint32; + + fileEntry : PFile_Entry; + buffer : PuInt32; + + position : uint32; + offset : uint32; + +const + fileCount : uint32 = 1000; +begin + status^ = 0; + + directories := read_directory(volume, directory, status); + + if status^ = 0 then begin + for i := 0 to fileCount - 1 do begin + fileEntry := PFile_Entry(LL_Get(directories, i)); + + if fileEntry^.attribues = 0 then begin + fileEntry^.attribues := $10; + fileEntry^.size := 0; + fileEntry^.start := 0; + memcpy(uint32(@fileEntry^.name), uint32(@directory), strlen(directory)); + + //write file table + buffer := PuInt32(Kalloc(512)); + memset(uint32(buffer), 0, 512); + + //read file table cointaining entry of interest + position := (i * sizeof(TFile_Entry)) div 512; + volume^.device^.readCallback(volume^.device, sectorStart + 1 + position, 1, buffer); + + //calculate entry offset into sector + offset := (i * sizeof(TFile_Entry)) mod 512; + offset := offset div sizeof(TFile_Entry); + + //set entry in buffer + PFile_Entry(buffer)[offset] := fileEntry^; + + //write updated file table sector + volume^.device^.writeCallback(volume^.device, sectorStart + 1 + position, 1, buffer); + + Kfree(buffer); + + break; + + end; + end; + end; + + if fileEntry^.attribues = 0 then begin + status^ := 1; + end; + + LL_Destroy(directories); +end; + +function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase; +var + directories : PLinkedListBase; + fileEntrys : PFile_Entry; + i : uint32; + + compString : PChar; + afterString : PChar; + compStringLength : uint32; + + fileCount : uint32 = 1000; + +begin + + compString := pchar(kalloc(60)); + memset(uint32(compString), 0, 60); + + afterString := pchar(kalloc(60)); + memset(uint32(afterString), 0, 60); + + directories := STRLL_New(); + + fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount)); + volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys)); + + for i := 0 to fileCount - 1 do begin + // if fileEntrys[i].attribues and $10 = $10 then begin + + writestringlnWND(fileEntrys[i].name, getterminalhwnd()); + + compString := stringSub(fileEntrys[i].name, 0, stringSize(directory)); + afterString := stringSub(fileEntrys[i].name, stringSize(directory), stringSize(fileEntrys[i].name)-1); + + if stringEquals(compString, directory) and + (not stringContains(afterString, '/')) then begin + + console.writestringlnWND(afterString, getTerminalHWND()); + STRLL_Add(directories, afterString); + end; + + // end; + end; + + Kfree(puint32(fileEntrys)); + + read_directory := directories; +end; + +procedure quicksort_start(list : PFile_Entry; begining : uint32; stop : uint32); +var + pivot : uint32; + i : uint32; + j : uint32; + temp : PLinkedListBase; + + tempFileEntry : PFile_Entry; +begin + + i:=begining; + j:=stop; + + pivot := list[(begining + stop) div 2].start; + + while i <= j do begin + while list[i].start < pivot do begin + i := i + 1; + end; + + while list[j].start > pivot do begin + j := j - 1; + end; + + if i <= j then begin + tempFileEntry := list[i]; + list[i] := list[j]; + list[j] := tempFileEntry; + + i := i + 1; + j := j - 1; + end; + end; + + if begining < j then begin + quicksort_start(list, begining, j); + end; + + if i < stop then begin + quicksort_start(list, i, stop); + end; + +end; + +function find_free_space(volume : PStorage_Volume; size : uint32; status : PuInt32) : uint32; +var + fileEntrys : PFile_Entry; + fileEntry : TFile_Entry; + i : uint32; + fileCount : uint32 = 1000; +begin + fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount)); + volume^.device^.readCallback(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys)); + + //sort file table by start address using quicksort + quicksort(fileEntrys, 0, fileCount - 1); + + //find free space big enough to fit size + for i := 0 to fileCount - 1 do begin + if fileEntrys[i+1].start - (fileEntrys[i].start + fileEntrys[i].size) > size+1 then begin + find_free_space := fileEntrys[i].start + fileEntrys[i].size; + status^ := 0; + break; + end; + end; + + Kfree(puint32(fileEntrys)); + + find_free_space := freeSpace; +end; + +procedure write_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; size : uint32; status : PuInt32); +var + directories : PLinkedListBase; + i : uint32; + + fileEntry : PFile_Entry; + buffer : PuInt32; + + position : uint32; + offset : uint32; + + fileCount : uint32 = 1000; + + exsists : boolean; +begin + + //load file table + directories := read_directory(volume, '/', status); + + + //check if file exists else find free entry + for i := 0 to fileCount - 1 do begin + fileEntry := PFile_Entry(LL_Get(directories, i)); + + if stringEquals(fileEntry^.name, fileName) then begin + exsists := true; + break; + end; + + if fileEntry^.attribues = 0 then begin + exsists := false; + break; + end; + end; + + //if entry is directory then exit + if fileEntry^.attribues and $10 = $10 then begin + status^ := 1; + exit; + end; + + //allocate file table + buffer := PuInt32(Kalloc(512)); + memset(uint32(buffer), 0, 512); + + //read file table cointaining entry of interest + position := (i * sizeof(TFile_Entry)) div 512; + volume^.device^.readCallback(volume^.device, sectorStart + 1 + position, 1, buffer); + + //calculate entry offset into sector + offset := (i * sizeof(TFile_Entry)) mod 512; + offset := offset div sizeof(TFile_Entry); + + //if file exists update entry else create new entry + if exsists then do begin + //check if size is greater than current size + if size > fileEntry^.size then begin + //find free space + fileEntry^.start := find_free_space(volume, size); + fileEntry^.size := size; + end else begin + //update size + fileEntry^.size := size; + end; + + end else begin + //find free space + fileEntry^.start := find_free_space(volume, size); + fileEntry^.size := size; + fileEntry^.attribues := $01; + + //add file name + fileEntry^.name := fileName; + + //add file to table + LL_Add(directories, fileEntry); + end; + + //write file table + volume^.device^.writeCallback(volume^.device, sectorStart + 1 + position, 1, buffer); + + //write file + volume^.device^.writeCallback(volume^.device, fileEntry^.start, size div 512 + 1, data); + + //free buffer + Kfree(puint32(buffer)); + + //free directories + LL_Free(directories); +end; + procedure detect_volumes(disk : PStorage_Device); var buffer : puint32; @@ -92,14 +432,14 @@ end; procedure init(); begin push_trace('flatfs.init()'); - filesystem.sName:= 'FlatFS'; + filesystem.sName:= 'flatfs'; filesystem.system_id:= $02; - filesystem.readDirCallback:= @readDirectoryGen; - filesystem.createDirCallback:= @writeDirectoryGen; + filesystem.readDirCallback:= @read_directory; + // filesystem.createDirCallback:= @writeDirectoryGen; filesystem.createcallback:= @create_volume; filesystem.detectcallback:= @detect_volumes; - filesystem.writecallback:= @writeFile; - filesystem.readcallback := @readFile; + // filesystem.writecallback:= @writeFile; + // filesystem.readcallback := @readFile; // filesystem.formatVolumeCallback := @create_volume; volumemanager.register_filesystem(@filesystem); diff --git a/src/driver/storage/volumemanager.pas b/src/driver/storage/volumemanager.pas index 75f25663..f45353e1 100644 --- a/src/driver/storage/volumemanager.pas +++ b/src/driver/storage/volumemanager.pas @@ -44,7 +44,7 @@ type PPWriteHook = procedure(volume : PStorage_volume; directory : pchar; entry : PDirectory_Entry; byteCount : uint32; buffer : puint32; statusOut : puint32); PPReadHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; fileExtension : pchar; buffer : puint32; bytecount : puint32) : uint32; PPHIOHook = procedure(volume : PStorage_device; addr : uint32; sectors : uint32; buffer : puint32); - PPCreateHook = procedure(disk : PStorage_Device; start : uint32; size : uint32; config : puint32); + PPCreateHook = procedure(volume : PStorage_volume; start : uint32; size : uint32; config : puint32); PPDetectHook = procedure(disk : PStorage_Device); PPCreateDirHook = procedure(volume : PStorage_volume; directory : pchar; dirname : pchar; attributes : uint32; status : puint32); PPReadDirHook = function(volume : PStorage_volume; directory : pchar; status : puint32) : PLinkedListBase; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error @@ -290,6 +290,22 @@ begin end; +procedure remove_volume(list : PLinkedListBase; volume : PStorage_Volume); +var + i : uint32; + elm : void; +begin + + for i:=0 to LL_Size(list) - 1 do begin + elm := LL_Get(list, i); + if (PStorage_Volume(elm)^.device = volume^.device) + and (PStorage_Volume(elm)^.sectorStart = volume^.sectorStart) then begin + LL_Delete(list, i); + break; + end; + end; +end; + procedure create_volume(disk : PStorage_device; filesystem : PChar; sectorStart : uint32; sectorCount : uint32); var volume : PStorage_Volume; @@ -298,10 +314,12 @@ var config : PuInt32; begin + push_trace('VolumeManager.create_volume'); + volume := PStorage_Volume(kalloc(SizeOf(TStorage_Volume))); volume^.device := disk; volume^.sectorStart := sectorStart; - volume^.sectorCount := sectorCount - 10; //-10 is temp also in storagemanager + volume^.sectorCount := sectorCount - 10; volume^.sectorSize := disk^.sectorSize; volume^.freeSectors := 0; //setup by filesystem @@ -312,17 +330,30 @@ begin end; end; + //format volume - volume^.filesystem^.createCallback(disk, sectorStart, sectorCount, config); + volume^.filesystem^.createCallback(volume, sectorCount, sectorStart, config); + + push_trace('VolumeManager.create_volume.2'); + + //remove volume from list of volumes + remove_volume(storageVolumes, volume); //add volume to list elm := LL_Add(storageVolumes); memcpy(uint32(volume), uint32(elm), SizeOf(TStorage_Volume)); + push_trace('VolumeManager.create_volume.3'); + + //remove volume from list of volumes on device + remove_volume(disk^.volumes, volume); + //add volume to device elm := LL_Add(disk^.volumes); memcpy(uint32(volume), uint32(elm), SizeOf(TStorage_Volume)); + //free memory + kfree(puint32(volume)); end; procedure register_volume(device : PStorage_Device; volume : PStorage_Volume); diff --git a/src/kernel.pas b/src/kernel.pas index 1594685b..2bcd88b7 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -46,6 +46,7 @@ uses lists, net, fat32, + flatfs, isrmanager, faults, fonts, @@ -218,6 +219,7 @@ begin { Filsystems } fat32.init(); + flatfs.init(); { Device Drivers } tracer.push_trace('kmain.DEVDRV');