diff options
author | Paulo Alcantara <pcacjr@gmail.com> | 2011-07-07 21:28:05 +0000 |
---|---|---|
committer | Paulo Alcantara <pcacjr@gmail.com> | 2011-09-07 07:19:06 +0000 |
commit | 045bc5cd1118fee51b19d89dc316038c8a93e5bf (patch) | |
tree | 92e8008767611b08ee9b3a6289c7a32c77634697 | |
parent | b0ac906b283b428ba1c7f35fe1e71a84b3d3d9c6 (diff) | |
download | syslinux-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.c | 105 | ||||
-rw-r--r-- | core/fs/ntfs/ntfs.h | 64 | ||||
-rw-r--r-- | core/ldlinux.asm | 2 |
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" |