Implemented partition detection

This commit is contained in:
Alex 2022-11-02 04:14:06 +02:00
parent 2650202bc5
commit ca33e7b85b
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
4 changed files with 320 additions and 1 deletions

155
Core/Disk.cpp Normal file
View File

@ -0,0 +1,155 @@
#include <disk.hpp>
#include <memory.hpp>
#include <printf.h>
#include "../kernel.h"
#include "../DAPI.hpp"
#include "../Fex.hpp"
namespace Disk
{
void Manager::FetchDisks(unsigned long DriverUID)
{
KernelCallback *callback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = FetchReason;
DriverManager->IOCB(DriverUID, (void *)callback);
this->AvailablePorts = callback->DiskCallback.Fetch.Ports;
this->BytesPerSector = callback->DiskCallback.Fetch.BytesPerSector;
if (this->AvailablePorts <= 0)
{
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
return;
}
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector));
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
{
Drive *drive = new Drive;
sprintf_(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
// TODO: Implement disk type detection. Very useful in the future.
drive->MechanicalDisk = true;
memset(RWBuffer, 0, this->BytesPerSector);
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 0,
.SectorCount = 2,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, (void *)callback);
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
/*
----> Add to devfs the disk
*/
if (drive->Table.GPT.Signature == GPT_MAGIC)
{
drive->Style = GPT;
uint32_t Entries = 512 / drive->Table.GPT.EntrySize;
uint32_t Sectors = drive->Table.GPT.PartCount / Entries;
for (uint32_t Block = 0; Block < Sectors; Block++)
{
memset(RWBuffer, 0, this->BytesPerSector);
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 2 + Block,
.SectorCount = 1,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, (void *)callback);
for (uint32_t e = 0; e < Entries; e++)
{
GUIDPartitionTablePartition GPTPartition = reinterpret_cast<GUIDPartitionTablePartition *>(RWBuffer)[e];
if (GPTPartition.TypeLow || GPTPartition.TypeHigh)
{
Partition *partition = new Partition;
memcpy(partition->Label, GPTPartition.Label, sizeof(partition->Label));
partition->StartLBA = GPTPartition.StartLBA;
partition->EndLBA = GPTPartition.EndLBA;
partition->Sectors = partition->EndLBA - partition->StartLBA;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = GPT;
if (GPTPartition.Attributes & 1)
partition->Flags |= EFISystemPartition;
partition->Index = drive->Partitions.size();
// why there is NUL (\0) between every char?????
char PartName[72];
memcpy(PartName, GPTPartition.Label, 72);
for (char i = 0; i < 72; i++)
if (PartName[i] == '\0')
PartName[i] = ' ';
PartName[71] = '\0';
trace("GPT partition \"%s\" found with %lld sectors", PartName, partition->Sectors);
drive->Partitions.push_back(partition);
char *PartitionName = new char[64];
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
----> Add to devfs the disk
*/
delete[] PartitionName;
}
}
}
trace("%d GPT partitions found.", drive->Partitions.size());
}
else if (drive->Table.MBR.Signature[0] == MBR_MAGIC0 && drive->Table.MBR.Signature[1] == MBR_MAGIC1)
{
drive->Style = MBR;
for (size_t p = 0; p < 4; p++)
if (drive->Table.MBR.Partitions[p].LBAFirst != 0)
{
Partition *partition = new Partition;
partition->StartLBA = drive->Table.MBR.Partitions[p].LBAFirst;
partition->EndLBA = drive->Table.MBR.Partitions[p].LBAFirst + drive->Table.MBR.Partitions[p].Sectors;
partition->Sectors = drive->Table.MBR.Partitions[p].Sectors;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = MBR;
partition->Index = drive->Partitions.size();
trace("Partition \"%#llx\" found with %lld sectors.", drive->Table.MBR.UniqueID, partition->Sectors);
drive->Partitions.push_back(partition);
char *PartitionName = new char[64];
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
----> Add to devfs the disk
*/
delete[] PartitionName;
}
trace("%d MBR partitions found.", drive->Partitions.size());
}
else
warn("No partition table found on port %d!", ItrPort);
drives.push_back(drive);
}
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
}
Manager::Manager()
{
}
Manager::~Manager()
{
}
}

View File

