mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] try not to clear MBR/GPT sectors higher than the lowest partition
* This ensures that a drive can be reformatted without error after writing an image such as super_grub2_disk_x86_64_efi_2.02s4.iso
This commit is contained in:
		
							parent
							
								
									2f88286dc1
								
							
						
					
					
						commit
						91eec034b1
					
				
					 4 changed files with 29 additions and 17 deletions
				
			
		
							
								
								
									
										18
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -108,7 +108,7 @@ BOOL GetAutoMount(BOOL* enabled) | ||||||
|  */ |  */ | ||||||
| #define CheckDriveIndex(DriveIndex) do { \ | #define CheckDriveIndex(DriveIndex) do { \ | ||||||
| 	if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \ | 	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; \ | 		goto out; \ | ||||||
| 	} \ | 	} \ | ||||||
| 	DriveIndex -= DRIVE_INDEX_MIN; } while (0) | 	DriveIndex -= DRIVE_INDEX_MIN; } while (0) | ||||||
|  | @ -691,6 +691,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys | ||||||
| 	} | 	} | ||||||
| 	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart; | 	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart; | ||||||
| 	SelectedDrive.SectorSize = DiskGeometry->Geometry.BytesPerSector; | 	SelectedDrive.SectorSize = DiskGeometry->Geometry.BytesPerSector; | ||||||
|  | 	SelectedDrive.FirstDataSector = MAXDWORD; | ||||||
| 	if (SelectedDrive.SectorSize < 512) { | 	if (SelectedDrive.SectorSize < 512) { | ||||||
| 		suprintf("Warning: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n", | 		suprintf("Warning: Drive 0x%02x reports a sector size of %d - Correcting to 512 bytes.\n", | ||||||
| 			DriveIndex, SelectedDrive.SectorSize); | 			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
 | 				// 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, | 					((part_type==0x07)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), part_type, | ||||||
| 					SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), | 					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.BootIndicator?"Yes":"No", | ||||||
| 					DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"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)) | 				if ((part_type == RUFUS_EXTRA_PARTITION_TYPE) || (isUefiNtfs)) | ||||||
| 					// This is a partition Rufus created => we can safely ignore it
 | 					// This is a partition Rufus created => we can safely ignore it
 | ||||||
| 					--SelectedDrive.nPartitions; | 					--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, | 			suprintf("Partition %d:\r\n  Type: %s\r\n  Name: '%s'\n", i+1, | ||||||
| 				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp); | 				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", | 			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), | 				GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), | ||||||
| 				DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector, | 				SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), | ||||||
|  | 				DriveLayout->PartitionEntry[i].PartitionLength, | ||||||
|  | 				DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / SelectedDrive.SectorSize, | ||||||
| 				DriveLayout->PartitionEntry[i].Gpt.Attributes); | 				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
 | 			// Don't register the partitions that we don't care about destroying
 | ||||||
| 			if ( (strcmp(tmp, "UEFI:NTFS") == 0) || | 			if ( (strcmp(tmp, "UEFI:NTFS") == 0) || | ||||||
| 				 (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) || | 				 (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_MSFT_RESERVED_GUID)) || | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ typedef struct { | ||||||
| 	DWORD DeviceNumber; | 	DWORD DeviceNumber; | ||||||
| 	DWORD SectorsPerTrack; | 	DWORD SectorsPerTrack; | ||||||
| 	DWORD SectorSize; | 	DWORD SectorSize; | ||||||
| 	DWORD FirstSector; | 	DWORD FirstDataSector; | ||||||
| 	MEDIA_TYPE MediaType; | 	MEDIA_TYPE MediaType; | ||||||
| 	int PartitionType; | 	int PartitionType; | ||||||
| 	int nPartitions;	// number of partitions we actually care about
 | 	int nPartitions;	// number of partitions we actually care about
 | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -808,7 +808,7 @@ out: | ||||||
| static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSize, BOOL add1MB) | static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSize, BOOL add1MB) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	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); | 	unsigned char* pBuf = (unsigned char*) calloc(SectorSize, 1); | ||||||
| 
 | 
 | ||||||
| 	PrintInfoDebug(0, MSG_224); | 	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
 | 	// 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.
 | 	// with reluctant access to large drive.
 | ||||||
| 
 | 
 | ||||||
| 	// Must clear at least 1MB + the PBR for large FAT32 format to work on a large drive
 | 	// We try to clear at least 1MB + the PBR when Large FAT32 is selected (add1MB), but
 | ||||||
| 	// Don't do it if Large FAT32 is not enabled, as it can take time for slow drives.
 | 	// don't do it otherwise, as it seems unnecessary and may take time for slow drives.
 | ||||||
| 	uprintf("Erasing %d sectors", (add1MB?2048:0)+MAX_SECTORS_TO_CLEAR); | 	// Also, for various reasons (one of which being that Windows seems to have issues
 | ||||||
| 	for (i=0; i<((add1MB?2048:0)+MAX_SECTORS_TO_CLEAR); i++) { | 	// 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<num_sectors_to_clear; i++) { | ||||||
| 		if ((IS_ERROR(FormatStatus)) || (write_sectors(hPhysicalDrive, SectorSize, i, 1, pBuf) != SectorSize)) { | 		if ((IS_ERROR(FormatStatus)) || (write_sectors(hPhysicalDrive, SectorSize, i, 1, pBuf) != SectorSize)) { | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -1678,7 +1682,7 @@ DWORD WINAPI FormatThread(void* param) | ||||||
| 	// Note, Microsoft's way of cleaning partitions (IOCTL_DISK_CREATE_DISK, which is what we apply
 | 	// Note, Microsoft's way of cleaning partitions (IOCTL_DISK_CREATE_DISK, which is what we apply
 | ||||||
| 	// in InitializeDisk) is *NOT ENOUGH* to reset a disk and can render it inoperable for partitioning
 | 	// in InitializeDisk) is *NOT ENOUGH* to reset a disk and can render it inoperable for partitioning
 | ||||||
| 	// or formatting under Windows. See https://github.com/pbatard/rufus/issues/759 for details.
 | 	// or formatting under Windows. See https://github.com/pbatard/rufus/issues/759 for details.
 | ||||||
| 	if ((!ClearMBRGPT(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.SectorSize, FALSE)) || (!InitializeDisk(hPhysicalDrive)) ) { | 	if ((!ClearMBRGPT(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.SectorSize, use_large_fat32)) || (!InitializeDisk(hPhysicalDrive)) ) { | ||||||
| 		uprintf("Could not reset partitions\n"); | 		uprintf("Could not reset partitions\n"); | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 242, 376 | IDD_DIALOG DIALOGEX 12, 12, 242, 376 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 2.10.966" | CAPTION "Rufus 2.10.967" | ||||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 |     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||||
|  | @ -320,8 +320,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 2,10,966,0 |  FILEVERSION 2,10,967,0 | ||||||
|  PRODUCTVERSION 2,10,966,0 |  PRODUCTVERSION 2,10,967,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -338,13 +338,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" |             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "2.10.966" |             VALUE "FileVersion", "2.10.967" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "2.10.966" |             VALUE "ProductVersion", "2.10.967" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue