1#ifndef SQUASHFS_FS
2#define SQUASHFS_FS
3
4/*
5 * Squashfs
6 *
7 * Copyright (c) 2002, 2003, 2004, 2005, 2006
8 * Phillip Lougher <phillip@lougher.demon.co.uk>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2,
13 * or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 * squashfs_fs.h
25 */
26
27#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
28#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
29#endif
30
31#ifdef CONFIG_SQUASHFS_VMALLOC
32#define SQUASHFS_ALLOC(a)		vmalloc(a)
33#define SQUASHFS_FREE(a)		vfree(a)
34#else
35#define SQUASHFS_ALLOC(a)		kmalloc(a, GFP_KERNEL)
36#define SQUASHFS_FREE(a)		kfree(a)
37#endif
38#ifdef CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
39#define SQUASHFS_CACHED_FRAGMENTS	CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
40#else
41#define SQUASHFS_CACHED_FRAGMENTS	3
42#endif
43#define SQUASHFS_MAJOR			3
44#define SQUASHFS_MINOR			0
45#define SQUASHFS_MAGIC			0x73717368
46#define SQUASHFS_MAGIC_SWAP		0x68737173
47#define SQUASHFS_START			0
48
49/* size of metadata (inode and directory) blocks */
50#define SQUASHFS_METADATA_SIZE		8192
51#define SQUASHFS_METADATA_LOG		13
52
53/* default size of data blocks */
54#define SQUASHFS_FILE_SIZE		65536
55#define SQUASHFS_FILE_LOG		16
56
57#define SQUASHFS_FILE_MAX_SIZE		65536
58
59/* Max number of uids and gids */
60#define SQUASHFS_UIDS			256
61#define SQUASHFS_GUIDS			255
62
63/* Max length of filename (not 255) */
64#define SQUASHFS_NAME_LEN		256
65
66#define SQUASHFS_INVALID		((long long) 0xffffffffffff)
67#define SQUASHFS_INVALID_FRAG		((unsigned int) 0xffffffff)
68#define SQUASHFS_INVALID_BLK		((long long) -1)
69#define SQUASHFS_USED_BLK		((long long) -2)
70
71/* Filesystem flags */
72#define SQUASHFS_NOI			0
73#define SQUASHFS_NOD			1
74#define SQUASHFS_CHECK			2
75#define SQUASHFS_NOF			3
76#define SQUASHFS_NO_FRAG		4
77#define SQUASHFS_ALWAYS_FRAG		5
78#define SQUASHFS_DUPLICATE		6
79
80#define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
81
82#define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, \
83						SQUASHFS_NOI)
84
85#define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, \
86						SQUASHFS_NOD)
87
88#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
89						SQUASHFS_NOF)
90
91#define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, \
92						SQUASHFS_NO_FRAG)
93
94#define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, \
95						SQUASHFS_ALWAYS_FRAG)
96
97#define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, \
98						SQUASHFS_DUPLICATE)
99
100#define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, \
101						SQUASHFS_CHECK)
102
103#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
104		duplicate_checking)	(noi | (nod << 1) | (check_data << 2) \
105		| (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
106		(duplicate_checking << 6))
107
108/* Max number of types and file types */
109#define SQUASHFS_DIR_TYPE		1
110#define SQUASHFS_FILE_TYPE		2
111#define SQUASHFS_SYMLINK_TYPE		3
112#define SQUASHFS_BLKDEV_TYPE		4
113#define SQUASHFS_CHRDEV_TYPE		5
114#define SQUASHFS_FIFO_TYPE		6
115#define SQUASHFS_SOCKET_TYPE		7
116#define SQUASHFS_LDIR_TYPE		8
117#define SQUASHFS_LREG_TYPE		9
118
119/* 1.0 filesystem type definitions */
120#define SQUASHFS_TYPES			5
121#define SQUASHFS_IPC_TYPE		0
122
123/* Flag whether block is compressed or uncompressed, bit is set if block is
124 * uncompressed */
125#define SQUASHFS_COMPRESSED_BIT		(1 << 15)
126
127#define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
128		(B) & ~SQUASHFS_COMPRESSED_BIT :  SQUASHFS_COMPRESSED_BIT)
129
130#define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
131
132#define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
133
134#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	(((B) & \
135	~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
136	~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
137
138#define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
139
140/*
141 * Inode number ops.  Inodes consist of a compressed block number, and an
142 * uncompressed  offset within that block
143 */
144#define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
145
146#define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
147
148#define SQUASHFS_MKINODE(A, B)		((squashfs_inode_t)(((squashfs_inode_t) (A)\
149					<< 16) + (B)))
150
151/* Compute 32 bit VFS inode number from squashfs inode number */
152#define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + \
153					((b) >> 2) + 1))
154/* XXX */
155
156/* Translate between VFS mode and squashfs mode */
157#define SQUASHFS_MODE(a)		((a) & 0xfff)
158
159/* fragment and fragment table defines */
160#define SQUASHFS_FRAGMENT_BYTES(A)	(A * sizeof(struct squashfs_fragment_entry))
161
162#define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / \
163					SQUASHFS_METADATA_SIZE)
164
165#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % \
166						SQUASHFS_METADATA_SIZE)
167
168#define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + \
169					SQUASHFS_METADATA_SIZE - 1) / \
170					SQUASHFS_METADATA_SIZE)
171
172#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) *\
173						sizeof(long long))
174
175/* cached data constants for filesystem */
176#define SQUASHFS_CACHED_BLKS		8
177
178#define SQUASHFS_MAX_FILE_SIZE_LOG	64
179
180#define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << \
181					(SQUASHFS_MAX_FILE_SIZE_LOG - 2))
182
183#define SQUASHFS_MARKER_BYTE		0xff
184
185/* meta index cache */
186#define SQUASHFS_META_INDEXES	(SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
187#define SQUASHFS_META_ENTRIES	31
188#define SQUASHFS_META_NUMBER	8
189#define SQUASHFS_SLOTS		4
190
191struct meta_entry {
192	long long		data_block;
193	unsigned int		index_block;
194	unsigned short		offset;
195	unsigned short		pad;
196};
197
198struct meta_index {
199	unsigned int		inode_number;
200	unsigned int		offset;
201	unsigned short		entries;
202	unsigned short		skip;
203	unsigned short		locked;
204	unsigned short		pad;
205	struct meta_entry	meta_entry[SQUASHFS_META_ENTRIES];
206};
207
208
209/*
210 * definitions for structures on disk
211 */
212
213typedef long long		squashfs_block_t;
214typedef long long		squashfs_inode_t;
215
216struct squashfs_super_block {
217	unsigned int		s_magic;
218	unsigned int		inodes;
219	unsigned int		bytes_used_2;
220	unsigned int		uid_start_2;
221	unsigned int		guid_start_2;
222	unsigned int		inode_table_start_2;
223	unsigned int		directory_table_start_2;
224	unsigned int		s_major:16;
225	unsigned int		s_minor:16;
226	unsigned int		block_size_1:16;
227	unsigned int		block_log:16;
228	unsigned int		flags:8;
229	unsigned int		no_uids:8;
230	unsigned int		no_guids:8;
231	unsigned int		mkfs_time /* time of filesystem creation */;
232	squashfs_inode_t	root_inode;
233	unsigned int		block_size;
234	unsigned int		fragments;
235	unsigned int		fragment_table_start_2;
236	long long		bytes_used;
237	long long		uid_start;
238	long long		guid_start;
239	long long		inode_table_start;
240	long long		directory_table_start;
241	long long		fragment_table_start;
242	long long		unused;
243} __attribute__ ((packed));
244
245struct squashfs_dir_index {
246	unsigned int		index;
247	unsigned int		start_block;
248	unsigned char		size;
249	unsigned char		name[0];
250} __attribute__ ((packed));
251
252#define SQUASHFS_BASE_INODE_HEADER		\
253	unsigned int		inode_type:4;	\
254	unsigned int		mode:12;	\
255	unsigned int		uid:8;		\
256	unsigned int		guid:8;		\
257	unsigned int		mtime;		\
258	unsigned int 		inode_number;
259
260struct squashfs_base_inode_header {
261	SQUASHFS_BASE_INODE_HEADER;
262} __attribute__ ((packed));
263
264struct squashfs_ipc_inode_header {
265	SQUASHFS_BASE_INODE_HEADER;
266	unsigned int		nlink;
267} __attribute__ ((packed));
268
269struct squashfs_dev_inode_header {
270	SQUASHFS_BASE_INODE_HEADER;
271	unsigned int		nlink;
272	unsigned short		rdev;
273} __attribute__ ((packed));
274
275struct squashfs_symlink_inode_header {
276	SQUASHFS_BASE_INODE_HEADER;
277	unsigned int		nlink;
278	unsigned short		symlink_size;
279	char			symlink[0];
280} __attribute__ ((packed));
281
282struct squashfs_reg_inode_header {
283	SQUASHFS_BASE_INODE_HEADER;
284	squashfs_block_t	start_block;
285	unsigned int		fragment;
286	unsigned int		offset;
287	unsigned int		file_size;
288	unsigned short		block_list[0];
289} __attribute__ ((packed));
290
291struct squashfs_lreg_inode_header {
292	SQUASHFS_BASE_INODE_HEADER;
293	unsigned int		nlink;
294	squashfs_block_t	start_block;
295	unsigned int		fragment;
296	unsigned int		offset;
297	long long		file_size;
298	unsigned short		block_list[0];
299} __attribute__ ((packed));
300
301struct squashfs_dir_inode_header {
302	SQUASHFS_BASE_INODE_HEADER;
303	unsigned int		nlink;
304	unsigned int		file_size:19;
305	unsigned int		offset:13;
306	unsigned int		start_block;
307	unsigned int		parent_inode;
308} __attribute__  ((packed));
309
310struct squashfs_ldir_inode_header {
311	SQUASHFS_BASE_INODE_HEADER;
312	unsigned int		nlink;
313	unsigned int		file_size:27;
314	unsigned int		offset:13;
315	unsigned int		start_block;
316	unsigned int		i_count:16;
317	unsigned int		parent_inode;
318	struct squashfs_dir_index	index[0];
319} __attribute__  ((packed));
320
321union squashfs_inode_header {
322	struct squashfs_base_inode_header	base;
323	struct squashfs_dev_inode_header	dev;
324	struct squashfs_symlink_inode_header	symlink;
325	struct squashfs_reg_inode_header	reg;
326	struct squashfs_lreg_inode_header	lreg;
327	struct squashfs_dir_inode_header	dir;
328	struct squashfs_ldir_inode_header	ldir;
329	struct squashfs_ipc_inode_header	ipc;
330};
331
332struct squashfs_dir_entry {
333	unsigned int		offset:13;
334	unsigned int		type:3;
335	unsigned int		size:8;
336	int			inode_number:16;
337	char			name[0];
338} __attribute__ ((packed));
339
340struct squashfs_dir_header {
341	unsigned int		count:8;
342	unsigned int		start_block;
343	unsigned int		inode_number;
344} __attribute__ ((packed));
345
346struct squashfs_fragment_entry {
347	long long		start_block;
348	unsigned int		size;
349	unsigned int		unused;
350} __attribute__ ((packed));
351
352extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
353extern int squashfs_uncompress_init(void);
354extern int squashfs_uncompress_exit(void);
355
356/*
357 * macros to convert each packed bitfield structure from little endian to big
358 * endian and vice versa.  These are needed when creating or using a filesystem
359 * on a machine with different byte ordering to the target architecture.
360 *
361 */
362
363#define SQUASHFS_SWAP_START \
364	int bits;\
365	int b_pos;\
366	unsigned long long val;\
367	unsigned char *s;\
368	unsigned char *d;
369
370#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
371	SQUASHFS_SWAP_START\
372	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
373	SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
374	SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
375	SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
376	SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
377	SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
378	SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
379	SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
380	SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
381	SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
382	SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
383	SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
384	SQUASHFS_SWAP((s)->flags, d, 288, 8);\
385	SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
386	SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
387	SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
388	SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
389	SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
390	SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
391	SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
392	SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
393	SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
394	SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
395	SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
396	SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
397	SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
398	SQUASHFS_SWAP((s)->unused, d, 888, 64);\
399}
400
401#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
402	SQUASHFS_MEMSET(s, d, n);\
403	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
404	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
405	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
406	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
407	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
408	SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
409
410#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
411	SQUASHFS_SWAP_START\
412	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
413}
414
415#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
416	SQUASHFS_SWAP_START\
417	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
418			sizeof(struct squashfs_ipc_inode_header))\
419	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
420}
421
422#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
423	SQUASHFS_SWAP_START\
424	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
425			sizeof(struct squashfs_dev_inode_header)); \
426	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
427	SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
428}
429
430#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
431	SQUASHFS_SWAP_START\
432	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
433			sizeof(struct squashfs_symlink_inode_header));\
434	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
435	SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
436}
437
438#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
439	SQUASHFS_SWAP_START\
440	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
441			sizeof(struct squashfs_reg_inode_header));\
442	SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
443	SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
444	SQUASHFS_SWAP((s)->offset, d, 192, 32);\
445	SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
446}
447
448#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
449	SQUASHFS_SWAP_START\
450	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
451			sizeof(struct squashfs_lreg_inode_header));\
452	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
453	SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
454	SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
455	SQUASHFS_SWAP((s)->offset, d, 224, 32);\
456	SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
457}
458
459#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
460	SQUASHFS_SWAP_START\
461	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
462			sizeof(struct squashfs_dir_inode_header));\
463	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
464	SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
465	SQUASHFS_SWAP((s)->offset, d, 147, 13);\
466	SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
467	SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
468}
469
470#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
471	SQUASHFS_SWAP_START\
472	SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
473			sizeof(struct squashfs_ldir_inode_header));\
474	SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
475	SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
476	SQUASHFS_SWAP((s)->offset, d, 155, 13);\
477	SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
478	SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
479	SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
480}
481
482#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
483	SQUASHFS_SWAP_START\
484	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
485	SQUASHFS_SWAP((s)->index, d, 0, 32);\
486	SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
487	SQUASHFS_SWAP((s)->size, d, 64, 8);\
488}
489
490#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
491	SQUASHFS_SWAP_START\
492	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
493	SQUASHFS_SWAP((s)->count, d, 0, 8);\
494	SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
495	SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
496}
497
498#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
499	SQUASHFS_SWAP_START\
500	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
501	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
502	SQUASHFS_SWAP((s)->type, d, 13, 3);\
503	SQUASHFS_SWAP((s)->size, d, 16, 8);\
504	SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
505}
506
507#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
508	SQUASHFS_SWAP_START\
509	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
510	SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
511	SQUASHFS_SWAP((s)->size, d, 64, 32);\
512}
513
514#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
515	int entry;\
516	int bit_position;\
517	SQUASHFS_SWAP_START\
518	SQUASHFS_MEMSET(s, d, n * 2);\
519	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
520			16)\
521		SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
522}
523
524#define SQUASHFS_SWAP_INTS(s, d, n) {\
525	int entry;\
526	int bit_position;\
527	SQUASHFS_SWAP_START\
528	SQUASHFS_MEMSET(s, d, n * 4);\
529	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
530			32)\
531		SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
532}
533
534#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
535	int entry;\
536	int bit_position;\
537	SQUASHFS_SWAP_START\
538	SQUASHFS_MEMSET(s, d, n * 8);\
539	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
540			64)\
541		SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
542}
543
544#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
545	int entry;\
546	int bit_position;\
547	SQUASHFS_SWAP_START\
548	SQUASHFS_MEMSET(s, d, n * bits / 8);\
549	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
550			bits)\
551		SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
552}
553
554#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
555
556#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
557
558struct squashfs_base_inode_header_1 {
559	unsigned int		inode_type:4;
560	unsigned int		mode:12; /* protection */
561	unsigned int		uid:4; /* index into uid table */
562	unsigned int		guid:4; /* index into guid table */
563} __attribute__ ((packed));
564
565struct squashfs_ipc_inode_header_1 {
566	unsigned int		inode_type:4;
567	unsigned int		mode:12; /* protection */
568	unsigned int		uid:4; /* index into uid table */
569	unsigned int		guid:4; /* index into guid table */
570	unsigned int		type:4;
571	unsigned int		offset:4;
572} __attribute__ ((packed));
573
574struct squashfs_dev_inode_header_1 {
575	unsigned int		inode_type:4;
576	unsigned int		mode:12; /* protection */
577	unsigned int		uid:4; /* index into uid table */
578	unsigned int		guid:4; /* index into guid table */
579	unsigned short		rdev;
580} __attribute__ ((packed));
581
582struct squashfs_symlink_inode_header_1 {
583	unsigned int		inode_type:4;
584	unsigned int		mode:12; /* protection */
585	unsigned int		uid:4; /* index into uid table */
586	unsigned int		guid:4; /* index into guid table */
587	unsigned short		symlink_size;
588	char			symlink[0];
589} __attribute__ ((packed));
590
591struct squashfs_reg_inode_header_1 {
592	unsigned int		inode_type:4;
593	unsigned int		mode:12; /* protection */
594	unsigned int		uid:4; /* index into uid table */
595	unsigned int		guid:4; /* index into guid table */
596	unsigned int		mtime;
597	unsigned int		start_block;
598	unsigned int		file_size:32;
599	unsigned short		block_list[0];
600} __attribute__ ((packed));
601
602struct squashfs_dir_inode_header_1 {
603	unsigned int		inode_type:4;
604	unsigned int		mode:12; /* protection */
605	unsigned int		uid:4; /* index into uid table */
606	unsigned int		guid:4; /* index into guid table */
607	unsigned int		file_size:19;
608	unsigned int		offset:13;
609	unsigned int		mtime;
610	unsigned int		start_block:24;
611} __attribute__  ((packed));
612
613#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
614	SQUASHFS_MEMSET(s, d, n);\
615	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
616	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
617	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
618	SQUASHFS_SWAP((s)->guid, d, 20, 4);
619
620#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
621	SQUASHFS_SWAP_START\
622	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
623}
624
625#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
626	SQUASHFS_SWAP_START\
627	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
628			sizeof(struct squashfs_ipc_inode_header_1));\
629	SQUASHFS_SWAP((s)->type, d, 24, 4);\
630	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
631}
632
633#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
634	SQUASHFS_SWAP_START\
635	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
636			sizeof(struct squashfs_dev_inode_header_1));\
637	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
638}
639
640#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
641	SQUASHFS_SWAP_START\
642	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
643			sizeof(struct squashfs_symlink_inode_header_1));\
644	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
645}
646
647#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
648	SQUASHFS_SWAP_START\
649	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
650			sizeof(struct squashfs_reg_inode_header_1));\
651	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
652	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
653	SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
654}
655
656#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
657	SQUASHFS_SWAP_START\
658	SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
659			sizeof(struct squashfs_dir_inode_header_1));\
660	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
661	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
662	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
663	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
664}
665
666#endif
667
668#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
669
670struct squashfs_dir_index_2 {
671	unsigned int		index:27;
672	unsigned int		start_block:29;
673	unsigned char		size;
674	unsigned char		name[0];
675} __attribute__ ((packed));
676
677struct squashfs_base_inode_header_2 {
678	unsigned int		inode_type:4;
679	unsigned int		mode:12; /* protection */
680	unsigned int		uid:8; /* index into uid table */
681	unsigned int		guid:8; /* index into guid table */
682} __attribute__ ((packed));
683
684struct squashfs_ipc_inode_header_2 {
685	unsigned int		inode_type:4;
686	unsigned int		mode:12; /* protection */
687	unsigned int		uid:8; /* index into uid table */
688	unsigned int		guid:8; /* index into guid table */
689} __attribute__ ((packed));
690
691struct squashfs_dev_inode_header_2 {
692	unsigned int		inode_type:4;
693	unsigned int		mode:12; /* protection */
694	unsigned int		uid:8; /* index into uid table */
695	unsigned int		guid:8; /* index into guid table */
696	unsigned short		rdev;
697} __attribute__ ((packed));
698
699struct squashfs_symlink_inode_header_2 {
700	unsigned int		inode_type:4;
701	unsigned int		mode:12; /* protection */
702	unsigned int		uid:8; /* index into uid table */
703	unsigned int		guid:8; /* index into guid table */
704	unsigned short		symlink_size;
705	char			symlink[0];
706} __attribute__ ((packed));
707
708struct squashfs_reg_inode_header_2 {
709	unsigned int		inode_type:4;
710	unsigned int		mode:12; /* protection */
711	unsigned int		uid:8; /* index into uid table */
712	unsigned int		guid:8; /* index into guid table */
713	unsigned int		mtime;
714	unsigned int		start_block;
715	unsigned int		fragment;
716	unsigned int		offset;
717	unsigned int		file_size:32;
718	unsigned short		block_list[0];
719} __attribute__ ((packed));
720
721struct squashfs_dir_inode_header_2 {
722	unsigned int		inode_type:4;
723	unsigned int		mode:12; /* protection */
724	unsigned int		uid:8; /* index into uid table */
725	unsigned int		guid:8; /* index into guid table */
726	unsigned int		file_size:19;
727	unsigned int		offset:13;
728	unsigned int		mtime;
729	unsigned int		start_block:24;
730} __attribute__  ((packed));
731
732struct squashfs_ldir_inode_header_2 {
733	unsigned int		inode_type:4;
734	unsigned int		mode:12; /* protection */
735	unsigned int		uid:8; /* index into uid table */
736	unsigned int		guid:8; /* index into guid table */
737	unsigned int		file_size:27;
738	unsigned int		offset:13;
739	unsigned int		mtime;
740	unsigned int		start_block:24;
741	unsigned int		i_count:16;
742	struct squashfs_dir_index_2	index[0];
743} __attribute__  ((packed));
744
745union squashfs_inode_header_2 {
746	struct squashfs_base_inode_header_2	base;
747	struct squashfs_dev_inode_header_2	dev;
748	struct squashfs_symlink_inode_header_2	symlink;
749	struct squashfs_reg_inode_header_2	reg;
750	struct squashfs_dir_inode_header_2	dir;
751	struct squashfs_ldir_inode_header_2	ldir;
752	struct squashfs_ipc_inode_header_2	ipc;
753};
754
755struct squashfs_dir_header_2 {
756	unsigned int		count:8;
757	unsigned int		start_block:24;
758} __attribute__ ((packed));
759
760struct squashfs_dir_entry_2 {
761	unsigned int		offset:13;
762	unsigned int		type:3;
763	unsigned int		size:8;
764	char			name[0];
765} __attribute__ ((packed));
766
767struct squashfs_fragment_entry_2 {
768	unsigned int		start_block;
769	unsigned int		size;
770} __attribute__ ((packed));
771
772#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
773	SQUASHFS_MEMSET(s, d, n);\
774	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
775	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
776	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
777	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
778
779#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
780	SQUASHFS_SWAP_START\
781	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
782}
783
784#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
785	SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
786
787#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
788	SQUASHFS_SWAP_START\
789	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
790			sizeof(struct squashfs_dev_inode_header_2)); \
791	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
792}
793
794#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
795	SQUASHFS_SWAP_START\
796	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
797			sizeof(struct squashfs_symlink_inode_header_2));\
798	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
799}
800
801#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
802	SQUASHFS_SWAP_START\
803	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
804			sizeof(struct squashfs_reg_inode_header_2));\
805	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
806	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
807	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
808	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
809	SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
810}
811
812#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
813	SQUASHFS_SWAP_START\
814	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
815			sizeof(struct squashfs_dir_inode_header_2));\
816	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
817	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
818	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
819	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
820}
821
822#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
823	SQUASHFS_SWAP_START\
824	SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
825			sizeof(struct squashfs_ldir_inode_header_2));\
826	SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
827	SQUASHFS_SWAP((s)->offset, d, 59, 13);\
828	SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
829	SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
830	SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
831}
832
833#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
834	SQUASHFS_SWAP_START\
835	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
836	SQUASHFS_SWAP((s)->index, d, 0, 27);\
837	SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
838	SQUASHFS_SWAP((s)->size, d, 56, 8);\
839}
840#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
841	SQUASHFS_SWAP_START\
842	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
843	SQUASHFS_SWAP((s)->count, d, 0, 8);\
844	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
845}
846
847#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
848	SQUASHFS_SWAP_START\
849	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
850	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
851	SQUASHFS_SWAP((s)->type, d, 13, 3);\
852	SQUASHFS_SWAP((s)->size, d, 16, 8);\
853}
854
855#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
856	SQUASHFS_SWAP_START\
857	SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
858	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
859	SQUASHFS_SWAP((s)->size, d, 32, 32);\
860}
861
862#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
863
864/* fragment and fragment table defines */
865#define SQUASHFS_FRAGMENT_BYTES_2(A)	(A * sizeof(struct squashfs_fragment_entry_2))
866
867#define SQUASHFS_FRAGMENT_INDEX_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) / \
868					SQUASHFS_METADATA_SIZE)
869
870#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A)	(SQUASHFS_FRAGMENT_BYTES_2(A) % \
871						SQUASHFS_METADATA_SIZE)
872
873#define SQUASHFS_FRAGMENT_INDEXES_2(A)	((SQUASHFS_FRAGMENT_BYTES_2(A) + \
874					SQUASHFS_METADATA_SIZE - 1) / \
875					SQUASHFS_METADATA_SIZE)
876
877#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A)	(SQUASHFS_FRAGMENT_INDEXES_2(A) *\
878						sizeof(int))
879
880#endif
881
882#ifdef __KERNEL__
883
884/*
885 * macros used to swap each structure entry, taking into account
886 * bitfields and different bitfield placing conventions on differing
887 * architectures
888 */
889
890#include <asm/byteorder.h>
891
892#ifdef __BIG_ENDIAN
893	/* convert from little endian to big endian */
894#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
895		tbits, b_pos)
896#else
897	/* convert from big endian to little endian */
898#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
899		tbits, 64 - tbits - b_pos)
900#endif
901
902#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
903	b_pos = pos % 8;\
904	val = 0;\
905	s = (unsigned char *)p + (pos / 8);\
906	d = ((unsigned char *) &val) + 7;\
907	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
908		*d-- = *s++;\
909	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
910}
911
912#define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
913
914#endif
915#endif
916