[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:
Pete Batard 2016-06-09 17:49:58 +01:00
parent c0393aec08
commit 3fdf622933
4 changed files with 63 additions and 23 deletions

View file

@ -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);