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/

Reply via email to