*** empty log message ***
authorcharles <charles>
Wed, 16 Jul 2003 03:00:48 +0000 (03:00 +0000)
committercharles <charles>
Wed, 16 Jul 2003 03:00:48 +0000 (03:00 +0000)
utils/mkyaffsimage.c

index 814e2af779224bf73afc1017f05ab13cf1ae1342..c21c631f3272379b64121b31b53ae6a8d229b55c 100644 (file)
@@ -17,6 +17,9 @@
  *
  * Nick Bane modifications flagged NCB
  *
+ * Endian handling patches by James Ng.
+ * 
+ *
  */
  
 #include <stdlib.h>
@@ -33,7 +36,7 @@
 
 #define MAX_OBJECTS 10000
 
-const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.6 2002-12-13 00:13:06 charles Exp $";
+const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.7 2003-07-16 03:00:48 charles Exp $";
 
 // External functions for ECC on data
 void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
@@ -58,6 +61,7 @@ static int outFile;
 
 static int error;
 
+static int convert_endian = 0;
 
 static int obj_compare(const void *a, const void * b)
 {
@@ -147,7 +151,17 @@ static void yaffs_CalcTagsECC(yaffs_Tags *tags)
        unsigned  ecc = 0;
        unsigned bit = 0;
 
-       tags->ecc = 0;
+    // Clear ECC fields
+    if (!convert_endian)
+    {
+           tags->ecc = 0;
+    }
+    else
+    {
+        // Because we're in "munged tag" mode, we have to clear it manually
+        b[6] &= 0xC0;
+        b[7] &= 0x03;
+    }
        
        for(i = 0; i < 8; i++)
        {
@@ -162,9 +176,17 @@ static void yaffs_CalcTagsECC(yaffs_Tags *tags)
                }
        }
        
-       tags->ecc = ecc;
-       
-       
+       // Write out ECC
+    if (!convert_endian)
+    {
+        tags->ecc = ecc;
+    }
+    else
+    {
+           // We have to munge the ECC again.
+           b[6] |= ((ecc >> 6) & 0x3F);
+        b[7] |= ((ecc & 0x3F) << 2);
+    }
 }
 static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
 {
@@ -182,7 +204,36 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
        sparePtr->tagByte7 = tu->asBytes[7];
 }
 
-
+/* This little function converts a little endian tag to a big endian tag.
+ * NOTE: The tag is not usable after this other than calculating the CRC
+ * with.
+ */
+static void little_to_big_endian(yaffs_Tags *tagsPtr)
+{
+    yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes.
+    yaffs_TagsUnion   temp;
+
+    memset(&temp, 0, sizeof(temp));
+    // Ick, I hate magic numbers.
+    temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4);
+    temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4);
+    temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6);
+    temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6);
+    temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2);
+    temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2);
+    temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F);
+    temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6);
+
+    // Now copy it back.
+    tags->asBytes[0] = temp.asBytes[0];
+    tags->asBytes[1] = temp.asBytes[1];
+    tags->asBytes[2] = temp.asBytes[2];
+    tags->asBytes[3] = temp.asBytes[3];
+    tags->asBytes[4] = temp.asBytes[4];
+    tags->asBytes[5] = temp.asBytes[5];
+    tags->asBytes[6] = temp.asBytes[6];
+    tags->asBytes[7] = temp.asBytes[7];
+}
 
 static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
 {
@@ -199,6 +250,11 @@ static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
        t.serialNumber = 0;
        t.byteCount = nBytes;
        t.objectId = objId;
+
+    if (convert_endian)
+    {
+        little_to_big_endian(&t);
+    }
        
        yaffs_CalcTagsECC(&t);
        yaffs_LoadTagsIntoSpare(&s,&t);
@@ -210,6 +266,72 @@ static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
        
 }
 
+#define SWAP32(x)   ((((x) & 0x000000FF) << 24) | \
+                     (((x) & 0x0000FF00) << 8 ) | \
+                     (((x) & 0x00FF0000) >> 8 ) | \
+                     (((x) & 0xFF000000) >> 24))
+
+#define SWAP16(x)   ((((x) & 0x00FF) << 8) | \
+                     (((x) & 0xFF00) >> 8))
+        
+// This one is easier, since the types are more standard. No funky shifts here.
+static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh)
+{
+    oh->type = SWAP32(oh->type); // GCC makes enums 32 bits.
+    oh->parentObjectId = SWAP32(oh->parentObjectId); // int
+    oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness.
+    // name = skip. Char array. Not swapped.
+    oh->st_mode = SWAP32(oh->st_mode);
+#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. 
+    // In fact, WinCE would be *THE* place where this would be an issue!
+    oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]);
+    oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]);
+    oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]);
+    oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]);
+    oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]);
+#else
+    // Regular POSIX.
+    oh->st_uid = SWAP32(oh->st_uid);
+    oh->st_gid = SWAP32(oh->st_gid);
+    oh->st_atime = SWAP32(oh->st_atime);
+    oh->st_mtime = SWAP32(oh->st_mtime);
+    oh->st_ctime = SWAP32(oh->st_ctime);
+#endif
+
+    oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that!
+    oh->equivalentObjectId = SWAP32(oh->equivalentObjectId);
+    // alias  - char array.
+    oh->st_rdev = SWAP32(oh->st_rdev);
+
+#ifdef CONFIG_YAFFS_WINCE
+    oh->win_ctime[0] = SWAP32(oh->win_ctime[0]);
+    oh->win_ctime[1] = SWAP32(oh->win_ctime[1]);
+    oh->win_atime[0] = SWAP32(oh->win_atime[0]);
+    oh->win_atime[1] = SWAP32(oh->win_atime[1]);
+    oh->win_mtime[0] = SWAP32(oh->win_mtime[0]);
+    oh->win_mtime[1] = SWAP32(oh->win_mtime[1]);
+    oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
+    oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
+    oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
+    oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
+    oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
+    oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
+#else
+    oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
+    oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
+    oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
+    oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
+    oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
+    oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
+    oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]);
+    oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]);
+    oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]);
+    oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]);
+    oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]);
+    oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]);
+#endif
+}
+
 static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
 {
        __u8 bytes[512];
@@ -252,6 +374,11 @@ static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, in
        {
                strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH);
        }
+
+    if (convert_endian)
+    {
+        object_header_little_to_big_endian(oh);
+    }
        
        return write_chunk(bytes,objId,0,0xffff);
        
@@ -409,14 +536,20 @@ int main(int argc, char *argv[])
        
        printf("mkyaffsimage: image building tool for YAFFS built "__DATE__"\n");
        
-       if(argc != 3)
+       if(argc <= 3)
        {
-               printf("usage: mkyaffsimage dir image_file\n");
+               printf("usage: mkyaffsimage dir image_file [convert]\n");
                printf("           dir        the directory tree to be converted\n");
                printf("           image_file the output file to hold the image\n");
+        printf("           'convert'  produce a big-endian image from a little-endian machine\n");
                exit(1);
        }
 
+    if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
+    {
+        convert_endian = 1;
+    }
+    
        if(stat(argv[1],&stats) < 0)
        {
                printf("Could not stat %s\n",argv[1]);