mirror of https://gitlab.com/nakst/essence
gpt partition table parsing
This commit is contained in:
parent
d005957fc5
commit
dad8952e87
|
@ -78,8 +78,10 @@ run_kernel64:
|
|||
mov rcx,[rbx + 24]
|
||||
|
||||
; Map the first MB at 0xFFFFFE0000000000 --> 0xFFFFFE0000100000
|
||||
mov rax,[0xFFFFFF7FBFDFE000]
|
||||
mov [0xFFFFFF7FBFDFEFE0],rax
|
||||
mov rdi,0xFFFFFF7FBFDFE000
|
||||
mov rax,[rdi]
|
||||
mov rdi,0xFFFFFF7FBFDFEFE0
|
||||
mov [rdi],rax
|
||||
mov rax,cr3
|
||||
mov cr3,rax
|
||||
|
||||
|
|
|
@ -1882,7 +1882,6 @@ struct EsFontInformation {
|
|||
struct EsBlockDeviceInformation {
|
||||
size_t sectorSize;
|
||||
EsFileOffset sectorCount;
|
||||
bool noMBR;
|
||||
bool readOnly;
|
||||
uint8_t nestLevel;
|
||||
uint8_t driveType;
|
||||
|
|
|
@ -488,7 +488,6 @@ static void DeviceAttach(KDevice *parent) {
|
|||
}
|
||||
}
|
||||
|
||||
volume->rootDirectory->driverNode = volume->root;
|
||||
volume->directoryEntryDataBytes = sizeof(DirectoryEntryReference);
|
||||
volume->nodeDataBytes = sizeof(FSNode);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ struct ElfSectionHeader {
|
|||
uint64_t entrySize;
|
||||
};
|
||||
|
||||
struct ElfProgramHeader{
|
||||
struct ElfProgramHeader {
|
||||
uint32_t type; // 0 = unused, 1 = load, 2 = dynamic, 3 = interp, 4 = note
|
||||
uint32_t flags; // 1 = executable, 2 = writable, 4 = readable
|
||||
uint64_t fileOffset;
|
||||
|
|
|
@ -1679,7 +1679,8 @@ void FSPartitionDeviceAccess(KBlockDeviceAccessRequest request) {
|
|||
FSBlockDeviceAccess(request);
|
||||
}
|
||||
|
||||
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *model, size_t modelBytes) {
|
||||
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, uint32_t flags, const char *model, size_t modelBytes) {
|
||||
(void) flags;
|
||||
PartitionDevice *child = (PartitionDevice *) KDeviceCreate("Partition", parent, sizeof(PartitionDevice));
|
||||
if (!child) return;
|
||||
|
||||
|
@ -1691,7 +1692,6 @@ void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOf
|
|||
child->maxAccessSectorCount = parent->maxAccessSectorCount;
|
||||
child->sectorOffset = offset;
|
||||
child->information.sectorCount = sectorCount;
|
||||
child->information.noMBR = flags & FS_PARTITION_DEVICE_NO_MBR ? true : false;
|
||||
child->information.readOnly = parent->information.readOnly;
|
||||
child->access = FSPartitionDeviceAccess;
|
||||
child->information.modelBytes = modelBytes;
|
||||
|
@ -1739,7 +1739,26 @@ bool FSCheckMBR(KBlockDevice *device) {
|
|||
if (partitions[i].present) {
|
||||
KernelLog(LOG_INFO, "FS", "MBR partition", "Found MBR partition %d with offset %d and count %d.\n",
|
||||
i, partitions[i].offset, partitions[i].count);
|
||||
FSPartitionDeviceCreate(device, partitions[i].offset, partitions[i].count, FS_PARTITION_DEVICE_NO_MBR, EsLiteral("MBR partition"));
|
||||
FSPartitionDeviceCreate(device, partitions[i].offset, partitions[i].count, ES_FLAGS_DEFAULT, EsLiteral("MBR partition"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FSCheckGPT(KBlockDevice *device) {
|
||||
GPTPartition *partitions = (GPTPartition *) EsHeapAllocate(sizeof(GPTPartition) * GPT_PARTITION_COUNT, false, K_FIXED);
|
||||
EsDefer(EsHeapFree(partitions, sizeof(GPTPartition) * GPT_PARTITION_COUNT, K_FIXED));
|
||||
|
||||
if (GPTGetPartitions(device->signatureBlock, device->information.sectorCount, device->information.sectorSize, partitions)) {
|
||||
for (uintptr_t i = 0; i < GPT_PARTITION_COUNT; i++) {
|
||||
if (partitions[i].present) {
|
||||
KernelLog(LOG_INFO, "FS", "GPT partition", "Found GPT partition %d with offset %d and count %d%z.\n",
|
||||
i, partitions[i].offset, partitions[i].count, partitions[i].isESP ? "; this is the ESP" : "");
|
||||
FSPartitionDeviceCreate(device, partitions[i].offset, partitions[i].count, ES_FLAGS_DEFAULT, EsLiteral("GPT partition"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1828,9 @@ void FSDetectFileSystem(KBlockDevice *device) {
|
|||
// We could not access the block device.
|
||||
KernelLog(LOG_ERROR, "FS", "detect fileSystem read failure", "The signature block could not be read on block device %x.\n", device);
|
||||
} else {
|
||||
if (!device->information.noMBR && FSCheckMBR(device)) {
|
||||
if (!device->information.nestLevel && FSCheckGPT(device)) {
|
||||
// Found a GPT.
|
||||
} else if (!device->information.nestLevel && FSCheckMBR(device)) {
|
||||
// Found an MBR.
|
||||
} else {
|
||||
KDeviceAttach(device, "Files", FSSignatureCheck);
|
||||
|
|
|
@ -640,8 +640,7 @@ struct KBlockDevice : KDevice {
|
|||
KMutex detectFileSystemMutex;
|
||||
};
|
||||
|
||||
#define FS_PARTITION_DEVICE_NO_MBR (1 << 0)
|
||||
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *name, size_t nameBytes);
|
||||
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, uint32_t flags, const char *name, size_t nameBytes);
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// PCI.
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#ifndef K_SIGNATURE_BLOCK_SIZE
|
||||
#define K_SIGNATURE_BLOCK_SIZE (65536)
|
||||
#endif
|
||||
|
||||
typedef struct MBRPartition {
|
||||
uint32_t offset, count;
|
||||
bool present;
|
||||
} MBRPartition;
|
||||
|
||||
bool MBRGetPartitions(uint8_t *firstBlock, EsFileOffset sectorCount, MBRPartition *partitions) {
|
||||
bool MBRGetPartitions(uint8_t *firstBlock, EsFileOffset sectorCount, MBRPartition *partitions /* 4 */) {
|
||||
if (firstBlock[510] != 0x55 || firstBlock[511] != 0xAA) {
|
||||
return false;
|
||||
}
|
||||
|
@ -53,3 +57,76 @@ void MBRFixPartition(uint32_t *partitions) {
|
|||
partitions[0] |= (partitionOffsetHead << 8) | (partitionOffsetSector << 16) | (partitionOffsetCylinder << 24) | ((partitionOffsetCylinder >> 8) << 16);
|
||||
partitions[1] |= (partitionSizeHead << 8) | (partitionSizeSector << 16) | (partitionSizeCylinder << 24) | ((partitionSizeCylinder >> 8) << 16);
|
||||
}
|
||||
|
||||
#define GPT_PARTITION_COUNT (0x80)
|
||||
|
||||
typedef struct GPTPartition {
|
||||
uint64_t offset, count;
|
||||
bool present, isESP;
|
||||
} GPTPartition;
|
||||
|
||||
bool GPTGetPartitions(uint8_t *block /* K_SIGNATURE_BLOCK_SIZE */, EsFileOffset sectorCount,
|
||||
EsFileOffset sectorBytes, GPTPartition *partitions /* GPT_PARTITION_COUNT */) {
|
||||
for (uintptr_t i = 0; i < GPT_PARTITION_COUNT; i++) {
|
||||
partitions[i].present = false;
|
||||
}
|
||||
|
||||
if (sectorBytes * 2 >= K_SIGNATURE_BLOCK_SIZE || sectorCount <= 2 || sectorBytes < 0x200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *signature = "EFI PART";
|
||||
|
||||
for (uintptr_t i = 0; i < 8; i++) {
|
||||
if (block[sectorBytes + i] != signature[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t partitionEntryCount = *(uint32_t *) (block + sectorBytes + 80);
|
||||
uint32_t partitionEntryBytes = *(uint32_t *) (block + sectorBytes + 84);
|
||||
|
||||
if (partitionEntryBytes < 0x80 || partitionEntryBytes > sectorBytes || sectorBytes % partitionEntryBytes
|
||||
|| partitionEntryCount == 0 || partitionEntryBytes > 0x1000 || partitionEntryCount > 0x1000
|
||||
|| partitionEntryBytes * partitionEntryCount / sectorBytes + 2 >= sectorCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (partitionEntryCount > GPT_PARTITION_COUNT) {
|
||||
partitionEntryCount = GPT_PARTITION_COUNT;
|
||||
}
|
||||
|
||||
bool foundESP = false;
|
||||
|
||||
for (uintptr_t i = 0; i < partitionEntryCount; i++) {
|
||||
uint8_t *entry = block + sectorBytes * 2 + i * partitionEntryBytes;
|
||||
|
||||
uint64_t guidLow = *(uint64_t *) (entry + 0);
|
||||
uint64_t guidHigh = *(uint64_t *) (entry + 8);
|
||||
uint64_t firstLBA = *(uint64_t *) (entry + 32);
|
||||
uint64_t lastLBA = *(uint64_t *) (entry + 40);
|
||||
|
||||
if (!guidLow && !guidHigh) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!guidLow && !guidHigh) || firstLBA >= sectorCount || lastLBA >= sectorCount || firstLBA >= lastLBA) {
|
||||
return false;
|
||||
}
|
||||
|
||||
partitions[i].present = true;
|
||||
partitions[i].offset = firstLBA;
|
||||
partitions[i].count = lastLBA - firstLBA;
|
||||
partitions[i].isESP = guidLow == 0x11D2F81FC12A7328 && guidHigh == 0x3BC93EC9A0004BBA;
|
||||
|
||||
if (partitions[i].isESP) {
|
||||
if (foundESP) {
|
||||
return false;
|
||||
} else {
|
||||
foundESP = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1051,6 +1051,8 @@ void BuildBootloader(Application *application) {
|
|||
ExecuteForApp(application, toolchainNasm, "-MD", "bin/boot3.d", "-fbin",
|
||||
"boot/x86/loader.s", "-obin/stage2",
|
||||
"-Pboot/x86/esfs-stage2.s", (forEmulator && !bootUseVBE) ? "" : "-D BOOT_USE_VBE");
|
||||
ExecuteForApp(application, toolchainNasm, "-MD", "bin/boot4.d", "-fbin",
|
||||
"boot/x86/uefi_loader.s", "-obin/uefi_loader");
|
||||
}
|
||||
|
||||
File _drive;
|
||||
|
@ -1098,6 +1100,10 @@ void Install(const char *driveFile, uint64_t partitionSize, const char *partitio
|
|||
installationIdentifier.d[i] = rand();
|
||||
}
|
||||
|
||||
File iid = FileOpen("bin/iid.dat", 'w');
|
||||
FileWrite(iid, 16, &installationIdentifier);
|
||||
FileClose(iid);
|
||||
|
||||
File f = FileOpen(driveFile, 'w');
|
||||
|
||||
File mbr = FileOpen("bin/mbr", 'r');
|
||||
|
@ -1446,6 +1452,7 @@ int main(int argc, char **argv) {
|
|||
ADD_DEPENDENCY_FILE(application, "bin/boot1.d", "Boot1");
|
||||
ADD_DEPENDENCY_FILE(application, "bin/boot2.d", "Boot2");
|
||||
ADD_DEPENDENCY_FILE(application, "bin/boot3.d", "Boot3");
|
||||
ADD_DEPENDENCY_FILE(application, "bin/boot4.d", "Boot4");
|
||||
arrput(applications, application);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue