/*========================================================================== * Utility function to make a device tree string from an EFI_GUID */ static inline char * mallocStringForGuid(EFI_GUID const *pGuid) { char *string = malloc(37); efi_guid_unparse_upper(pGuid, string); return string; }
BVRef diskScanGPTBootVolumes(int biosdev, int * countPtr) { _DISK_DEBUG_DUMP("In diskScanGPTBootVolumes(%d)\n", biosdev); void *buffer = malloc(BPS); if (readBytes(biosdev, 1, 0, BPS, buffer) == 0) { int gptID = 1; gpt_ent * gptMap = 0; gpt_hdr * headerMap = buffer; // Partition header signature present? if (memcmp(headerMap->hdr_sig, GPT_HDR_SIG, strlen(GPT_HDR_SIG)) == 0) { UInt32 headerSize = OSSwapLittleToHostInt32(headerMap->hdr_size); // Valid partition header size? if (headerSize >= offsetof(gpt_hdr, padding)) { // No header size overrun (limiting to 512 bytes)? if (headerSize <= BPS) { UInt32 headerCheck = OSSwapLittleToHostInt32(headerMap->hdr_crc_self); headerMap->hdr_crc_self = 0; // Valid partition header checksum? if (crc32(0, headerMap, headerSize) == headerCheck) { UInt64 gptBlock = OSSwapLittleToHostInt64(headerMap->hdr_lba_table); UInt32 gptCount = OSSwapLittleToHostInt32(headerMap->hdr_entries); UInt32 gptSize = OSSwapLittleToHostInt32(headerMap->hdr_entsz); free(buffer); if (gptSize >= sizeof(gpt_ent)) { UInt32 bufferSize = IORound(gptCount * gptSize, BPS); buffer = malloc(bufferSize); // Allocate a buffer. if (readBytes(biosdev, gptBlock, 0, bufferSize, buffer) == 0) { // Allocate a new map for this device and insert it into the chain. struct DiskBVMap *map = malloc(sizeof(*map)); map->biosdev = biosdev; map->bvr = NULL; map->bvrcnt = 0; map->next = gDiskBVMap; gDiskBVMap = map; for (; gptID <= gptCount; gptID++) { gptMap = (gpt_ent *) (buffer + ((gptID - 1) * gptSize)); if (isPartitionUsed(gptMap)) { BVRef bvr = NULL; int bvrFlags = -1; #if DEBUG_DISK char stringuuid[100]; efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid); printf("Reading GPT partition %d, type %s\n", gptID, stringuuid); sleep(1); #endif if (efi_guid_compare(&GPT_HFS_GUID, (EFI_GUID const *)gptMap->ent_type) == 0) { _DISK_DEBUG_DUMP("Matched: GPT_HFS_GUID\n"); bvrFlags = kBVFlagZero; } /* else if (efi_guid_compare(&GPT_BOOT_GUID, (EFI_GUID const *)gptMap->ent_type) == 0) { _DISK_DEBUG_DUMP("Matched: GPT_BOOT_GUID\n"); bvrFlags = kBVFlagBooter; } */ #if EFI_SYSTEM_PARTITION_SUPPORT else if (efi_guid_compare(&GPT_EFISYS_GUID, (EFI_GUID const *)gptMap->ent_type) == 0) { _DISK_DEBUG_DUMP("Matched: GPT_EFISYS_GUID, probing for HFS format...\n"); //-------------- START ------------- // Allocate buffer for 4 sectors. void * probeBuffer = malloc(2048); bool probeOK = false; // Read the first 4 sectors. if (readBytes(biosdev, gptMap->ent_lba_start, 0, 2048, (void *)probeBuffer) == 0) { // Probing (returns true for HFS partitions). probeOK = HFSProbe(probeBuffer); _DISK_DEBUG_DUMP("HFSProbe status: Is %s a HFS partition.\n", probeOK ? "" : "not"); } free(probeBuffer); // Veto non-HFS partitions to be invalid. if (!probeOK) { continue; } //-------------- END --------------- bvrFlags = kBVFlagEFISystem; } #endif // Only true when we found a usable partition. if (bvrFlags >= 0) { bvr = newGPTBVRef(biosdev, gptID, gptMap->ent_lba_start, gptMap, bvrFlags); if (bvr) { bvr->part_type = FDISK_HFS; bvr->next = map->bvr; map->bvr = bvr; ++map->bvrcnt; // Don't waste time checking for boot.efi on ESP partitions. if ((bvrFlags & kBVFlagEFISystem) == 0) { // Flag System Volumes with kBVFlagSystemVolume. hasBootEFI(bvr); } // True on the initial run only. if (gPlatform.BootVolume == NULL) { // Initialize with the first bootable volume. gPlatform.BootVolume = gPlatform.RootVolume = bvr; _DISK_DEBUG_DUMP("Init B/RootVolume - partition: %d, flags: %d, gptID: %d\n", bvr->part_no, bvr->flags, gptID); } // Bail out after finding the first System Volume. if (bvr->flags & kBVFlagSystemVolume) { _DISK_DEBUG_DUMP("Partition %d is a System Volume\n", gptID); break; } } } } } free(buffer); *countPtr = map->bvrcnt; _DISK_DEBUG_DUMP("map->bvrcnt: %d\n", map->bvrcnt); _DISK_DEBUG_SLEEP(5); return map->bvr; } } } } } } } free(buffer); *countPtr = 0; _DISK_DEBUG_SLEEP(5); return NULL; }