feat: auto-mount boot drive to /boot; fix FAT32 deleted entry triple fault
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Decode multiboot boot_device byte in storagemanager to identify boot device - Add isBootDevice to TStorage_Device; propagate isBootDrive to volumes - Create /boot VFS directory at init; mount boot volume there in auto_mount_volumes - Fix getDirEntries skipping \-marked (deleted) FAT32 entries to prevent triple fault when navigating into a deleted directory via file picker
This commit is contained in:
1 parent
deb513c925
commit
3a733b1559
14 files changed
+1063
-310
No files matched your search
@@ -490,6 +490,12 @@ begin
|
||||
while i < maxEntries do begin
|
||||
if PDirectory(buffer)[i].fileName[0] = char(0) then break;
|
||||
|
||||
{ Skip deleted entries ($E5 = FAT32 deleted marker) }
|
||||
if PDirectory(buffer)[i].fileName[0] = char($E5) then begin
|
||||
i+=1;
|
||||
continue;
|
||||
end;
|
||||
|
||||
dirElm:= LL_Add(directories);
|
||||
PDirectory(dirElm)^:= PDirectory(buffer)[i];
|
||||
i+=1;
|
||||
@@ -535,6 +541,9 @@ begin
|
||||
for i:= 0 to LL_Size(list) - 1 do begin
|
||||
dir := PDirectory(LL_get(list, i));
|
||||
|
||||
{ Skip deleted entries (should already be filtered by getDirEntries, but guard here too) }
|
||||
if dir^.fileName[0] = char($E5) then continue;
|
||||
|
||||
{ Trim trailing spaces from fileName (8 bytes) }
|
||||
nameLen := 8;
|
||||
while (nameLen > 0) and (dir^.fileName[nameLen - 1] = ' ') do
|
||||
|
||||
@@ -448,7 +448,7 @@ begin
|
||||
volume^.sectorCount := pvd^.volumeSpaceSizeLSB;
|
||||
volume^.freeSectors := 0;
|
||||
volume^.filesystem := @filesystem;
|
||||
volume^.isBootDrive := false;
|
||||
volume^.isBootDrive := disk^.isBootDevice;
|
||||
|
||||
volumemanager.register_volume(disk, volume);
|
||||
|
||||
|
||||
@@ -52,7 +52,15 @@ var
|
||||
storageDevices : PDList;
|
||||
nextDeviceId : uint32;
|
||||
|
||||
{ BIOS drive byte from multiboot — set once during kernel init before any
|
||||
device drivers run. $80=first HDD, $81=second HDD, $9F/other=CD-ROM. }
|
||||
bootDriveByte : uint8;
|
||||
hdCount : uint32; { non-ATAPI devices registered so far }
|
||||
atapiCount : uint32; { ATAPI devices registered so far }
|
||||
|
||||
procedure init();
|
||||
procedure set_boot_drive_byte(driveByte : uint8);
|
||||
function get_boot_drive_byte() : uint8;
|
||||
procedure register_device(device : PStorage_Device);
|
||||
function get_device_list() : PDList;
|
||||
function get_device_count() : uint32;
|
||||
@@ -147,7 +155,22 @@ procedure init();
|
||||
begin
|
||||
push_trace('StorageManager.init');
|
||||
storageDevices := DL_New(sizeof(TStorage_Device));
|
||||
nextDeviceId := 0;
|
||||
nextDeviceId := 0;
|
||||
bootDriveByte := $FF; { $FF = unknown/uninitialised }
|
||||
hdCount := 0;
|
||||
atapiCount := 0;
|
||||
end;
|
||||
|
||||
procedure set_boot_drive_byte(driveByte : uint8);
|
||||
begin
|
||||
bootDriveByte := driveByte;
|
||||
syslog.log('STRMGR', 'Boot drive BIOS byte = 0x');
|
||||
syslog.writehexln(driveByte);
|
||||
end;
|
||||
|
||||
function get_boot_drive_byte() : uint8;
|
||||
begin
|
||||
get_boot_drive_byte := bootDriveByte;
|
||||
end;
|
||||
|
||||
procedure register_device(device : PStorage_Device);
|
||||
@@ -163,6 +186,7 @@ begin
|
||||
device^.requestQueue := CFIFO_New(SizeOf(TIORequest), 32);
|
||||
device^.activeRequest := nil;
|
||||
device^.cachedMBR := nil;
|
||||
device^.isBootDevice := false;
|
||||
{ dispatchRead/dispatchWrite: left as-is — driver sets them before
|
||||
calling register_device. memset(0) guarantees nil for unmigrated drivers. }
|
||||
|
||||
@@ -172,6 +196,31 @@ begin
|
||||
{ Get pointer to the DList copy so volumes reference the canonical device }
|
||||
storedDev := PStorage_Device(DL_Get(storageDevices, DL_Size(storageDevices) - 1));
|
||||
|
||||
{ Identify whether this is the boot device using the BIOS drive byte.
|
||||
BIOS numbers HDDs from $80 upward; the nth HDD is $80 + (n-1).
|
||||
ATAPI/CD-ROM devices are NOT in the $80-range HDD sequence, so if
|
||||
bootDriveByte does not match any HDD we have seen, the first ATAPI
|
||||
device is marked as the boot device (covers standard ISO boot). }
|
||||
if (storedDev^.controller = ControllerATAPI) or
|
||||
(storedDev^.controller = ControllerAHCI_ATAPI) then begin
|
||||
{ ATAPI device: boot if the drive byte is outside the known HDD range }
|
||||
if bootDriveByte < ($80 + hdCount) then begin
|
||||
{ drive byte refers to an HDD — this ATAPI is not the boot device }
|
||||
end else if atapiCount = 0 then begin
|
||||
{ first ATAPI and boot byte is not a known HDD → this is the boot drive }
|
||||
storedDev^.isBootDevice := true;
|
||||
syslog.logln('STRMGR', 'Boot device identified (ATAPI/ISO).');
|
||||
end;
|
||||
atapiCount := atapiCount + 1;
|
||||
end else begin
|
||||
{ Non-ATAPI (HDD): boot if BIOS drive byte matches $80 + index }
|
||||
if bootDriveByte = ($80 + hdCount) then begin
|
||||
storedDev^.isBootDevice := true;
|
||||
syslog.logln('STRMGR', 'Boot device identified (HDD).');
|
||||
end;
|
||||
hdCount := hdCount + 1;
|
||||
end;
|
||||
|
||||
{ Discover partitions and register volumes automatically }
|
||||
if storedDev^.maxSectorCount > 0 then
|
||||
volumemanager.discover_volumes(storedDev);
|
||||
|
||||
@@ -209,6 +209,7 @@ type
|
||||
sectorSize : uint32; //in bytes
|
||||
start : uint32; //start of device in sectors
|
||||
cachedMBR : pointer; { cached MBR data, nil if not yet read }
|
||||
isBootDevice : boolean; { true if this is the device GRUB booted from }
|
||||
end;
|
||||
|
||||
{ Filesystem driver descriptor }
|
||||
|
||||
@@ -430,6 +430,7 @@ begin
|
||||
if (dirList <> nil) and (status^ = 0) and (LL_Size(dirList) > 0) then begin
|
||||
for i := 0 to LL_Size(dirList) - 1 do begin
|
||||
entry := PDirectory_Entry(LL_Get(dirList, i));
|
||||
if (entry = nil) or (entry^.fileName = nil) then continue;
|
||||
newObj := PVFSObject(kalloc(sizeof(TVFSObject)));
|
||||
newObj^.Parent := Parent;
|
||||
newObj^.Reference := nil;
|
||||
@@ -2062,6 +2063,12 @@ begin
|
||||
syslog.writestring(' volume at ');
|
||||
syslog.writestringln(mountPath);
|
||||
|
||||
{ If this is the boot volume, also mount it at /boot }
|
||||
if vol^.isBootDrive then begin
|
||||
mountVolume('/boot', vol);
|
||||
syslog.writestringln('VFS: Boot volume mounted at /boot');
|
||||
end;
|
||||
|
||||
kfree(void(volName));
|
||||
kfree(void(prefix));
|
||||
kfree(void(mountPath));
|
||||
@@ -2135,6 +2142,7 @@ begin
|
||||
newVirtualDirectory('/disk');
|
||||
newVirtualDirectory('/mnt');
|
||||
newVirtualDirectory('/cfg');
|
||||
newVirtualDirectory('/boot');
|
||||
|
||||
{ Register Terminal Commands }
|
||||
stdio.registerCommand('LS', @VFS_COMMAND_LS, 'List directory contents.');
|
||||
|
||||
@@ -81,7 +81,7 @@ begin
|
||||
volume^.sectorSize := device^.sectorSize;
|
||||
volume^.freeSectors := 0;
|
||||
volume^.filesystem := nil;
|
||||
volume^.isBootDrive := false;
|
||||
volume^.isBootDrive := device^.isBootDevice;
|
||||
filesystemmanager.probe_volume(volume);
|
||||
register_volume(device, volume);
|
||||
end;
|
||||
|
||||
+27
-1
@@ -22,7 +22,12 @@ unit hashmap;
|
||||
interface
|
||||
|
||||
uses
|
||||
md5, util, strings, lmemorymanager, tracer, syslog;
|
||||
lmemorymanager,
|
||||
md5,
|
||||
strings,
|
||||
syslog,
|
||||
tracer,
|
||||
util;
|
||||
|
||||
type
|
||||
DPHashItem = ^PHashItem;
|
||||
@@ -45,12 +50,16 @@ const
|
||||
HASHMAP_DEFAULT_SIZE = 16;
|
||||
HASHMAP_DEFAULT_LOADFACTOR = 0.75;
|
||||
|
||||
type
|
||||
THashForEachCb = procedure(key: pchar; data: void; ud: void);
|
||||
|
||||
function new : PHashMap;
|
||||
function newEx(size : uint32; loadFactor : Single) : PHashMap;
|
||||
procedure add(map : PHashMap; key : pchar; value : void);
|
||||
function get(map : PHashMap; key : pchar) : void;
|
||||
procedure delete(map : PHashMap; key : pchar; freeItem : boolean);
|
||||
procedure printMap(map : PHashMap);
|
||||
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||
|
||||
implementation
|
||||
|
||||
@@ -257,6 +266,23 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
||||
var
|
||||
i : uint32;
|
||||
item : PHashItem;
|
||||
begin
|
||||
if (map = nil) or (map^.Size = 0) or (map^.Table = nil) then exit;
|
||||
if cb = nil then exit;
|
||||
for i := 0 to map^.Size - 1 do begin
|
||||
item := map^.Table[i];
|
||||
while item <> nil do begin
|
||||
if item^.Key <> nil then
|
||||
cb(item^.Key, item^.Data, ud);
|
||||
item := item^.Next;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure printMap(map : PHashMap);
|
||||
var
|
||||
i,c : uint32;
|
||||
|
||||
@@ -230,6 +230,7 @@ begin
|
||||
drivermanagement.init();
|
||||
tracer.push_trace('kmain.STRMGMT');
|
||||
storagemanager.init();
|
||||
storagemanager.set_boot_drive_byte((multibootinfo^.boot_device shr 24) and $FF);
|
||||
volumemanager.init();
|
||||
filesystemmanager.init();
|
||||
|
||||
|
||||
+902
-213
File diff suppressed because it is too large.
Load diff
+21
-66
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user