This patch modifies mkfs.cramfs in a way that it only produces little endian 
images.
To support the creation of big endian formats, a new option -k ("keep 
endianness")
was added. This option can only be set on big endian machines.
A second option called -b (followed by the blocksize) was added, too. It 
enables the user
to specify the desired blocksize (in terms of cramfs).

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 cramfs.h      |  117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs.cramfs.c |   82 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 192 insertions(+), 7 deletions(-)

diff --git a/disk-utils/cramfs.h b/disk-utils/cramfs.h
index 34b32ca..3cb4c51 100644
--- a/disk-utils/cramfs.h
+++ b/disk-utils/cramfs.h
@@ -6,6 +6,7 @@ typedef unsigned short u16;
 typedef unsigned int u32;
 
 #define CRAMFS_MAGIC           0x28cd3d45      /* some random number */
+#define CRAMFS_MAGIC_WEND      0x453dcd28      /* magic number with the wrong 
endianess */
 #define CRAMFS_SIGNATURE       "Compressed ROMFS"
 
 /*
@@ -78,4 +79,120 @@ int cramfs_uncompress_block(void *dst, int dstlen, void 
*src, int srclen);
 int cramfs_uncompress_init(void);
 int cramfs_uncompress_exit(void);
 
+#define swab16(x) \
+       ((u16)( \
+               (((u16)(x) & (u16)0x00ffU) << 8) | \
+               (((u16)(x) & (u16)0xff00U) >> 8) ))
+
+#define swab32(x) \
+       ((u32)( \
+               (((u32)(x) & (u32)0x000000ffUL) << 24) | \
+               (((u32)(x) & (u32)0x0000ff00UL) <<  8) | \
+               (((u32)(x) & (u32)0x00ff0000UL) >>  8) | \
+               (((u32)(x) & (u32)0xff000000UL) >> 24) ))
+
+/* Converts a cramfs_info from big endian to little endian. */
+static inline void cramfs_convert_info_betole(struct cramfs_info* info)
+{
+        info->crc = swab32(info->crc);
+        info->edition = swab32(info->edition);
+        info->blocks = swab32(info->blocks);
+        info->files = swab32(info->files);
+}
+
+/* Same function for the inverse way */
+#define cramfs_convert_info_letobe(info) cramfs_convert_info_betole(info)
+
+/* Converts a cramfs_info from big endian to little endian. */
+static inline void cramfs_convert_inode_betole(struct cramfs_inode* inode)
+{
+       u8* inode_bytes = (u8*)inode;
+       u8 old_nloffs[4];
+
+       inode->mode = swab16(inode->mode);
+       inode->uid = swab16(inode->uid);
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+       inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[4]);
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+       inode->size = (inode_bytes[4] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[6]);
+#endif
+
+       /* Save the old values of the namelength and the offset */
+       memcpy(old_nloffs, inode_bytes+8, 4);
+
+       inode_bytes[8] = ((old_nloffs[3] & 0x03) << 6) | ((old_nloffs[0] & 
0xfc) >> 2);
+       inode_bytes[9] = ((old_nloffs[2] & 0x03) << 6) | ((old_nloffs[3] & 
0xfc) >> 2);
+       inode_bytes[10] = ((old_nloffs[1] & 0x03) << 6) | ((old_nloffs[2] & 
0xfc) >> 2);
+       inode_bytes[11] = ((old_nloffs[0] & 0x03) << 6) | ((old_nloffs[1] & 
0xfc) >> 2);
+}
+
+/* Converts a cramfs_info from little endian to big endian.
+   Unfortunately, this is not exact inverse of cramfs_convert_inode_betole
+   because of the bitfields used in the inode structure. */
+static inline void cramfs_convert_inode_letobe(struct cramfs_inode* inode)
+{
+       u8* inode_bytes = (u8*)inode;
+       u8 old_nloffs[4];
+
+       inode->mode = swab16(inode->mode);
+       inode->uid = swab16(inode->uid);
+       inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[4]);
+
+       /* Save the old values of the namelength and the offset */
+       memcpy(old_nloffs, inode_bytes+8, 4);
+
+       /* Convert the namelength and the offset */
+       inode_bytes[8] = ((old_nloffs[0] & 0x3f) << 2) | ((old_nloffs[3] & 
0xc0) >> 6);
+       inode_bytes[9] = ((old_nloffs[3] & 0x3f) << 2) | ((old_nloffs[2] & 
0xc0) >> 6);
+       inode_bytes[10] = ((old_nloffs[2] & 0x3f) << 2) | ((old_nloffs[1] & 
0xc0) >> 6);
+       inode_bytes[11] = ((old_nloffs[1] & 0x3f) << 2) | ((old_nloffs[0] & 
0xc0) >> 6);
+}
+
+/* Converts a cramfs superblock from big endian to little endian. */
+static inline void cramfs_convert_super_betole(struct cramfs_super* super)
+{
+       super->magic = swab32(super->magic);
+       super->size = swab32(super->size);
+       super->flags = swab32(super->flags);
+       super->future = swab32(super->future);
+       cramfs_convert_info_betole(&super->fsid);
+       cramfs_convert_inode_betole(&super->root);
+}
+
+/* Converts a cramfs superblock from little endian to big endian. */
+static inline void cramfs_convert_super_letobe(struct cramfs_super* super)
+{
+       super->magic = swab32(super->magic);
+       super->size = swab32(super->size);
+       super->flags = swab32(super->flags);
+       super->future = swab32(super->future);
+       cramfs_convert_info_letobe(&super->fsid);
+       cramfs_convert_inode_letobe(&super->root);
+}
+
+/* Converts a 32 bit integer from big endian to little endian */
+static inline u32 cramfs_convert_u32_betole(u32 val)
+{
+       return swab32(val);
+}
+
+#define cramfs_convert_u32_letobe(val) cramfs_convert_u32_betole(val)
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define cramfsck_convert_info(x) cramfs_convert_info_letobe(x)
+#define cramfsck_convert_inode(x) cramfs_convert_inode_letobe(x)
+#define cramfsck_convert_super(x) cramfs_convert_super_letobe(x)
+#define cramfsck_convert_u32(x) cramfs_convert_u32_letobe(x)
+
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define cramfsck_convert_info(x) cramfs_convert_info_betole(x)
+#define cramfsck_convert_inode(x) cramfs_convert_inode_betole(x)
+#define cramfsck_convert_super(x) cramfs_convert_super_betole(x)
+#define cramfsck_convert_u32(x) cramfs_convert_u32_betole(x)
+
+#else
+#error "Neither __BIG_ENDIAN nor __LITTLE_ENDIAN defined."
+#endif
+
 #endif
