fix(storage): harden disk operations, add volume labels, and stabilize AHCI discovery
This commit is contained in:
1 parent
7e99bc2db1
commit
d1ecd3fc41
18 files changed
+1551
-1481
No files matched your search
+324
-174
File diff suppressed because it is too large.
Load diff
+17
-8
@@ -288,7 +288,9 @@ begin
|
|||||||
if bootrecord <> nil then begin
|
if bootrecord <> nil then begin
|
||||||
if bootrecord^.boot_sector <> $AA55 then begin
|
if bootrecord^.boot_sector <> $AA55 then begin
|
||||||
println('No valid mbr found, initialising disk...');
|
println('No valid mbr found, initialising disk...');
|
||||||
driver.storage.vol.mgr.init_disk(device);
|
if driver.storage.vol.mgr.init_disk(device) <> eNone then begin
|
||||||
|
println('Error: disk initialization failed.'); exit;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
kfree(puint32(bootrecord));
|
kfree(puint32(bootrecord));
|
||||||
end;
|
end;
|
||||||
@@ -335,7 +337,9 @@ begin
|
|||||||
|
|
||||||
driver.storage.vol.mbr.setup_partition(@part, lba, sectors);
|
driver.storage.vol.mbr.setup_partition(@part, lba, sectors);
|
||||||
part.system_id := 0;
|
part.system_id := 0;
|
||||||
driver.storage.vol.mgr.add_partition(device, slot, part);
|
if driver.storage.vol.mgr.add_partition(device, slot, part) <> eNone then begin
|
||||||
|
println('Error: partition creation failed.'); exit;
|
||||||
|
end;
|
||||||
|
|
||||||
print('Partition added in slot ');
|
print('Partition added in slot ');
|
||||||
printint(slot);
|
printint(slot);
|
||||||
@@ -407,7 +411,9 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
driver.storage.vol.mgr.remove_partition(device, slot);
|
if driver.storage.vol.mgr.remove_partition(device, slot) <> eNone then begin
|
||||||
|
println('Error: partition removal failed.'); exit;
|
||||||
|
end;
|
||||||
|
|
||||||
print('Partition slot ');
|
print('Partition slot ');
|
||||||
printint(slot);
|
printint(slot);
|
||||||
@@ -523,11 +529,14 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
vol^.filesystem := fs;
|
i := 0;
|
||||||
fs^.createCallback(vol, vol^.sectorCount, vol^.sectorStart, nil);
|
while i < driver.storage.vol.mgr.get_volume_count() do begin
|
||||||
|
if driver.storage.vol.mgr.get_volume(i) = vol then break;
|
||||||
{ Re-probe filesystem so identify picks up the new signature }
|
Inc(i);
|
||||||
driver.storage.fs.mgr.probe_volume(vol);
|
end;
|
||||||
|
if not driver.storage.vol.mgr.format_volume(device, i, fsName, nil) then begin
|
||||||
|
println('Error: format failed; the volume was not reported ready.'); exit;
|
||||||
|
end;
|
||||||
|
|
||||||
print('Partition ');
|
print('Partition ');
|
||||||
printint(slot);
|
printint(slot);
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ procedure fpc_shortstr_assign(len: longint; sstr, dstr: Pointer); compilerproc;
|
|||||||
any int64/uint64 arithmetic occurs (e.g. sint32 * uint32 promotion).
|
any int64/uint64 arithmetic occurs (e.g. sint32 * uint32 promotion).
|
||||||
Must live in the system unit so the compiler can resolve it. }
|
Must live in the system unit so the compiler can resolve it. }
|
||||||
function fpc_mul_int64(f1, f2: int64): int64; compilerproc;
|
function fpc_mul_int64(f1, f2: int64): int64; compilerproc;
|
||||||
|
function fpc_mul_dword_to_qword(f1, f2: uint32): qword; compilerproc;
|
||||||
function fpc_div_int64(d, n: int64): int64; compilerproc;
|
function fpc_div_int64(d, n: int64): int64; compilerproc;
|
||||||
function fpc_mod_int64(d, n: int64): int64; compilerproc;
|
function fpc_mod_int64(d, n: int64): int64; compilerproc;
|
||||||
function fpc_mod_qword(d, n: qword): qword; compilerproc;
|
function fpc_mod_qword(d, n: qword): qword; compilerproc;
|
||||||
@@ -523,6 +524,18 @@ begin
|
|||||||
fpc_mul_int64 := res;
|
fpc_mul_int64 := res;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function fpc_mul_dword_to_qword(f1, f2: uint32): qword; [public, alias: 'FPC_MUL_DWORD_TO_QWORD']; compilerproc;
|
||||||
|
var res: qword;
|
||||||
|
begin
|
||||||
|
asm
|
||||||
|
MOV EAX, f1
|
||||||
|
MUL f2
|
||||||
|
MOV DWORD [res], EAX
|
||||||
|
MOV DWORD [res+4], EDX
|
||||||
|
end;
|
||||||
|
fpc_mul_dword_to_qword := res;
|
||||||
|
end;
|
||||||
|
|
||||||
{ ---------- 64-bit division / modulo ---------- }
|
{ ---------- 64-bit division / modulo ---------- }
|
||||||
|
|
||||||
{ Helper: unsigned 64÷64→64 using shift-subtract (binary long division).
|
{ Helper: unsigned 64÷64→64 using shift-subtract (binary long division).
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -154,7 +154,8 @@ type
|
|||||||
sleVolumeInvalidated,
|
sleVolumeInvalidated,
|
||||||
sleVolumeRemoved,
|
sleVolumeRemoved,
|
||||||
sleDeviceAdded,
|
sleDeviceAdded,
|
||||||
sleDeviceRemoved
|
sleDeviceRemoved,
|
||||||
|
sleVolumeLabelChanged
|
||||||
);
|
);
|
||||||
|
|
||||||
TStorageLifecycleCallback = procedure(event : TStorageLifecycleEvent;
|
TStorageLifecycleCallback = procedure(event : TStorageLifecycleEvent;
|
||||||
@@ -163,6 +164,8 @@ type
|
|||||||
error : TError;
|
error : TError;
|
||||||
userdata : pointer);
|
userdata : pointer);
|
||||||
|
|
||||||
|
TVolumeLabel = array[0..32] of char; { cached, NUL-terminated display name }
|
||||||
|
|
||||||
TFSFormatParams = record
|
TFSFormatParams = record
|
||||||
Version : uint16;
|
Version : uint16;
|
||||||
Flags : uint16;
|
Flags : uint16;
|
||||||
@@ -186,13 +189,15 @@ type
|
|||||||
TIOCallback = procedure(error : TError; userdata : pointer);
|
TIOCallback = procedure(error : TError; userdata : pointer);
|
||||||
|
|
||||||
{ Filesystem callback core.types }
|
{ Filesystem callback core.types }
|
||||||
PPCreateHook = procedure(volume : PStorage_volume; start : uint32; size : uint32; config : PFSFormatParams);
|
PPCreateHook = function(volume : PStorage_volume; sectors : uint32; start : uint32; config : PFSFormatParams) : TError;
|
||||||
PPCreateAsyncHook = procedure(volume : PStorage_volume; start : uint32; size : uint32; config : PFSFormatParams; callback : TIOCallback; callbackData : pointer);
|
PPCreateAsyncHook = procedure(volume : PStorage_volume; start : uint32; size : uint32; config : PFSFormatParams; callback : TIOCallback; callbackData : pointer);
|
||||||
PPDetectHook = procedure(disk : PStorage_Device);
|
PPDetectHook = procedure(disk : PStorage_Device);
|
||||||
PPCreateDirHook = procedure(volume : PStorage_volume; directory : pchar; dirname : pchar; attributes : uint32; status : puint32);
|
PPCreateDirHook = procedure(volume : PStorage_volume; directory : pchar; dirname : pchar; attributes : uint32; status : puint32);
|
||||||
PPReadDirHook = function(volume : PStorage_volume; directory : pchar; status : puint32) : PLinkedListBase;
|
PPReadDirHook = function(volume : PStorage_volume; directory : pchar; status : puint32) : PLinkedListBase;
|
||||||
PPDeleteFileHook = procedure(volume : PStorage_Volume; filePath : pchar; status : puint32);
|
PPDeleteFileHook = procedure(volume : PStorage_Volume; filePath : pchar; status : puint32);
|
||||||
PPDeleteDirHook = procedure(volume : PStorage_Volume; path : pchar; status : puint32);
|
PPDeleteDirHook = procedure(volume : PStorage_Volume; path : pchar; status : puint32);
|
||||||
|
PPValidateLabelHook = function(text : pchar; var normalized : TVolumeLabel) : TError;
|
||||||
|
PPSetLabelHook = function(volume : PStorage_Volume; text : pchar) : TError;
|
||||||
PPIdentifyHook = function(volume : PStorage_Volume) : boolean;
|
PPIdentifyHook = function(volume : PStorage_Volume) : boolean;
|
||||||
PPRenameFileHook = procedure(volume : PStorage_Volume; filePath : pchar; newName : pchar; status : puint32);
|
PPRenameFileHook = procedure(volume : PStorage_Volume; filePath : pchar; newName : pchar; status : puint32);
|
||||||
{ Offset-based read: reads byteCount bytes starting at byte offset into the file.
|
{ Offset-based read: reads byteCount bytes starting at byte offset into the file.
|
||||||
@@ -271,6 +276,8 @@ type
|
|||||||
maxSectorCount : uint32;
|
maxSectorCount : uint32;
|
||||||
sectorSize : uint32; //in bytes
|
sectorSize : uint32; //in bytes
|
||||||
start : uint32; //start of device in sectors
|
start : uint32; //start of device in sectors
|
||||||
|
metadataBusy : boolean; { volume/partition operation owns device }
|
||||||
|
mbrWriteBusy : boolean; { serializes staged sector-zero writes }
|
||||||
cachedMBR : pointer; { cached mbr data, nil if not yet read }
|
cachedMBR : pointer; { cached mbr data, nil if not yet read }
|
||||||
isBootDevice : boolean; { true if this is the device GRUB booted from }
|
isBootDevice : boolean; { true if this is the device GRUB booted from }
|
||||||
end;
|
end;
|
||||||
@@ -280,6 +287,7 @@ type
|
|||||||
sName : pchar;
|
sName : pchar;
|
||||||
system_id : uint8;
|
system_id : uint8;
|
||||||
createCallback : PPCreateHook;
|
createCallback : PPCreateHook;
|
||||||
|
validateFormat : PPCreateHook; { pure preflight, before invalidation }
|
||||||
detectCallback : PPDetectHook;
|
detectCallback : PPDetectHook;
|
||||||
createDirCallback : PPCreateDirHook;
|
createDirCallback : PPCreateDirHook;
|
||||||
readDirCallback : PPReadDirHook;
|
readDirCallback : PPReadDirHook;
|
||||||
@@ -304,6 +312,8 @@ type
|
|||||||
openFileCallback : PPOpenFileHook;
|
openFileCallback : PPOpenFileHook;
|
||||||
closeFileCallback : PPCloseFileHook;
|
closeFileCallback : PPCloseFileHook;
|
||||||
formatParamFlags : uint32;
|
formatParamFlags : uint32;
|
||||||
|
validateLabelCallback : PPValidateLabelHook;
|
||||||
|
setLabelCallback : PPSetLabelHook;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Generic storage volume }
|
{ Generic storage volume }
|
||||||
@@ -317,6 +327,7 @@ type
|
|||||||
filesystem : PFilesystem;
|
filesystem : PFilesystem;
|
||||||
isBootDrive : boolean;
|
isBootDrive : boolean;
|
||||||
lifecycleFlags : uint32;
|
lifecycleFlags : uint32;
|
||||||
|
labelText : TVolumeLabel;
|
||||||
fsPrivate : pointer; { FS-driver private data (e.g. PFATCache for FAT32) }
|
fsPrivate : pointer; { FS-driver private data (e.g. PFATCache for FAT32) }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ procedure UnwatchDirectory(WatchID : uint32);
|
|||||||
{ Volume invalidation — must be called before freeing a volume.
|
{ Volume invalidation — must be called before freeing a volume.
|
||||||
Closes all open FDs referencing the volume across all processes,
|
Closes all open FDs referencing the volume across all processes,
|
||||||
evicts directory cache entries, and removes VFS mount points. }
|
evicts directory cache entries, and removes VFS mount points. }
|
||||||
|
function VolumeHasOpenHandles(vol : PStorage_Volume) : boolean;
|
||||||
function InvalidateVolume(vol : PStorage_Volume) : boolean;
|
function InvalidateVolume(vol : PStorage_Volume) : boolean;
|
||||||
|
|
||||||
{ VFS Functions }
|
{ VFS Functions }
|
||||||
@@ -509,7 +510,7 @@ end;
|
|||||||
function GetObjectFromPath(path : pchar) : PVFSObject; forward;
|
function GetObjectFromPath(path : pchar) : PVFSObject; forward;
|
||||||
function GetObjectFromPathEx(path : pchar; var volRelPath : pchar) : PVFSObject; forward;
|
function GetObjectFromPathEx(path : pchar; var volRelPath : pchar) : PVFSObject; forward;
|
||||||
|
|
||||||
function volumeHasAsyncHandles(vol : PStorage_Volume) : boolean;
|
function volumeHasHandles(vol : PStorage_Volume; asyncOnly : boolean) : boolean;
|
||||||
var
|
var
|
||||||
pCount : uint32;
|
pCount : uint32;
|
||||||
pi : uint32;
|
pi : uint32;
|
||||||
@@ -517,7 +518,7 @@ var
|
|||||||
pCtx : proc.types.PProcessContext;
|
pCtx : proc.types.PProcessContext;
|
||||||
tbl : PFDTable;
|
tbl : PFDTable;
|
||||||
begin
|
begin
|
||||||
volumeHasAsyncHandles := false;
|
volumeHasHandles := false;
|
||||||
if vol = nil then exit;
|
if vol = nil then exit;
|
||||||
|
|
||||||
pCount := proc.mgr.processCount();
|
pCount := proc.mgr.processCount();
|
||||||
@@ -530,14 +531,17 @@ begin
|
|||||||
if tbl = nil then continue;
|
if tbl = nil then continue;
|
||||||
for fi := 0 to MAX_FDS - 1 do begin
|
for fi := 0 to MAX_FDS - 1 do begin
|
||||||
if tbl^.Entries[fi].InUse and (tbl^.Entries[fi].Volume = vol)
|
if tbl^.Entries[fi].InUse and (tbl^.Entries[fi].Volume = vol)
|
||||||
and (tbl^.Entries[fi].AsyncRefs > 0) then begin
|
and ((not asyncOnly) or (tbl^.Entries[fi].AsyncRefs > 0)) then begin
|
||||||
volumeHasAsyncHandles := true;
|
volumeHasHandles := true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function VolumeHasOpenHandles(vol : PStorage_Volume) : boolean;
|
||||||
|
begin VolumeHasOpenHandles := volumeHasHandles(vol,false); end;
|
||||||
|
|
||||||
function InvalidateVolume(vol : PStorage_Volume) : boolean;
|
function InvalidateVolume(vol : PStorage_Volume) : boolean;
|
||||||
var
|
var
|
||||||
pCount : uint32;
|
pCount : uint32;
|
||||||
@@ -554,7 +558,7 @@ begin
|
|||||||
debug.tracer.push_trace('driver.storage.vfs.InvalidateVolume.enter');
|
debug.tracer.push_trace('driver.storage.vfs.InvalidateVolume.enter');
|
||||||
InvalidateVolume := false;
|
InvalidateVolume := false;
|
||||||
if vol = nil then exit;
|
if vol = nil then exit;
|
||||||
if volumeHasAsyncHandles(vol) then begin
|
if volumeHasHandles(vol,true) then begin
|
||||||
debug.tracer.push_trace('driver.storage.vfs.InvalidateVolume.busy');
|
debug.tracer.push_trace('driver.storage.vfs.InvalidateVolume.busy');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@@ -986,6 +990,7 @@ begin
|
|||||||
volumeGetDirectories := nil;
|
volumeGetDirectories := nil;
|
||||||
|
|
||||||
if vol = nil then exit;
|
if vol = nil then exit;
|
||||||
|
if (vol^.device = nil) or vol^.device^.metadataBusy or driver.storage.vol.mgr.volume_is_busy(vol) then exit;
|
||||||
if vol^.filesystem = nil then exit;
|
if vol^.filesystem = nil then exit;
|
||||||
if vol^.filesystem^.readDirCallback = nil then exit;
|
if vol^.filesystem^.readDirCallback = nil then exit;
|
||||||
|
|
||||||
@@ -1153,6 +1158,15 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
mountObj := PVFSObject(core.ds.hashmap.get(ht, mountName));
|
||||||
|
if mountObj <> nil then begin
|
||||||
|
if (mountObj^.ObjectType = otDRIVE) and (mountObj^.Reference = void(volume)) then begin
|
||||||
|
mountVolume := pvRegistered;
|
||||||
|
driver.storage.vol.mgr.volume_set_mounted(volume, true);
|
||||||
|
end;
|
||||||
|
kfree(void(parentPath)); STRLL_Free(splitPath); exit;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Create the mount object storing the volume pointer }
|
{ Create the mount object storing the volume pointer }
|
||||||
mountObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
mountObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
||||||
|
|
||||||
@@ -1219,6 +1233,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
volOut^ := PStorage_Volume(Obj^.Reference);
|
volOut^ := PStorage_Volume(Obj^.Reference);
|
||||||
|
if (volOut^ = nil) or (volOut^^.device = nil) then begin
|
||||||
|
if volRel <> nil then kfree(void(volRel)); exit;
|
||||||
|
end;
|
||||||
|
if volOut^^.device^.metadataBusy or driver.storage.vol.mgr.volume_is_busy(volOut^) then begin
|
||||||
|
if volRel <> nil then kfree(void(volRel)); volOut^ := nil; exit;
|
||||||
|
end;
|
||||||
|
|
||||||
{ volRel is the path within the volume, e.g. '/mydir/myfile.txt' }
|
{ volRel is the path within the volume, e.g. '/mydir/myfile.txt' }
|
||||||
if (volRel = nil) or StringEquals(volRel, '/') then begin
|
if (volRel = nil) or StringEquals(volRel, '/') then begin
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -392,6 +392,15 @@ end;
|
|||||||
|
|
||||||
{ ==================== Filesystem callbacks ==================== }
|
{ ==================== Filesystem callbacks ==================== }
|
||||||
|
|
||||||
|
procedure cacheVolumeLabel(volume : PStorage_Volume; pvd : PPVD);
|
||||||
|
var n, i : uint32;
|
||||||
|
begin
|
||||||
|
memset(uint32(@volume^.labelText[0]),0,sizeof(volume^.labelText));
|
||||||
|
n := 32;
|
||||||
|
while (n > 0) and ((pvd^.volumeId[n-1] = ' ') or (pvd^.volumeId[n-1] = #0)) do Dec(n);
|
||||||
|
i := 0; while i < n do begin volume^.labelText[i] := pvd^.volumeId[i]; Inc(i); end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ Identify: check for 'CD001' at sector 16 }
|
{ Identify: check for 'CD001' at sector 16 }
|
||||||
function identify_volume(volume : PStorage_Volume) : boolean;
|
function identify_volume(volume : PStorage_Volume) : boolean;
|
||||||
var
|
var
|
||||||
@@ -405,6 +414,7 @@ begin
|
|||||||
buf := readSectors(volume^.device, volume^.sectorStart + PVD_SECTOR, 1);
|
buf := readSectors(volume^.device, volume^.sectorStart + PVD_SECTOR, 1);
|
||||||
if buf = nil then exit;
|
if buf = nil then exit;
|
||||||
identify_volume := isPVD(buf);
|
identify_volume := isPVD(buf);
|
||||||
|
if identify_volume then cacheVolumeLabel(volume,PPVD(buf));
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -437,6 +447,7 @@ begin
|
|||||||
volume^.filesystem := @filesystem;
|
volume^.filesystem := @filesystem;
|
||||||
volume^.isBootDrive := disk^.isBootDevice;
|
volume^.isBootDrive := disk^.isBootDevice;
|
||||||
|
|
||||||
|
cacheVolumeLabel(volume,pvd);
|
||||||
driver.storage.vol.mgr.register_volume(disk, volume);
|
driver.storage.vol.mgr.register_volume(disk, volume);
|
||||||
|
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
|
|||||||
@@ -94,10 +94,7 @@ end;
|
|||||||
|
|
||||||
function fatMaxClusterCount(bootRecord : PBootRecord) : uint32;
|
function fatMaxClusterCount(bootRecord : PBootRecord) : uint32;
|
||||||
begin
|
begin
|
||||||
if (bootRecord = nil) or (bootRecord^.sectorSize = 0) then
|
fatMaxClusterCount := FAT32ClusterLimit(bootRecord);
|
||||||
fatMaxClusterCount := 0
|
|
||||||
else
|
|
||||||
fatMaxClusterCount := (bootRecord^.FATSize * bootRecord^.sectorSize) div 4;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function fatClustersForBytes(byteCount : uint32; bytesPerCluster : uint32) : uint32;
|
function fatClustersForBytes(byteCount : uint32; bytesPerCluster : uint32) : uint32;
|
||||||
@@ -391,7 +388,9 @@ begin
|
|||||||
sectorBuf := puint32(kalloc(bufSize));
|
sectorBuf := puint32(kalloc(bufSize));
|
||||||
if sectorBuf = nil then exit;
|
if sectorBuf = nil then exit;
|
||||||
memset(uint32(sectorBuf), 0, bufSize);
|
memset(uint32(sectorBuf), 0, bufSize);
|
||||||
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart, 1, sectorBuf);
|
if driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart, 1, sectorBuf) <> eNone then begin
|
||||||
|
kfree(sectorBuf); exit;
|
||||||
|
end;
|
||||||
bootRecord := PBootRecord(sectorBuf)^;
|
bootRecord := PBootRecord(sectorBuf)^;
|
||||||
kfree(sectorBuf);
|
kfree(sectorBuf);
|
||||||
readBootRecordRaw := true;
|
readBootRecordRaw := true;
|
||||||
@@ -699,9 +698,13 @@ begin
|
|||||||
|
|
||||||
{ Keep runtime addressing compatible with the legacy formatter and metadata paths. }
|
{ Keep runtime addressing compatible with the legacy formatter and metadata paths. }
|
||||||
ctx^.Info.DataStart := volume^.sectorStart + ctx^.Info.BootRecord.rsvSectors +
|
ctx^.Info.DataStart := volume^.sectorStart + ctx^.Info.BootRecord.rsvSectors +
|
||||||
ctx^.Info.BootRecord.FATSize;
|
uint32(ctx^.Info.BootRecord.numFats) * ctx^.Info.BootRecord.FATSize;
|
||||||
ctx^.Info.BytesPerCluster := uint32(ctx^.Info.BootRecord.spc) * uint32(ctx^.Info.BootRecord.sectorSize);
|
ctx^.Info.BytesPerCluster := uint32(ctx^.Info.BootRecord.spc) * uint32(ctx^.Info.BootRecord.sectorSize);
|
||||||
ctx^.Info.MaxCluster := fatMaxClusterCount(@ctx^.Info.BootRecord);
|
ctx^.Info.MaxCluster := fatMaxClusterCount(@ctx^.Info.BootRecord);
|
||||||
|
if (ctx^.Info.MaxCluster <= 2) or
|
||||||
|
(ctx^.Info.BootRecord.manySectors > volume^.sectorCount) then begin
|
||||||
|
fatCtxFree(ctx); exit;
|
||||||
|
end;
|
||||||
ctx^.InfoValid := true;
|
ctx^.InfoValid := true;
|
||||||
|
|
||||||
ctx^.Cache.Data := puint32(kalloc(FAT_CACHE_LINES * 512));
|
ctx^.Cache.Data := puint32(kalloc(FAT_CACHE_LINES * 512));
|
||||||
@@ -1135,6 +1138,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
if dir^.fileName[0] = char($E5) then
|
if dir^.fileName[0] = char($E5) then
|
||||||
continue;
|
continue;
|
||||||
|
if (dir^.attributes and $08) <> 0 then continue; { volume labels and LFN entries are not files }
|
||||||
if compareByteArray8(dir^.fileName, cleanName) and matchExtension(dir^.fileExtension, ext) then begin
|
if compareByteArray8(dir^.fileName, cleanName) and matchExtension(dir^.fileExtension, ext) then begin
|
||||||
findEntryInSector := integer(idx);
|
findEntryInSector := integer(idx);
|
||||||
exit;
|
exit;
|
||||||
@@ -2048,7 +2052,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
if dir^.fileName[0] = char($E5) then
|
if dir^.fileName[0] = char($E5) then
|
||||||
continue;
|
continue;
|
||||||
if dir^.attributes = $0F then
|
if (dir^.attributes and $08) <> 0 then
|
||||||
continue;
|
continue;
|
||||||
if fatIsDotEntry(dir) then
|
if fatIsDotEntry(dir) then
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -16,6 +16,7 @@ uses
|
|||||||
io.syslog,
|
io.syslog,
|
||||||
core.util,
|
core.util,
|
||||||
driver.storage.fs.fat32.vol,
|
driver.storage.fs.fat32.vol,
|
||||||
|
driver.storage.fs.fat32.labels,
|
||||||
driver.storage.fs.fat32.core,
|
driver.storage.fs.fat32.core,
|
||||||
driver.storage.fs.fat32.transfer;
|
driver.storage.fs.fat32.transfer;
|
||||||
|
|
||||||
@@ -36,7 +37,8 @@ begin
|
|||||||
filesystem.readDirCallback := @FAT32ReadDirectory;
|
filesystem.readDirCallback := @FAT32ReadDirectory;
|
||||||
filesystem.createDirCallback := @FAT32CreateDirectory;
|
filesystem.createDirCallback := @FAT32CreateDirectory;
|
||||||
filesystem.createCallback := @create_volume;
|
filesystem.createCallback := @create_volume;
|
||||||
filesystem.createAsyncCallback := @create_volume_async;
|
filesystem.validateFormat := @validate_format;
|
||||||
|
filesystem.createAsyncCallback := nil; { volume manager runs checked formatter in a worker }
|
||||||
filesystem.detectCallback := @detect_volumes;
|
filesystem.detectCallback := @detect_volumes;
|
||||||
filesystem.readOffsetCallback := @FAT32ReadFileAtOffset;
|
filesystem.readOffsetCallback := @FAT32ReadFileAtOffset;
|
||||||
filesystem.writeOffsetCallback := @FAT32WriteFileAtOffset;
|
filesystem.writeOffsetCallback := @FAT32WriteFileAtOffset;
|
||||||
@@ -51,7 +53,9 @@ begin
|
|||||||
filesystem.closeFileCallback := @FAT32CloseFile;
|
filesystem.closeFileCallback := @FAT32CloseFile;
|
||||||
filesystem.createDirAsyncCallback := nil;
|
filesystem.createDirAsyncCallback := nil;
|
||||||
filesystem.readDirAsyncCallback := nil;
|
filesystem.readDirAsyncCallback := nil;
|
||||||
filesystem.formatParamFlags := FS_FORMAT_PARAM_CLUSTER_SIZE;
|
filesystem.formatParamFlags := FS_FORMAT_PARAM_CLUSTER_SIZE or FS_FORMAT_PARAM_LABEL;
|
||||||
|
filesystem.validateLabelCallback := @normalize_label;
|
||||||
|
filesystem.setLabelCallback := @write_label;
|
||||||
|
|
||||||
FAT32VolInit(@filesystem);
|
FAT32VolInit(@filesystem);
|
||||||
driver.storage.fs.mgr.register_filesystem(@filesystem);
|
driver.storage.fs.mgr.register_filesystem(@filesystem);
|
||||||
|
|||||||
@@ -224,6 +224,28 @@ type
|
|||||||
WriteRefs : array[0..FAT_OPEN_HANDLE_SLOTS - 1] of TFATWriteRef;
|
WriteRefs : array[0..FAT_OPEN_HANDLE_SLOTS - 1] of TFATWriteRef;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Exclusive cluster bound, constrained by both data area and FAT capacity. }
|
||||||
|
function FAT32ClusterLimit(br : PBootRecord) : uint32;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
function FAT32ClusterLimit(br : PBootRecord) : uint32;
|
||||||
|
var overhead, total, capacity, limit : uint64;
|
||||||
|
begin
|
||||||
|
FAT32ClusterLimit := 0;
|
||||||
|
if br = nil then exit;
|
||||||
|
if (br^.sectorSize <> 512) or (br^.spc = 0) or (br^.spc > 128) or
|
||||||
|
((br^.spc and (br^.spc - 1)) <> 0) or (br^.rsvSectors = 0) or
|
||||||
|
(br^.numFats = 0) or (br^.FATSize = 0) then exit;
|
||||||
|
total := br^.manySectors;
|
||||||
|
if total = 0 then total := br^.numSectors;
|
||||||
|
overhead := uint64(br^.rsvSectors) + uint64(br^.numFats) * br^.FATSize;
|
||||||
|
if overhead >= total then exit;
|
||||||
|
limit := (total - overhead) div br^.spc + 2;
|
||||||
|
capacity := uint64(br^.FATSize) * (br^.sectorSize div 4);
|
||||||
|
if (limit > capacity) or (limit > $0FFFFFF0) then exit;
|
||||||
|
FAT32ClusterLimit := uint32(limit);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -86,7 +86,7 @@ procedure set_bootable(partition_table : PPartition_table);
|
|||||||
begin
|
begin
|
||||||
push_trace('driver.storage.vol.mbr.set_bootable');
|
push_trace('driver.storage.vol.mbr.set_bootable');
|
||||||
//set the bootble bit in attributes
|
//set the bootble bit in attributes
|
||||||
partition_table^.attributes := (partition_table^.attributes and $80);
|
partition_table^.attributes := (partition_table^.attributes or $80);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Check a partitions bootable bit }
|
{ Check a partitions bootable bit }
|
||||||
@@ -105,7 +105,7 @@ begin
|
|||||||
partition_table^.LBA_start := address;
|
partition_table^.LBA_start := address;
|
||||||
partition_table^.sector_count := sectorSize;
|
partition_table^.sector_count := sectorSize;
|
||||||
partition_table^.CHS_start := LBA_2_CHS(address);
|
partition_table^.CHS_start := LBA_2_CHS(address);
|
||||||
partition_table^.CHS_start := LBA_2_CHS(address + sectorSize);
|
partition_table^.CHS_end := LBA_2_CHS(address + sectorSize - 1);
|
||||||
push_trace('driver.storage.vol.mbr.setup_partition.end');
|
push_trace('driver.storage.vol.mbr.setup_partition.end');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -12,6 +12,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
core.strings,
|
core.strings,
|
||||||
|
app.diskutil,
|
||||||
driver.bus.usb.types,
|
driver.bus.usb.types,
|
||||||
driver.bus.usb.core,
|
driver.bus.usb.core,
|
||||||
driver.bus.usb.uhci,
|
driver.bus.usb.uhci,
|
||||||
@@ -32,6 +33,7 @@ uses
|
|||||||
core.ds.prio,
|
core.ds.prio,
|
||||||
driver.storage.vfs,
|
driver.storage.vfs,
|
||||||
driver.storage.test,
|
driver.storage.test,
|
||||||
|
driver.storage.metatest,
|
||||||
core.enc.fnv1a,
|
core.enc.fnv1a,
|
||||||
core.enc.djb2,
|
core.enc.djb2,
|
||||||
core.ds.bloom,
|
core.ds.bloom,
|
||||||
@@ -46,6 +48,7 @@ procedure runAllTests();
|
|||||||
begin
|
begin
|
||||||
{ Run unit tests }
|
{ Run unit tests }
|
||||||
core.strings.UnitTest;
|
core.strings.UnitTest;
|
||||||
|
app.diskutil.UnitTest;
|
||||||
driver.bus.usb.types.UnitTest;
|
driver.bus.usb.types.UnitTest;
|
||||||
driver.bus.usb.core.UnitTest;
|
driver.bus.usb.core.UnitTest;
|
||||||
driver.bus.usb.uhci.UnitTest;
|
driver.bus.usb.uhci.UnitTest;
|
||||||
@@ -66,6 +69,7 @@ begin
|
|||||||
core.ds.prio.UnitTest;
|
core.ds.prio.UnitTest;
|
||||||
driver.storage.vfs.UnitTest;
|
driver.storage.vfs.UnitTest;
|
||||||
driver.storage.test.UnitTest;
|
driver.storage.test.UnitTest;
|
||||||
|
driver.storage.metatest.UnitTest;
|
||||||
core.enc.fnv1a.UnitTest;
|
core.enc.fnv1a.UnitTest;
|
||||||
core.enc.djb2.UnitTest;
|
core.enc.djb2.UnitTest;
|
||||||
core.ds.bloom.UnitTest;
|
core.ds.bloom.UnitTest;
|
||||||
|
|||||||
Reference in new issue
Block a user