feat: support for USB mass storage devices, hotplugging

This commit is contained in:
2026-05-18 17:47:12 +02:00
parent f8e8af1d78
commit 41d2841cc9
36 changed files with 1537 additions and 130 deletions
+126 -40
View File
@@ -13,6 +13,8 @@ namespace Fs::FsProbe {
static ProbeFn g_probes[MaxProbes] = {};
static int g_probeCount = 0;
static bool g_mounted[Drivers::Storage::Gpt::MaxPartitions] = {};
static int g_driveForPart[Drivers::Storage::Gpt::MaxPartitions] = {};
void Register(ProbeFn fn) {
if (g_probeCount < MaxProbes && fn) {
@@ -27,56 +29,93 @@ namespace Fs::FsProbe {
memcmp(a.Data4, b.Data4, 8) == 0;
}
static int TryMountPartitionAtLowestDrive(int partIndex, int firstDrive, bool efiLog) {
if (!Vfs::IsInitialized()) return 0;
if (partIndex < 0 || partIndex >= Drivers::Storage::Gpt::MaxPartitions) return 0;
if (g_mounted[partIndex]) return 0;
auto* part = Drivers::Storage::Gpt::GetPartition(partIndex);
if (!part) return 0;
int driveNum = Vfs::FindLowestAvailableDrive(firstDrive);
if (driveNum < 0) {
Kt::KernelLogStream(Kt::WARNING, "FsProbe") << "No free drive slot for partition "
<< partIndex;
return -1;
}
for (int p = 0; p < g_probeCount; p++) {
Vfs::FsDriver* driver = g_probes[p](
part->BlockDevIndex, part->StartLba, part->SectorCount);
if (!driver) continue;
if (Vfs::RegisterDrive(driveNum, driver) == 0) {
g_mounted[partIndex] = true;
g_driveForPart[partIndex] = driveNum;
Kt::KernelLogStream(Kt::OK, "FsProbe")
<< (efiLog ? "Mounted EFI partition " : "Mounted partition ")
<< partIndex << " as drive " << driveNum;
return 1;
}
return -1;
}
Kt::KernelLogStream(Kt::INFO, "FsProbe") << "No filesystem recognized on partition "
<< partIndex;
return 0;
}
void MountPartitions(int firstDrive) {
int partCount = Drivers::Storage::Gpt::GetPartitionCount();
if (partCount == 0 || g_probeCount == 0) return;
int driveNum = firstDrive;
// First pass: mount non-EFI partitions so they get lower drive numbers
for (int i = 0; i < partCount && driveNum < Vfs::MaxDrives; i++) {
// First pass: mount non-EFI partitions so they get lower drive numbers.
for (int i = 0; i < partCount; i++) {
auto* part = Drivers::Storage::Gpt::GetPartition(i);
if (!part) continue;
if (IsEfiPartition(part)) continue;
for (int p = 0; p < g_probeCount; p++) {
Vfs::FsDriver* driver = g_probes[p](
part->BlockDevIndex, part->StartLba, part->SectorCount);
if (driver) {
Vfs::RegisterDrive(driveNum, driver);
Kt::KernelLogStream(Kt::OK, "FsProbe") << "Mounted partition "
<< i << " as drive " << driveNum;
driveNum++;
break;
}
}
if (!part || IsEfiPartition(part)) continue;
TryMountPartitionAtLowestDrive(i, firstDrive, false);
}
// Second pass: mount EFI system partitions after all others
for (int i = 0; i < partCount && driveNum < Vfs::MaxDrives; i++) {
// Second pass: mount EFI system partitions after all others.
for (int i = 0; i < partCount; i++) {
auto* part = Drivers::Storage::Gpt::GetPartition(i);
if (!part) continue;
if (!IsEfiPartition(part)) continue;
for (int p = 0; p < g_probeCount; p++) {
Vfs::FsDriver* driver = g_probes[p](
part->BlockDevIndex, part->StartLba, part->SectorCount);
if (driver) {
Vfs::RegisterDrive(driveNum, driver);
Kt::KernelLogStream(Kt::OK, "FsProbe") << "Mounted EFI partition "
<< i << " as drive " << driveNum;
driveNum++;
break;
}
}
if (!part || !IsEfiPartition(part)) continue;
TryMountPartitionAtLowestDrive(i, firstDrive, true);
}
}
int MountPartitionsForBlockDevice(int blockDevIndex, int firstDrive) {
if (!Vfs::IsInitialized() || g_probeCount == 0) return 0;
int partCount = Drivers::Storage::Gpt::GetPartitionCount();
int mounted = 0;
for (int i = 0; i < partCount; i++) {
auto* part = Drivers::Storage::Gpt::GetPartition(i);
if (!part || part->BlockDevIndex != blockDevIndex || IsEfiPartition(part)) continue;
int result = TryMountPartitionAtLowestDrive(i, firstDrive, false);
if (result > 0) mounted += result;
}
for (int i = 0; i < partCount; i++) {
auto* part = Drivers::Storage::Gpt::GetPartition(i);
if (!part || part->BlockDevIndex != blockDevIndex || !IsEfiPartition(part)) continue;
int result = TryMountPartitionAtLowestDrive(i, firstDrive, true);
if (result > 0) mounted += result;
}
return mounted;
}
int MountPartition(int partIndex, int driveNum) {
if (driveNum < 0 || driveNum >= Vfs::MaxDrives) return -1;
if (g_probeCount == 0) return -1;
if (partIndex >= 0 && partIndex < Drivers::Storage::Gpt::MaxPartitions && g_mounted[partIndex]) return -1;
if (Vfs::IsDriveRegistered(driveNum)) return -1;
auto* part = Drivers::Storage::Gpt::GetPartition(partIndex);
if (!part) return -1;
@@ -86,10 +125,16 @@ namespace Fs::FsProbe {
part->BlockDevIndex, part->StartLba, part->SectorCount);
if (driver) {
Vfs::RegisterDrive(driveNum, driver);
Kt::KernelLogStream(Kt::OK, "FsProbe") << "Mounted partition "
<< partIndex << " as drive " << driveNum;
return 0;
if (Vfs::RegisterDrive(driveNum, driver) == 0) {
if (partIndex >= 0 && partIndex < Drivers::Storage::Gpt::MaxPartitions) {
g_mounted[partIndex] = true;
g_driveForPart[partIndex] = driveNum;
}
Kt::KernelLogStream(Kt::OK, "FsProbe") << "Mounted partition "
<< partIndex << " as drive " << driveNum;
return 0;
}
return -1;
}
}
@@ -97,4 +142,45 @@ namespace Fs::FsProbe {
return -1;
}
int UnmountPartitionsForBlockDevice(int blockDevIndex) {
int partCount = Drivers::Storage::Gpt::GetPartitionCount();
int unmounted = 0;
int dst = 0;
for (int src = 0; src < partCount; src++) {
auto* part = Drivers::Storage::Gpt::GetPartition(src);
bool remove = part && part->BlockDevIndex == blockDevIndex;
if (remove) {
if (src < Drivers::Storage::Gpt::MaxPartitions &&
g_mounted[src] && g_driveForPart[src] >= 0) {
if (Vfs::UnregisterDrive(g_driveForPart[src]) == 0) {
unmounted++;
}
}
if (src < Drivers::Storage::Gpt::MaxPartitions) {
g_mounted[src] = false;
g_driveForPart[src] = -1;
}
continue;
}
if (src < Drivers::Storage::Gpt::MaxPartitions &&
dst < Drivers::Storage::Gpt::MaxPartitions) {
if (dst != src) {
g_mounted[dst] = g_mounted[src];
g_driveForPart[dst] = g_driveForPart[src];
}
dst++;
}
}
for (int i = dst; i < partCount && i < Drivers::Storage::Gpt::MaxPartitions; i++) {
g_mounted[i] = false;
g_driveForPart[i] = -1;
}
return unmounted;
}
};