From 9e7b0bad893b8c07d3cb85b412c31fbdaa17aa0d Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 2 Jun 2015 21:47:44 +0100 Subject: [PATCH] [syslinux] add support for 4K sector size * Also add 4K sector size support in ms-sys --- src/ms-sys/br.c | 51 +++++++++++++++------------- src/rufus.rc | 16 ++++----- src/syslinux.c | 24 ++++++++++++- src/syslinux/libfat/cache.c | 4 +-- src/syslinux/libfat/libfat.h | 11 ++++-- src/syslinux/libfat/libfatint.h | 2 +- src/syslinux/libfat/searchdir.c | 2 +- src/syslinux/libinstaller/syslinux.h | 7 ++-- 8 files changed, 75 insertions(+), 42 deletions(-) diff --git a/src/ms-sys/br.c b/src/ms-sys/br.c index e03e201d..1ea0caac 100644 --- a/src/ms-sys/br.c +++ b/src/ms-sys/br.c @@ -169,123 +169,126 @@ int is_zero_mbr(FILE *fp) /* Don't bother to check 55AA signature */ } /* is_zero_mbr */ +/* Handle nonstandard sector sizes (such as 4K) by writing + the boot marker at every 512-2 bytes location */ +static int write_bootmark(FILE *fp) +{ + unsigned char aucRef[] = {0x55, 0xAA}; + int pos = 0x1FE; + + /* We use fp->_bufsiz as our sector size indicator */ + for (pos = 0x1FE; pos < fp->_bufsiz; pos += 0x200) { + if (!write_data(fp, pos, aucRef, sizeof(aucRef))) + return 0; + } + return 1; +} + int write_dos_mbr(FILE *fp) { #include "mbr_dos.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_dos_0x0, sizeof(mbr_dos_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_dos_mbr */ int write_95b_mbr(FILE *fp) { #include "mbr_95b.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_95b_0x0, sizeof(mbr_95b_0x0)) && write_data(fp, 0x0e0, mbr_95b_0x0e0, sizeof(mbr_95b_0x0e0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_95b_mbr */ int write_2000_mbr(FILE *fp) { #include "mbr_2000.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_2000_0x0, sizeof(mbr_2000_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_2000_mbr */ int write_vista_mbr(FILE *fp) { #include "mbr_vista.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_vista_0x0, sizeof(mbr_vista_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_vista_mbr */ int write_win7_mbr(FILE *fp) { #include "mbr_win7.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_win7_0x0, sizeof(mbr_win7_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_win7_mbr */ int write_rufus_mbr(FILE *fp) { #include "mbr_rufus.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_rufus_0x0, sizeof(mbr_rufus_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_rufus_mbr */ int write_reactos_mbr(FILE *fp) { #include "mbr_reactos.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_reactos_0x0, sizeof(mbr_reactos_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_reactos_mbr */ int write_kolibri_mbr(FILE *fp) { #include "mbr_kolibri.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_kolibri_0x0, sizeof(mbr_kolibri_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_kolibri_mbr */ int write_syslinux_mbr(FILE *fp) { #include "mbr_syslinux.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_syslinux_0x0, sizeof(mbr_syslinux_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_syslinux_mbr */ int write_grub_mbr(FILE *fp) { #include "mbr_grub.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_grub_0x0, sizeof(mbr_grub_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } int write_grub2_mbr(FILE *fp) { #include "mbr_grub2.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_grub2_0x0, sizeof(mbr_grub2_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } int write_zero_mbr(FILE *fp) { #include "mbr_zero.h" - unsigned char aucRef[] = {0x55, 0xAA}; return write_data(fp, 0x0, mbr_zero_0x0, sizeof(mbr_zero_0x0)) && - write_data(fp, 0x1FE, aucRef, sizeof(aucRef)); + write_bootmark(fp); } /* write_zero_mbr */ diff --git a/src/rufus.rc b/src/rufus.rc index c922c428..7ff4679c 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -32,7 +32,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 -CAPTION "Rufus 2.2.668" +CAPTION "Rufus 2.2.669" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -157,7 +157,7 @@ END IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.2.668" +CAPTION "Rufus 2.2.669" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -283,7 +283,7 @@ END IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.2.668" +CAPTION "Rufus 2.2.669" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -415,7 +415,7 @@ END IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.2.668" +CAPTION "Rufus 2.2.669" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -671,8 +671,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,668,0 - PRODUCTVERSION 2,2,668,0 + FILEVERSION 2,2,669,0 + PRODUCTVERSION 2,2,669,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -689,13 +689,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.2.668" + VALUE "FileVersion", "2.2.669" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.2.668" + VALUE "ProductVersion", "2.2.669" END END BLOCK "VarFileInfo" diff --git a/src/syslinux.c b/src/syslinux.c index f867cdb6..d76d1bf8 100644 --- a/src/syslinux.c +++ b/src/syslinux.c @@ -43,6 +43,13 @@ DWORD syslinux_ldlinux_len[2]; unsigned char* syslinux_mboot = NULL; DWORD syslinux_mboot_len; +// Workaround for 4K support +uint32_t SECTOR_SHIFT = 9; +uint32_t SECTOR_SIZE = 512; +uint32_t LIBFAT_SECTOR_SHIFT = 9; +uint32_t LIBFAT_SECTOR_SIZE = 512; +uint32_t LIBFAT_SECTOR_MASK = 511; + /* * Wrapper for ReadFile suitable for libfat */ @@ -82,7 +89,7 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) FILE* fd; size_t length; - static unsigned char sectbuf[SECTOR_SIZE]; + static unsigned char* sectbuf = NULL; static char* resource[2][2] = { { MAKEINTRESOURCEA(IDR_SL_LDLINUX_V4_SYS), MAKEINTRESOURCEA(IDR_SL_LDLINUX_V4_BSS) }, { MAKEINTRESOURCEA(IDR_SL_LDLINUX_V6_SYS), MAKEINTRESOURCEA(IDR_SL_LDLINUX_V6_BSS) } }; @@ -102,6 +109,20 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) PrintInfoDebug(0, MSG_234, (dt == DT_ISO)?iso_report.sl_version_str:embedded_sl_version_str[use_v5?1:0]); + // 4K sector size workaround + SECTOR_SHIFT = 0; + SECTOR_SIZE = SelectedDrive.Geometry.BytesPerSector; + while (SECTOR_SIZE>>=1) + SECTOR_SHIFT++; + SECTOR_SIZE = SelectedDrive.Geometry.BytesPerSector; + LIBFAT_SECTOR_SHIFT = SECTOR_SHIFT; + LIBFAT_SECTOR_SIZE = SECTOR_SIZE; + LIBFAT_SECTOR_MASK = SECTOR_SIZE - 1; + + sectbuf = malloc(SECTOR_SIZE); + if (sectbuf == NULL) + goto out; + /* Initialize the ADV -- this should be smarter */ syslinux_reset_adv(syslinux_adv); @@ -335,6 +356,7 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs_type) r = TRUE; out: + safe_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 85b7eadf..68c90d57 100644 --- a/src/syslinux/libfat/cache.c +++ b/src/syslinux/libfat/cache.c @@ -29,10 +29,10 @@ void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n) } /* Not found in cache */ - ls = malloc(sizeof(struct libfat_sector)); + ls = malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE); if (!ls) { libfat_flush(fs); - ls = malloc(sizeof(struct libfat_sector)); + ls = malloc(sizeof(struct libfat_sector) + LIBFAT_SECTOR_SIZE); if (!ls) return NULL; /* Can't allocate memory */ diff --git a/src/syslinux/libfat/libfat.h b/src/syslinux/libfat/libfat.h index a0179d7c..60b3654b 100644 --- a/src/syslinux/libfat/libfat.h +++ b/src/syslinux/libfat/libfat.h @@ -22,9 +22,14 @@ #include #include -#define LIBFAT_SECTOR_SHIFT 9 -#define LIBFAT_SECTOR_SIZE 512 -#define LIBFAT_SECTOR_MASK 511 +// Workaround for 4K support +extern uint32_t LIBFAT_SECTOR_SHIFT; +extern uint32_t LIBFAT_SECTOR_SIZE; +extern uint32_t LIBFAT_SECTOR_MASK; +#define MAX_LIBFAT_SECTOR_SIZE 4096 +//#define LIBFAT_SECTOR_SHIFT 9 +//#define LIBFAT_SECTOR_SIZE 512 +//#define LIBFAT_SECTOR_MASK 511 typedef uint64_t libfat_sector_t; struct libfat_filesystem; diff --git a/src/syslinux/libfat/libfatint.h b/src/syslinux/libfat/libfatint.h index adfad00b..36f4e02e 100644 --- a/src/syslinux/libfat/libfatint.h +++ b/src/syslinux/libfat/libfatint.h @@ -25,7 +25,7 @@ struct libfat_sector { libfat_sector_t n; /* Sector number */ struct libfat_sector *next; /* Next in list */ - char data[LIBFAT_SECTOR_SIZE]; + char data[0]; }; enum fat_type { diff --git a/src/syslinux/libfat/searchdir.c b/src/syslinux/libfat/searchdir.c index 4964120b..7e47fe58 100644 --- a/src/syslinux/libfat/searchdir.c +++ b/src/syslinux/libfat/searchdir.c @@ -25,7 +25,7 @@ int32_t libfat_searchdir(struct libfat_filesystem *fs, int32_t dirclust, const void *name, struct libfat_direntry *direntry) { struct fat_dirent *dep; - int nent; + unsigned int nent; libfat_sector_t s = libfat_clustertosector(fs, dirclust); while (1) { diff --git a/src/syslinux/libinstaller/syslinux.h b/src/syslinux/libinstaller/syslinux.h index 8907321c..1f6fe278 100644 --- a/src/syslinux/libinstaller/syslinux.h +++ b/src/syslinux/libinstaller/syslinux.h @@ -41,8 +41,11 @@ extern const unsigned int syslinux_mbr_len; extern const int syslinux_mbr_mtime; /* Sector size assumptions... */ -#define SECTOR_SHIFT 9 -#define SECTOR_SIZE (1 << SECTOR_SHIFT) +// Workaround for 4K support +extern uint32_t SECTOR_SHIFT; +extern uint32_t SECTOR_SIZE; +//#define SECTOR_SHIFT 9 +//#define SECTOR_SIZE (1 << SECTOR_SHIFT) /* This takes a boot sector and merges in the syslinux fields */ void syslinux_make_bootsect(void *bs, int fs_type);