X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs%2F.git;a=blobdiff_plain;f=utils%2Fmkyaffsimage.c;h=8d57bc3272330be454f7396990153db9ad724b69;hp=814e2af779224bf73afc1017f05ab13cf1ae1342;hb=c370031e8cc127ad5af4ac7fbbe794fb6a56a672;hpb=3d5f3cc536fd1e1c2ce477c4f3ba5147eb8678be diff --git a/utils/mkyaffsimage.c b/utils/mkyaffsimage.c index 814e2af..8d57bc3 100644 --- a/utils/mkyaffsimage.c +++ b/utils/mkyaffsimage.c @@ -17,6 +17,9 @@ * * Nick Bane modifications flagged NCB * + * Endian handling patches by James Ng. + * + * */ #include @@ -27,17 +30,13 @@ #include #include #include - +#include "yaffs_ecc.h" #include "yaffs_guts.h" #define MAX_OBJECTS 10000 -const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.6 2002-12-13 00:13:06 charles Exp $"; - -// External functions for ECC on data -void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); -int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); +const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.8 2005-10-11 23:39:56 charles Exp $"; typedef struct @@ -58,6 +57,7 @@ static int outFile; static int error; +static int convert_endian = 0; static int obj_compare(const void *a, const void * b) { @@ -135,8 +135,8 @@ static __u16 yaffs_CalcNameSum(const char *name) static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) { - nand_calculate_ecc (data , spare->ecc1); - nand_calculate_ecc (&data[256] , spare->ecc2); + yaffs_ECCCalculate(data , spare->ecc1); + yaffs_ECCCalculate(&data[256] , spare->ecc2); } static void yaffs_CalcTagsECC(yaffs_Tags *tags) @@ -147,7 +147,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 +172,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 +200,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 +246,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 +262,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->yst_mode = SWAP32(oh->yst_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->yst_uid = SWAP32(oh->yst_uid); + oh->yst_gid = SWAP32(oh->yst_gid); + oh->yst_atime = SWAP32(oh->yst_atime); + oh->yst_mtime = SWAP32(oh->yst_mtime); + oh->yst_ctime = SWAP32(oh->yst_ctime); +#endif + + oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! + oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); + // alias - char array. + oh->yst_rdev = SWAP32(oh->yst_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]; @@ -228,14 +346,14 @@ static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, in if(t != YAFFS_OBJECT_TYPE_HARDLINK) { - oh->st_mode = s->st_mode; - oh->st_uid = s->st_uid; -// NCB 12/9/02 oh->st_gid = s->st_uid; - oh->st_gid = s->st_gid; - oh->st_atime = s->st_atime; - oh->st_mtime = s->st_mtime; - oh->st_ctime = s->st_ctime; - oh->st_rdev = s->st_rdev; + oh->yst_mode = s->st_mode; + oh->yst_uid = s->st_uid; +// NCB 12/9/02 oh->yst_gid = s->yst_uid; + oh->yst_gid = s->st_gid; + oh->yst_atime = s->st_atime; + oh->yst_mtime = s->st_mtime; + oh->yst_ctime = s->st_ctime; + oh->yst_rdev = s->st_rdev; } if(t == YAFFS_OBJECT_TYPE_FILE) @@ -252,6 +370,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 +532,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]);