aboutsummaryrefslogtreecommitdiffstats
path: root/libinstaller
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 /libinstaller
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>
Diffstat (limited to 'libinstaller')
-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
10 files changed, 184 insertions, 60 deletions
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 */