mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[syslinux] fix Syslinux installation for some media
* Some disk devices, such as O2Micro PCI-E SD card readers, return ERROR_INVALID_PARAMETER when attempting to use ReadFile() on a volume against a non 8-byte aligned buffer. * This patch ensures that the Syslinux buffers for sector patching are 16-byte aligned. * HUGE THANKS to 424778940z, for the numerous testing that allowed to troubleshoot this issue. * Closes #767
This commit is contained in:
		
							parent
							
								
									c0393aec08
								
							
						
					
					
						commit
						3fdf622933
					
				
					 4 changed files with 63 additions and 23 deletions
				
			
		
							
								
								
									
										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.956" | CAPTION "Rufus 2.10.957" | ||||||
| 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,956,0 |  FILEVERSION 2,10,957,0 | ||||||
|  PRODUCTVERSION 2,10,956,0 |  PRODUCTVERSION 2,10,957,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.956" |             VALUE "FileVersion", "2.10.957" | ||||||
|             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.956" |             VALUE "ProductVersion", "2.10.957" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
|  | @ -105,18 +105,19 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) | ||||||
| 	const char* ldlinux_ext[3] = { "sys", "bss", "c32" }; | 	const char* ldlinux_ext[3] = { "sys", "bss", "c32" }; | ||||||
| 	const char* mboot_c32 = "mboot.c32"; | 	const char* mboot_c32 = "mboot.c32"; | ||||||
| 	char path[MAX_PATH], tmp[64]; | 	char path[MAX_PATH], tmp[64]; | ||||||
|  | 	const char *errmsg; | ||||||
| 	struct libfat_filesystem *fs; | 	struct libfat_filesystem *fs; | ||||||
| 	libfat_sector_t s, *secp; | 	libfat_sector_t s, *secp; | ||||||
| 	libfat_sector_t *sectors = NULL; | 	libfat_sector_t *sectors = NULL; | ||||||
| 	int ldlinux_sectors; | 	int ldlinux_sectors; | ||||||
| 	uint32_t ldlinux_cluster; | 	uint32_t ldlinux_cluster; | ||||||
| 	int i, nsectors; | 	int i, nsectors, sl_fs_stype; | ||||||
| 	int bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | 	int bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||||
| 	BOOL use_v5 = (bt == BT_SYSLINUX_V6) || ((bt == BT_ISO) && (SL_MAJOR(img_report.sl_version) >= 5)); | 	BOOL use_v5 = (bt == BT_SYSLINUX_V6) || ((bt == BT_ISO) && (SL_MAJOR(img_report.sl_version) >= 5)); | ||||||
| 
 | 
 | ||||||
| 	PrintInfoDebug(0, MSG_234, (bt == BT_ISO)?img_report.sl_version_str:embedded_sl_version_str[use_v5?1:0]); | 	PrintInfoDebug(0, MSG_234, (bt == BT_ISO)?img_report.sl_version_str:embedded_sl_version_str[use_v5?1:0]); | ||||||
| 
 | 
 | ||||||
| 	// 4K sector size workaround
 | 	/* 4K sector size workaround */ | ||||||
| 	SECTOR_SHIFT = 0; | 	SECTOR_SHIFT = 0; | ||||||
| 	SECTOR_SIZE = SelectedDrive.SectorSize; | 	SECTOR_SIZE = SelectedDrive.SectorSize; | ||||||
| 	while (SECTOR_SIZE>>=1) | 	while (SECTOR_SIZE>>=1) | ||||||
|  | @ -126,10 +127,32 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) | ||||||
| 	LIBFAT_SECTOR_SIZE = SECTOR_SIZE; | 	LIBFAT_SECTOR_SIZE = SECTOR_SIZE; | ||||||
| 	LIBFAT_SECTOR_MASK = SECTOR_SIZE - 1; | 	LIBFAT_SECTOR_MASK = SECTOR_SIZE - 1; | ||||||
| 
 | 
 | ||||||
