diff options
author | Paulo Alcantara <pcacjr@gmail.com> | 2011-07-05 21:32:51 +0000 |
---|---|---|
committer | Paulo Alcantara <pcacjr@gmail.com> | 2011-09-07 07:19:05 +0000 |
commit | b0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6 (patch) | |
tree | fe5f5498e0dfdf8a0136cd00f0fd79683d691dbd | |
parent | 67954e370003d9bbfd8b58042669f2e9d532636f (diff) | |
download | syslinux-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/Makefile | 2 | ||||
-rw-r--r-- | dos/syslinux.c | 5 | ||||
-rw-r--r-- | extlinux/Makefile | 2 | ||||
-rwxr-xr-x | extlinux/main.c | 59 | ||||
-rw-r--r-- | extlinux/ntfs.h | 19 | ||||
-rw-r--r-- | libinstaller/fs.c (renamed from libinstaller/fat.c) | 120 | ||||
-rw-r--r-- | libinstaller/linuxioctl.h | 5 | ||||
-rw-r--r-- | libinstaller/setadv.c | 1 | ||||
-rw-r--r-- | libinstaller/syslinux.h | 4 | ||||
-rw-r--r-- | libinstaller/syslxcom.c | 6 | ||||
-rw-r--r-- | libinstaller/syslxcom.h | 9 | ||||
-rw-r--r-- | libinstaller/syslxfs.h | 26 | ||||
-rw-r--r-- | libinstaller/syslxint.h | 70 | ||||
-rw-r--r-- | libinstaller/syslxmod.c | 2 | ||||
-rw-r--r-- | libinstaller/syslxopt.c | 1 | ||||
-rw-r--r-- | linux/Makefile | 4 | ||||
-rwxr-xr-x | linux/syslinux.c | 24 | ||||
-rwxr-xr-x | mtools/Makefile | 2 | ||||
-rwxr-xr-x | mtools/syslinux.c | 5 | ||||
-rw-r--r-- | win/syslinux.c | 9 | ||||
-rw-r--r-- | win32/Makefile | 2 | ||||
-rw-r--r-- | win64/Makefile | 2 |
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(§buf->bsMedia) != 0xF0 && get_8(§buf->bsMedia) < 0xF8) - return "invalid media signature (not a FAT filesystem?)"; sectorsize = get_16(§buf->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(§buf->bsSecPerClust); if (clustersize == 0 || (clustersize & (clustersize - 1))) - return "impossible cluster size"; + return "impossible cluster size on an FAT volume"; sectors = get_16(§buf->bsSectors); sectors = sectors ? sectors : get_32(§buf->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(§buf->bsFATsecs); + fatsectors = fatsectors ? fatsectors : get_32(§buf->bs32.FATSz32); + fatsectors *= get_8(§buf->bsFATs); + + if (!fatsectors) + return "zero FAT sectors"; + if (clusters < 0xFFF5) { /* FAT12 or FAT16 */ - if (!get_16(§buf->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(§buf->bs16.FileSysType, "FAT32 ", 8)) { - return "less than 65525 clusters but claims FAT32"; + return "less than 65525 clusters but claims FAT32"; } else if (memcmp(§buf->bs16.FileSysType, "FAT ", 8)) { - static char fserr[] = - "filesystem type \"????????\" not supported"; + static char fserr[] = "filesystem type \"????????\" not " + "supported"; memcpy(fserr + 17, §buf->bs16.FileSysType, 8); return fserr; } @@ -119,8 +119,54 @@ const char *syslinux_check_bootsect(const void *bs) memcmp(§buf->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(§buf->bsOemName, "NTFS ", 8) && + memcmp(§buf->bsOemName, "MSWIN4.0", 8) && + memcmp(§buf->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(§buf->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(§buf->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 \ |