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]
|
mov rcx,[rbx + 24]
|
||||||
|
|
||||||
; Map the first MB at 0xFFFFFE0000000000 --> 0xFFFFFE0000100000
|
; Map the first MB at 0xFFFFFE0000000000 --> 0xFFFFFE0000100000
|
||||||
mov rax,[0xFFFFFF7FBFDFE000]
|
mov rdi,0xFFFFFF7FBFDFE000
|
||||||
mov [0xFFFFFF7FBFDFEFE0],rax
|
mov rax,[rdi]
|
||||||
|
mov rdi,0xFFFFFF7FBFDFEFE0
|
||||||
|
mov [rdi],rax
|
||||||
mov rax,cr3
|
mov rax,cr3
|
||||||
mov cr3,rax
|
mov cr3,rax
|
||||||
|
|
||||||
|
|
|
@ -1882,7 +1882,6 @@ struct EsFontInformation {
|
||||||
struct EsBlockDeviceInformation {
|
struct EsBlockDeviceInformation {
|
||||||
size_t sectorSize;
|
size_t sectorSize;
|
||||||
EsFileOffset sectorCount;
|
EsFileOffset sectorCount;
|
||||||
bool noMBR;
|
|
||||||
bool readOnly;
|
bool readOnly;
|
||||||
uint8_t nestLevel;
|
uint8_t nestLevel;
|
||||||
uint8_t driveType;
|
uint8_t driveType;
|
||||||
|
|
|
@ -488,7 +488,6 @@ static void DeviceAttach(KDevice *parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
volume->rootDirectory->driverNode = volume->root;
|
|
||||||
volume->directoryEntryDataBytes = sizeof(DirectoryEntryReference);
|
volume->directoryEntryDataBytes = sizeof(DirectoryEntryReference);
|
||||||
volume->nodeDataBytes = sizeof(FSNode);
|
volume->nodeDataBytes = sizeof(FSNode);
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct ElfSectionHeader {
|
||||||
uint64_t entrySize;
|
uint64_t entrySize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ElfProgramHeader{
|
struct ElfProgramHeader {
|
||||||
uint32_t type; // 0 = unused, 1 = load, 2 = dynamic, 3 = interp, 4 = note
|
uint32_t type; // 0 = unused, 1 = load, 2 = dynamic, 3 = interp, 4 = note
|
||||||
uint32_t flags; // 1 = executable, 2 = writable, 4 = readable
|
uint32_t flags; // 1 = executable, 2 = writable, 4 = readable
|
||||||
uint64_t fileOffset;
|
uint64_t fileOffset;
|
||||||
|
|
|
@ -1679,7 +1679,8 @@ void FSPartitionDeviceAccess(KBlockDeviceAccessRequest request) {
|
||||||
FSBlockDeviceAccess(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));
|
PartitionDevice *child = (PartitionDevice *) KDeviceCreate("Partition", parent, sizeof(PartitionDevice));
|
||||||
if (!child) return;
|
if (!child) return;
|
||||||
|
|
||||||
|
@ -1691,7 +1692,6 @@ void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOf
|
||||||
child->maxAccessSectorCount = parent->maxAccessSectorCount;
|
child->maxAccessSectorCount = parent->maxAccessSectorCount;
|
||||||
child->sectorOffset = offset;
|
child->sectorOffset = offset;
|
||||||
child->information.sectorCount = sectorCount;
|
child->information.sectorCount = sectorCount;
|
||||||
child->information.noMBR = flags & FS_PARTITION_DEVICE_NO_MBR ? true : false;
|
|
||||||
child->information.readOnly = parent->information.readOnly;
|
child->information.readOnly = parent->information.readOnly;
|
||||||
child->access = FSPartitionDeviceAccess;
|
child->access = FSPartitionDeviceAccess;
|
||||||
child->information.modelBytes = modelBytes;
|
child->information.modelBytes = modelBytes;
|
||||||
|
@ -1739,7 +1739,26 @@ bool FSCheckMBR(KBlockDevice *device) {
|
||||||
if (partitions[i].present) {
|
if (partitions[i].present) {
|
||||||
KernelLog(LOG_INFO, "FS", "MBR partition", "Found MBR partition %d with offset %d and count %d.\n",
|
KernelLog(LOG_INFO, "FS", "MBR partition", "Found MBR partition %d with offset %d and count %d.\n",
|
||||||
i, partitions[i].offset, partitions[i].count);
|
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.
|
// 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);
|
KernelLog(LOG_ERROR, "FS", "detect fileSystem read failure", "The signature block could not be read on block device %x.\n", device);
|
||||||
} else {
|
} 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.
|
// Found an MBR.
|
||||||
} else {
|
} else {
|
||||||
KDeviceAttach(device, "Files", FSSignatureCheck);
|
KDeviceAttach(device, "Files", FSSignatureCheck);
|
||||||
|
|
|
@ -640,8 +640,7 @@ struct KBlockDevice : KDevice {
|
||||||
KMutex detectFileSystemMutex;
|
KMutex detectFileSystemMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FS_PARTITION_DEVICE_NO_MBR (1 << 0)
|
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, uint32_t flags, const char *name, size_t nameBytes);
|
||||||
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *name, size_t nameBytes);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------
|
||||||
// PCI.
|
// PCI.
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
#ifndef K_SIGNATURE_BLOCK_SIZE
|
||||||
|
#define K_SIGNATURE_BLOCK_SIZE (65536)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct MBRPartition {
|
typedef struct MBRPartition {
|
||||||
uint32_t offset, count;
|
uint32_t offset, count;
|
||||||
bool present;
|
bool present;
|
||||||
} MBRPartition;
|
} 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) {
|
if (firstBlock[510] != 0x55 || firstBlock[511] != 0xAA) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -53,3 +57,76 @@ void MBRFixPartition(uint32_t *partitions) {
|
||||||
partitions[0] |= (partitionOffsetHead << 8) | (partitionOffsetSector << 16) | (partitionOffsetCylinder << 24) | ((partitionOffsetCylinder >> 8) << 16);
|
partitions[0] |= (partitionOffsetHead << 8) | (partitionOffsetSector << 16) | (partitionOffsetCylinder << 24) | ((partitionOffsetCylinder >> 8) << 16);
|
||||||
partitions[1] |= (partitionSizeHead << 8) | (partitionSizeSector << 16) | (partitionSizeCylinder << 24) | ((partitionSizeCylinder >> 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",
|
ExecuteForApp(application, toolchainNasm, "-MD", "bin/boot3.d", "-fbin",
|
||||||
"boot/x86/loader.s", "-obin/stage2",
|
"boot/x86/loader.s", "-obin/stage2",
|
||||||
"-Pboot/x86/esfs-stage2.s", (forEmulator && !bootUseVBE) ? "" : "-D BOOT_USE_VBE");
|
"-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;
|
File _drive;
|
||||||
|
@ -1098,6 +1100,10 @@ void Install(const char *driveFile, uint64_t partitionSize, const char *partitio
|
||||||
installationIdentifier.d[i] = rand();
|
installationIdentifier.d[i] = rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File iid = FileOpen("bin/iid.dat", 'w');
|
||||||
|
FileWrite(iid, 16, &installationIdentifier);
|
||||||
|
FileClose(iid);
|
||||||
|
|
||||||
File f = FileOpen(driveFile, 'w');
|
File f = FileOpen(driveFile, 'w');
|
||||||
|
|
||||||
File mbr = FileOpen("bin/mbr", 'r');
|
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/boot1.d", "Boot1");
|
||||||
ADD_DEPENDENCY_FILE(application, "bin/boot2.d", "Boot2");
|
ADD_DEPENDENCY_FILE(application, "bin/boot2.d", "Boot2");
|
||||||
ADD_DEPENDENCY_FILE(application, "bin/boot3.d", "Boot3");
|
ADD_DEPENDENCY_FILE(application, "bin/boot3.d", "Boot3");
|
||||||
|
ADD_DEPENDENCY_FILE(application, "bin/boot4.d", "Boot4");
|
||||||
arrput(applications, application);
|
arrput(applications, application);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue