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…
Reference in a new issue