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 | */ |
---|
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_ */ |
---|