Hi all, Here is a small patch that makes mkcramfs endianness-aware. I simply added a "-e" command line option that takes one of the following arguments : b makes a _b_ig endian image l makes a _l_ittle endian image h makes a _h_ost-like image (big on big, little on little) r makes a _r_everse-host image (big on little and vice versa) The default behaviour (if -e unspecified) is to make a host-like image for backwards compatibility. Oh, and yes, it IS ugly :-) Have a nice day, Daniel Marmier ------------------------------------------------------------------------ --- work/linux/scripts/cramfs/mkcramfs.c Mon Jun 26 08:02:14 2000 +++ ppc/soft/kernel/scripts/cramfs/mkcramfs.c Tue Oct 3 13:49:36 2000 @@ -25,7 +25,7 @@ static void usage(void) { - fprintf(stderr, "Usage: '%s dirname outfile'\n" + fprintf(stderr, "Usage: '%s [-e{b,l,h,r}] dirname outfile'\n" " where <dirname> is the root of the\n" " filesystem to be compressed.\n", progname); exit(1); @@ -47,6 +47,8 @@ static int warn_dev, warn_gid, warn_namelen, warn_size, warn_uid; +static int reverse_endian; + #ifndef MIN # define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b)) #endif @@ -87,6 +89,17 @@ */ #define MAX_INPUT_NAMELEN 255 +static unsigned long htocl(unsigned long x) +{ + if (reverse_endian) + return ((x << 24) & 0xff000000) | + ((x << 8) & 0x00ff0000) | + ((x >> 8) & 0x0000ff00) | + ((x >> 24) & 0x000000ff); + else + return x; +} + static int find_identical_file(struct entry *orig,struct entry *newfile) { if(orig==newfile) return 1; @@ -273,41 +286,59 @@ memset(area, 0x00, size); } +static unsigned int write_entry(struct entry *entry, char *base) +{ + unsigned long *p = (unsigned long *)base; + + p[0] = htocl((entry->mode << 16) | (entry->uid & 0xffff)); + p[1] = htocl((entry->size << 8) | (entry->gid & 0xff)); + p[2] = htocl(entry->offset & 0x03ffffff); + return sizeof(struct entry); +} + /* Returns sizeof(struct cramfs_super), which includes the root inode. */ static unsigned int write_superblock(struct entry *root, char *base) { struct cramfs_super *super = (struct cramfs_super *) base; unsigned int offset = sizeof(struct cramfs_super); - super->magic = CRAMFS_MAGIC; - super->flags = 0; + super->magic = htocl(CRAMFS_MAGIC); + super->flags = htocl(0); /* Note: 0x10000 is meaningless, which is a bug; but super->size is never used anyway. */ - super->size = 0x10000; + super->size = htocl(0x10000); + super->future = htocl(0); memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature)); set_random(super->fsid, sizeof(super->fsid)); strncpy(super->name, "Compressed", sizeof(super->name)); - super->root.mode = root->mode; - super->root.uid = root->uid; - super->root.gid = root->gid; - super->root.size = root->size; - super->root.offset = offset >> 2; - + root->offset = offset >> 2; + write_entry(root, (char *)&super->root); return offset; } static void set_data_offset(struct entry *entry, char *base, unsigned long offset) { - struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset); + unsigned long *p = (unsigned long *)(base + entry->dir_offset); + unsigned long value; assert ((offset & 3) == 0); if (offset >= (1 << (2 + OFFSET_WIDTH))) { fprintf(stderr, "filesystem too big. Exiting.\n"); exit(1); } - inode->offset = (offset >> 2); + value = (htocl(p[2]) & 0xfc000000) | ((offset >> 2) & 0x03ffffff); + p[2] = htocl(value); } +static unsigned int write_inode(struct cramfs_inode *inode, char *base) +{ + unsigned long *p = (unsigned long *)base; + + p[0] = htocl((inode->mode << 16) | (inode->uid & 0xffff)); + p[1] = htocl((inode->size << 8) | (inode->gid & 0xff)); + p[2] = htocl((inode->namelen << 26) | (inode->offset & 0x03ffffff)); + return sizeof(struct cramfs_inode); +} /* * We do a width-first printout of the directory @@ -323,27 +354,27 @@ for (;;) { int dir_start = stack_entries; while (entry) { - struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset); + struct cramfs_inode inode; size_t len = strlen(entry->name); entry->dir_offset = offset; - inode->mode = entry->mode; - inode->uid = entry->uid; - inode->gid = entry->gid; - inode->size = entry->size; - inode->offset = 0; + inode.mode = entry->mode; + inode.uid = entry->uid; + inode.gid = entry->gid; + inode.size = entry->size; + inode.offset = 0; + inode.namelen = (len + 3) >> 2; + offset += write_inode(&inode, base + offset); /* Non-empty directories, regfiles and symlinks will write over inode->offset later. */ - offset += sizeof(struct cramfs_inode); memcpy(base + offset, entry->name, len); /* Pad up the name to a 4-byte boundary */ while (len & 3) { *(base + offset + len) = '\0'; len++; } - inode->namelen = len >> 2; offset += len; /* TODO: this may get it wrong for chars >= 0x80. @@ -451,7 +482,7 @@ exit(1); } - *(u32 *) (base + offset) = curr; + *(u32 *) (base + offset) = htocl(curr); offset += 4; } while (size); @@ -517,6 +548,11 @@ */ int main(int argc, char **argv) { + int opt; + const char optstring[] = "e:"; + char endian = 'h'; + int big_endian; + unsigned char test_endian[] = { 0x12, 0x34 }; struct stat st; struct entry *root_entry; char *rom_image; @@ -529,14 +565,47 @@ if (argc) progname = argv[0]; - if (argc != 3) + if (argc < 3) usage(); - if (stat(dirname = argv[1], &st) < 0) { - perror(argv[1]); + while ((opt = getopt(argc, argv, optstring)) != -1) + switch(opt) { + case 'e': + endian = *optarg; + break; + default: + usage(); + } + + /* find out host endianness */ + big_endian = *(unsigned short *)test_endian == 0x1234; + /* find out (from host endianness and user's wish) if we need to swap words */ + switch(endian) { + case 'b': + /* big endian image */ + reverse_endian = !big_endian; + break; + case 'h': + /* host-like image (default) */ + reverse_endian = 0; + break; + case 'l': + /* little endian image */ + reverse_endian = big_endian; + break; + case 'r': + /* reverse-host image (big on little and vice versa) */ + reverse_endian = 1; + break; + default: + usage(); + } + + if (stat(dirname = argv[argc - 2], &st) < 0) { + perror(argv[argc - 2]); exit(1); } - fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666); + fd = open(argv[argc - 1], O_WRONLY | O_CREAT | O_TRUNC, 0666); root_entry = calloc(1, sizeof(struct entry)); if (!root_entry) { @@ -547,7 +616,7 @@ root_entry->uid = st.st_uid; root_entry->gid = st.st_gid; - root_entry->size = parse_directory(root_entry, argv[1], &root_entry->child, &fslen_ub); + root_entry->size = parse_directory(root_entry, argv[argc - 2], +&root_entry->child, &fslen_ub); if (fslen_ub > MAXFSLEN) { fprintf(stderr, "warning: guestimate of required size (upper bound) is %luMB, but maximum image size is %uMB. We might die prematurely.\n", - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] Please read the FAQ at http://www.tux.org/lkml/