| 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) { |