diff options
Diffstat (limited to 'core/fs/ufs/ufs.h')
-rw-r--r-- | core/fs/ufs/ufs.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/core/fs/ufs/ufs.h b/core/fs/ufs/ufs.h new file mode 100644 index 0000000..04e9f84 --- /dev/null +++ b/core/fs/ufs/ufs.h @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2013 Raphael S. Carvalho <raphael.scarv@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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _UFS_H_ +#define _UFS_H_ + +#include <stdint.h> + +/* Sector addresses */ +#define UFS1_SBLOCK_OFFSET 8192 +#define UFS2_SBLOCK_OFFSET 65536 +#define UFS2_SBLOCK2_OFFSET 262144 + +#define UFS1_ADDR_SHIFT 2 +#define UFS2_ADDR_SHIFT 3 + +/* Super magic numbers */ +#define UFS1_SUPER_MAGIC (0x011954) +#define UFS2_SUPER_MAGIC (0x19540119) + +#define UFS_ROOT_INODE 2 + +#define UFS_DIRECT_BLOCKS 12 +#define UFS_INDIRECT_BLOCK 1 +#define UFS_DOUBLE_INDIRECT_BLOCK 1 +#define UFS_TRIPLE_INDIRECT_BLOCK 1 +/* Total number of block addr hold by inodes */ +#define UFS_NBLOCKS 15 + +/* Blocks span 8 fragments */ +#define FRAGMENTS_PER_BLK 8 + +/* UFS types */ +typedef enum { + NONE, + UFS1, + UFS2, + UFS2_PIGGY, +} ufs_t; + +/* + * UFS1/UFS2 SUPERBLOCK structure + * CG stands for Cylinder Group. + * + * Variables prepended with off store offsets relative to + * base address of a Cylinder Group (CG). + */ +struct ufs_super_block { // supporting either ufs1 or ufs2 + uint8_t unused[8]; + /* Offset values */ + uint32_t off_backup_sb; // Backup super block + uint32_t off_group_desc; // Group Descriptor + uint32_t off_inode_tbl; // Inode table + uint32_t off_data_block; // First data block + union { + struct { /* Used for UFS1 */ + uint32_t delta_value; // For calc staggering offset + uint32_t cycle_mask; // Mask for staggering offset + uint32_t last_written; // Last written time + uint32_t nr_frags; // Number of frags in FS + uint32_t storable_frags_nr; // Nr of frags that can store data + } ufs1; + uint8_t unused1[20]; + }; + uint32_t nr_cyl_groups; // Number of cylinder groups. + uint32_t block_size; // Block size in bytes. + uint32_t fragment_size; // Fragment size in bytes. + uint8_t unused2[16]; + uint32_t block_addr_mask; // to calculate the address + uint32_t frag_addr_mask; + uint32_t block_shift; // to calculate byte address + uint32_t frag_shift; + uint32_t nr_contiguous_blk; // max number of continuous blks to alloc + uint32_t nr_blks_per_cg; // max number of blks per cylinder group + uint32_t c_blk_frag_shift; // Bits to convert blk and frag address. + uint32_t c_frag_sect_shift; // Bits to convert frag and sect address. + uint32_t superblk_size; // Superblock size. + uint8_t unused3[76]; + uint32_t inodes_per_cg; // Inodes per cylinder group + uint32_t frags_per_cg; // Fragments per cylinder group + union { + struct { /* Used for UFS2 */ + uint8_t unused[888]; + uint64_t nr_frags; // Number of fragments in FS + uint8_t unused1[232]; + } ufs2; + uint8_t unused4[1128]; + }; + uint32_t maxlen_isymlink; // Max length of internal symlink + uint32_t inodes_format; // Format of inodes + uint8_t unused5[44]; + uint32_t magic; // Magic value + uint8_t pad[160]; // padding up to sector (512 bytes) boundary +} __attribute__((__packed__)); + +/* + * Info about UFS1/2 super block. + */ +struct ufs_sb_info { + uint32_t blocks_per_cg; // Blocks per cylinder group + uint32_t inodes_per_cg; // Inodes per cylinder group + uint32_t inode_size; + uint32_t inodes_per_block; // Inodes per block + struct { /* UFS1 only! */ + /* Values for calculating staggering offset */ + uint32_t delta_value; + uint32_t cycle_mask; + } ufs1; + uint32_t off_inode_tbl; // Inode table offset. + uint32_t groups_count; // Number of groups in the fs + uint32_t addr_shift; // 2 ^ addr_shift = size in bytes of default addr. + uint32_t c_blk_frag_shift; // Convert blk/frag addr (vice-versa) + uint32_t maxlen_isymlink; // Max length of internal symlink + struct inode *(*ufs_iget_by_inr)(struct fs_info *, uint32_t); + void (*ufs_read_blkaddrs)(struct inode *, char *); + ufs_t fs_type; // { UFS1, UFS2, UFS2_PIGGY } +}; + +/* + * Get super block info struct + */ +static inline struct ufs_sb_info *UFS_SB(struct fs_info *fs) +{ + return fs->fs_info; +} + +/* + * Convert frag addr to blk addr + */ +static inline block_t frag_to_blk(struct fs_info *fs, uint64_t frag) +{ + return frag >> UFS_SB(fs)->c_blk_frag_shift; +} + +/* + * UFS1 inode structures + */ +struct ufs1_inode { + uint16_t file_mode; + uint16_t link_count; + uint8_t unused[4]; + uint64_t size; + uint32_t a_time; // Access time + uint32_t a_time_nanosec; + uint32_t m_time; // Modified time + uint32_t m_time_nanosec; + uint32_t ch_time; // Change time + uint32_t ch_time_nanosec; + uint32_t direct_blk_ptr[12]; + uint32_t indirect_blk_ptr; + uint32_t double_indirect_blk_ptr; + uint32_t triple_indirect_blk_ptr; + uint32_t flags; // Status flags + uint32_t blocks_held; // Blocks held + uint32_t generation_nrb; // (NFS) + uint32_t used_id; + uint32_t group_id; + uint8_t unused1[8]; +} __attribute__((__packed__)); + +/* + * UFS2 inode structures + */ +struct ufs2_inode { + uint16_t file_mode; + uint16_t link_count; + uint32_t user_id; + uint32_t group_id; + uint32_t inode_blocksize; + uint64_t size; + uint64_t bytes_held; + uint64_t a_time; // Access time + uint64_t m_time; // Modified time + uint64_t ch_time; // Change time + uint64_t creat_time; // Creation time + uint32_t a_time_nanosec; + uint32_t m_time_nanosec; + uint32_t ch_time_nanosec; + uint32_t creat_time_nanosec; + uint32_t generation_nrb; // (NFS) + uint32_t kernel_flags; + uint32_t flags; + uint32_t ext_attr_size; // Extended attrib size. + uint64_t ext_direct_blk_ptrs[2]; // Ext. attrib blk pointers. + uint64_t direct_blk_ptr[12]; + uint64_t indirect_blk_ptr; + uint64_t double_indirect_blk_ptr; + uint64_t triple_indirect_blk_ptr; + uint8_t unused[24]; +} __attribute__((__packed__)); + +#define PVT(p) ((struct ufs_inode_pvt *) p->pvt) + +struct ufs_inode_pvt { + uint64_t direct_blk_ptr[12]; + uint64_t indirect_blk_ptr; + uint64_t double_indirect_blk_ptr; + uint64_t triple_indirect_blk_ptr; +}; + +struct ufs_dir_entry { + uint32_t inode_value; + uint16_t dir_entry_len; + uint8_t file_type; + uint8_t name_length; + uint8_t name[1]; // Dir names are null terminated!!! +} __attribute__((__packed__)); + +enum inode_type_flags { + UFS_INO_FIFO = 0x1000, + UFS_INO_CHARDEV = 0x2000, + UFS_INO_DIRECTORY = 0x4000, + UFS_INO_BLOCKDEV = 0x6000, + UFS_INO_RFILE = 0x8000, + UFS_INO_SYMLINK = 0xA000, + UFS_INO_UNIXSOCKET = 0xC000, +}; + +enum dir_type_flags { + UFS_DTYPE_UNKNOWN = 0, + UFS_DTYPE_FIFO = 1, + UFS_DTYPE_CHARDEV = 2, + UFS_DTYPE_DIR = 4, + UFS_DTYPE_BLOCK = 6, + UFS_DTYPE_RFILE = 8, + UFS_DTYPE_SYMLINK = 10, + UFS_DTYPE_SOCKET = 12, + UFS_DTYPE_WHITEOUT = 14, +}; + +/* Functions from bmap.c */ +extern uint64_t ufs_bmap (struct inode *, block_t, size_t *); +extern int ufs_next_extent(struct inode *, uint32_t); + +#define ufs_debug dprintf +//extern void ufs_checking (struct fs_info *); + +#endif /* _UFS_H_ */ |