diff --git a/boot/x86/uefi_loader.s b/boot/x86/uefi_loader.s index 57efc90..76d52d9 100644 --- a/boot/x86/uefi_loader.s +++ b/boot/x86/uefi_loader.s @@ -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 diff --git a/boot/x86/uefi.c b/boot/x86/uefi_old.c similarity index 100% rename from boot/x86/uefi.c rename to boot/x86/uefi_old.c diff --git a/desktop/os.header b/desktop/os.header index 0892234..ac97a90 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -1882,7 +1882,6 @@ struct EsFontInformation { struct EsBlockDeviceInformation { size_t sectorSize; EsFileOffset sectorCount; - bool noMBR; bool readOnly; uint8_t nestLevel; uint8_t driveType; diff --git a/drivers/fat.cpp b/drivers/fat.cpp index 78d6c63..820e6ac 100644 --- a/drivers/fat.cpp +++ b/drivers/fat.cpp @@ -488,7 +488,6 @@ static void DeviceAttach(KDevice *parent) { } } - volume->rootDirectory->driverNode = volume->root; volume->directoryEntryDataBytes = sizeof(DirectoryEntryReference); volume->nodeDataBytes = sizeof(FSNode); diff --git a/kernel/elf.cpp b/kernel/elf.cpp index bfc176b..0302e95 100644 --- a/kernel/elf.cpp +++ b/kernel/elf.cpp @@ -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; diff --git a/kernel/files.cpp b/kernel/files.cpp index d733d90..d9389c0 100644 --- a/kernel/files.cpp +++ b/kernel/files.cpp @@ -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); diff --git a/kernel/module.h b/kernel/module.h index 53bf01b..a26113d 100644 --- a/kernel/module.h +++ b/kernel/module.h @@ -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. diff --git a/shared/partitions.cpp b/shared/partitions.cpp index 3c1aed4..f899011 100644 --- a/shared/partitions.cpp +++ b/shared/partitions.cpp @@ -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; +} diff --git a/util/build_core.c b/util/build_core.c index b696971..30dc69b 100644 --- a/util/build_core.c +++ b/util/build_core.c @@ -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); }