aboutsummaryrefslogtreecommitdiffstats
path: root/package/cramfs/cramfs-02-endian.patch
blob: 0da55bfae6bedb244eacea8afa433d608f599b6c (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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
--- cramfs-1.1/mkcramfs.c.orig	2005-04-13 05:55:57.000000000 -0600
+++ cramfs-1.1/mkcramfs.c	2005-04-13 16:19:57.000000000 -0600
@@ -117,6 +117,7 @@
 static int opt_squash = 0;
 static char *opt_image = NULL;
 static char *opt_name = NULL;
+static int swap_endian = 0;
 
 static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
 static const char *const memory_exhausted = "memory exhausted";
@@ -155,6 +156,8 @@
 		" -i file    insert a file image into the filesystem (requires >= 2.4.0)\n"
 		" -n name    set name of cramfs filesystem\n"
 		" -p         pad by %d bytes for boot code\n"
+		" -l         litte endian filesystem\n"
+		" -b         big endian filesystem\n"
 		" -s         sort directory entries (old option, ignored)\n"
 		" -v         be more verbose\n"
 		" -z         make explicit holes (requires >= 2.3.39)\n"
@@ -504,6 +506,50 @@
 	return totalsize;
 }
 
+/* routines to swap endianness/bitfields in inode/superblock block data */
+static void fix_inode(struct cramfs_inode *inode)
+{
+#define wswap(x)    (((x)>>24) | (((x)>>8)&0xff00) | (((x)&0xff00)<<8) | (((x)&0xff)<<24))
+	/* attempt #2 */
+	inode->mode = (inode->mode >> 8) | ((inode->mode&0xff)<<8);
+	inode->uid = (inode->uid >> 8) | ((inode->uid&0xff)<<8);
+	inode->size = (inode->size >> 16) | (inode->size&0xff00) |
+		((inode->size&0xff)<<16);
+	((u32*)inode)[2] = wswap(inode->offset | (inode->namelen<<26));
+}
+
+static void fix_offset(struct cramfs_inode *inode, u32 offset)
+{
+	u32 tmp = wswap(((u32*)inode)[2]);
+	((u32*)inode)[2] = wswap((offset >> 2) | (tmp&0xfc000000));
+}
+
+static void fix_block_pointer(u32 *p)
+{
+	*p = wswap(*p);
+}
+
+static void fix_super(struct cramfs_super *super)
+{
+	u32 *p = (u32*)super;
+
+	/* fix superblock fields */
+	p[0] = wswap(p[0]);	/* magic */
+	p[1] = wswap(p[1]);	/* size */
+	p[2] = wswap(p[2]);	/* flags */
+	p[3] = wswap(p[3]);	/* future */
+
+	/* fix filesystem info fields */
+	p = (u32*)&super->fsid;
+	p[0] = wswap(p[0]);	/* crc */
+	p[1] = wswap(p[1]);	/* edition */
+	p[2] = wswap(p[2]);	/* blocks */
+	p[3] = wswap(p[3]);	/* files */
+
+	fix_inode(&super->root);
+#undef wswap
+}
+
 /* Returns sizeof(struct cramfs_super), which includes the root inode. */
 static unsigned int write_superblock(struct entry *root, char *base, int size)
 {
@@ -539,6 +585,7 @@
 	super->root.gid = root->gid;
 	super->root.size = root->size;
 	super->root.offset = offset >> 2;
+	if (swap_endian) fix_super(super);
 
 	return offset;
 }
@@ -553,7 +600,10 @@
 	if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
 		error_msg_and_die("filesystem too big");
 	}
-	inode->offset = (offset >> 2);
+	if (swap_endian)
+		fix_offset(inode, offset);
+	else
+		inode->offset = (offset >> 2);
 }
 
 /*
@@ -638,6 +688,7 @@
 				stack_entries++;
 			}
 			entry = entry->next;
+			if (swap_endian) fix_inode(inode);
 		}
 
 		/*
@@ -734,6 +785,7 @@
 		}
 
 		*(u32 *) (base + offset) = curr;
+		if (swap_endian) fix_block_pointer((u32*)(base + offset));
 		offset += 4;
 	} while (size);
 
@@ -1146,7 +1198,7 @@
 		progname = argv[0];
 
 	/* command line options */