| 	sectbuf = malloc(SECTOR_SIZE); | 	/* sectbuf should be aligned to at least 8 bytes - see github #767 */ | ||||||
|  | 	sectbuf = _aligned_malloc(SECTOR_SIZE, 16); | ||||||
| 	if (sectbuf == NULL) | 	if (sectbuf == NULL) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
|  | 	/* First, reopen the volume (we already have a lock) */ | ||||||
|  | 	d_handle = GetLogicalHandle(drive_index, TRUE, FALSE); | ||||||
|  | 	if ((d_handle == INVALID_HANDLE_VALUE) || (d_handle == NULL)) { | ||||||
|  | 		uprintf("Could open volume for Syslinux installation"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Make sure we can read the boot sector (NB: Re-open already set us to offset 0) */ | ||||||
|  | 	if (!ReadFile(d_handle, sectbuf, SECTOR_SIZE, &bytes_read, NULL)) { | ||||||
|  | 		uprintf("Could not read VBR"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if (bytes_read != SECTOR_SIZE) { | ||||||
|  | 		uprintf("Could not read the whole VBR"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if ((errmsg = syslinux_check_bootsect(sectbuf, &sl_fs_stype))) { | ||||||
|  | 		uprintf("Error: %s", errmsg); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/* Initialize the ADV -- this should be smarter */ | 	/* Initialize the ADV -- this should be smarter */ | ||||||
| 	syslinux_reset_adv(syslinux_adv); | 	syslinux_reset_adv(syslinux_adv); | ||||||
| 
 | 
 | ||||||
|  | @ -201,13 +224,6 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Reopen the volume (we already have a lock) */ |  | ||||||
| 	d_handle = GetLogicalHandle(drive_index, TRUE, FALSE); |  | ||||||
| 	if ((d_handle == INVALID_HANDLE_VALUE) || (d_handle == NULL)) { |  | ||||||
| 		uprintf("Could open volume for Syslinux installation"); |  | ||||||
| 		goto out; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* Map the file (is there a better way to do this?) */ | 	/* Map the file (is there a better way to do this?) */ | ||||||
| 	ldlinux_sectors = (syslinux_ldlinux_len[0] + 2 * ADV_SIZE + SECTOR_SIZE - 1) >> SECTOR_SHIFT; | 	ldlinux_sectors = (syslinux_ldlinux_len[0] + 2 * ADV_SIZE + SECTOR_SIZE - 1) >> SECTOR_SHIFT; | ||||||
| 	sectors = (libfat_sector_t*) calloc(ldlinux_sectors, sizeof *sectors); | 	sectors = (libfat_sector_t*) calloc(ldlinux_sectors, sizeof *sectors); | ||||||
|  | @ -366,7 +382,8 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) | ||||||
| 	r = TRUE; | 	r = TRUE; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	safe_free(sectbuf); | 	if (sectbuf != NULL) | ||||||
|  | 		_aligned_free(sectbuf); | ||||||
| 	safe_free(syslinux_ldlinux[0]); | 	safe_free(syslinux_ldlinux[0]); | ||||||
| 	safe_free(syslinux_ldlinux[1]); | 	safe_free(syslinux_ldlinux[1]); | ||||||
| 	safe_free(sectors); | 	safe_free(sectors); | ||||||
|  |  | ||||||
|  | @ -19,6 +19,20 @@ | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include "libfatint.h" | #include "libfatint.h" | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * We need to align our sector buffers to at least the 8-byte mark, as some Windows | ||||||
|  |  * disk devices, notably O2Micro PCI-E SD card readers, return ERROR_INVALID_PARAMETER | ||||||
|  |  * when attempting to use ReadFile() against a non 8-byte aligned buffer. | ||||||
|  |  * For good measure, we'll go further and align our buffers on a 16-byte boundary. | ||||||
|  |  * Also, since struct libfat_sector's data[0] is our buffer, this means we must BOTH | ||||||
|  |  * align that member in the struct declaration, and use aligned malloc/free. | ||||||
|  |  */ | ||||||
|  | #if defined(__MINGW32__) | ||||||
|  | #define _aligned_malloc                 __mingw_aligned_malloc | ||||||
|  | #define _aligned_free                   __mingw_aligned_free | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | extern void _uprintf(const char *format, ...); | ||||||
| void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) | void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) | ||||||
| { | { | ||||||
|     struct libfat_sector *ls; |     struct libfat_sector *ls; | ||||||
|  | @ -29,10 +43,10 @@ void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Not found in cache */ |     /* Not found in cache */ | ||||||
|     ls = malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE); |     ls = _aligned_malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE, 16); | ||||||
|     if (!ls) { |     if (!ls) { | ||||||
| 	libfat_flush(fs); | 	libfat_flush(fs); | ||||||
| 	ls = malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE); | 	ls = _aligned_malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE, 16); | ||||||
| 
 | 
 | ||||||
| 	if (!ls) | 	if (!ls) | ||||||
| 	    return NULL;	/* Can't allocate memory */ | 	    return NULL;	/* Can't allocate memory */ | ||||||
|  | @ -40,7 +54,7 @@ void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) | ||||||
| 
 | 
 | ||||||
|     if (fs->read(fs->readptr, ls->data, LIBFAT_SECTOR_SIZE, n) |     if (fs->read(fs->readptr, ls->data, LIBFAT_SECTOR_SIZE, n) | ||||||
| 	!= LIBFAT_SECTOR_SIZE) { | 	!= LIBFAT_SECTOR_SIZE) { | ||||||
| 	free(ls); | 	_aligned_free(ls); | ||||||
| 	return NULL;		/* I/O error */ | 	return NULL;		/* I/O error */ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -60,6 +74,6 @@ void libfat_flush(struct libfat_filesystem *fs) | ||||||
| 
 | 
 | ||||||
|     for (ls = lsnext; ls; ls = lsnext) { |     for (ls = lsnext; ls; ls = lsnext) { | ||||||
| 	lsnext = ls->next; | 	lsnext = ls->next; | ||||||
| 	free(ls); | 	_aligned_free(ls); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,10 +22,19 @@ | ||||||
| #include "libfat.h" | #include "libfat.h" | ||||||
| #include "fat.h" | #include "fat.h" | ||||||
| 
 | 
 | ||||||
|  | #if defined(__GNUC__) | ||||||
|  | #define ALIGN_START(m) | ||||||
|  | #define ALIGN_END(m) __attribute__ ((__aligned__(m))) | ||||||
|  | #elif defined(_MSC_VER) | ||||||
|  | #define ALIGN_START(m) __declspec(align(m)) | ||||||
|  | #define ALIGN_END(m) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| struct libfat_sector { | struct libfat_sector { | ||||||
|     libfat_sector_t n;		/* Sector number */ | 	libfat_sector_t n;		/* Sector number */ | ||||||
|     struct libfat_sector *next;	/* Next in list */ | 	struct libfat_sector *next;	/* Next in list */ | ||||||
|     char data[0]; | 	/* data[0] MUST be aligned to at least 8 bytes - see cache.c */ | ||||||
|  | 	ALIGN_START(16) char data[0] ALIGN_END(16); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum fat_type { | enum fat_type { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue