aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@gmail.com>2011-07-05 21:32:51 +0000
committerPaulo Alcantara <pcacjr@gmail.com>2011-09-07 07:19:05 +0000
commitb0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6 (patch)
treefe5f5498e0dfdf8a0136cd00f0fd79683d691dbd
parent67954e370003d9bbfd8b58042669f2e9d532636f (diff)
downloadsyslinux-b0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6.tar.gz
syslinux-b0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6.tar.xz
syslinux-b0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6.zip
Add NTFS filesystem support to Linux and Windows installers
Signed-off-by: Paulo Alcantara <pcacjr@gmail.com>
-rw-r--r--dos/Makefile2
-rw-r--r--dos/syslinux.c5
-rw-r--r--extlinux/Makefile2
-rwxr-xr-xextlinux/main.c59
-rw-r--r--extlinux/ntfs.h19
-rw-r--r--libinstaller/fs.c (renamed from libinstaller/fat.c)120
-rw-r--r--libinstaller/linuxioctl.h5
-rw-r--r--libinstaller/setadv.c1
-rw-r--r--libinstaller/syslinux.h4
-rw-r--r--libinstaller/syslxcom.c6
-rw-r--r--libinstaller/syslxcom.h9
-rw-r--r--libinstaller/syslxfs.h26
-rw-r--r--libinstaller/syslxint.h70
-rw-r--r--libinstaller/syslxmod.c2
-rw-r--r--libinstaller/syslxopt.c1
-rw-r--r--linux/Makefile4
-rwxr-xr-xlinux/syslinux.c24
-rwxr-xr-xmtools/Makefile2
-rwxr-xr-xmtools/syslinux.c5
-rw-r--r--win/syslinux.c9
-rw-r--r--win32/Makefile2
-rw-r--r--win64/Makefile2
22 files changed, 285 insertions, 94 deletions
diff --git a/dos/Makefile b/dos/Makefile
index 5e5fc63f..f9420084 100644
--- a/dos/Makefile
+++ b/dos/Makefile
@@ -27,7 +27,7 @@ INCLUDES = -include code16.h -nostdinc -iwithprefix include \
-I. -I.. -I../libfat -I ../libinstaller -I ../libinstaller/getopt
SRCS = syslinux.c \
- ../libinstaller/fat.c \
+ ../libinstaller/fs.c \
../libinstaller/syslxmod.c \
../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
diff --git a/dos/syslinux.c b/dos/syslinux.c
index b5fdfc52..fa4bf387 100644
--- a/dos/syslinux.c
+++ b/dos/syslinux.c
@@ -31,6 +31,7 @@
#include "sysexits.h"
#include "syslxopt.h"
#include "syslxint.h"
+#include "syslxfs.h"
char *program = "syslinux.com"; /* Name of program */
uint16_t dos_version;
@@ -638,7 +639,7 @@ int main(int argc, char *argv[])
/*
* Check to see that what we got was indeed an MS-DOS boot sector/superblock
*/
- if ((errmsg = syslinux_check_bootsect(sectbuf))) {
+ if ((errmsg = syslinux_check_bootsect(sectbuf, NULL))) {
unlock_device(0);
puts(errmsg);
putchar('\n');
@@ -749,7 +750,7 @@ int main(int argc, char *argv[])
read_device(dev_fd, sectbuf, 1, 0);
/* Copy the syslinux code into the boot sector */
- syslinux_make_bootsect(sectbuf);
+ syslinux_make_bootsect(sectbuf, VFAT);
/* Write new boot sector */
if (opt.bootsecfile) {
diff --git a/extlinux/Makefile b/extlinux/Makefile
index 12213d88..865c7a64 100644
--- a/extlinux/Makefile
+++ b/extlinux/Makefile
@@ -11,7 +11,7 @@
## -----------------------------------------------------------------------
##
-## Linux vfat, ext2/ext3/ext4 and btrfs installer
+## Linux vfat, ntfs, ext2/ext3/ext4 and btrfs installer
##
topdir = ..
diff --git a/extlinux/main.c b/extlinux/main.c
index e574051b..d85d03c8 100755
--- a/extlinux/main.c
+++ b/extlinux/main.c
@@ -14,7 +14,7 @@
/*
* extlinux.c
*
- * Install the syslinux boot block on an fat, ext2/3/4 and btrfs filesystem
+ * Install the syslinux boot block on an fat, ntfs, ext2/3/4 and btrfs filesystem
*/
#define _GNU_SOURCE /* Enable everything */
@@ -45,9 +45,11 @@
#include "btrfs.h"
#include "fat.h"
+#include "ntfs.h"
#include "../version.h"
#include "syslxint.h"
#include "syslxcom.h" /* common functions shared with extlinux and syslinux */
+#include "syslxfs.h"
#include "setadv.h"
#include "syslxopt.h" /* unified options */
@@ -214,7 +216,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
sector_t *sectp;
uint64_t totalbytes, totalsectors;
int nsect;
- struct boot_sector *sbs;
+ struct fat_boot_sector *sbs;
char *dirpath, *subpath, *xdirpath;
int rv;
@@ -271,7 +273,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
early bootstrap share code with the FAT version. */
dprintf("heads = %u, sect = %u\n", geo.heads, geo.sectors);
- sbs = (struct boot_sector *)syslinux_bootsect;
+ sbs = (struct fat_boot_sector *)syslinux_bootsect;
totalsectors = totalbytes >> SECTOR_SHIFT;
if (totalsectors >= 65536) {
@@ -292,7 +294,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
nsect = (boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
nsect += 2; /* Two sectors for the ADV */
sectp = alloca(sizeof(sector_t) * nsect);
- if (fs_type == EXT2 || fs_type == VFAT) {
+ if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS) {
if (sectmap(fd, sectp, nsect)) {
perror("bmap");
exit(1);
@@ -323,7 +325,8 @@ int install_bootblock(int fd, const char *device)
{
struct ext2_super_block sb;
struct btrfs_super_block sb2;
- struct boot_sector sb3;
+ struct fat_boot_sector sb3;
+ struct ntfs_boot_sector sb4;
bool ok = false;
if (fs_type == EXT2) {
@@ -348,20 +351,39 @@ int install_bootblock(int fd, const char *device)
}
if (fat_check_sb_fields(&sb3))
ok = true;
+ } else if (fs_type == NTFS) {
+ if (xpread(fd, &sb4, sizeof(sb4), 0) != sizeof(sb4)) {
+ perror("reading ntfs superblock");
+ return 1;
+ }
+
+ if (ntfs_check_sb_fields(&sb4))
+ ok = true;
}
if (!ok) {
- fprintf(stderr, "no fat, ext2/3/4 or btrfs superblock found on %s\n",
+ fprintf(stderr, "no fat, ntfs, ext2/3/4 or btrfs superblock found on %s\n",
device);
return 1;
}
if (fs_type == VFAT) {
- struct boot_sector *sbs = (struct boot_sector *)syslinux_bootsect;
- if (xpwrite(fd, &sbs->bsHead, bsHeadLen, 0) != bsHeadLen ||
- xpwrite(fd, &sbs->bsCode, bsCodeLen,
- offsetof(struct boot_sector, bsCode)) != bsCodeLen) {
+ struct fat_boot_sector *sbs = (struct fat_boot_sector *)syslinux_bootsect;
+ if (xpwrite(fd, &sbs->FAT_bsHead, FAT_bsHeadLen, 0) != FAT_bsHeadLen ||
+ xpwrite(fd, &sbs->FAT_bsCode, FAT_bsCodeLen,
+ offsetof(struct fat_boot_sector, FAT_bsCode)) != FAT_bsCodeLen) {
perror("writing fat bootblock");
return 1;
}
+ } else if (fs_type == NTFS) {
+ struct ntfs_boot_sector *sbs =
+ (struct ntfs_boot_sector *)syslinux_bootsect;
+ if (xpwrite(fd, &sbs->NTFS_bsHead,
+ NTFS_bsHeadLen, 0) != NTFS_bsHeadLen ||
+ xpwrite(fd, &sbs->NTFS_bsCode, NTFS_bsCodeLen,
+ offsetof(struct ntfs_boot_sector,
+ NTFS_bsCode)) != NTFS_bsCodeLen) {
+ perror("writing ntfs bootblock");
+ return 1;
+ }
} else {
if (xpwrite(fd, syslinux_bootsect, syslinux_bootsect_len, 0)
!= syslinux_bootsect_len) {
@@ -754,7 +776,7 @@ static char * get_default_subvol(char * rootdir, char * subvol)
int install_file(const char *path, int devfd, struct stat *rst)
{
- if (fs_type == EXT2 || fs_type == VFAT)
+ if (fs_type == EXT2 || fs_type == VFAT || fs_type == NTFS)
return ext2_fat_install_file(path, devfd, rst);
else if (fs_type == BTRFS)
return btrfs_install_file(path, devfd, rst);
@@ -828,6 +850,16 @@ static const char *find_device(const char *mtab_file, dev_t dev)
done = true;
break;
}
+ case NTFS:
+ if ((!strcmp(mnt->mnt_type, "fuseblk") /* ntfs-3g */ ||
+ !strcmp(mnt->mnt_type, "ntfs")) &&
+ !stat(mnt->mnt_fsname, &dst) &&
+ dst.st_rdev == dev) {
+ done = true;
+ break;
+ }
+
+ break;
case NONE:
break;
}
@@ -910,9 +942,12 @@ static int open_device(const char *path, struct stat *st, const char **_devname)
fs_type = BTRFS;
else if (sfs.f_type == MSDOS_SUPER_MAGIC)
fs_type = VFAT;
+ else if (sfs.f_type == NTFS_SB_MAGIC ||
+ sfs.f_type == FUSE_SUPER_MAGIC /* ntfs-3g */)
+ fs_type = NTFS;
if (!fs_type) {
- fprintf(stderr, "%s: not a fat, ext2/3/4 or btrfs filesystem: %s\n",
+ fprintf(stderr, "%s: not a fat, ntfs, ext2/3/4 or btrfs filesystem: %s\n",
program, path);
return -1;
}
diff --git a/extlinux/ntfs.h b/extlinux/ntfs.h
new file mode 100644
index 00000000..d907d452
--- /dev/null
+++ b/extlinux/ntfs.h
@@ -0,0 +1,19 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2011 Paulo Alcantara <pcacjr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef _NTFS_H_
+#define _NTFS_H_
+
+#define NTFS_SB_MAGIC 0x5346544E
+#define FUSE_SUPER_MAGIC 0x65735546
+
+#endif /* _NTFS_H_ */
diff --git a/libinstaller/fat.c b/libinstaller/fs.c
index 9cde00c2..179629e9 100644
--- a/libinstaller/fat.c
+++ b/libinstaller/fs.c
@@ -1,7 +1,8 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author H. Peter Anvin
+ * Copyright 1998-2011 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2011 Intel Corporation; author H. Peter Anvin
+ * Copyright 2011 Paulo Alcantara <pcacjr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,7 +13,7 @@
* ----------------------------------------------------------------------- */
/*
- * fat.c - Initial sanity check for FAT-based installers
+ * fs.c - Generic sanity check for FAT/NTFS-based installers
*/
#define _XOPEN_SOURCE 500 /* Required on glibc 2.x */
@@ -25,45 +26,41 @@
#include "syslinux.h"
#include "syslxint.h"
+#include "syslxcom.h"
+#include "syslxfs.h"
-void syslinux_make_bootsect(void *bs)
+void syslinux_make_bootsect(void *bs, int fs_type)
{
- struct boot_sector *bootsect = bs;
- const struct boot_sector *sbs =
- (const struct boot_sector *)boot_sector;
-
- memcpy(&bootsect->bsHead, &sbs->bsHead, bsHeadLen);
- memcpy(&bootsect->bsCode, &sbs->bsCode, bsCodeLen);
+ if (fs_type == VFAT) {
+ struct fat_boot_sector *bootsect = bs;
+ const struct fat_boot_sector *sbs =
+ (const struct fat_boot_sector *)boot_sector;
+
+ memcpy(&bootsect->FAT_bsHead, &sbs->FAT_bsHead, FAT_bsHeadLen);
+ memcpy(&bootsect->FAT_bsCode, &sbs->FAT_bsCode, FAT_bsCodeLen);
+ } else if (fs_type == NTFS) {
+ struct ntfs_boot_sector *bootsect = bs;
+ const struct ntfs_boot_sector *sbs =
+ (const struct ntfs_boot_sector *)boot_sector;
+
+ memcpy(&bootsect->NTFS_bsHead, &sbs->NTFS_bsHead, NTFS_bsHeadLen);
+ memcpy(&bootsect->NTFS_bsCode, &sbs->NTFS_bsCode, NTFS_bsCodeLen);
+ }
}
-/*
- * Check to see that what we got was indeed an MS-DOS boot sector/superblock;
- * Return NULL if OK and otherwise an error message;
- */
-const char *syslinux_check_bootsect(const void *bs)
+static const char *check_fat_bootsect(const void *bs, int *fs_type)
{
int sectorsize;
+ const struct fat_boot_sector *sectbuf = bs;
long long sectors, fatsectors, dsectors;
long long clusters;
int rootdirents, clustersize;
- const struct boot_sector *sectbuf = bs;
-
- /* Must be 0xF0 or 0xF8..0xFF */
- if (get_8(&sectbuf->bsMedia) != 0xF0 && get_8(&sectbuf->bsMedia) < 0xF8)
- return "invalid media signature (not a FAT filesystem?)";
sectorsize = get_16(&sectbuf->bsBytesPerSec);
- if (sectorsize == SECTOR_SIZE)
- ; /* ok */
- else if (sectorsize >= 512 && sectorsize <= 4096 &&
- (sectorsize & (sectorsize - 1)) == 0)
- return "unsupported sectors size";
- else
- return "impossible sector size";
clustersize = get_8(&sectbuf->bsSecPerClust);
if (clustersize == 0 || (clustersize & (clustersize - 1)))
- return "impossible cluster size";
+ return "impossible cluster size on an FAT volume";
sectors = get_16(&sectbuf->bsSectors);
sectors = sectors ? sectors : get_32(&sectbuf->bsHugeSectors);
@@ -79,16 +76,19 @@ const char *syslinux_check_bootsect(const void *bs)
dsectors -= (rootdirents + sectorsize / 32 - 1) / sectorsize;
if (dsectors < 0)
- return "negative number of data sectors";
-
- if (fatsectors == 0)
- return "zero FAT sectors";
+ return "negative number of data sectors on an FAT volume";
clusters = dsectors / clustersize;
+ fatsectors = get_16(&sectbuf->bsFATsecs);
+ fatsectors = fatsectors ? fatsectors : get_32(&sectbuf->bs32.FATSz32);
+ fatsectors *= get_8(&sectbuf->bsFATs);
+
+ if (!fatsectors)
+ return "zero FAT sectors";
+
if (clusters < 0xFFF5) {
/* FAT12 or FAT16 */
-
if (!get_16(&sectbuf->bsFATsecs))
return "zero FAT sectors (FAT12/16)";
@@ -100,10 +100,10 @@ const char *syslinux_check_bootsect(const void *bs)
if (clusters < 0xFF5)
return "less than 4084 clusters but claims FAT16";
} else if (!memcmp(&sectbuf->bs16.FileSysType, "FAT32 ", 8)) {
- return "less than 65525 clusters but claims FAT32";
+ return "less than 65525 clusters but claims FAT32";
} else if (memcmp(&sectbuf->bs16.FileSysType, "FAT ", 8)) {
- static char fserr[] =
- "filesystem type \"????????\" not supported";
+ static char fserr[] = "filesystem type \"????????\" not "
+ "supported";
memcpy(fserr + 17, &sectbuf->bs16.FileSysType, 8);
return fserr;
}
@@ -119,8 +119,54 @@ const char *syslinux_check_bootsect(const void *bs)
memcmp(&sectbuf->bs32.FileSysType, "FAT32 ", 8))
return "missing FAT32 signature";
} else {
- return "impossibly large number of clusters";
+ return "impossibly large number of clusters on an FAT volume";
}
+ if (fs_type)
+ *fs_type = VFAT;
+
+ return NULL;
+}
+
+static const char *check_ntfs_bootsect(const void *bs, int *fs_type)
+{
+ const struct ntfs_boot_sector *sectbuf = bs;
+
+ if (memcmp(&sectbuf->bsOemName, "NTFS ", 8) &&
+ memcmp(&sectbuf->bsOemName, "MSWIN4.0", 8) &&
+ memcmp(&sectbuf->bsOemName, "MSWIN4.1", 8))
+ return "unknown OEM name but claims NTFS";
+
+ if (fs_type)
+ *fs_type = NTFS;
+
return NULL;
}
+
+const char *syslinux_check_bootsect(const void *bs, int *fs_type)
+{
+ uint8_t media_sig;
+ int sectorsize;
+ const struct fat_boot_sector *sectbuf = bs;
+ const char *retval;
+
+ media_sig = get_8(&sectbuf->bsMedia);
+ /* Must be 0xF0 or 0xF8-0xFF for FAT/NTFS volumes */
+ if (media_sig != 0xF0 && media_sig < 0xF8)
+ return "invalid media signature (not an FAT/NTFS volume?)";
+
+ sectorsize = get_16(&sectbuf->bsBytesPerSec);
+ if (sectorsize == SECTOR_SIZE) ; /* ok */
+ else if (sectorsize >= 512 && sectorsize <= 4096 &&
+ (sectorsize & (sectorsize - 1)) == 0)
+ return "unsupported sectors size";
+ else
+ return "impossible sector size";
+
+ if (ntfs_check_zero_fields((struct ntfs_boot_sector *)bs))
+ retval = check_ntfs_bootsect(bs, fs_type);
+ else
+ retval = check_fat_bootsect(bs, fs_type);
+
+ return retval;
+}
diff --git a/libinstaller/linuxioctl.h b/libinstaller/linuxioctl.h
index 7ef919a3..c339480a 100644
--- a/libinstaller/linuxioctl.h
+++ b/libinstaller/linuxioctl.h
@@ -15,7 +15,6 @@
#include <linux/hdreg.h> /* Hard disk geometry */
#include <linux/fs.h> /* FIGETBSZ, FIBMAP, FS_IOC_FIEMAP */
-#include <linux/msdos_fs.h> /* FAT_IOCTL_SET_ATTRIBUTES */
#undef SECTOR_SIZE /* Defined in msdos_fs.h for no good reason */
#undef SECTOR_BITS
@@ -25,9 +24,7 @@
# define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32)
#endif
-#ifndef FAT_IOCTL_SET_ATTRIBUTES
-# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
-#endif
+#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
#include <linux/fiemap.h> /* FIEMAP definitions */
diff --git a/libinstaller/setadv.c b/libinstaller/setadv.c
index 9cf6f188..214f7fc1 100644
--- a/libinstaller/setadv.c
+++ b/libinstaller/setadv.c
@@ -30,6 +30,7 @@
#include <errno.h>
#include "syslxint.h"
#include "syslxcom.h"
+#include "syslxfs.h"
unsigned char syslinux_adv[2 * ADV_SIZE];
diff --git a/libinstaller/syslinux.h b/libinstaller/syslinux.h
index 710d30e5..8b86f881 100644
--- a/libinstaller/syslinux.h
+++ b/libinstaller/syslinux.h
@@ -40,10 +40,10 @@ extern const int syslinux_mbr_mtime;
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
/* This takes a boot sector and merges in the syslinux fields */
-void syslinux_make_bootsect(void *);
+void syslinux_make_bootsect(void *bs, int fs_type);
/* Check to see that what we got was indeed an MS-DOS boot sector/superblock */
-const char *syslinux_check_bootsect(const void *bs);
+const char *syslinux_check_bootsect(const void *bs, int *fs_type);
/* This patches the boot sector and ldlinux.sys based on a sector map */
typedef uint64_t sector_t;
diff --git a/libinstaller/syslxcom.c b/libinstaller/syslxcom.c
index 1de85aa5..651f982d 100644
--- a/libinstaller/syslxcom.c
+++ b/libinstaller/syslxcom.c
@@ -30,8 +30,10 @@
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/vfs.h>
+
#include "linuxioctl.h"
#include "syslxcom.h"
+#include "syslxfs.h"
const char *program;
@@ -133,6 +135,8 @@ void clear_attributes(int fd)
ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
break;
}
+ case NTFS:
+ break;
default:
break;
}
@@ -163,6 +167,8 @@ void set_attributes(int fd)
ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
break;
}
+ case NTFS:
+ break;
default:
break;
}
diff --git a/libinstaller/syslxcom.h b/libinstaller/syslxcom.h
index bf186ca6..8b3b4614 100644
--- a/libinstaller/syslxcom.h
+++ b/libinstaller/syslxcom.h
@@ -3,15 +3,6 @@
#include "syslinux.h"
-/* Global fs_type for handling fat, ext2/3/4 and btrfs */
-enum filesystem {
- NONE,
- EXT2,
- BTRFS,
- VFAT,
-};
-
-extern int fs_type;
extern const char *program;
ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
diff --git a/libinstaller/syslxfs.h b/libinstaller/syslxfs.h
new file mode 100644
index 00000000..7a231461
--- /dev/null
+++ b/libinstaller/syslxfs.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 Paulo Alcantara <pcacjr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef _SYSLXFS_H_
+#define _SYSLXFS_H_
+
+/* Global fs_type for handling fat, ntfs, ext2/3/4 and btrfs */
+enum filesystem {
+ NONE,
+ EXT2,
+ BTRFS,
+ VFAT,
+ NTFS,
+};
+
+extern int fs_type;
+
+#endif /* _SYSLXFS_H_ */
diff --git a/libinstaller/syslxint.h b/libinstaller/syslxint.h
index 7c9da516..2e317d0e 100644
--- a/libinstaller/syslxint.h
+++ b/libinstaller/syslxint.h
@@ -2,6 +2,7 @@
*
* Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
* Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2011 Paulo Alcantara <pcacjr@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -192,7 +193,7 @@ struct syslinux_extent {
} __attribute__((packed));
/* FAT bootsector format, also used by other disk-based derivatives */
-struct boot_sector {
+struct fat_boot_sector {
uint8_t bsJump[3];
char bsOemName[8];
uint16_t bsBytesPerSec;
@@ -241,13 +242,68 @@ struct boot_sector {
uint16_t bsSignature;
} __attribute__ ((packed));
-#define bsHead bsJump
-#define bsHeadLen offsetof(struct boot_sector, bsBytesPerSec)
-#define bsCode bs32.Code /* The common safe choice */
-#define bsCodeLen (offsetof(struct boot_sector, bsSignature) - \
- offsetof(struct boot_sector, bsCode))
+/* NTFS bootsector format */
+struct ntfs_boot_sector {
+ uint8_t bsJump[3];
+ char bsOemName[8];
+ uint16_t bsBytesPerSec;
+ uint8_t bsSecPerClust;
+ uint16_t bsResSectors;
+ uint8_t bsZeroed_0[3];
+ uint16_t bsZeroed_1;
+ uint8_t bsMedia;
+ uint16_t bsZeroed_2;
+ uint16_t bsUnused_0;
+ uint16_t bsUnused_1;
+ uint32_t bsUnused_2;
+ uint32_t bsZeroed_3;
+ uint32_t bsUnused_3;
+ uint64_t bsTotalSectors;
+ uint64_t bsMFTLogicalClustNr;
+ uint64_t bsMFTMirrLogicalClustNr;
+ uint8_t bsClustPerMFTrecord;
+ uint8_t bsUnused_4[3];
+ uint8_t bsClustPerIdxBuf;
+ uint8_t bsUnused_5[3];
+ uint64_t bsVolSerialNr;
+ uint32_t bsUnused_6;
+
+ uint8_t Code[420];
+
+ uint32_t bsMagic;
+ uint16_t bsForwardPtr;
+ uint16_t bsSignature;
+} __attribute__((packed));
+
+#define FAT_bsHead bsJump
+#define FAT_bsHeadLen offsetof(struct fat_boot_sector, bsBytesPerSec)
+#define FAT_bsCode bs32.Code /* The common safe choice */
+#define FAT_bsCodeLen (offsetof(struct fat_boot_sector, bsSignature) - \
+ offsetof(struct fat_boot_sector, FAT_bsCode))
+
+#define NTFS_bsHead bsJump
+#define NTFS_bsHeadLen offsetof(struct ntfs_boot_sector, bsOemName)
+#define NTFS_bsCode Code
+#define NTFS_bsCodeLen (offsetof(struct ntfs_boot_sector, bsSignature) - \
+ offsetof(struct ntfs_boot_sector, NTFS_bsCode))
+
+/* Check if there are specific zero fields in an NTFS boot sector */
+static inline int ntfs_check_zero_fields(const struct ntfs_boot_sector *sb)
+{
+ return !sb->bsResSectors && (!sb->bsZeroed_0[0] && !sb->bsZeroed_0[1] &&
+ !sb->bsZeroed_0[2]) && !sb->bsZeroed_1 && !sb->bsZeroed_2 &&
+ !sb->bsZeroed_3;
+}
+
+static inline int ntfs_check_sb_fields(const struct ntfs_boot_sector *sb)
+{
+ return ntfs_check_zero_fields(sb) &&
+ (!memcmp(sb->bsOemName, "NTFS ", 8) ||
+ !memcmp(sb->bsOemName, "MSWIN4.0", 8) ||
+ !memcmp(sb->bsOemName, "MSWIN4.1", 8));
+}
-static inline int fat_check_sb_fields(const struct boot_sector *sb)
+static inline int fat_check_sb_fields(const struct fat_boot_sector *sb)
{
return sb->bsResSectors && sb->bsFATs &&
(!memcmp(sb->bs16.FileSysType, "FAT12 ", 8) ||
diff --git a/libinstaller/syslxmod.c b/libinstaller/syslxmod.c
index 8847b736..24368459 100644
--- a/libinstaller/syslxmod.c
+++ b/libinstaller/syslxmod.c
@@ -109,7 +109,7 @@ int syslinux_patch(const sector_t *sectp, int nsectors,
int nsect = ((boot_image_len + SECTOR_SIZE - 1) >> SECTOR_SHIFT) + 2;
uint32_t csum;
int i, dw, nptrs;
- struct boot_sector *sbs = (struct boot_sector *)boot_sector;
+ struct fat_boot_sector *sbs = (struct fat_boot_sector *)boot_sector;
uint64_t *advptrs;
if (nsectors < nsect)
diff --git a/libinstaller/syslxopt.c b/libinstaller/syslxopt.c
index 7ceb3ba2..e081a00e 100644
--- a/libinstaller/syslxopt.c
+++ b/libinstaller/syslxopt.c
@@ -25,6 +25,7 @@
#include <sysexits.h>
#include "../version.h"
#include "syslxcom.h"
+#include "syslxfs.h"
#include "syslxopt.h"
/* These are the options we can set their values */
diff --git a/linux/Makefile b/linux/Makefile
index 82bf1118..08a3ed49 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -11,7 +11,7 @@
## -----------------------------------------------------------------------
##
-## Linux FAT installer
+## Linux FAT/NTFS installer
##
topdir = ..
@@ -28,7 +28,7 @@ SRCS = syslinux.c \
../libinstaller/syslxcom.c \
../libinstaller/setadv.c \
../libinstaller/advio.c \
- ../libinstaller/fat.c \
+ ../libinstaller/fs.c \
../libinstaller/syslxmod.c \
../libinstaller/bootsect_bin.c \
../libinstaller/ldlinux_bin.c
diff --git a/linux/syslinux.c b/linux/syslinux.c
index c7a9ecc4..4b13b7fe 100755
--- a/linux/syslinux.c
+++ b/linux/syslinux.c
@@ -69,6 +69,7 @@
#include <getopt.h>
#include <sysexits.h>
#include "syslxcom.h"
+#include "syslxfs.h"
#include "setadv.h"
#include "syslxopt.h" /* unified options */
@@ -294,14 +295,14 @@ int main(int argc, char *argv[])
die("can't combine an offset with a block device");
}
- fs_type = VFAT;
xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
fsync(dev_fd);
/*
- * Check to see that what we got was indeed an MS-DOS boot sector/superblock
+ * Check to see that what we got was indeed an FAT/NTFS
+ * boot sector/superblock
*/
- if ((errmsg = syslinux_check_bootsect(sectbuf))) {
+ if ((errmsg = syslinux_check_bootsect(sectbuf, &fs_type))) {
fprintf(stderr, "%s: %s\n", opt.device, errmsg);
exit(1);
}
@@ -357,10 +358,17 @@ int main(int argc, char *argv[])
mntpath = mntname;
}
- if (do_mount(dev_fd, &mnt_cookie, mntpath, "vfat") &&
- do_mount(dev_fd, &mnt_cookie, mntpath, "msdos")) {
- rmdir(mntpath);
- die("mount failed");
+ if (fs_type == VFAT) {
+ if (do_mount(dev_fd, &mnt_cookie, mntpath, "vfat") &&
+ do_mount(dev_fd, &mnt_cookie, mntpath, "msdos")) {
+ rmdir(mntpath);
+ die("failed on mounting fat volume");
+ }
+ } else if (fs_type == NTFS) {
+ if (do_mount(dev_fd, &mnt_cookie, mntpath, "ntfs-3g")) {
+ rmdir(mntpath);
+ die("failed on mounting ntfs volume");
+ }
}
ldlinux_path = alloca(strlen(mntpath) + strlen(subdir) + 1);
@@ -474,7 +482,7 @@ umount:
xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
/* Copy the syslinux code into the boot sector */
- syslinux_make_bootsect(sectbuf);
+ syslinux_make_bootsect(sectbuf, fs_type);
/* Write new boot sector */
xpwrite(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
diff --git a/mtools/Makefile b/mtools/Makefile
index 3e172fd6..78cea1e2 100755
--- a/mtools/Makefile
+++ b/mtools/Makefile
@@ -8,7 +8,7 @@ CFLAGS = $(GCCWARN) -D_FILE_OFFSET_BITS=64 $(OPTFLAGS) $(INCLUDES)
LDFLAGS =
SRCS = syslinux.c \
- ../libinstaller/fat.c \
+ ../libinstaller/fs.c \
../libinstaller/syslxmod.c \
../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
diff --git a/mtools/syslinux.c b/mtools/syslinux.c
index ac189c61..c65021bb 100755
--- a/mtools/syslinux.c
+++ b/mtools/syslinux.c
@@ -41,6 +41,7 @@
#include "libfat.h"
#include "setadv.h"
#include "syslxopt.h"
+#include "syslxfs.h"
char *program; /* Name of program */
pid_t mypid;
@@ -197,7 +198,7 @@ int main(int argc, char *argv[])
/*
* Check to see that what we got was indeed an MS-DOS boot sector/superblock
*/
- if ((errmsg = syslinux_check_bootsect(sectbuf))) {
+ if ((errmsg = syslinux_check_bootsect(sectbuf, NULL))) {
die(errmsg);
}
@@ -356,7 +357,7 @@ int main(int argc, char *argv[])
xpread(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
/* Copy the syslinux code into the boot sector */
- syslinux_make_bootsect(sectbuf);
+ syslinux_make_bootsect(sectbuf, VFAT);
/* Write new boot sector */
xpwrite(dev_fd, sectbuf, SECTOR_SIZE, opt.offset);
diff --git a/win/syslinux.c b/win/syslinux.c
index 0e833d8d..4e4435ef 100644
--- a/win/syslinux.c
+++ b/win/syslinux.c
@@ -254,6 +254,7 @@ int main(int argc, char *argv[])
int ldlinux_sectors;
uint32_t ldlinux_cluster;
int nsectors;
+ int fs_type;
if (!checkver()) {
fprintf(stderr,
@@ -326,8 +327,10 @@ int main(int argc, char *argv[])
exit(1);
}
- /* Check to see that what we got was indeed an MS-DOS boot sector/superblock */
- if ((errmsg = syslinux_check_bootsect(sectbuf))) {
+ /* Check to see that what we got was indeed an FAT/NTFS
+ * boot sector/superblock
+ */
+ if ((errmsg = syslinux_check_bootsect(sectbuf, &fs_type))) {
fprintf(stderr, "%s\n", errmsg);
exit(1);
}
@@ -472,7 +475,7 @@ int main(int argc, char *argv[])
}
/* Make the syslinux boot sector */
- syslinux_make_bootsect(sectbuf);
+ syslinux_make_bootsect(sectbuf, fs_type);
/* Write the syslinux boot sector into the boot sector */
if (opt.bootsecfile) {
diff --git a/win32/Makefile b/win32/Makefile
index d4133ff8..cdb18f24 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -49,7 +49,7 @@ WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
SRCS = ../win/syslinux.c
OBJS = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
-LIBSRC = ../libinstaller/fat.c \
+LIBSRC = ../libinstaller/fs.c \
../libinstaller/syslxmod.c \
../libinstaller/syslxopt.c \
../libinstaller/setadv.c \
diff --git a/win64/Makefile b/win64/Makefile
index 0bc746d5..6853fb20 100644
--- a/win64/Makefile
+++ b/win64/Makefile
@@ -39,7 +39,7 @@ WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
SRCS = ../win/syslinux.c
OBJS = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
-LIBSRC = ../libinstaller/fat.c \
+LIBSRC = ../libinstaller/fs.c \
../libinstaller/syslxmod.c \
../libinstaller/syslxopt.c \
../libinstaller/setadv.c \