1 /*
2 * Copyright (C) 2013 Raphael S. Carvalho <raphael.scarv@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 */
UFS_SB(struct fs_info * fs)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 */
frag_to_blk(struct fs_info * fs,uint64_t frag)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