From b7523db308dcefa46f0992eab60b8fbaa1aebcd2 Mon Sep 17 00:00:00 2001 From: aaron Date: Sun, 15 Apr 2018 05:00:59 +0000 Subject: [PATCH] git-svn-id: https://spexeah.com:8443/svn/Asuro@530 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c --- src/driver/storage/IDE.pas | 7 +- src/driver/storage/fat32.pas | 234 +++++++++++++++++++++-- src/driver/storage/storagemanagement.pas | 3 +- src/include/strings.pas | 4 +- 4 files changed, 223 insertions(+), 25 deletions(-) diff --git a/src/driver/storage/IDE.pas b/src/driver/storage/IDE.pas index b4a08b24..da27ec84 100644 --- a/src/driver/storage/IDE.pas +++ b/src/driver/storage/IDE.pas @@ -389,6 +389,7 @@ begin outb($1F5, LBA shr 16); outb($1F7, $20); //read command + for i:=0 to sectorCount do begin //poll status @@ -403,11 +404,11 @@ begin end; for ii:=0 to 127 do begin //read data - Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^ := uint32(inw($1F0)); //wrong - for iii:=0 to 1000 do if(ii = iii) then begin end; + Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^ := uint32(inw($1F0)); + while true do if (inw($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy if ii <> 127 then begin Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^ := ((uint32(inw($1F0)) shl 16) or Puint32(buffer + ((i * 512) + (ii * 32) DIV 32))^); //wrong - for iii:=0 to 1000 do if(ii = iii) then begin end + while true do if (inw($1f7) and (1 shl 7)) = 0 then break; //Wait until drive not busy end; end; end; diff --git a/src/driver/storage/fat32.pas b/src/driver/storage/fat32.pas index e5c9e3e0..83d29525 100644 --- a/src/driver/storage/fat32.pas +++ b/src/driver/storage/fat32.pas @@ -13,7 +13,13 @@ unit FAT32; interface uses - console, storagemanagement, util, lmemorymanager, strings; + console, + storagemanagement, + util, + lmemorymanager, + strings, + lists, + tracer; type @@ -53,7 +59,7 @@ type TDirectory = bitpacked record fileName : array[0..7] of char; - fileExtension : ubit24; + fileExtension : array[0..2] of char; attributes : uint8; reserved0 : uint8; timeFine : uint8; @@ -69,8 +75,13 @@ type PDirectory = ^TDirectory; TFilesystemInfo = record - FATBaseAddress : uint32; - RootDirectory : uint32; + leadSignature : uint32; + reserved0 : array[0..479] of uint8; + structSignature : uint32; + freeSectors : uint32; + nextFreeSector : uint32; + reserved1 : array[0..11] of uint8; + trailSignature : uint32; end; TFatVolumeInfo = record @@ -92,12 +103,181 @@ begin console.outputln('DUMMY DRIVER', 'LOADED.') end; -procedure readDirectory(volume : PStorage_volume; directory : pchar; buffer : puint32); +function readBootRecord(volume : PStorage_volume) : TBootRecord; // need write functions for boot record! +var + buffer : puint32; begin - //get location of first directory entre - - //check if it takes up more than one cluster - //read all entries + buffer:= puint32(kalloc(512)); + volume^.device^.readcallback(volume^.device, volume^.sectorStart + 1, 1, buffer); + readBootRecord:= PBootRecord(buffer)^; + kfree(buffer); +end; + +function readFat(volume : PStorage_volume; cluster : uint32): uint32; +var + buffer : puint32; + bootRecord : TBootRecord; + fatSize : uint32; +begin + bootRecord := readBootRecord(volume); + fatSize:= bootrecord.fatSize; + buffer:= puint32(kalloc(fatSize)); + volume^.device^.readcallback(volume^.device, volume^.sectorStart + 2 + (cluster * 32 div volume^.sectorSize), 1, buffer); + readFat:= buffer[cluster]; + kfree(buffer); +end; + +procedure writeFat(volume : PStorage_volume; cluster : uint32; value : uint32); // untested, but should work +var + buffer : puint32; + bootRecord : TBootRecord; + fatSize : uint32; +begin + bootRecord := readBootRecord(volume); + fatSize:= bootrecord.fatSize; + buffer:= puint32(kalloc(fatSize)); + volume^.device^.readcallback(volume^.device, volume^.sectorStart + 2 + (cluster * 32 div volume^.sectorSize), 1, buffer); + buffer[cluster]:= value; + volume^.device^.writeCallback(volume^.device, volume^.sectorStart + 2 + (cluster * 32 div volume^.sectorSize), 1, buffer); + kfree(buffer); +end; + + +function readDirectory(volume : PStorage_volume; directory : pchar; listPtr : PLinkedListBase) : uint8; //returns: 0 = success, 1 = dir not exsist, 2 = not directory, 3 = error +var + directories : PLinkedListBase; + rootTable : PLinkedListBase; + clusters : PLinkedListBase; + dirElm : void; + buffer : puint32; + bufferI : puint32; + bootRecord : TBootRecord; + clusterInfo : uint32; + cc : uint32; + clusterByteSize : uint32; + fatSectorSize : uint32; + device : PStorage_Device; + i : uint32; + dirI : uint32 = 0; + str : pchar; + targetStr : pchar; + dir : PDirectory; +begin + push_trace('fat32.readDirectory'); + + rootTable := LL_New(sizeof(TDirectory)); + clusters := LL_New(sizeof(uint32)); + directories := stringToLL(directory, '/'); + bootRecord := readBootRecord(volume); + device := volume^.device; + clusterByteSize := bootrecord.spc * bootrecord.sectorSize; + fatSectorSize := bootrecord.fatSize; + + + // if readFat(volume, bootrecord.rootCluster) = $FFFFFFF8 then begin + // buffer:= puint32(kalloc((bootrecord.spc * 512) + 1)); + // volume^.device^.readcallback(volume^.device, volume^.sectorStart + 1 + (bootrecord.fatSize div 512) + (bootRecord.spc * bootRecord.rootCluster), bootrecord.spc, buffer); + // end else if readFat(volume, bootrecord.rootCluster) <> $FFFFFFF7 then begin + // //need to read multiple clusters to get full directory table + // end; + + + cc:= bootrecord.rootCluster; + + while true do begin + + targetStr:= pchar(LL_Get(directories, dirI)); + + //build list of clusters for current directory table + while true do begin + console.writestring('cluster: '); + console.writeintln(cc); + clusterInfo:= readFat(volume, cc); + console.writestring('info: '); + console.writehexln(clusterInfo); + if clusterInfo = $FFFFFFF7 then begin + readDirectory:= 3; //ERROR + break; + end else if clusterInfo = $FFFFFFF8 then begin + //last dir table cluster + dirElm:= LL_Add(clusters); + uint32(dirElm^):= cc; + break; + end else if clusterInfo = 0 then begin + break; + end else begin + //dir is longer than one cluster + dirElm:= LL_Add(clusters); + uint32(dirElm^):= cc; + cc:= clusterInfo; + end; + end; + + //load clusters into buffer + buffer:= puint32(kalloc( (clusterByteSize * (LL_size(clusters) - 1)) + 1)); + bufferI := buffer; + for i:= 0 to LL_size(clusters) - 1 do begin + cc:= uint32(LL_Get(clusters, i)^); + console.writeintln(volume^.sectorStart + 1 + fatSectorSize + (bootRecord.spc * cc)); + console.writeintln(cc); + console.writeintln(bootrecord.fatSize); + device^.readcallback(device, volume^.sectorStart + 1 + fatSectorSize + (bootRecord.spc * cc), bootrecord.spc, puint32(buffer + (i * clusterByteSize)) ); + end; + + console.writestringln('loaded table clusters'); + if dirI = LL_size(directories) - 1 then break; + + //get elements in the directory table + while true do begin + dir:= PDirectory(bufferI); + if dir^.fileName[0] = char(0) then break; //need to check if I have found the right directoy and set cc if not last + if (dir^.attributes and $10) = $10 then begin // is a directory; + str:= dir^.fileName; + str[9]:= char(0); + if stringEquals(str, targetStr) then begin //need to get current folder searching for + cc:= dir^.clusterLow; + cc:= cc or (dir^.clusterHigh shl 16); + end; + end; + + dirElm:= LL_Add(rootTable); + PDirectory(dirElm)^:= PDirectory(bufferI)^; + bufferI:= puint32(bufferI + 8); + end; + + //set CC + dirI += 1; + console.writestringln('finished loop'); + end; + + while true do begin + dir:= PDirectory(bufferI); + if dir^.fileName[0] = char(0) then break; //need to check if I have found the right directoy and set cc if not last + dirElm:= LL_Add(rootTable); + PDirectory(dirElm)^:= PDirectory(bufferI)^; + + console.writestringln(PDirectory(bufferI)^.fileName); + //console.writecharln(PDirectory(bufferI)^.fileName[1]); + psleep(300); + bufferI:= puint32(bufferI + 8); + end; + + kfree(buffer); + readDirectory:= 0; + listPtr := rootTable; + + // while true do begin // I need to be inside another loop + // if PDirectory(buffer)^.fileName[0] = char(0) then break; + // dirElm:= LL_Add(rootTable); + // PDirectory(dirElm)^:= PDirectory(buffer)^; + + // console.writestring('FileName: '); + // console.writechar(PDirectory(buffer)^.fileName[0]); + // //console.writecharln(PDirectory(buffer)^.fileName[1]); + // buffer:= puint32(buffer + 8); + // end; + + pop_trace(); end; procedure writeDirectory(volume : PStorage_volume; directory : pchar; buffer : puint32); @@ -143,7 +323,8 @@ begin bootrecord.jmp2boot:= $00; // TODO what ahppens here??? bootRecord.OEMName:= asuroArray; bootrecord.sectorsize:= disk^.sectorSize; - bootrecord.spc:= PFatVolumeInfo(config)^.sectorsPerCluster; + bootrecord.spc:= config^; + console.writeintln(uint32(config^)); bootrecord.rsvSectors:= 32; //Is this acceptable? bootrecord.numFats:= 1; bootrecord.numDirEnt:= 0; @@ -156,11 +337,13 @@ begin bootRecord.manySectors:= sectors; //BootRecord.FATSize:= ((sectors DIV PFatVolumeInfo(config)^.sectorsPerCluster) * 16 DIV disk^.sectorSize); - BootRecord.FATSize:= ((sectors DIV 4) * 16 DIV disk^.sectorSize); + //BootRecord.FATSize:= ((sectors DIV 4) * 2 DIV disk^.sectorSize); + BootRecord.FATSize:= ((sectors DIV bootrecord.spc) * 4) DIV 512; + //sectors div spc, * BootRecord.flags:= 0; //1 shl 7 for mirroring BootRecord.FATVersion:= 0; - BootRecord.rootCluster:= 2; // can be changed if needed. - BootRecord.FSInfoCluster:=1; //TODO need FSINFO + BootRecord.rootCluster:= start + 2; // can be changed if needed. + BootRecord.FSInfoCluster:= start + 1 + bootrecord.fatSize; //TODO need FSINFO BootRecord.driveNumber:= $80; //BootRecord.reserved0:=0; //BootRecord.reserved1:=0; @@ -174,15 +357,16 @@ begin disk^.writeCallback(disk, start + 1, 1, buffer); - dataStart:= (sectors DIV bootrecord.spc) + 2; + dataStart:= (bootrecord.fatSize) + 1 + start; //TODO FSINFO struct //write fat buffer := puint32(kalloc((sectors DIV bootrecord.spc) * 4)); - memset(uint32(buffer), 0, sectors DIV bootrecord.spc); - puint32(buffer + 1)^:= $FFF8; //root directory table cluster, currently root is only 1 cluster long - disk^.writeCallback(disk, start + 2, sectors DIV bootrecord.spc, buffer); + memset(uint32(buffer), 0, (sectors DIV bootrecord.spc) * 4); + puint32(buffer + bootRecord.rootCluster - 1)^:= $FFFFFFF7; //make space for fsinfo, by setting this field to bad. + puint32(buffer + bootRecord.rootCluster)^:= $FFFFFFF8; //root directory table cluster, currently root is only 1 cluster long + disk^.writeCallback(disk, start + 2, (sectors DIV bootrecord.spc) * 4, buffer); //disk^.writeCallback(disk, start + 2 + (sectors Div bootrecord.sectorsPerCluster DIV 512), sectors DIV bootrecord.sectorsPerCluster, buffer); kfree(buffer); @@ -208,7 +392,16 @@ begin PDirectory(buffer + (sizeof(TDirectory) DIV 4) )^.attributes:= $08; // volume id PDirectory(buffer + (sizeof(TDirectory) DIV 4) )^.clusterLow:= 2; //my cluster location - disk^.writeCallback(disk, dataStart + (bootRecord.spc), 1, buffer); + tmpArray[0]:= 'M'; + tmpArray[1]:= 'U'; + tmpArray[2]:= 'S'; + tmpArray[3]:= 'I'; + tmpArray[4]:= 'C'; + PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4 ) )^.fileName:= tmpArray; + PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4) )^.attributes:= $10; // volume id + PDirectory(buffer + (sizeof(TDirectory) * 2 DIV 4) )^.clusterLow:= 2; //my cluster location + + disk^.writeCallback(disk, dataStart + (bootRecord.spc * bootrecord.rootCluster), 1, buffer); end; @@ -218,6 +411,7 @@ var i : uint8; volume : PStorage_volume; begin + push_trace('detect volume'); volume:= PStorage_volume(kalloc(sizeof(TStorage_Volume))); //check first address for MBR //if found then add volume and use info to see if there is another volume @@ -227,12 +421,16 @@ begin if (puint32(buffer + (127))^ = $55AA) and (PBootRecord(buffer)^.bsignature = $29) then begin console.writestringln('FAT32: volume found!'); + volume^.device:= disk; volume^.sectorStart:= 1; volume^.sectorSize:= PBootRecord(buffer)^.sectorSize; volume^.freeSectors:= 1000000; //TODO implement get free sectors need FSINFO implemented first volume^.filesystem := @filesystem; storagemanagement.register_volume(disk, volume); end; + + readDirectory(volume, 'hello/word', nil); + pop_trace(); end; end. \ No newline at end of file diff --git a/src/driver/storage/storagemanagement.pas b/src/driver/storage/storagemanagement.pas index 9d9a18bf..d4950f54 100644 --- a/src/driver/storage/storagemanagement.pas +++ b/src/driver/storage/storagemanagement.pas @@ -46,6 +46,7 @@ type PFileSystem = ^TFilesystem; TStorage_Volume = record + device : PStorage_device; sectorStart : uint32; sectorSize : uint32; freeSectors : uint32; @@ -133,7 +134,7 @@ begin drive := stringToInt(getParam(1, params)); console.writeintln(drive); // works if stringEquals(getParam(2, params), 'fat32') then begin - PFilesystem(LL_Get(filesystems, 0))^.createCallback((PStorage_Device(LL_Get(storageDevices, drive))), 100000, 1, @spc); //todo check fs + PFilesystem(LL_Get(filesystems, 0))^.createCallback((PStorage_Device(LL_Get(storageDevices, drive))), 1000000, 1, spc); //todo check fs console.writestring('Drive '); //console.writeint(drive); // page faults console.writestringln(' formatted.'); diff --git a/src/include/strings.pas b/src/include/strings.pas index 52747d3c..2e477913 100644 --- a/src/include/strings.pas +++ b/src/include/strings.pas @@ -201,16 +201,14 @@ begin if (head^ = delimter) or (head^ = char(0)) then begin if head^ = char(0) then null_delim:= true; size:= uint32(head) - uint32(tail); - console.writeintln(size); if size > 0 then begin elm:= puint32(LL_Add(list)); - out_str:= stringNew(size); + out_str:= stringNew(size + 1); //maybe memcpy(uint32(tail), uint32(out_str), size); elm^:= uint32(out_str); end; tail:= head+1; end else begin - console.writecharln(head^); end; inc(head); end;