diff --git a/disk-utils/mkfs.cramfs.c b/disk-utils/mkfs.cramfs.c
index e61ac9e..93466c2 100644
--- a/disk-utils/mkfs.cramfs.c
+++ b/disk-utils/mkfs.cramfs.c
@@ -23,6 +23,10 @@
  * files one by one instaed of all simultaneously. - aeb, 2002-11-01
  */
 
+/*
+ * Made cramfs little endian only. - Andi Drebes, 11/2007
+ */
+
 #include <sys/types.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -51,6 +55,7 @@
 
 static const char *progname = "mkcramfs";
 static int verbose = 0;
+static int keep_endianness = 0;
 
 static unsigned int blksize; /* settable via -b option */
 static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
@@ -131,6 +136,7 @@ usage(int status) {
                  " -e edition set edition number (part of fsid)\n"
                  " -i file    insert a file image into the filesystem "
                    "(requires >= 2.4.0)\n"
+                 " -k         keep machine's endianness (for big endian 
machines only)\n"
                  " -n name    set name of cramfs filesystem\n"
                  " -p         pad by %d bytes for boot code\n"
                  " -s         sort directory entries (old option, ignored)\n"
@@ -630,7 +636,13 @@ do_compress(char *base, unsigned int offset, unsigned char 
const *name,
                        exit(8);
                }
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+               if (!keep_endianness)
+                       *(u32 *) (base + offset) = 
cramfs_convert_u32_betole(curr);
+               else
+#endif
                *(u32 *) (base + offset) = curr;
