aboutsummaryrefslogtreecommitdiff
path: root/core/fs/ufs/ufs.h
blob: 04e9f84214a82f0846119748e43a8cd0ceb70097 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
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_ */