@ -6,13 +6,19 @@
#include <printf.h>
#include <cwalk.h>
#include "DAPI.hpp"
#include "Fex.hpp"
Driver::Driver *DriverManager = nullptr;
Disk::Manager *DiskManager = nullptr;
void StartFilesystem()
{
KPrint("Initializing Filesystem...");
vfs = new FileSystem::Virtual;
new FileSystem::USTAR((uint64_t)bInfo->Modules[0].Address, vfs); // TODO: Detect initrd
KPrint("Initializing Disk Manager...");
DiskManager = new Disk::Manager;
/* ... */
TEXIT(0);
}
@ -24,6 +30,19 @@ void LoadDrivers()
TEXIT(0);
}
void FetchDisks()
{
KPrint("Fetching Disks...");
foreach (auto Driver in DriverManager->GetDrivers())
{
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)Driver->Address + EXTENDED_SECTION_ADDRESS);
if (DrvExtHdr->Driver.Type == FexDriverType::FexDriverType_Storage)
DiskManager->FetchDisks(Driver->DriverUID);
}
TEXIT(0);
}
void KernelMainThread()
{
Tasking::TCB *CurrentWorker = nullptr;
@ -31,7 +50,7 @@ void KernelMainThread()
KPrint("C++ Language Version (__cplusplus) :%ld", __cplusplus);
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)StartFilesystem);
CurrentWorker->Rename("Filesystem");
CurrentWorker->Rename("Disk");
CurrentWorker->SetPriority(100);
TaskManager->WaitForThread(CurrentWorker);
@ -39,6 +58,12 @@ void KernelMainThread()
CurrentWorker->Rename("Drivers");
CurrentWorker->SetPriority(100);
TaskManager->WaitForThread(CurrentWorker);
CurrentWorker = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (Tasking::IP)FetchDisks);
CurrentWorker->Rename("Fetch Disks");
CurrentWorker->SetPriority(100);
TaskManager->WaitForThread(CurrentWorker);
KPrint("Waiting for userspace process to start...");
/* Load init file */
CPU::Halt(true);

137
include/disk.hpp Normal file
View File

@ -0,0 +1,137 @@
#ifndef __FENNIX_KERNEL_DISK_H__
#define __FENNIX_KERNEL_DISK_H__
#include <types.h>
#include <vector.hpp>
namespace Disk
{
#define MBR_MAGIC0 0x55
#define MBR_MAGIC1 0xAA
// "EFI PART"
#define GPT_MAGIC 0x5452415020494645ULL
enum PartitionStyle
{
Unknown,
MBR,
GPT
};
enum PartitionFlags
{
Present,
Bootable,
EFISystemPartition
};
struct MasterBootRecordPartition
{
uint8_t Flags;
uint8_t CHSFirst[3];
uint8_t Type;
uint8_t CHSLast[3];
uint32_t LBAFirst;
uint32_t Sectors;
} __attribute__((packed));
struct MasterBootRecord
{
uint8_t Bootstrap[440];
uint32_t UniqueID;
uint16_t Reserved;
MasterBootRecordPartition Partitions[4];
uint8_t Signature[2];
} __attribute__((packed));
struct GUIDPartitionTablePartition
{
uint64_t TypeLow;
uint64_t TypeHigh;
uint64_t GUIDLow;
uint64_t GUIDHigh;
uint64_t StartLBA;
uint64_t EndLBA;
uint64_t Attributes;
char Label[72];
} __attribute__((packed));
struct GUIDPartitionTable
{
uint64_t Signature;
uint32_t Revision;
uint32_t HdrSize;
uint32_t HdrCRC32;
uint32_t Reserved;
uint64_t LBA;
uint64_t ALTLBA;
uint64_t FirstBlock;
uint64_t LastBlock;
uint64_t GUIDLow;
uint64_t GUIDHigh;
uint64_t PartLBA;
uint32_t PartCount;
uint32_t EntrySize;
uint32_t PartCRC32;
} __attribute__((packed));
struct PartitionTable
{
MasterBootRecord MBR;
GUIDPartitionTable GPT;
};
class Partition
{
public:
char Label[72] = "Unidentified Partition";
uint64_t StartLBA = 0xdeadbeef;
uint64_t EndLBA = 0xdeadbeef;
uint64_t Sectors = 0xdeadbeef;
uint64_t Flags = 0xdeadbeef;
unsigned char Port = 0xdeadbeef;
PartitionStyle Style = PartitionStyle::Unknown;
size_t Index = 0;
uint64_t Read(uint64_t Offset, uint64_t Count, uint8_t *Buffer) {}
uint64_t Write(uint64_t Offset, uint64_t Count, uint8_t *Buffer) {}
Partition() {}
~Partition() {}
};
class Drive
{
public:
char Name[64] = "Unidentified Drive";
uint8_t *Buffer = nullptr;
PartitionTable Table;
PartitionStyle Style = PartitionStyle::Unknown;
Vector<Partition *> Partitions;
bool MechanicalDisk = false;
uint64_t UniqueIdentifier = 0xdeadbeef;
uint64_t Read(uint64_t Offset, uint64_t Count, uint8_t *Buffer) {}
uint64_t Write(uint64_t Offset, uint64_t Count, uint8_t *Buffer) {}
Drive()
{ // TODO: Allocate buffer
}
~Drive() {}
};
class Manager
{
private:
unsigned char AvailablePorts = 0;
int BytesPerSector = 0;
Vector<Drive *> drives;
public:
void FetchDisks(unsigned long DriverUID);
Manager();
~Manager();
};
}
#endif // !__FENNIX_KERNEL_DISK_H__

View File

@ -13,6 +13,7 @@
#include <power.hpp>
#include <task.hpp>
#include <time.hpp>
#include <disk.hpp>
#include <pci.hpp>
#endif
@ -27,6 +28,7 @@ extern Tasking::Task *TaskManager;
extern Time::time *TimeManager;
extern FileSystem::Virtual *vfs;
extern Driver::Driver *DriverManager;
extern Disk::Manager *DiskManager;
#define PEXIT(Code) TaskManager->GetCurrentProcess()->ExitCode = Code
#define TEXIT(Code) TaskManager->GetCurrentThread()->ExitCode = Code