-	while ((c = getopt(argc, argv, "hEe:i:n:psvzD:q")) != EOF) {
+	while ((c = getopt(argc, argv, "hEe:i:n:psvzD:qlb")) != EOF) {
 		switch (c) {
 		case 'h':
 			usage(MKFS_OK);
@@ -1174,6 +1227,18 @@
 			opt_pad = PAD_SIZE;
 			fslen_ub += PAD_SIZE;
 			break;
+		case 'b':
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+			swap_endian = 1;
+			printf("Swapping filesystem endian-ness\n");
+#endif
+			break;
+		case 'l':
+#if __BYTE_ORDER == __BIG_ENDIAN
+			swap_endian = 1;
+			printf("Swapping filesystem endian-ness\n");
+#endif
+			break;
 		case 's':
 			/* old option, ignored */
 			break;
--- cramfs-1.1/cramfsck.c.orig	2005-04-25 11:50:31.000000000 -0700
+++ cramfs-1.1/cramfsck.c	2005-04-25 16:53:25.000000000 -0700
@@ -30,6 +30,7 @@
  * 2000/07/15: Daniel Quinlan (initial support for block devices)
  * 2002/01/10: Daniel Quinlan (additional checks, test more return codes,
  *                            use read if mmap fails, standardize messages)
+ * 2004/09/01: Alfonso Acosta (Add swapping support)
  */
 
 /* compile-time options */
@@ -51,6 +52,7 @@
 #include <utime.h>
 #include <sys/ioctl.h>
 #define _LINUX_STRING_H_
+#include <byteswap.h>
 #include "linux/cramfs_fs.h"
 #include <zlib.h>
 
@@ -74,6 +76,7 @@
 static char *filename;		/* ROM image filename */
 struct cramfs_super super;	/* just find the cramfs superblock once */
 static int opt_verbose = 0;	/* 1 = verbose (-v), 2+ = very verbose (-vv) */
+static int need_swapping = 0;   /* fs and host dont have the same endianness */
 #ifdef INCLUDE_FS_TESTS
 static int opt_extract = 0;		/* extract cramfs (-x) */
 static char *extract_dir = "/";	/* extraction directory (-x) */
@@ -85,6 +88,9 @@
 static unsigned long start_data = ~0UL;	/* start of the data (256 MB = max) */
 static unsigned long end_data = 0;	/* end of the data */
 
+/* access 32 byte variables */
+#define CRAMFS_32(x)  (need_swapping ? bswap_32(x) : x)
+
 /* Guarantee access to at least 8kB at a time */
 #define ROMBUFFER_BITS	13
 #define ROMBUFFERSIZE	(1 << ROMBUFFER_BITS)
@@ -166,20 +172,34 @@
 	if (super.magic == CRAMFS_MAGIC) {
 		*start = 0;
 	}
+	else if (super.magic == bswap_32(CRAMFS_MAGIC)) {
+		*start = 0;
+		need_swapping = 1;
+	}
+
 	else if (*length >= (PAD_SIZE + sizeof(super))) {
 		lseek(fd, PAD_SIZE, SEEK_SET);
 		if (read(fd, &super, sizeof(super)) != sizeof(super)) {
 			die(FSCK_ERROR, 1, "read failed: %s", filename);
 		}
-		if (super.magic == CRAMFS_MAGIC) {
+		if (super.magic == CRAMFS_32(CRAMFS_MAGIC)) {
 			*start = PAD_SIZE;
 		}
 	}
 
 	/* superblock tests */
-	if (super.magic != CRAMFS_MAGIC) {
+	if (super.magic != CRAMFS_32(CRAMFS_MAGIC)) {
 		die(FSCK_UNCORRECTED, 0, "superblock magic not found");
 	}
+	if (need_swapping){
+		super.size = bswap_32(super.size);
+		super.flags = bswap_32(super.flags);
+		super.future = bswap_32(super.future);
+		super.fsid.crc = bswap_32(super.fsid.crc);
+		super.fsid.edition = bswap_32(super.fsid.edition);
+		super.fsid.blocks = bswap_32(super.fsid.blocks);
+		super.fsid.files = bswap_32(super.fsid.files); 
+	}	
 	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
 		die(FSCK_ERROR, 0, "unsupported filesystem features");
 	}
@@ -215,7 +235,10 @@
 		die(FSCK_USAGE, 0, "unable to test CRC: old cramfs format");
 #endif /* not INCLUDE_FS_TESTS */
 	}
-
+	else if (need_swapping) {
+       /* crc checking in this case would mean  translating the whole file */
+		return;
+	}
 	crc = crc32(0L, Z_NULL, 0);
 
 	buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
@@ -300,12 +323,23 @@
 
 static struct cramfs_inode *cramfs_iget(struct cramfs_inode * i)
 {
+#define wswap(x)    (((x)>>24) | (((x)>>8)&0xff00) | (((x)&0xff00)<<8) | (((x)&0xff)<<24))
 	struct cramfs_inode *inode = malloc(sizeof(struct cramfs_inode));
 
 	if (!inode) {
 		die(FSCK_ERROR, 1, "malloc failed");
 	}
-	*inode = *i;
+	if(!need_swapping) {
+		*inode = *i;
+	}
+	else { 
+		inode->mode=bswap_16(i->mode);
+		inode->uid=bswap_16(i->uid);
+		inode->size=bswap_32(i->size << 8);
+		inode->gid=i->gid;
+		inode->namelen = bswap_32(((u32*)i)[2]) >> 26;
+		inode->offset = bswap_32(((u32*)i)[2]) & 0x3FFFFFFF;
+	}
 	return inode;
 }
 
@@ -324,9 +358,9 @@
  */
 static struct cramfs_inode *read_super(void)
 {
-	unsigned long offset = super.root.offset << 2;
-
-	if (!S_ISDIR(super.root.mode))
+	struct cramfs_inode *root = cramfs_iget(&super.root);
+	unsigned long offset = root->offset << 2; 
+	if (!S_ISDIR(root->mode))
 		die(FSCK_UNCORRECTED, 0, "root inode is not directory");
 	if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
 	    ((offset != sizeof(struct cramfs_super)) &&
@@ -334,7 +368,7 @@
 	{
 		die(FSCK_UNCORRECTED, 0, "bad root offset (%lu)", offset);
 	}
-	return cramfs_iget(&super.root);
+	return root;
 }
 
 static int uncompress_block(void *src, int len)
@@ -366,7 +400,7 @@
 
 	do {
 		unsigned long out = PAGE_CACHE_SIZE;
-		unsigned long next = *(u32 *) romfs_read(offset);
+		unsigned long next = CRAMFS_32(*(u32 *) romfs_read(offset));
 
 		if (next > end_data) {
 			end_data = next;
@@ -529,7 +563,7 @@
 {
 	unsigned long offset = i->offset << 2;
 	unsigned long curr = offset + 4;
-	unsigned long next = *(u32 *) romfs_read(offset);
+	unsigned long next = CRAMFS_32(*(u32 *) romfs_read(offset));
 	unsigned long size;
 
 	if (offset == 0) {