Initial NTFS readonly support code to Syslinux
authorPaulo Alcantara <pcacjr@gmail.com>
Thu, 7 Jul 2011 21:28:05 +0000 (21:28 +0000)
committerPaulo Alcantara <pcacjr@gmail.com>
Wed, 7 Sep 2011 07:19:06 +0000 (07:19 +0000)
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>
core/fs/ntfs/ntfs.c [new file with mode: 0644]
core/fs/ntfs/ntfs.h [new file with mode: 0644]
core/ldlinux.asm

diff --git a/core/fs/ntfs/ntfs.c b/core/fs/ntfs/ntfs.c
new file mode 100644 (file)
index 0000000..24c9859
--- /dev/null
@@ -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 (file)
index 0000000..b5919a3
--- /dev/null
@@ -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_ */
index f62f55b..d4c5eec 100644 (file)
@@ -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"