Port storage and filesystems to x86_64 with stable device ownership

This commit is contained in:
Aaron committed 2026-11-08 09:02:33 +00:00
1 parent a27d9cb39d
commit f8911ccdec
24 files changed
+1131 -695

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -28,8 +28,7 @@ uses
core.ds.lists, core.ds.lists,
memory.heap, memory.heap,
driver.bus.pci, driver.bus.pci,
core.util, arch.x86.util, core.util;
arch.x86.memory.virtual;
const const
AHCI_CONTROLLER_MODE = $80000000; AHCI_CONTROLLER_MODE = $80000000;
@@ -278,6 +277,7 @@ type
device_type : TDeviceType; device_type : TDeviceType;
ata_info : TIdentResponse; ata_info : TIdentResponse;
supportsNCQ : boolean; supportsNCQ : boolean;
supports64BitDMA: boolean;
queueDepth : uint32; { safe active depth for this device } queueDepth : uint32; { safe active depth for this device }
slotCount : uint32; { controller slot count from CAP.NCS + 1 } slotCount : uint32; { controller slot count from CAP.NCS + 1 }
command_list : PHBA_CMD_HEADER; command_list : PHBA_CMD_HEADER;
File diff suppressed because it is too large. Load diff
@@ -62,7 +62,7 @@ implementation
uses uses
driver.storage.vfs, driver.storage.types, memory.heap, core.strings, driver.storage.vfs, driver.storage.types, memory.heap, core.strings,
core.strings.helpers, debug.tracer, io.syslog, core.util, arch.x86.util; core.strings.helpers, debug.tracer, io.syslog, core.util, arch.platform.cpu;
type type
THandlerEntry = record THandlerEntry = record
@@ -124,7 +124,7 @@ begin
Handlers[i].Used := true; Handlers[i].Used := true;
Handlers[i].Kind := hkMagic; Handlers[i].Kind := hkMagic;
Handlers[i].MagicLen := magicLen; Handlers[i].MagicLen := magicLen;
memcpy(uint32(magic), uint32(@Handlers[i].Magic[0]), magicLen); memcpy(PtrUInt(magic), PtrUInt(@Handlers[i].Magic[0]), magicLen);
copyName(@Handlers[i].Name[0], name, 16); copyName(@Handlers[i].Name[0], name, 16);
Handlers[i].Handler := handler; Handlers[i].Handler := handler;
inc(HandlerCount); inc(HandlerCount);
@@ -149,7 +149,7 @@ begin
if not Handlers[i].Used then begin if not Handlers[i].Used then begin
Handlers[i].Used := true; Handlers[i].Used := true;
Handlers[i].Kind := hkExtension; Handlers[i].Kind := hkExtension;
memcpy(uint32(extList), uint32(@Handlers[i].ExtList[0]), len); memcpy(PtrUInt(extList), PtrUInt(@Handlers[i].ExtList[0]), len);
Handlers[i].ExtList[len] := #0; Handlers[i].ExtList[len] := #0;
copyName(@Handlers[i].Name[0], name, 16); copyName(@Handlers[i].Name[0], name, 16);
Handlers[i].Handler := handler; Handlers[i].Handler := handler;
@@ -224,7 +224,7 @@ begin
fh := driver.storage.vfs.OpenFile(absPath, omRead, @err); fh := driver.storage.vfs.OpenFile(absPath, omRead, @err);
if fh = 0 then exit; if fh = 0 then exit;
memset(uint32(@headerBuf[0]), 0, MAX_MAGIC_LEN); memset(PtrUInt(@headerBuf[0]), 0, MAX_MAGIC_LEN);
bytesRead := driver.storage.vfs.ReadFile(fh, 0, @headerBuf[0], MAX_MAGIC_LEN); bytesRead := driver.storage.vfs.ReadFile(fh, 0, @headerBuf[0], MAX_MAGIC_LEN);
driver.storage.vfs.CloseFile(fh); driver.storage.vfs.CloseFile(fh);
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
+140
View File
@@ -0,0 +1,140 @@
// Copyright 2026 Aaron Hance
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{ Path syntax shared by VFS and boot consumers; no volume or driver access.
Returned strings are caller-owned. Normalization is lexical, not symlink
resolution, and never climbs above the root. }
unit driver.storage.path;
interface
function absolute(path, baseDir: pchar): pchar;
function normalize(path: pchar): pchar;
procedure UnitTest;
implementation
uses core.strings, core.util, memory.heap, arch.platform.diagnostics;
function absolute(path, baseDir: pchar): pchar;
var
pathLen, baseLen, separator: uint32;
result: pchar;
begin
absolute := nil;
if path = nil then begin
absolute := stringCopy('/');
exit;
end;
if path[0] = '/' then begin
absolute := stringCopy(path);
exit;
end;
if (baseDir = nil) or (baseDir[0] = #0) then baseDir := '/';
pathLen := StringSize(path);
baseLen := StringSize(baseDir);
separator := 0;
if baseDir[baseLen - 1] <> '/' then separator := 1;
if pathLen >= High(uint32) - separator then exit;
if baseLen >= High(uint32) - pathLen - separator then exit;
result := stringNew(baseLen + separator + pathLen);
if result = nil then exit;
memcpy(PtrUInt(baseDir), PtrUInt(result), baseLen);
if separator <> 0 then result[baseLen] := '/';
memcpy(PtrUInt(path), PtrUInt(result) + baseLen + separator, pathLen);
absolute := result;
end;
function normalize(path: pchar): pchar;
var
length, readPos, start, count, used: uint32;
result: pchar;
begin
normalize := nil;
if path = nil then path := '';
length := StringSize(path);
if length >= High(uint32) - 1 then exit;
result := stringNew(length + 1);
if result = nil then exit;
result[0] := '/';
used := 1;
readPos := 0;
while readPos < length do begin
if path[readPos] = '/' then begin
inc(readPos);
continue;
end;
start := readPos;
while (readPos < length) and (path[readPos] <> '/') do inc(readPos);
count := readPos - start;
if (count = 1) and (path[start] = '.') then continue;
if (count = 2) and (path[start] = '.') and (path[start + 1] = '.') then begin
while (used > 1) and (result[used - 1] <> '/') do dec(used);
if used > 1 then dec(used);
end else begin
if used > 1 then begin
result[used] := '/';
inc(used);
end;
memcpy(PtrUInt(path) + start, PtrUInt(result) + used, count);
inc(used, count);
end;
end;
result[used] := #0;
normalize := result;
end;
procedure UnitTest;
var
passed, failed: uint32;
beforeFree: SizeUInt;
procedure Check(actual, expected: pchar);
begin
if StringEquals(actual, expected) then
inc(passed)
else begin
inc(failed);
log('PATH', 'FAIL: path result');
end;
kfree(void(actual));
end;
begin
passed := 0;
failed := 0;
beforeFree := lmm_total_free;
Check(absolute('file', '/disk'), '/disk/file');
Check(absolute('file', '/disk/'), '/disk/file');
Check(absolute('/file', '/disk'), '/file');
Check(absolute('file', ''), '/file');
Check(absolute('file', nil), '/file');
Check(absolute(nil, '/disk'), '/');
Check(absolute('', '/disk'), '/disk/');
Check(normalize('/a//b/./c/../..'), '/a');
Check(normalize('../../a/..'), '/');
Check(normalize('/a/../b/../c'), '/c');
Check(normalize('a/b/'), '/a/b');
Check(normalize('/.../.hidden'), '/.../.hidden');
Check(normalize(''), '/');
Check(normalize(nil), '/');
if lmm_total_free = beforeFree then
inc(passed)
else begin
inc(failed);
log('PATH', 'FAIL: path allocation accounting');
end;
testSummary('PATH', 'PATH_TESTS_PASSED', 'PATH_TESTS_FAILED', passed, failed);
end;
end.
+1 -1
View File
@@ -275,7 +275,7 @@ type
TStorage_Device = record TStorage_Device = record
id : uint8; id : uint8;
controller : TControllerType; controller : TControllerType;
controllerId0 : uint32; controllerId0 : PtrUInt;
writable : boolean; writable : boolean;
removed : boolean; { true if device was hot-unplugged } removed : boolean; { true if device was hot-unplugged }
volumes : PDList; volumes : PDList;
File diff suppressed because it is too large. Load diff
@@ -32,7 +32,7 @@ uses
core.strings, core.strings,
io.stdio, io.stdio,
debug.tracer, debug.tracer,
core.util, arch.x86.util; core.util, arch.platform.cpu;
type type
@@ -91,7 +91,7 @@ var
begin begin
buffer := puint32(kalloc(disk^.sectorSize)) buffer := puint32(kalloc(disk^.sectorSize))
memset(uint32(buffer), 0, disk^.sectorSize); memset(PtrUInt(buffer), 0, disk^.sectorSize);
PFilesystemRecord := PFilesystemRecord(buffer); PFilesystemRecord := PFilesystemRecord(buffer);
filesystemRecord^.magicNumber := $A2F2; filesystemRecord^.magicNumber := $A2F2;
@@ -102,7 +102,7 @@ begin
//filesystemRecord.volumeLabel := config^ //filesystemRecord.volumeLabel := config^
driver.storage.mgr.storage_write(disk, start, 1, buffer); driver.storage.mgr.storage_write(disk, start, 1, buffer);
memset(uint32(buffer), 0, disk^.sectorSize); memset(PtrUInt(buffer), 0, disk^.sectorSize);
fileEntry := PFileEntry(buffer)[0]; fileEntry := PFileEntry(buffer)[0];
fileEntry^.filename := thisArray; fileEntry^.filename := thisArray;
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
File diff suppressed because it is too large. Load diff
@@ -14,7 +14,7 @@ uses driver.storage.fs.ext2.types, driver.storage.fs.ext2.core,
function ValidateLabel(text : pchar; var normalized : TVolumeLabel) : TError; function ValidateLabel(text : pchar; var normalized : TVolumeLabel) : TError;
var i : uint32; var i : uint32;
begin begin
memset(uint32(@normalized),0,sizeof(normalized)); memset(PtrUInt(@normalized),0,sizeof(normalized));
ValidateLabel:=eInvalidArgument; if text=nil then exit; ValidateLabel:=eInvalidArgument; if text=nil then exit;
i:=0; i:=0;
while (i<16) and (text[i]<>char(0)) do begin while (i<16) and (text[i]<>char(0)) do begin
@@ -29,7 +29,7 @@ function Geometry(volume : PStorage_Volume; sectors, start : uint32; config : PF
var g, count, minimum, perBlock, tables, reserve : uint32; labelText : TVolumeLabel; var g, count, minimum, perBlock, tables, reserve : uint32; labelText : TVolumeLabel;
begin begin
Geometry:=eInvalidArgument; Geometry:=eInvalidArgument;
memset(uint32(@v),0,sizeof(v)); memset(PtrUInt(@v),0,sizeof(v));
if volume=nil then exit; if volume=nil then exit;
if volume^.device=nil then exit; if volume^.device=nil then exit;
if not volume^.device^.writable then begin Geometry:=eReadOnly; exit; end; if not volume^.device^.writable then begin Geometry:=eReadOnly; exit; end;
@@ -98,7 +98,7 @@ begin
if err<>eNone then begin kfree(void(v)); FormatVolume:=err; exit; end; if err<>eNone then begin kfree(void(v)); FormatVolume:=err; exit; end;
op:=PExt2Op(kalloc(sizeof(TExt2Op))); op:=PExt2Op(kalloc(sizeof(TExt2Op)));
if op=nil then begin kfree(void(v)); exit; end; if op=nil then begin kfree(void(v)); exit; end;
memset(uint32(op),0,sizeof(TExt2Op)); op^.V:=v; memset(PtrUInt(op),0,sizeof(TExt2Op)); op^.V:=v;
v^.Super:=puint8(kalloc(1024)); v^.Groups:=puint8(kalloc(v^.GDTBlocks*v^.BlockSize)); v^.Super:=puint8(kalloc(1024)); v^.Groups:=puint8(kalloc(v^.GDTBlocks*v^.BlockSize));
op^.Scratch:=puint8(kalloc(v^.BlockSize)); op^.Scratch:=puint8(kalloc(v^.BlockSize));
if (v^.Super=nil) or (v^.Groups=nil) or (op^.Scratch=nil) then begin if (v^.Super=nil) or (v^.Groups=nil) or (op^.Scratch=nil) then begin
@@ -106,7 +106,7 @@ begin
if op^.Scratch<>nil then kfree(void(op^.Scratch)); if op^.Scratch<>nil then kfree(void(op^.Scratch));
kfree(void(op)); kfree(void(v)); exit; kfree(void(op)); kfree(void(v)); exit;
end; end;
memset(uint32(v^.Super),0,1024); memset(uint32(v^.Groups),0,v^.GDTBlocks*v^.BlockSize); memset(PtrUInt(v^.Super),0,1024); memset(PtrUInt(v^.Groups),0,v^.GDTBlocks*v^.BlockSize);
Put32(v^.Super,0,v^.InodeCount); Put32(v^.Super,4,v^.BlockCount); Put32(v^.Super,0,v^.InodeCount); Put32(v^.Super,4,v^.BlockCount);
Put32(v^.Super,16,v^.InodeCount-10); Put32(v^.Super,20,v^.FirstBlock); Put32(v^.Super,16,v^.InodeCount-10); Put32(v^.Super,20,v^.FirstBlock);
i:=0; if v^.BlockSize=2048 then i:=1 else if v^.BlockSize=4096 then i:=2; i:=0; if v^.BlockSize=2048 then i:=1 else if v^.BlockSize=4096 then i:=2;
@@ -120,13 +120,13 @@ begin
v^.Super[110]:=(v^.Super[110] and $0F) or $40; v^.Super[110]:=(v^.Super[110] and $0F) or $40;
v^.Super[112]:=(v^.Super[112] and $3F) or $80; v^.Super[112]:=(v^.Super[112] and $3F) or $80;
if config<>nil then if (config^.Flags and FS_FORMAT_PARAM_LABEL)<>0 then if config<>nil then if (config^.Flags and FS_FORMAT_PARAM_LABEL)<>0 then
memcpy(uint32(@config^.LabelText[0]),uint32(v^.Super)+120,11); memcpy(PtrUInt(@config^.LabelText[0]),PtrUInt(v^.Super)+120,11);
tables:=v^.InodesPerGroup div (v^.BlockSize div 128); freeBlocks:=0; rootBlock:=0; tables:=v^.InodesPerGroup div (v^.BlockSize div 128); freeBlocks:=0; rootBlock:=0;
for g:=0 to v^.GroupCount-1 do begin for g:=0 to v^.GroupCount-1 do begin
first:=v^.FirstBlock+g*v^.BlocksPerGroup; count:=v^.BlockCount-first; first:=v^.FirstBlock+g*v^.BlocksPerGroup; count:=v^.BlockCount-first;
if count>v^.BlocksPerGroup then count:=v^.BlocksPerGroup; if count>v^.BlocksPerGroup then count:=v^.BlocksPerGroup;
reserve:=0; if HasSuper(g,1) then reserve:=1+v^.GDTBlocks; reserve:=0; if HasSuper(g,1) then reserve:=1+v^.GDTBlocks;
d:=PExt2Group(uint32(v^.Groups)+g*32); d:=PExt2Group(PtrUInt(v^.Groups)+g*32);
d^.BlockBitmap:=first+reserve; d^.InodeBitmap:=first+reserve+1; d^.InodeTable:=first+reserve+2; d^.BlockBitmap:=first+reserve; d^.InodeBitmap:=first+reserve+1; d^.InodeTable:=first+reserve+2;
used:=reserve+2+tables; used:=reserve+2+tables;
d^.FreeInodes:=v^.InodesPerGroup; d^.FreeInodes:=v^.InodesPerGroup;
@@ -135,42 +135,42 @@ begin
end; end;
Put32(v^.Super,12,freeBlocks); Put32(v^.Super,12,freeBlocks);
{ Invalidate the primary signature before writing metadata. Publish it last. } { Invalidate the primary signature before writing metadata. Publish it last. }
memset(uint32(op^.Scratch),0,v^.BlockSize); memset(PtrUInt(op^.Scratch),0,v^.BlockSize);
op^.Error:=storage_write(volume^.device,start+2,2,puint32(op^.Scratch)); op^.Error:=storage_write(volume^.device,start+2,2,puint32(op^.Scratch));
g:=0; g:=0;
while (g<v^.GroupCount) and (op^.Error=eNone) do begin while (g<v^.GroupCount) and (op^.Error=eNone) do begin
first:=v^.FirstBlock+g*v^.BlocksPerGroup; count:=v^.BlockCount-first; first:=v^.FirstBlock+g*v^.BlocksPerGroup; count:=v^.BlockCount-first;
if count>v^.BlocksPerGroup then count:=v^.BlocksPerGroup; if count>v^.BlocksPerGroup then count:=v^.BlocksPerGroup;
d:=PExt2Group(uint32(v^.Groups)+g*32); used:=count-d^.FreeBlocks; d:=PExt2Group(PtrUInt(v^.Groups)+g*32); used:=count-d^.FreeBlocks;
memset(uint32(op^.Scratch),$FF,v^.BlockSize); memset(PtrUInt(op^.Scratch),$FF,v^.BlockSize);
for bit:=used to count-1 do op^.Scratch[bit div 8]:=op^.Scratch[bit div 8] and not (1 shl (bit mod 8)); for bit:=used to count-1 do op^.Scratch[bit div 8]:=op^.Scratch[bit div 8] and not (1 shl (bit mod 8));
WriteBlock(op,d^.BlockBitmap,op^.Scratch); WriteBlock(op,d^.BlockBitmap,op^.Scratch);
memset(uint32(op^.Scratch),$FF,v^.BlockSize); memset(PtrUInt(op^.Scratch),$FF,v^.BlockSize);
used:=0; if g=0 then used:=10; used:=0; if g=0 then used:=10;
for bit:=used to v^.InodesPerGroup-1 do op^.Scratch[bit div 8]:=op^.Scratch[bit div 8] and not (1 shl (bit mod 8)); for bit:=used to v^.InodesPerGroup-1 do op^.Scratch[bit div 8]:=op^.Scratch[bit div 8] and not (1 shl (bit mod 8));
WriteBlock(op,d^.InodeBitmap,op^.Scratch); WriteBlock(op,d^.InodeBitmap,op^.Scratch);
memset(uint32(op^.Scratch),0,v^.BlockSize); memset(PtrUInt(op^.Scratch),0,v^.BlockSize);
for i:=0 to tables-1 do begin for i:=0 to tables-1 do begin
if not WriteBlock(op,d^.InodeTable+i,op^.Scratch) then break; if not WriteBlock(op,d^.InodeTable+i,op^.Scratch) then break;
end; end;
if HasSuper(g,1) then begin if HasSuper(g,1) then begin
for i:=0 to v^.GDTBlocks-1 do for i:=0 to v^.GDTBlocks-1 do
if not WriteBlock(op,first+1+i,pointer(uint32(v^.Groups)+i*v^.BlockSize)) then break; if not WriteBlock(op,first+1+i,pointer(PtrUInt(v^.Groups)+i*v^.BlockSize)) then break;
if g<>0 then begin if g<>0 then begin
memset(uint32(op^.Scratch),0,v^.BlockSize); memset(PtrUInt(op^.Scratch),0,v^.BlockSize);
memcpy(uint32(v^.Super),uint32(op^.Scratch),1024); Put16(op^.Scratch,90,g); memcpy(PtrUInt(v^.Super),PtrUInt(op^.Scratch),1024); Put16(op^.Scratch,90,g);
WriteBlock(op,first,op^.Scratch); WriteBlock(op,first,op^.Scratch);
end; end;
end; end;
Inc(g); Inc(g);
end; end;
if op^.Error=eNone then begin if op^.Error=eNone then begin
memset(uint32(op^.Scratch),0,v^.BlockSize); memset(PtrUInt(op^.Scratch),0,v^.BlockSize);
inode:=PExt2Inode(uint32(op^.Scratch)+128); inode:=PExt2Inode(PtrUInt(op^.Scratch)+128);
inode^.Mode:=EXT2_DIR or $1ED; inode^.Size:=v^.BlockSize; inode^.Links:=2; inode^.Mode:=EXT2_DIR or $1ED; inode^.Size:=v^.BlockSize; inode^.Links:=2;
inode^.Sectors:=v^.SectorsPerBlock; inode^.Blocks[0]:=rootBlock; inode^.Sectors:=v^.SectorsPerBlock; inode^.Blocks[0]:=rootBlock;
WriteBlock(op,PExt2Group(v^.Groups)^.InodeTable,op^.Scratch); WriteBlock(op,PExt2Group(v^.Groups)^.InodeTable,op^.Scratch);
memset(uint32(op^.Scratch),0,v^.BlockSize); memset(PtrUInt(op^.Scratch),0,v^.BlockSize);
Put32(op^.Scratch,0,2); Put16(op^.Scratch,4,12); op^.Scratch[6]:=1; op^.Scratch[7]:=2; op^.Scratch[8]:=ord('.'); Put32(op^.Scratch,0,2); Put16(op^.Scratch,4,12); op^.Scratch[6]:=1; op^.Scratch[7]:=2; op^.Scratch[8]:=ord('.');
Put32(op^.Scratch,12,2); Put16(op^.Scratch,16,v^.BlockSize-12); op^.Scratch[18]:=2; op^.Scratch[19]:=2; Put32(op^.Scratch,12,2); Put16(op^.Scratch,16,v^.BlockSize-12); op^.Scratch[18]:=2; op^.Scratch[19]:=2;
op^.Scratch[20]:=ord('.'); op^.Scratch[21]:=ord('.'); op^.Scratch[20]:=ord('.'); op^.Scratch[21]:=ord('.');
@@ -188,14 +188,14 @@ begin
SetLabel:=ValidateLabel(text,labelText); if SetLabel<>eNone then exit; SetLabel:=ValidateLabel(text,labelText); if SetLabel<>eNone then exit;
op:=BeginOp(volume); if op=nil then begin SetLabel:=eOutOfMemory; exit; end; op:=BeginOp(volume); if op=nil then begin SetLabel:=eOutOfMemory; exit; end;
if BeginMutation(op) then begin if BeginMutation(op) then begin
memcpy(uint32(@labelText),uint32(op^.V^.Super)+120,16); memcpy(PtrUInt(@labelText),PtrUInt(op^.V^.Super)+120,16);
for g:=1 to op^.V^.GroupCount-1 do if HasSuper(g,Get32(op^.V^.Super,100)) then begin for g:=1 to op^.V^.GroupCount-1 do if HasSuper(g,Get32(op^.V^.Super,100)) then begin
first:=op^.V^.FirstBlock+g*op^.V^.BlocksPerGroup; first:=op^.V^.FirstBlock+g*op^.V^.BlocksPerGroup;
if not ReadBlock(op,first,op^.Scratch) then break; if not ReadBlock(op,first,op^.Scratch) then break;
memcpy(uint32(@labelText),uint32(op^.Scratch)+120,16); memcpy(PtrUInt(@labelText),PtrUInt(op^.Scratch)+120,16);
if not WriteBlock(op,first,op^.Scratch) then break; if not WriteBlock(op,first,op^.Scratch) then break;
end; end;
if FinishMutation(op) then memcpy(uint32(@labelText),uint32(@volume^.labelText),sizeof(labelText)); if FinishMutation(op) then memcpy(PtrUInt(@labelText),PtrUInt(@volume^.labelText),sizeof(labelText));
end; end;
SetLabel:=op^.Error; EndOp(op); SetLabel:=op^.Error; EndOp(op);
end; end;
@@ -1,12 +1,13 @@
unit driver.storage.fs.ext2; unit driver.storage.fs.ext2;
interface interface
uses driver.storage.types; uses arch.platform.cpu, driver.storage.types;
procedure StartWorker;
procedure init; procedure init;
procedure ReleaseVolume(volume : PStorage_Volume); procedure ReleaseVolume(volume : PStorage_Volume);
implementation implementation
uses boot.mgr, driver.storage.fs.mgr, driver.storage.vol.mgr, uses driver.storage.fs.mgr, driver.storage.vol.mgr,
driver.storage.fs.ext2.types, driver.storage.fs.ext2.core, driver.storage.fs.ext2.types, driver.storage.fs.ext2.core,
driver.storage.fs.ext2.format, memory.heap, core.util, core.strings, driver.storage.fs.ext2.format, memory.heap, core.util, core.strings,
proc.mgr, proc.types; proc.mgr, proc.types;
@@ -62,15 +63,17 @@ begin
end; end;
procedure WorkLoop(pctx : PProcessContext); procedure WorkLoop(pctx : PProcessContext);
var work : PWork; done : uint32; error : TError; callback : TIOCallback; data : pointer; var
savedIRQ: PtrUInt;
work : PWork; done : uint32; error : TError; callback : TIOCallback; data : pointer;
begin begin
while true do begin while true do begin
asm pushf; cli end; savedIRQ := arch.platform.cpu.lock;
work:=head; work:=head;
if work<>nil then begin if work<>nil then begin
head:=work^.Next; if head=nil then tail:=nil; Dec(queued); head:=work^.Next; if head=nil then tail:=nil; Dec(queued);
end else pctx^.State:=psAwaiting; end else pctx^.State:=psAwaiting;
asm popf end; arch.platform.cpu.unlock(savedIRQ);
if work=nil then begin if work=nil then begin
{ Queue publication wakes the worker under the same CLI section. { Queue publication wakes the worker under the same CLI section.
No per-I/O process, IRQ continuation, or volatile spin is needed. } No per-I/O process, IRQ continuation, or volatile spin is needed. }
@@ -92,7 +95,9 @@ begin worker:=proc.mgr.create('ext2.io',@WorkLoop,nil,1); end;
procedure QueueTransfer(volume : PStorage_Volume; directory, name : pchar; offset : uint32; procedure QueueTransfer(volume : PStorage_Volume; directory, name : pchar; offset : uint32;
buffer : puint32; count : uint32; ctx : pointer; completed : puint32; buffer : puint32; count : uint32; ctx : pointer; completed : puint32;
callback : TIOCallback; data : pointer; writing : boolean); callback : TIOCallback; data : pointer; writing : boolean);
var work : PWork; error : TError; var
savedIRQ: PtrUInt;
work : PWork; error : TError;
begin begin
if completed<>nil then completed^:=0; if completed<>nil then completed^:=0;
error:=eNone; error:=eNone;
@@ -101,7 +106,7 @@ begin
if error<>eNone then begin if callback<>nil then callback(error,data); exit; end; if error<>eNone then begin if callback<>nil then callback(error,data); exit; end;
work:=PWork(kalloc(sizeof(TWork))); work:=PWork(kalloc(sizeof(TWork)));
if work=nil then begin if callback<>nil then callback(eOutOfMemory,data); exit; end; if work=nil then begin if callback<>nil then callback(eOutOfMemory,data); exit; end;
memset(uint32(work),0,sizeof(TWork)); memset(PtrUInt(work),0,sizeof(TWork));
if ctx=nil then begin if ctx=nil then begin
if (directory=nil) or (name=nil) then error:=eInvalidArgument else begin if (directory=nil) or (name=nil) then error:=eInvalidArgument else begin
work^.Directory:=stringCopy(directory); work^.Name:=stringCopy(name); work^.Directory:=stringCopy(directory); work^.Name:=stringCopy(name);
@@ -112,13 +117,13 @@ begin
work^.Volume:=volume; work^.FileCtx:=PExt2File(ctx); work^.Offset:=offset; work^.Volume:=volume; work^.FileCtx:=PExt2File(ctx); work^.Offset:=offset;
work^.Buffer:=buffer; work^.Count:=count; work^.Completed:=completed; work^.Buffer:=buffer; work^.Count:=count; work^.Completed:=completed;
work^.Writing:=writing; work^.Callback:=callback; work^.CallbackData:=data; work^.Writing:=writing; work^.Callback:=callback; work^.CallbackData:=data;
asm pushf; cli end; savedIRQ := arch.platform.cpu.lock;
if queued>=64 then error:=eQueueFull else begin if queued>=64 then error:=eQueueFull else begin
if tail=nil then head:=work else tail^.Next:=work; if tail=nil then head:=work else tail^.Next:=work;
tail:=work; Inc(queued); tail:=work; Inc(queued);
if worker^.State=psAwaiting then worker^.State:=psReady; if worker^.State=psAwaiting then worker^.State:=psReady;
end; end;
asm popf end; arch.platform.cpu.unlock(savedIRQ);
if error<>eNone then begin FreeWork(work); if callback<>nil then callback(error,data); end; if error<>eNone then begin FreeWork(work); if callback<>nil then callback(error,data); end;
end; end;
@@ -177,7 +182,7 @@ var volume : PStorage_Volume;
begin begin
if device=nil then exit; if device=nil then exit;
volume:=PStorage_Volume(kalloc(sizeof(TStorage_Volume))); if volume=nil then exit; volume:=PStorage_Volume(kalloc(sizeof(TStorage_Volume))); if volume=nil then exit;
memset(uint32(volume),0,sizeof(TStorage_Volume)); memset(PtrUInt(volume),0,sizeof(TStorage_Volume));
volume^.device:=device; volume^.sectorCount:=device^.maxSectorCount; volume^.sectorSize:=device^.sectorSize; volume^.device:=device; volume^.sectorCount:=device^.maxSectorCount; volume^.sectorSize:=device^.sectorSize;
if Identify(volume) then begin if Identify(volume) then begin
volume^.filesystem:=@filesystem; volume^.filesystem:=@filesystem;
@@ -187,7 +192,7 @@ end;
procedure init; procedure init;
begin begin
memset(uint32(@filesystem),0,sizeof(filesystem)); memset(PtrUInt(@filesystem),0,sizeof(filesystem));
filesystem.sName:='EXT2'; filesystem.system_id:=$83; filesystem.sName:='EXT2'; filesystem.system_id:=$83;
filesystem.identifyCallback:=@Identify; filesystem.detectCallback:=@Detect; filesystem.identifyCallback:=@Identify; filesystem.detectCallback:=@Detect;
filesystem.validateFormat:=@ValidateFormat; filesystem.createCallback:=@FormatVolume; filesystem.validateFormat:=@ValidateFormat; filesystem.createCallback:=@FormatVolume;
@@ -203,7 +208,4 @@ begin
driver.storage.fs.mgr.register_filesystem(@filesystem); driver.storage.fs.mgr.register_filesystem(@filesystem);
end; end;
initialization
boot.mgr.registerBoot('driver.storage.fs.ext2',@init,'Ext2 Filesystem','driver.storage.fs.mgr');
boot.mgr.registerBoot('driver.storage.ext2.worker',@StartWorker,'Ext2 I/O Worker','proc.mgr');
end. end.
File diff suppressed because it is too large. Load diff
@@ -14,7 +14,7 @@ function normalize_label(text : pchar; var normalized : TVolumeLabel) : TError;
var i, n, first : uint32; c : char; var i, n, first : uint32; c : char;
begin begin
normalize_label := eInvalidArgument; normalize_label := eInvalidArgument;
memset(uint32(@normalized[0]), 0, sizeof(normalized)); memset(PtrUInt(@normalized[0]), 0, sizeof(normalized));
if text = nil then exit; if text = nil then exit;
n := 0; n := 0;
while (n < 12) and (text[n] <> #0) do Inc(n); while (n < 12) and (text[n] <> #0) do Inc(n);
@@ -37,7 +37,7 @@ end;
procedure unpack_label(src : pchar; var dest : TVolumeLabel); procedure unpack_label(src : pchar; var dest : TVolumeLabel);
var n, i : uint32; var n, i : uint32;
begin begin
memset(uint32(@dest[0]), 0, sizeof(dest)); memset(PtrUInt(@dest[0]), 0, sizeof(dest));
n := 11; while (n > 0) and ((src[n-1] = ' ') or (src[n-1] = #0)) do Dec(n); n := 11; while (n > 0) and ((src[n-1] = ' ') or (src[n-1] = #0)) do Dec(n);
for i := 0 to 10 do if i < n then dest[i] := src[i]; for i := 0 to 10 do if i < n then dest[i] := src[i];
end; end;
@@ -62,7 +62,7 @@ begin
br := PBootRecord(buffer); lim := FAT32ClusterLimit(br); br := PBootRecord(buffer); lim := FAT32ClusterLimit(br);
if (lim <= 2) or (br^.manySectors = 0) or (br^.manySectors > volume^.sectorCount) or if (lim <= 2) or (br^.manySectors = 0) or (br^.manySectors > volume^.sectorCount) or
(br^.rootCluster < 2) or (br^.rootCluster >= lim) or (br^.rootCluster < 2) or (br^.rootCluster >= lim) or
(puint16(uint32(buffer)+510)^ <> $AA55) then load_boot := eCorruptFilesystem; (puint16(PtrUInt(buffer)+510)^ <> $AA55) then load_boot := eCorruptFilesystem;
end; end;
{ Bounded walk of the root FAT chain. A label is authoritative when present. { Bounded walk of the root FAT chain. A label is authoritative when present.
@@ -113,12 +113,12 @@ var mem, boot, scratch : puint32; sector, offset, i : uint32; found, noName : bo
begin begin
mem := puint32(kalloc(1024)); mem := puint32(kalloc(1024));
if mem = nil then begin read_label := eOutOfMemory; exit; end; if mem = nil then begin read_label := eOutOfMemory; exit; end;
boot := mem; scratch := puint32(uint32(mem)+512); boot := mem; scratch := puint32(PtrUInt(mem)+512);
read_label := load_boot(volume,boot); read_label := load_boot(volume,boot);
if read_label = eNone then begin if read_label = eNone then begin
read_label := locate_label(volume,PBootRecord(boot),scratch,sector,offset,found); read_label := locate_label(volume,PBootRecord(boot),scratch,sector,offset,found);
if read_label = eNone then begin if read_label = eNone then begin
if found then unpack_label(pchar(uint32(scratch)+offset),value) if found then unpack_label(pchar(PtrUInt(scratch)+offset),value)
else begin else begin
unpack_label(pchar(@PBootRecord(boot)^.volumeLabel[0]),value); unpack_label(pchar(@PBootRecord(boot)^.volumeLabel[0]),value);
noName := true; noName := true;
@@ -142,8 +142,8 @@ begin
if not volume^.device^.writable then begin write_label := eReadOnly; exit; end; if not volume^.device^.writable then begin write_label := eReadOnly; exit; end;
mem := puint32(kalloc(5*512)); mem := puint32(kalloc(5*512));
if mem = nil then begin write_label := eOutOfMemory; exit; end; if mem = nil then begin write_label := eOutOfMemory; exit; end;
boot := mem; scratch := puint32(uint32(mem)+512); rootOld := puint32(uint32(mem)+1024); boot := mem; scratch := puint32(PtrUInt(mem)+512); rootOld := puint32(PtrUInt(mem)+1024);
backupOld := puint32(uint32(mem)+1536); bootOld := puint32(uint32(mem)+2048); backupOld := puint32(PtrUInt(mem)+1536); bootOld := puint32(PtrUInt(mem)+2048);
bootWritten := false; backupWritten := false; rootWritten := false; backup := 0; bootWritten := false; backupWritten := false; rootWritten := false; backup := 0;
repeat repeat
write_label := load_boot(volume,boot); if write_label <> eNone then break; write_label := load_boot(volume,boot); if write_label <> eNone then break;
@@ -153,17 +153,17 @@ begin
if (sector = 0) and (value[0] <> #0) then begin write_label := eDiskFull; break; end; if (sector = 0) and (value[0] <> #0) then begin write_label := eDiskFull; break; end;
if sector <> 0 then begin if sector <> 0 then begin
write_label := storage_read(volume^.device,sector,1,scratch); if write_label <> eNone then break; write_label := storage_read(volume^.device,sector,1,scratch); if write_label <> eNone then break;
memcpy(uint32(scratch),uint32(rootOld),512); memcpy(PtrUInt(scratch),PtrUInt(rootOld),512);
entry := PDirectory(uint32(scratch)+offset); entry := PDirectory(PtrUInt(scratch)+offset);
if value[0] = #0 then begin if value[0] = #0 then begin
if found then entry^.fileName[0] := char($E5); if found then entry^.fileName[0] := char($E5);
end else begin end else begin
if entry^.fileName[0] = #0 then begin if entry^.fileName[0] = #0 then begin
{ Retain an end marker after a newly inserted label. } { Retain an end marker after a newly inserted label. }
if offset = 480 then begin write_label := eDiskFull; break; end; if offset = 480 then begin write_label := eDiskFull; break; end;
puint8(uint32(entry)+32)^ := 0; puint8(PtrUInt(entry)+32)^ := 0;
end; end;
memset(uint32(entry),0,32); pack_label(@value[0],@entry^.fileName[0]); entry^.attributes := $08; memset(PtrUInt(entry),0,32); pack_label(@value[0],@entry^.fileName[0]); entry^.attributes := $08;
end; end;
end; end;
if (br^.backupCluster <> 0) and (br^.backupCluster <> $FFFF) then begin if (br^.backupCluster <> 0) and (br^.backupCluster <> $FFFF) then begin
@@ -171,7 +171,7 @@ begin
backup := volume^.sectorStart+br^.backupCluster; backup := volume^.sectorStart+br^.backupCluster;
write_label := storage_read(volume^.device,backup,1,backupOld); if write_label <> eNone then break; write_label := storage_read(volume^.device,backup,1,backupOld); if write_label <> eNone then break;
end; end;
memcpy(uint32(boot),uint32(bootOld),512); memcpy(PtrUInt(boot),PtrUInt(bootOld),512);
if value[0] = #0 then pack_label('NO NAME',pchar(@br^.volumeLabel[0])) if value[0] = #0 then pack_label('NO NAME',pchar(@br^.volumeLabel[0]))
else pack_label(@value[0],pchar(@br^.volumeLabel[0])); else pack_label(@value[0],pchar(@br^.volumeLabel[0]));
bootWritten := true; bootWritten := true;
@@ -180,7 +180,7 @@ begin
bootWritten := true; bootWritten := true;
if backup <> 0 then begin if backup <> 0 then begin
{ Preserve backup-specific bytes; only update its label. } { Preserve backup-specific bytes; only update its label. }
memcpy(uint32(backupOld),uint32(boot),512); memcpy(PtrUInt(backupOld),PtrUInt(boot),512);
if value[0] = #0 then pack_label('NO NAME',pchar(@br^.volumeLabel[0])) if value[0] = #0 then pack_label('NO NAME',pchar(@br^.volumeLabel[0]))
else pack_label(@value[0],pchar(@br^.volumeLabel[0])); else pack_label(@value[0],pchar(@br^.volumeLabel[0]));
backupWritten := true; backupWritten := true;
@@ -3,7 +3,6 @@ unit driver.storage.fs.fat32;
interface interface
uses uses
boot.mgr,
driver.storage.fs.mgr, driver.storage.fs.mgr,
driver.storage.types; driver.storage.types;
@@ -31,7 +30,7 @@ end;
procedure init; procedure init;
begin begin
io.syslog.logln('FAT32', 'init: registering FAT32 filesystem'); io.syslog.logln('FAT32', 'init: registering FAT32 filesystem');
memset(uint32(@filesystem), 0, sizeof(TFilesystem)); memset(PtrUInt(@filesystem), 0, sizeof(TFilesystem));
filesystem.sName := 'FAT32'; filesystem.sName := 'FAT32';
filesystem.system_id := $0B; filesystem.system_id := $0B;
filesystem.readDirCallback := @FAT32ReadDirectory; filesystem.readDirCallback := @FAT32ReadDirectory;
@@ -61,7 +60,4 @@ begin
driver.storage.fs.mgr.register_filesystem(@filesystem); driver.storage.fs.mgr.register_filesystem(@filesystem);
end; end;
initialization
boot.mgr.registerBoot('driver.storage.fs.fat32', @init, 'FAT32 Filesystem', 'driver.storage.fs.mgr');
end. end.
Loaded 20 of 24 files, more files were not shown because too many files have changed in this diff. Show more