mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
add cheat mode (alt-"-") to quickly erase a flash drive by skipping blocks that are already empty
(a flashdrive reads a lot faster than it writes)
This commit is contained in:
parent
d4a4506b16
commit
cbc505ee4d
3 changed files with 89 additions and 4 deletions
|
@ -564,6 +564,7 @@ t MSG_303 "Show the log"
|
||||||
t MSG_304 "Create a disk image of the selected device"
|
t MSG_304 "Create a disk image of the selected device"
|
||||||
t MSG_305 "Use this option to indicate whether you want to use this device to install Windows on another disk, "
|
t MSG_305 "Use this option to indicate whether you want to use this device to install Windows on another disk, "
|
||||||
"or if you want to run Windows directly from this drive (Windows To Go)."
|
"or if you want to run Windows directly from this drive (Windows To Go)."
|
||||||
|
t MSG_306 "Erasing drive: %0.1f%% completed"
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
############################# TRANSLATOR END COPY ##############################
|
############################# TRANSLATOR END COPY ##############################
|
||||||
|
@ -4550,6 +4551,7 @@ t MSG_303 "Toon het logboek"
|
||||||
t MSG_304 "Maak een schijfkopie van het geselecteerde apparaat"
|
t MSG_304 "Maak een schijfkopie van het geselecteerde apparaat"
|
||||||
t MSG_305 "Gebruik deze optie om aan te geven of u dit apparaat wilt gebruiken om Windows op een andere schijf te installeren, "
|
t MSG_305 "Gebruik deze optie om aan te geven of u dit apparaat wilt gebruiken om Windows op een andere schijf te installeren, "
|
||||||
"of als u Windows rechtstreeks vanaf deze schijf wilt opstarten (Windows To Go)."
|
"of als u Windows rechtstreeks vanaf deze schijf wilt opstarten (Windows To Go)."
|
||||||
|
t MSG_306 "Schijf wissen: %0.1f%% voltooid"
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
l "fi-FI" "Finnish (Suomi)" 0x040B
|
l "fi-FI" "Finnish (Suomi)" 0x040B
|
||||||
|
|
81
src/format.c
81
src/format.c
|
@ -61,7 +61,7 @@ static int task_number = 0;
|
||||||
extern const int nb_steps[FS_MAX];
|
extern const int nb_steps[FS_MAX];
|
||||||
extern uint32_t dur_mins, dur_secs;
|
extern uint32_t dur_mins, dur_secs;
|
||||||
static int fs_index = 0, wintogo_index = -1;
|
static int fs_index = 0, wintogo_index = -1;
|
||||||
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, enable_file_indexing, write_as_image;
|
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, smart_skip, enable_file_indexing, write_as_image;
|
||||||
uint8_t *grub2_buf = NULL;
|
uint8_t *grub2_buf = NULL;
|
||||||
long grub2_len;
|
long grub2_len;
|
||||||
static BOOL WritePBR(HANDLE hLogicalDrive);
|
static BOOL WritePBR(HANDLE hLogicalDrive);
|
||||||
|
@ -1547,11 +1547,13 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
{
|
{
|
||||||
BOOL s, ret = FALSE;
|
BOOL s, ret = FALSE;
|
||||||
LARGE_INTEGER li;
|
LARGE_INTEGER li;
|
||||||
DWORD rSize, wSize, BufSize;
|
DWORD rSize, wSize, xSize, BufSize;
|
||||||
uint64_t wb, target_size = hSourceImage?img_report.image_size:SelectedDrive.DiskSize;
|
uint64_t wb, target_size = hSourceImage?img_report.image_size:SelectedDrive.DiskSize;
|
||||||
int64_t bled_ret;
|
int64_t bled_ret;
|
||||||
uint8_t *buffer = NULL;
|
uint8_t *buffer = NULL;
|
||||||
|
uint8_t *readbuffer = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
int smartskip_backoff = 0;
|
||||||
|
|
||||||
// We poked the MBR and other stuff, so we need to rewind
|
// We poked the MBR and other stuff, so we need to rewind
|
||||||
li.QuadPart = 0;
|
li.QuadPart = 0;
|
||||||
|
@ -1571,7 +1573,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uprintf(hSourceImage?"Writing Image...":"Zeroing drive...");
|
uprintf(hSourceImage?"Writing Image...":smart_skip?"Erasing drive...":"Zeroing drive...");
|
||||||
// Our buffer size must be a multiple of the sector size and *ALIGNED* to the sector size
|
// Our buffer size must be a multiple of the sector size and *ALIGNED* to the sector size
|
||||||
BufSize = ((DD_BUFFER_SIZE + SelectedDrive.SectorSize - 1) / SelectedDrive.SectorSize) * SelectedDrive.SectorSize;
|
BufSize = ((DD_BUFFER_SIZE + SelectedDrive.SectorSize - 1) / SelectedDrive.SectorSize) * SelectedDrive.SectorSize;
|
||||||
buffer = (uint8_t*)_mm_malloc(BufSize, SelectedDrive.SectorSize);
|
buffer = (uint8_t*)_mm_malloc(BufSize, SelectedDrive.SectorSize);
|
||||||
|
@ -1586,6 +1588,21 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
uprintf("Write buffer is not aligned");
|
uprintf("Write buffer is not aligned");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
// Clear buffer
|
||||||
|
memset(buffer, smart_skip?0xff:0x00, BufSize);
|
||||||
|
|
||||||
|
readbuffer = (uint8_t*)_mm_malloc(BufSize, SelectedDrive.SectorSize);
|
||||||
|
if (readbuffer == NULL) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
uprintf("Could not allocate disk read buffer");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// Sanity check
|
||||||
|
if ((uintptr_t)readbuffer % SelectedDrive.SectorSize != 0) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_READ_FAULT;
|
||||||
|
uprintf("Read buffer is not aligned");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't bother trying for something clever, using double buffering overlapped and whatnot:
|
// Don't bother trying for something clever, using double buffering overlapped and whatnot:
|
||||||
// With Windows' default optimizations, sync read + sync write for sequential operations
|
// With Windows' default optimizations, sync read + sync write for sequential operations
|
||||||
|
@ -1595,7 +1612,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
if (GetTickCount64() > LastRefresh + MAX_REFRESH) {
|
if (GetTickCount64() > LastRefresh + MAX_REFRESH) {
|
||||||
LastRefresh = GetTickCount64();
|
LastRefresh = GetTickCount64();
|
||||||
format_percent = (100.0f*wb) / (1.0f*target_size);
|
format_percent = (100.0f*wb) / (1.0f*target_size);
|
||||||
PrintInfo(0, hSourceImage?MSG_261:MSG_286, format_percent);
|
PrintInfo(0, hSourceImage?MSG_261:smart_skip?MSG_306:MSG_286, format_percent);
|
||||||
UpdateProgress(OP_FORMAT, format_percent);
|
UpdateProgress(OP_FORMAT, format_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1617,6 +1634,61 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
// WriteFile fails unless the size is a multiple of sector size
|
// WriteFile fails unless the size is a multiple of sector size
|
||||||
if (rSize % SelectedDrive.SectorSize != 0)
|
if (rSize % SelectedDrive.SectorSize != 0)
|
||||||
rSize = ((rSize + SelectedDrive.SectorSize - 1) / SelectedDrive.SectorSize) * SelectedDrive.SectorSize;
|
rSize = ((rSize + SelectedDrive.SectorSize - 1) / SelectedDrive.SectorSize) * SelectedDrive.SectorSize;
|
||||||
|
|
||||||
|
// Smart-skip: Reading a flash drive is faster than writing, so we
|
||||||
|
// can skip erasing empty blocks, or skip writing when the data is the same
|
||||||
|
// * a block is empty when all bits are either 0 (zeros) or 1 (flash block erased)
|
||||||
|
// * a back-off strategy is used to limit reading
|
||||||
|
|
||||||
|
if (smartskip_backoff) {
|
||||||
|
smartskip_backoff--;
|
||||||
|
} else if (smart_skip && (hSourceImage == NULL)) { // currently only enabled for erase
|
||||||
|
|
||||||
|
CHECK_FOR_USER_CANCEL;
|
||||||
|
|
||||||
|
// Read block and compare against the block that needs to be written
|
||||||
|
s = ReadFile(hPhysicalDrive, readbuffer, rSize, &xSize, NULL);
|
||||||
|
if (!s || (xSize != rSize) ) {
|
||||||
|
uprintf("Read error: could not read data to compare - %s", WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// erase or write
|
||||||
|
if (hSourceImage == NULL) {
|
||||||
|
// Erase, check for an empty block
|
||||||
|
int *ptr = (int*)(readbuffer);
|
||||||
|
// Get first element
|
||||||
|
int value = ptr[0];
|
||||||
|
// Check all bits are the same
|
||||||
|
if (value!=0 && value!=-1) {
|
||||||
|
goto blocknotempty;
|
||||||
|
}
|
||||||
|
// Compare the rest of the block against the first element
|
||||||
|
for (i = 1; i < (int)(rSize/sizeof(int)); i++) {
|
||||||
|
if (ptr[i] != value)
|
||||||
|
goto blocknotempty;
|
||||||
|
}
|
||||||
|
// Block is empty, skip write
|
||||||
|
wSize = rSize;
|
||||||
|
continue;
|
||||||
|
blocknotempty:
|
||||||
|
;
|
||||||
|
} else if (memcmp(readbuffer, buffer, rSize)==0) {
|
||||||
|
// Write, block is unchanged, skip write
|
||||||
|
wSize = rSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the file pointer position back for writing
|
||||||
|
li.QuadPart = wb;
|
||||||
|
if (!SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN)) {
|
||||||
|
uprintf("Error: Could not reset position - %s", WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// throttle reading
|
||||||
|
smartskip_backoff = 15;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 1; i <= WRITE_RETRIES; i++) {
|
for (i = 1; i <= WRITE_RETRIES; i++) {
|
||||||
CHECK_FOR_USER_CANCEL;
|
CHECK_FOR_USER_CANCEL;
|
||||||
s = WriteFile(hPhysicalDrive, buffer, rSize, &wSize, NULL);
|
s = WriteFile(hPhysicalDrive, buffer, rSize, &wSize, NULL);
|
||||||
|
@ -1648,6 +1720,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage)
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
safe_mm_free(buffer);
|
safe_mm_free(buffer);
|
||||||
|
safe_mm_free(readbuffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/rufus.c
10
src/rufus.c
|
@ -114,6 +114,7 @@ BOOL enable_HDDs = FALSE, force_update = FALSE, enable_ntfs_compression = FALSE,
|
||||||
BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug;
|
BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug;
|
||||||
BOOL use_fake_units, preserve_timestamps = FALSE;
|
BOOL use_fake_units, preserve_timestamps = FALSE;
|
||||||
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE, write_as_image = FALSE;
|
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE, write_as_image = FALSE;
|
||||||
|
BOOL smart_skip = FALSE;
|
||||||
int dialog_showing = 0;
|
int dialog_showing = 0;
|
||||||
uint16_t rufus_version[3], embedded_sl_version[2];
|
uint16_t rufus_version[3], embedded_sl_version[2];
|
||||||
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
||||||
|
@ -4290,6 +4291,15 @@ relaunch:
|
||||||
// Alt-Z => Zero the drive
|
// Alt-Z => Zero the drive
|
||||||
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Z')) {
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Z')) {
|
||||||
zero_drive = TRUE;
|
zero_drive = TRUE;
|
||||||
|
smart_skip = FALSE;
|
||||||
|
// Simulate a button click for Start
|
||||||
|
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Alt-"-" => Erase the drive (skips empty blocks)
|
||||||
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == VK_OEM_MINUS)) {
|
||||||
|
zero_drive = TRUE;
|
||||||
|
smart_skip = TRUE;
|
||||||
// Simulate a button click for Start
|
// Simulate a button click for Start
|
||||||
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
|
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue