summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@gmail.com>2011-07-07 21:28:05 +0000
committerPaulo Alcantara <pcacjr@gmail.com>2011-09-07 07:19:06 +0000
commit045bc5cd1118fee51b19d89dc316038c8a93e5bf (patch)
tree92e8008767611b08ee9b3a6289c7a32c77634697
parentb0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6 (diff)
downloadsyslinux-045bc5cd1118fee51b19d89dc316038c8a93e5bf.tar.gz
Initial NTFS readonly support code to Syslinux
Basically add the NTFS filesystem structures and also implement ntfs_fs_init() to only initialize the filesystem metadata and return the block size in bits. Signed-off-by: Paulo Alcantara <pcacjr@gmail.com>
-rw-r--r--core/fs/ntfs/ntfs.c105
-rw-r--r--core/fs/ntfs/ntfs.h64
-rw-r--r--core/ldlinux.asm2
3 files changed, 171 insertions, 0 deletions
diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c
new file mode 100644
index 00000000..24c9859e
--- /dev/null
+++ b/core/fs/ntfs/ntfs.c
@@ -0,0 +1,105 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ntfs.c - The NTFS filesystem functions
+ */
+
+#include <dprintf.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/dirent.h>
+#include <cache.h>
+#include <core.h>
+#include <disk.h>
+#include <fs.h>
+#include <ilog2.h>
+#include <klibc/compiler.h>
+
+#include "codepage.h"
+#include "ntfs.h"
+
+/* Check if there are specific zero fields in an NTFS boot sector */
+static inline int ntfs_check_zero_fields(const struct ntfs_bpb *sb)
+{
+ return !sb->res_sectors && (!sb->zero_0[0] && !sb->zero_0[1] &&
+ !sb->zero_0[2]) && !sb->zero_1 && !sb->zero_2 &&
+ !sb->zero_3;
+}
+
+static inline int ntfs_check_sb_fields(const struct ntfs_bpb *sb)
+{
+ return ntfs_check_zero_fields(sb) &&
+ (!memcmp(sb->oem_name, "NTFS ", 8) ||
+ !memcmp(sb->oem_name, "MSWIN4.0", 8) ||
+ !memcmp(sb->oem_name, "MSWIN4.1", 8));
+}
+
+/* Initialize the filesystem metadata and return block size in bits */
+static int ntfs_fs_init(struct fs_info *fs)
+{
+ struct ntfs_bpb ntfs;
+ struct ntfs_sb_info *sbi;
+ struct disk *disk = fs->fs_dev->disk;
+
+ disk->rdwr_sectors(disk, &ntfs, 0, 1, 0);
+
+ /* sanity check */
+ if (!ntfs_check_sb_fields(&ntfs))
+ return -1;
+
+ SECTOR_SHIFT(fs) = BLOCK_SHIFT(fs) = disk->sector_shift;
+ SECTOR_SIZE(fs) = 1 << SECTOR_SHIFT(fs);
+ fs->block_size = 1 << BLOCK_SHIFT(fs);
+
+ sbi = malloc(sizeof(*sbi));
+ if (!sbi)
+ malloc_error("ntfs_sb_info structure");
+
+ fs->fs_info = sbi;
+
+ sbi->clust_shift = ilog2(ntfs.sec_per_clust);
+ sbi->clust_byte_shift = sbi->clust_shift + SECTOR_SHIFT(fs);
+ sbi->clust_mask = ntfs.sec_per_clust - 1;
+ sbi->clust_size = ntfs.sec_per_clust << SECTOR_SHIFT(fs);
+ sbi->mft_record_size = ntfs.clust_per_mft_record <<
+ sbi->clust_byte_shift;
+ sbi->root = sbi->mft + sbi->mft_size;
+
+ sbi->mft = ntfs.mft_lclust << sbi->clust_shift;
+ /* 16 MFT entries reserved for metadata files (approximately 16 KiB) */
+ sbi->mft_size = (ntfs.clust_per_mft_record << sbi->clust_shift) << 4;
+
+ sbi->clusters = (ntfs.total_sectors - sbi->root) >> sbi->clust_shift;
+ if (sbi->clusters > 0xFFFFFFFFFFF4ULL)
+ sbi->clusters = 0xFFFFFFFFFFF4ULL;
+
+ /* Initialize the cache */
+ cache_init(fs->fs_dev, BLOCK_SHIFT(fs));
+
+ return BLOCK_SHIFT(fs);
+}
+
+const struct fs_ops ntfs_fs_ops = {
+ .fs_name = "ntfs",
+ .fs_flags = FS_USEMEM | FS_THISIND,
+ .fs_init = ntfs_fs_init,
+ .searchdir = NULL,
+ .getfssec = NULL,
+ .close_file = NULL,
+ .mangle_name = NULL,
+ .load_config = NULL,
+ .readdir = NULL,
+ .iget_root = NULL,
+ .iget = NULL,
+ .next_extent = NULL,
+};
diff --git a/core/fs/ntfs/ntfs.h b/core/fs/ntfs/ntfs.h
new file mode 100644
index 00000000..b5919a3e
--- /dev/null
+++ b/core/fs/ntfs/ntfs.h
@@ -0,0 +1,64 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * 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.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ntfs.h - The NTFS filesystem structures
+ */
+
+#ifndef _NTFS_H_
+#define _NTFS_H_
+
+struct ntfs_bpb {
+ uint8_t jmp_boot[3];
+ char oem_name[8];
+ uint16_t sector_size;
+ uint8_t sec_per_clust;
+ uint16_t res_sectors;
+ uint8_t zero_0[3];
+ uint16_t zero_1;
+ uint8_t media;
+ uint16_t zero_2;
+ uint16_t unused_0;
+ uint16_t unused_1;
+ uint32_t unused_2;
+ uint32_t zero_3;
+ uint32_t unused_3;
+ uint64_t total_sectors;
+ uint64_t mft_lclust;
+ uint64_t mft_mirr_lclust;
+ uint8_t clust_per_mft_record;
+ uint8_t unused_4[3];
+ uint8_t clust_per_idx_buf;
+ uint8_t unused_5[3];
+ uint64_t vol_serial;
+ uint32_t unused_6;
+
+ uint8_t pad[428]; /* padding to a sector boundary (512 bytes) */
+} __attribute__((packed));
+
+struct ntfs_sb_info {
+ sector_t mft; /* The MFT region */
+ sector_t root; /* The root dir region */
+
+ unsigned mft_size; /* The MFT size in sectors */
+ unsigned mft_record_size; /* MFT record size in bytes */
+
+ unsigned long long clusters; /* Total number of clusters */
+
+ unsigned clust_shift; /* Based on sectors */
+ unsigned clust_byte_shift; /* Based on bytes */
+ unsigned clust_mask;
+ unsigned clust_size;
+
+} __attribute__((packed));
+
+#endif /* _NTFS_H_ */
diff --git a/core/ldlinux.asm b/core/ldlinux.asm
index f62f55b2..d4c5eec4 100644
--- a/core/ldlinux.asm
+++ b/core/ldlinux.asm
@@ -39,6 +39,8 @@ ROOT_FS_OPS:
dd ext2_fs_ops
extern btrfs_fs_ops
dd btrfs_fs_ops
+ extern ntfs_fs_ops
+ dd ntfs_fs_ops
dd 0
%include "diskfs.inc"