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 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 2.10.956" | ||||
| CAPTION "Rufus 2.10.957" | ||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||
|  | @ -320,8 +320,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 2,10,956,0 | ||||
|  PRODUCTVERSION 2,10,956,0 | ||||
|  FILEVERSION 2,10,957,0 | ||||
|  PRODUCTVERSION 2,10,957,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -338,13 +338,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "2.10.956" | ||||
|             VALUE "FileVersion", "2.10.957" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "2.10.956" | ||||
|             VALUE "ProductVersion", "2.10.957" | ||||
|         END | ||||
|     END | ||||
|     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* mboot_c32 = "mboot.c32"; | ||||
| 	char path[MAX_PATH], tmp[64]; | ||||
| 	const char *errmsg; | ||||
| 	struct libfat_filesystem *fs; | ||||
| 	libfat_sector_t s, *secp; | ||||
| 	libfat_sector_t *sectors = NULL; | ||||
| 	int ldlinux_sectors; | ||||
| 	uint32_t ldlinux_cluster; | ||||
| 	int i, nsectors; | ||||
| 	int i, nsectors, sl_fs_stype; | ||||
| 	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)); | ||||
| 
 | ||||
| 	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_SIZE = SelectedDrive.SectorSize; | ||||
| 	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_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) | ||||
| 		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 */ | ||||
| 	syslinux_reset_adv(syslinux_adv); | ||||
| 
 | ||||
|  | @ -201,13 +224,6 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) | |||
| 		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?) */ | ||||
| 	ldlinux_sectors = (syslinux_ldlinux_len[0] + 2 * ADV_SIZE + SECTOR_SIZE - 1) >> SECTOR_SHIFT; | ||||
| 	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; | ||||
| 
 | ||||
| out: | ||||
| 	safe_free(sectbuf); | ||||
| 	if (sectbuf != NULL) | ||||
| 		_aligned_free(sectbuf); | ||||
| 	safe_free(syslinux_ldlinux[0]); | ||||
| 	safe_free(syslinux_ldlinux[1]); | ||||
| 	safe_free(sectors); | ||||
|  |  | |||
|  | @ -19,6 +19,20 @@ | |||
| #include <stdlib.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) | ||||
| { | ||||
|     struct libfat_sector *ls; | ||||
|  | @ -29,10 +43,10 @@ void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) | |||
|     } | ||||
| 
 | ||||
|     /* 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) { | ||||
| 	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) | ||||
| 	    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) | ||||
| 	!= LIBFAT_SECTOR_SIZE) { | ||||
| 	free(ls); | ||||
| 	_aligned_free(ls); | ||||
| 	return NULL;		/* I/O error */ | ||||
|     } | ||||
| 
 | ||||
|  | @ -60,6 +74,6 @@ void libfat_flush(struct libfat_filesystem *fs) | |||
| 
 | ||||
|     for (ls = lsnext; ls; ls = lsnext) { | ||||
| 	lsnext = ls->next; | ||||
| 	free(ls); | ||||
| 	_aligned_free(ls); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -22,10 +22,19 @@ | |||
| #include "libfat.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 { | ||||
| 	libfat_sector_t n;		/* Sector number */ | ||||
| 	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 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue