0001-endian.patch 8.34 KB
Index: cramfs-1.1/mkcramfs.c
===================================================================
--- cramfs-1.1.orig/mkcramfs.c	2002-02-20 09:03:32.000000000 +0100
+++ cramfs-1.1/mkcramfs.c	2011-09-09 15:11:00.980895119 +0200
@@ -93,6 +93,7 @@
 static int opt_verbose = 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;
 
@@ -130,6 +131,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"
@@ -372,6 +375,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)
 {
@@ -405,6 +452,7 @@
 	super->root.gid = root->gid;
 	super->root.size = root->size;
 	super->root.offset = offset >> 2;
+	if (swap_endian) fix_super(super);
 
 	return offset;
 }
@@ -419,7 +467,10 @@
 	if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
 		die(MKFS_ERROR, 0, "filesystem too big");
 	}
-	inode->offset = (offset >> 2);
+	if (swap_endian)
+		fix_offset(inode, offset);
+	else
+		inode->offset = (offset >> 2);
 }
 
 /*
@@ -515,6 +566,7 @@
 				stack_entries++;
 			}
 			entry = entry->next;
+			if (swap_endian) fix_inode(inode);
 		}
 
 		/*
@@ -609,6 +661,7 @@
 		}
 
 		*(u32 *) (base + offset) = curr;
+		if (swap_endian) fix_block_pointer((u32*)(base + offset));
 		offset += 4;
 	} while (size);
 
@@ -699,7 +752,7 @@
 		progname = argv[0];
 
 	/* command line options */
-	while ((c = getopt(argc, argv, "hEe:i:n:psvz")) != EOF) {
+	while ((c = getopt(argc, argv, "hEe:i:n:psvzlb")) != EOF) {
 		switch (c) {
 		case 'h':
 			usage(MKFS_OK);
@@ -727,6 +780,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;
Index: cramfs-1.1/cramfsck.c
===================================================================
--- cramfs-1.1.orig/cramfsck.c	2002-02-23 01:00:42.000000000 +0100
+++ cramfs-1.1/cramfsck.c	2011-09-09 15:10:06.810894275 +0200
@@ -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 */
@@ -53,6 +54,7 @@
 #define _LINUX_STRING_H_
 #include <linux/fs.h>
 #include <linux/cramfs_fs.h>
+#include <byteswap.h>
 #include <zlib.h>
 
 /* Exit codes used by fsck-type programs */
@@ -73,6 +75,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 = "root";	/* extraction directory (-x) */
@@ -84,6 +87,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)
@@ -165,20 +171,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");
 	}
@@ -213,7 +233,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);
@@ -298,12 +321,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;
 }
 
@@ -322,9 +356,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)) &&
@@ -332,7 +366,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)
@@ -364,7 +398,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;
@@ -525,7 +559,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) {