+
                offset += 4;
        } while (size);
 
@@ -712,6 +724,34 @@ maxfslen(void) {
                + (1 << CRAMFS_SIZE_WIDTH) * 4 / blksize; /* block pointers */
 }
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+void convert_entry_betole(struct entry *entry, char *base)
+{
+       struct cramfs_inode *inode;
+       u32 *startseq;
+
+       if (!entry)
+               return;
+
+       while (entry) {
+               if (entry->child)
+                       convert_entry_betole(entry->child, base);
+
+               inode = (struct cramfs_inode*)(base+entry->dir_offset);
+               cramfs_convert_inode_betole(inode);
+               entry = entry->next;
+       }
+}
+
+void convert_image_betole(char *rom_image, struct entry *root_entry)
+{
+       struct cramfs_super *super = (struct cramfs_super*)(rom_image+opt_pad);
+
+       convert_entry_betole(root_entry->child, rom_image);
+       cramfs_convert_super_betole(super);
+}
+#endif /* __BIG_ENDIAN */
+
 /*
  * Usage:
  *
@@ -746,7 +786,7 @@ int main(int argc, char **argv)
        }
 
        /* command line options */
-       while ((c = getopt(argc, argv, "hb:Ee:i:n:psVvz")) != EOF) {
+       while ((c = getopt(argc, argv, "hb:Ee:ki:n:psVvz")) != EOF) {
                switch (c) {
                case 'h':
                        usage(0);
@@ -770,6 +810,9 @@ int main(int argc, char **argv)
                        image_length = st.st_size; /* may be padded later */
                        fslen_ub += (image_length + 3); /* 3 is for padding */
                        break;
+               case 'k':
+                       keep_endianness = 1;
+                       break;
                case 'n':
                        opt_name = optarg;
                        break;
@@ -885,12 +928,6 @@ int main(int argc, char **argv)
                printf(_("Super block: %zd bytes\n"),
                       sizeof(struct cramfs_super));
 
-       /* Put the checksum in. */
-       crc = crc32(crc, (unsigned char *) (rom_image+opt_pad), 
(offset-opt_pad));
-       ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc;
-       if (verbose)
-               printf(_("CRC: %x\n"), crc);
-
        /* Check to make sure we allocated enough space. */
        if (fslen_ub < offset) {
                fprintf(stderr,
@@ -900,6 +937,37 @@ int main(int argc, char **argv)
                exit(8);
        }
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+       /* Convert everything into little endian */
+       if (!keep_endianness)
+               convert_image_betole(rom_image, root_entry);
+#endif
+
+       if (verbose) {
+               printf(_("Endianness: "));
+#if __BYTE_ORDER == __BIG_ENDIAN
+               if (!keep_endianness)
+                       printf(_("little endian\n"));
+               else
+                       printf(_("big endian\n"));
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+               printf(_("little endian\n"));
+#endif
+
+               printf(_("Block size: %d\n"), blksize);
+       }
+
+       /* Put the checksum in. */
+       crc = crc32(crc, (unsigned char *) (rom_image+opt_pad), 
(offset-opt_pad));
+       if (verbose)
+               printf(_("CRC: %x\n"), crc);
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+       if (!keep_endianness)
+               crc = cramfs_convert_u32_betole(crc);
+#endif
+       ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc;
+
        written = write(fd, rom_image, offset);
        if (written < 0) {
                perror("ROM image");
-
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to