[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

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

View file

@ -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 {