1 /* 2 * Copyright (C) 2013 Raphael S. Carvalho <raphael.scarv (at) gmail.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the 16 * Free Software Foundation, Inc., 17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 */ 19 20 #ifndef _UFS_H_ 21 #define _UFS_H_ 22 23 #include <stdint.h> 24 25 /* Sector addresses */ 26 #define UFS1_SBLOCK_OFFSET 8192 27 #define UFS2_SBLOCK_OFFSET 65536 28 #define UFS2_SBLOCK2_OFFSET 262144 29 30 #define UFS1_ADDR_SHIFT 2 31 #define UFS2_ADDR_SHIFT 3 32 33 /* Super magic numbers */ 34 #define UFS1_SUPER_MAGIC (0x011954) 35 #define UFS2_SUPER_MAGIC (0x19540119) 36 37 #define UFS_ROOT_INODE 2 38 39 #define UFS_DIRECT_BLOCKS 12 40 #define UFS_INDIRECT_BLOCK 1 41 #define UFS_DOUBLE_INDIRECT_BLOCK 1 42 #define UFS_TRIPLE_INDIRECT_BLOCK 1 43 /* Total number of block addr hold by inodes */ 44 #define UFS_NBLOCKS 15 45 46 /* Blocks span 8 fragments */ 47 #define FRAGMENTS_PER_BLK 8 48 49 /* UFS types */ 50 typedef enum { 51 NONE, 52 UFS1, 53 UFS2, 54 UFS2_PIGGY, 55 } ufs_t; 56 57 /* 58 * UFS1/UFS2 SUPERBLOCK structure 59 * CG stands for Cylinder Group. 60 * 61 * Variables prepended with off store offsets relative to 62 * base address of a Cylinder Group (CG). 63 */ 64 struct ufs_super_block { // supporting either ufs1 or ufs2 65 uint8_t unused[8]; 66 /* Offset values */ 67 uint32_t off_backup_sb; // Backup super block 68 uint32_t off_group_desc; // Group Descriptor 69 uint32_t off_inode_tbl; // Inode table 70 uint32_t off_data_block; // First data block 71 union { 72 struct { /* Used for UFS1 */ 73 uint32_t delta_value; // For calc staggering offset 74 uint32_t cycle_mask; // Mask for staggering offset 75 uint32_t last_written; // Last written time 76 uint32_t nr_frags; // Number of frags in FS 77 uint32_t storable_frags_nr; // Nr of frags that can store data 78 } ufs1; 79 uint8_t unused1[20]; 80 }; 81 uint32_t nr_cyl_groups; // Number of cylinder groups. 82 uint32_t block_size; // Block size in bytes. 83 uint32_t fragment_size; // Fragment size in bytes. 84 uint8_t unused2[16]; 85 uint32_t block_addr_mask; // to calculate the address 86 uint32_t frag_addr_mask; 87 uint32_t block_shift; // to calculate byte address 88 uint32_t frag_shift; 89 uint32_t nr_contiguous_blk; // max number of continuous blks to alloc 90 uint32_t nr_blks_per_cg; // max number of blks per cylinder group 91 uint32_t c_blk_frag_shift; // Bits to convert blk and frag address. 92 uint32_t c_frag_sect_shift; // Bits to convert frag and sect address. 93 uint32_t superblk_size; // Superblock size. 94 uint8_t unused3[76]; 95 uint32_t inodes_per_cg; // Inodes per cylinder group 96 uint32_t frags_per_cg; // Fragments per cylinder group 97 union { 98 struct { /* Used for UFS2 */ 99 uint8_t unused[888]; 100 uint64_t nr_frags; // Number of fragments in FS 101 uint8_t unused1[232]; 102 } ufs2; 103 uint8_t unused4[1128]; 104 }; 105 uint32_t maxlen_isymlink; // Max length of internal symlink 106 uint32_t inodes_format; // Format of inodes 107 uint8_t unused5[44]; 108 uint32_t magic; // Magic value 109 uint8_t pad[160]; // padding up to sector (512 bytes) boundary 110 } __attribute__((__packed__)); 111 112 /* 113 * Info about UFS1/2 super block. 114 */ 115 struct ufs_sb_info { 116 uint32_t blocks_per_cg; // Blocks per cylinder group 117 uint32_t inodes_per_cg; // Inodes per cylinder group 118 uint32_t inode_size; 119 uint32_t inodes_per_block; // Inodes per block 120 struct { /* UFS1 only! */ 121 /* Values for calculating staggering offset */ 122 uint32_t delta_value; 123 uint32_t cycle_mask; 124 } ufs1; 125 uint32_t off_inode_tbl; // Inode table offset. 126 uint32_t groups_count; // Number of groups in the fs 127 uint32_t addr_shift; // 2 ^ addr_shift = size in bytes of default addr. 128 uint32_t c_blk_frag_shift; // Convert blk/frag addr (vice-versa) 129 uint32_t maxlen_isymlink; // Max length of internal symlink 130 struct inode *(*ufs_iget_by_inr)(struct fs_info *, uint32_t); 131 void (*ufs_read_blkaddrs)(struct inode *, char *); 132 ufs_t fs_type; // { UFS1, UFS2, UFS2_PIGGY } 133 }; 134 135 /* 136 * Get super block info struct 137 */ 138 static inline struct ufs_sb_info *UFS_SB(struct fs_info *fs) 139 { 140 return fs->fs_info; 141 } 142 143 /* 144 * Convert frag addr to blk addr 145 */ 146 static inline block_t frag_to_blk(struct fs_info *fs, uint64_t frag) 147 { 148 return frag >> UFS_SB(fs)->c_blk_frag_shift; 149 } 150 151 /* 152 * UFS1 inode structures 153 */ 154 struct ufs1_inode { 155 uint16_t file_mode; 156 uint16_t link_count; 157 uint8_t unused[4]; 158 uint64_t size; 159 uint32_t a_time; // Access time 160 uint32_t a_time_nanosec; 161 uint32_t m_time; // Modified time 162 uint32_t m_time_nanosec; 163 uint32_t ch_time; // Change time 164 uint32_t ch_time_nanosec; 165 uint32_t direct_blk_ptr[12]; 166 uint32_t indirect_blk_ptr; 167 uint32_t double_indirect_blk_ptr; 168 uint32_t triple_indirect_blk_ptr; 169 uint32_t flags; // Status flags 170 uint32_t blocks_held; // Blocks held 171 uint32_t generation_nrb; // (NFS) 172 uint32_t used_id; 173 uint32_t group_id; 174 uint8_t unused1[8]; 175 } __attribute__((__packed__)); 176 177 /* 178 * UFS2 inode structures 179 */ 180 struct ufs2_inode { 181 uint16_t file_mode; 182 uint16_t link_count; 183 uint32_t user_id; 184 uint32_t group_id; 185 uint32_t inode_blocksize; 186 uint64_t size; 187 uint64_t bytes_held; 188 uint64_t a_time; // Access time 189 uint64_t m_time; // Modified time 190 uint64_t ch_time; // Change time 191 uint64_t creat_time; // Creation time 192 uint32_t a_time_nanosec; 193 uint32_t m_time_nanosec; 194 uint32_t ch_time_nanosec; 195 uint32_t creat_time_nanosec; 196 uint32_t generation_nrb; // (NFS) 197 uint32_t kernel_flags; 198 uint32_t flags; 199 uint32_t ext_attr_size; // Extended attrib size. 200 uint64_t ext_direct_blk_ptrs[2]; // Ext. attrib blk pointers. 201 uint64_t direct_blk_ptr[12]; 202 uint64_t indirect_blk_ptr; 203 uint64_t double_indirect_blk_ptr; 204 uint64_t triple_indirect_blk_ptr; 205 uint8_t unused[24]; 206 } __attribute__((__packed__)); 207 208 #define PVT(p) ((struct ufs_inode_pvt *) p->pvt) 209 210 struct ufs_inode_pvt { 211 uint64_t direct_blk_ptr[12]; 212 uint64_t indirect_blk_ptr; 213 uint64_t double_indirect_blk_ptr; 214 uint64_t triple_indirect_blk_ptr; 215 }; 216 217 struct ufs_dir_entry { 218 uint32_t inode_value; 219 uint16_t dir_entry_len; 220 uint8_t file_type; 221 uint8_t name_length; 222 uint8_t name[1]; // Dir names are null terminated!!! 223 } __attribute__((__packed__)); 224 225 enum inode_type_flags { 226 UFS_INO_FIFO = 0x1000, 227 UFS_INO_CHARDEV = 0x2000, 228 UFS_INO_DIRECTORY = 0x4000, 229 UFS_INO_BLOCKDEV = 0x6000, 230 UFS_INO_RFILE = 0x8000, 231 UFS_INO_SYMLINK = 0xA000, 232 UFS_INO_UNIXSOCKET = 0xC000, 233 }; 234 235 enum dir_type_flags { 236 UFS_DTYPE_UNKNOWN = 0, 237 UFS_DTYPE_FIFO = 1, 238 UFS_DTYPE_CHARDEV = 2, 239 UFS_DTYPE_DIR = 4, 240 UFS_DTYPE_BLOCK = 6, 241 UFS_DTYPE_RFILE = 8, 242 UFS_DTYPE_SYMLINK = 10, 243 UFS_DTYPE_SOCKET = 12, 244 UFS_DTYPE_WHITEOUT = 14, 245 }; 246 247 /* Functions from bmap.c */ 248 extern uint64_t ufs_bmap (struct inode *, block_t, size_t *); 249 extern int ufs_next_extent(struct inode *, uint32_t); 250 251 #define ufs_debug dprintf 252 //extern void ufs_checking (struct fs_info *); 253 254 #endif /* _UFS_H_ */ 255