summaryrefslogtreecommitdiffstats
path: root/fs/ufs/ufs_swab.c
blob: 2dc4061a09c10c331ddc9bcc534b06ed37c4ac84 (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
/*
 *  linux/fs/ufs/ufs_swab.c
 *
 * Copyright (C) 1997
 * Francois-Rene Rideau <rideau@ens.fr>
 *
 */

/*
 * For inspiration, you might wanna check sys/ufs/ffs/fs.h from whateverBSD
 *
 * NOTES
 * 19970406 - Fare <rideau@ens.fr>
 *   1) I began from old very preliminary 2.0.x sources,
 *	but it was underfeatured;
 *	I later saw that 2.1.1 sources had a *global* UFS byteswap flag.
 *	EVIL: imagine that a swabbed partition be mounted
 *	while a non-swabbed partition are active (that sucks!)
 *	I merged that source tree with mine.
 *   2) I hope no one is using obNNUUXXIIous byteorder.
 *	That's the only thing I might have broken,
 *	though I rather think it's a fix:
 *	instead of __u64 like BSD,
 *	the former driver used an explicitly bigendian array of __u32!
 *   3) I provide a few macros that use GCC C Extensions.
 *	Port to other compilers would require avoiding them.
 *	in any case, 64 bit (long long) support is required,
 *	unless you're ready to workaround
 *   4) the swab routines below depend on the precise name and order
 *	of the structure elements. Watch out any modification in ufs_fs.h!!!
 *   5) putting byteswapping stuff in ufs_swab* seems cleaner to me.
 *   6) These sources should work with both 2.0 and 2.1 kernels...
 *
 * 19971013 - Fare <rideaufr@issy.cnet.fr>
 *   1) Ported to 2.1.57
 *   2) instead of byteswapping, use [bl]e_to_cpu:
 *     it might be that we run on a VAX!
 *
 * HOWTO continue adding swab support:
 *	basically, anywhere metadata is bread() (i.e. mapped to block device),
 *      data should either be SWAB()ed on the fly,
 *      or copied to a buffer and globally bswap_ufs_*() there.
 *
 */

#include <linux/fs.h>
#include "ufs_swab.h"

static __inline__ void n_be16_to_cpus(__u16*p,unsigned n) {
#ifndef __BIG_ENDIAN
        unsigned i;
        for(i=0;i<n;i++) {
		be16_to_cpus(&p[i]);
        }
#endif
}
static __inline__ void n_be32_to_cpus(__u32*p,unsigned n) {
#ifndef __BIG_ENDIAN
        unsigned i;
        for(i=0;i<n;i++) {
		be32_to_cpus(&p[i]);
        }
#endif
}
static __inline__ void n_le16_to_cpus(__u16*p,unsigned n) {
#ifndef __LITTLE_ENDIAN
        unsigned i;
        for(i=0;i<n;i++) {
		le16_to_cpus(&p[i]);
        }
#endif
}
static __inline__ void n_le32_to_cpus(__u32*p,unsigned n) {
#ifndef __LITTLE_ENDIAN
        unsigned i;
        for(i=0;i<n;i++) {
		le32_to_cpus(&p[i]);
        }
#endif
}

#define __length_before(p,member) \
        ((unsigned)(((char*)&((p)->member))-(char*)(p)))
#define __length_since(p,member) \
        ((unsigned)(sizeof(*p)-__length_before(p,member)))
#define __length_between(p,begin,after_end) \
        ((unsigned)(__length_before(p,after_end)-__length_before(p,begin)))
#define be32_to_cpus__between(s,begin,after_end) \
        n_be32_to_cpus((__u32*)&((s).begin), \
                __length_between(&s,begin,after_end)/4)
#define le32_to_cpus__between(s,begin,after_end) \
        n_le32_to_cpus((__u32*)&((s).begin), \
                __length_between(&s,begin,after_end)/4)
#define be32_to_cpus__since(s,begin) \
	n_be32_to_cpus((__u32*)&((s).begin), \
                __length_since(&s,begin)/4)
#define le32_to_cpus__since(s,begin) \
	n_le32_to_cpus((__u32*)&((s).begin), \
                __length_since(&s,begin)/4)
#define be16_to_cpus__between(s,begin,after_end) \
	n_be16_to_cpus((__u16*)&((s).begin), \
                __length_between(&s,begin,after_end)/2)
#define le16_to_cpus__between(s,begin,after_end) \
	n_le16_to_cpus((__u16*)&((s).begin), \
                __length_between(&s,begin,after_end)/2)

/*
 * Here are the whole-structure swabping routines...
 */

extern void ufs_superblock_be_to_cpus(struct ufs_superblock * usb) {
#ifndef __BIG_ENDIAN
	be32_to_cpus__between(*usb,fs_link,fs_fmod);
        /* XXX - I dunno what to do w/ fs_csp,
         * but it is unused by the current code, so that's ok for now.
         */
	be32_to_cpus(&usb->fs_cpc);
        be16_to_cpus__between(*usb,fs_opostbl,fs_sparecon);
        be32_to_cpus__between(*usb,fs_sparecon,fs_qbmask);
        be64_to_cpus(&usb->fs_qbmask);
        be64_to_cpus(&usb->fs_qfmask);
	be32_to_cpus__between(*usb,fs_postblformat,fs_magic);
#endif
}
extern void ufs_superblock_le_to_cpus(struct ufs_superblock * usb) {
#ifndef __LITTLE_ENDIAN
	le32_to_cpus__between(*usb,fs_link,fs_fmod);
        /* XXX - I dunno what to do w/ fs_csp,
         * but it is unused by the current code, so that's ok for now.
         */
	le32_to_cpus(&usb->fs_cpc);
        le16_to_cpus__between(*usb,fs_opostbl,fs_sparecon);
        le32_to_cpus__between(*usb,fs_sparecon,fs_qbmask);
        le64_to_cpus(&usb->fs_qbmask);
        le64_to_cpus(&usb->fs_qfmask);
	le32_to_cpus__between(*usb,fs_postblformat,fs_magic);
#endif
}