diff --git a/src/drive.c b/src/drive.c index e84c773f..15310495 100644 --- a/src/drive.c +++ b/src/drive.c @@ -108,7 +108,7 @@ BOOL GetAutoMount(BOOL* enabled) */ #define CheckDriveIndex(DriveIndex) do { \ if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \ - uprintf("ERROR: Bad index value. Please check the code!\n"); \ + uprintf("ERROR: Bad index value %d. Please check the code!", DriveIndex); \ goto out; \ } \ DriveIndex -= DRIVE_INDEX_MIN; } while (0) @@ -691,6 +691,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys } SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart; SelectedDrive.SectorSize = DiskGeometry->Geometry.BytesPerSector; + SelectedDrive.FirstDataSector = MAXDWORD; if (SelectedDrive.SectorSize < 512) { suprintf("Warning: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n", DriveIndex, SelectedDrive.SectorSize); @@ -741,12 +742,15 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys } } // NB: MinGW's gcc 4.9.2 broke "%lld" printout on XP so we use the inttypes.h "PRI##" qualifiers - suprintf(" Type: %s (0x%02x)\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %d, Boot: %s, Recognized: %s\n", + suprintf(" Type: %s (0x%02x)\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Boot: %s, Recognized: %s\n", ((part_type==0x07)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), part_type, SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), - DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, DriveLayout->PartitionEntry[i].Mbr.HiddenSectors, + DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, + DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize, DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No", DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No"); + SelectedDrive.FirstDataSector = min(SelectedDrive.FirstDataSector, + (DWORD)(DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize)); if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiNtfs)) // This is a partition Rufus created => we can safely ignore it --SelectedDrive.nPartitions; @@ -768,9 +772,13 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys suprintf("Partition %d:\r\n Type: %s\r\n Name: '%s'\n", i+1, GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp); suprintf(" ID: %s\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64 "\n", - GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), - DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector, + GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), + SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), + DriveLayout->PartitionEntry[i].PartitionLength, + DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize, DriveLayout->PartitionEntry[i].Gpt.Attributes); + SelectedDrive.FirstDataSector = min(SelectedDrive.FirstDataSector, + (DWORD)(DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize)); // Don't register the partitions that we don't care about destroying if ( (strcmp(tmp, "UEFI:NTFS") == 0) || (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) || diff --git a/src/drive.h b/src/drive.h index bab7b55f..f9f054f9 100644 --- a/src/drive.h +++ b/src/drive.h @@ -61,7 +61,7 @@ typedef struct { DWORD DeviceNumber; DWORD SectorsPerTrack; DWORD SectorSize; - DWORD FirstSector; + DWORD FirstDataSector; MEDIA_TYPE MediaType; int PartitionType; int nPartitions; // number of partitions we actually care about diff --git a/src/format.c b/src/format.c index bf4e67b1..2093bf56 100644 --- a/src/format.c +++ b/src/format.c @@ -808,7 +808,7 @@ out: static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSize, BOOL add1MB) { BOOL r = FALSE; - uint64_t i, last_sector = DiskSize/SectorSize; + uint64_t i, last_sector = DiskSize/SectorSize, num_sectors_to_clear; unsigned char* pBuf = (unsigned char*) calloc(SectorSize, 1); PrintInfoDebug(0, MSG_224); @@ -820,10 +820,14 @@ static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSi // beginning and 33 at the end. We bump these values to MAX_SECTORS_TO_CLEAR each end to help // with reluctant access to large drive. - // Must clear at least 1MB + the PBR for large FAT32 format to work on a large drive - // Don't do it if Large FAT32 is not enabled, as it can take time for slow drives. - uprintf("Erasing %d sectors", (add1MB?2048:0)+MAX_SECTORS_TO_CLEAR); - for (i=0; i<((add1MB?2048:0)+MAX_SECTORS_TO_CLEAR); i++) { + // We try to clear at least 1MB + the PBR when Large FAT32 is selected (add1MB), but + // don't do it otherwise, as it seems unnecessary and may take time for slow drives. + // Also, for various reasons (one of which being that Windows seems to have issues + // with GPT drives that contain a lot of small partitions) we try not not to clear + // sectors further than the lowest partition already residing on the disk. + num_sectors_to_clear = min(SelectedDrive.FirstDataSector, (add1MB ? 2048 : 0) + MAX_SECTORS_TO_CLEAR); + uprintf("Erasing %d sectors", num_sectors_to_clear); + for (i=0; i