I have tried to fix up the endian-swapping patch for
the mkcramfs from sourceforge CVS, circa Mon Jun 24, 2002
:pserver:anonymous at cvs.cramfs.sourceforge.net:/cvsroot/cramfs

No guarantees, of course, use at your own risk.

Currently, I get as far as trying to start init with this
patch, (the same filesystem via NFS works fine.)  This
may be due to the fact that I haven't touched the kernel
code, (that is, I have not allowed for ramdisk to handle
4k block size, as I've been led to believe I must.)

Here's what I'm seeing when I try to use my rootfs
(not that it's necessarily relevant, but I don't
want to imply that I know my patch is perfect):

        RAMDISK: Compressed image found at block 0
        Freeing initrd memory: 1270k freed
        VFS: Mounted root (cramfs filesystem) readonly.
        Freeing unused kernel memory: 196k init
        Warning: unable to open an initial console.
        Kernel panic: No init found.  Try passing init= option to kernel.
        <0>Rebooting in 180 seconds..

-- steve

And here's the patch:

diff -u -r1.1.1.1 mkcramfs.c
--- mkcramfs.c  24 Jun 2002 19:22:19 -0000      1.1.1.1
+++ mkcramfs.c  25 Jun 2002 15:56:42 -0000
@@ -95,6 +95,7 @@
 static char *opt_name = NULL;

 static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
+static int swap_endian = 0;

 /* In-core version of inode / directory entry. */
 struct entry {
@@ -130,6 +131,7 @@
                " -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"
+               " -r         reverse endianness of 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 +374,58 @@
        return totalsize;
 }

+#define wswap(x)       (((x)>>24) | (((x)>>8)&0xff00) | \
+                       (((x)&0xff00)<<8) | (((x)&0xff)<<24))
+
+/* routines to swap endianness/bitfields in inode/superblock block data */
+static void fix_inode(struct cramfs_inode *inode)
+{
+       if (!swap_endian) return;
+       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;
+       if (!swap_endian) return;
+       tmp = wswap(((u32*)inode)[2]);
+       ((u32*)inode)[2] = wswap((offset >> 2) | (tmp&0xfc000000));
+}
+
+static void fix_block_pointer(u32 *p)
+{
+       if (!swap_endian) return;
+       *p = wswap(*p);
+}
+
+static void fix_super(struct cramfs_super *super)
+{
+       u32 *p = (u32*)super;
+
+       if (!swap_endian) return;
+
+       /* 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,7 +459,9 @@
        super->root.uid = CRAMFS_16(root->uid);
        super->root.gid = root->gid;
        super->root.size = CRAMFS_24(root->size);
+       fix_super(super);
        CRAMFS_SET_OFFSET(&(super->root), offset >> 2);
+       fix_offset(&(super->root), offset);

        return offset;
 }
@@ -421,6 +477,7 @@
                die(MKFS_ERROR, 0, "filesystem too big");
        }
        CRAMFS_SET_OFFSET(inode, offset >> 2);
+       fix_offset(inode, offset);
 }

 /*
@@ -610,6 +667,7 @@
                }

                *(u32 *) (base + offset) = CRAMFS_32(curr);
+               fix_block_pointer((u32*)(base + offset));
                offset += 4;
        } while (size);

@@ -700,7 +758,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:prsvz")) != EOF) {
                switch (c) {
                case 'h':
                        usage(MKFS_OK);
@@ -727,6 +785,10 @@
                case 'p':
                        opt_pad = PAD_SIZE;
                        fslen_ub += PAD_SIZE;
+                       break;
+               case 'r':
+                       swap_endian = 1;
+                       fprintf(stderr, "Swapping filesystem endianness.\n");
                        break;
                case 's':
                        /* old option, ignored */

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/



Reply via email to