diff --git a/src/rufus.rc b/src/rufus.rc index 509a1cc3..f9547ca0 100644 --- a/src/rufus.rc +++ b/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" diff --git a/src/syslinux.c b/src/syslinux.c index 6281fc49..f67627e1 100644 --- a/src/syslinux.c +++ b/src/syslinux.c @@ -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); diff --git a/src/syslinux/libfat/cache.c b/src/syslinux/libfat/cache.c index 68c90d57..3d08b683 100644 --- a/src/syslinux/libfat/cache.c +++ b/src/syslinux/libfat/cache.c @@ -19,6 +19,20 @@ #include #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); } } diff --git a/src/syslinux/libfat/libfatint.h b/src/syslinux/libfat/libfatint.h index 36f4e02e..5f098b5a 100644 --- a/src/syslinux/libfat/libfatint.h +++ b/src/syslinux/libfat/libfatint.h @@ -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]; + libfat_sector_t n; /* Sector number */ + struct libfat_sector *next; /* Next in list */ + /* 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 {