X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs%2F.git;a=blobdiff_plain;f=utils%2Fmkyaffsimage.c;h=c21c631f3272379b64121b31b53ae6a8d229b55c;hp=bab5797501e20314b9c02d86206ca1944d4061a1;hb=24e04c35b63138c14224754f9636e6b2a6915f3b;hpb=4d9efb8e3f1bd240579632b4c1446d7384c3cc96 diff --git a/utils/mkyaffsimage.c b/utils/mkyaffsimage.c index bab5797..c21c631 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 @@ -33,7 +36,7 @@ #define MAX_OBJECTS 10000 -const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.3 2002-09-27 20:50:50 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,8 +61,9 @@ static int outFile; static int error; +static int convert_endian = 0; -int obj_compare(const void *a, const void * b) +static int obj_compare(const void *a, const void * b) { objItem *oa, *ob; @@ -75,7 +79,7 @@ int obj_compare(const void *a, const void * b) } -void add_obj_to_list(dev_t dev, ino_t ino, int obj) +static void add_obj_to_list(dev_t dev, ino_t ino, int obj) { if(n_obj < MAX_OBJECTS) { @@ -95,11 +99,11 @@ void add_obj_to_list(dev_t dev, ino_t ino, int obj) } -int find_obj_in_list(dev_t dev, ino_t ino) +static int find_obj_in_list(dev_t dev, ino_t ino) { objItem *i = NULL; objItem test; - + test.dev = dev; test.ino = ino; @@ -133,13 +137,13 @@ static __u16 yaffs_CalcNameSum(const char *name) } -void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) +static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) { nand_calculate_ecc (data , spare->ecc1); nand_calculate_ecc (&data[256] , spare->ecc2); } -void yaffs_CalcTagsECC(yaffs_Tags *tags) +static void yaffs_CalcTagsECC(yaffs_Tags *tags) { // Todo don't do anything yet. Need to calculate ecc unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; @@ -147,7 +151,17 @@ 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,15 +176,23 @@ 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) { yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; - yaffs_CalcTagsECC(tagsPtr); + //yaffs_CalcTagsECC(tagsPtr); sparePtr->tagByte0 = tu->asBytes[0]; sparePtr->tagByte1 = tu->asBytes[1]; @@ -182,16 +204,45 @@ 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]; +} - -int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) +static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) { yaffs_Tags t; yaffs_Spare s; - + error = write(outFile,data,512); if(error < 0) return error; - + memset(&t,0xff,sizeof (yaffs_Tags)); memset(&s,0xff,sizeof (yaffs_Spare)); @@ -199,6 +250,11 @@ 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,7 +266,73 @@ int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) } -int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) +#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]; @@ -225,8 +347,6 @@ int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int paren strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); - // NCB added 10/9/2001 - oh->sum = yaffs_CalcNameSum(oh->name); if(t != YAFFS_OBJECT_TYPE_HARDLINK) { @@ -254,19 +374,24 @@ int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int paren { 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); } -int process_directory(int parent, const char *path) +static int process_directory(int parent, const char *path) { DIR *dir; struct dirent *entry; - nDirectories++; + nDirectories++; dir = opendir(path); @@ -319,9 +444,9 @@ int process_directory(int parent, const char *path) char symname[500]; - memset(symname,0,500); + memset(symname,0, sizeof(symname)); - readlink(full_name,symname,499); + readlink(full_name,symname,sizeof(symname) -1); printf("symlink to \"%s\"\n",symname); error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); @@ -411,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 ouput file to hold the image\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]); @@ -441,7 +572,8 @@ int main(int argc, char *argv[]) } printf("Processing directory %s into image file %s\n",argv[1],argv[2]); - + error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); + if(error) error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]); close(outFile);