Advertisement
Guest User

mkyaffs2image.c for nandwrite --raw

a guest
Oct 8th, 2010
1,445
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.83 KB | None | 0 0
  1. /*
  2.  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3.  *
  4.  * Copyright (C) 2002-2007 Aleph One Ltd.
  5.  *   for Toby Churchill Ltd and Brightstar Engineering
  6.  *
  7.  * Created by Charles Manning <charles@aleph1.co.uk>
  8.  * Nick Bane modifications flagged NCB
  9.  * Endian handling patches by James Ng.
  10.  * mkyaffs2image hacks by NCB
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License version 2 as
  14.  * published by the Free Software Foundation.
  15.  */
  16.  
  17. /*
  18.  * makeyaffs2image.c
  19.  *
  20.  * Makes a YAFFS2 file system image that can be used to load up a file system.
  21.  * Uses default Linux MTD layout - search for "NAND LAYOUT" to change.
  22.  */
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <fcntl.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <dirent.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include <errno.h>
  33. #include <assert.h>
  34. #include "yaffs_ecc.h"
  35. #include "yaffs_guts.h"
  36.  
  37. #include "yaffs_tagsvalidity.h"
  38. #include "yaffs_packedtags2.h"
  39.  
  40. unsigned yaffs_traceMask=0;
  41.  
  42. #define MAX_OBJECTS 10000
  43.  
  44. // Adjust these to match your NAND LAYOUT:
  45. #define chunkSize 2048
  46. #define spareSize 64
  47. #define pagesPerBlock 64
  48.  
  49. const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.5 2010-01-11 21:43:18 charles Exp $";
  50.  
  51.  
  52. typedef struct
  53. {
  54.     dev_t dev;
  55.     ino_t ino;
  56.     int   obj;
  57. } objItem;
  58.  
  59.  
  60. static objItem obj_list[MAX_OBJECTS];
  61. static int n_obj = 0;
  62. static int obj_id = YAFFS_NOBJECT_BUCKETS + 1;
  63.  
  64. static int nObjects, nDirectories, nPages;
  65.  
  66. static int outFile;
  67.  
  68. static int error;
  69. static int savedErrno;
  70.  
  71. static int convert_endian = 0;
  72.  
  73. static void fatal(const char *fn)
  74. {
  75.     perror(fn);
  76.     error |= 1;
  77.     exit(error);
  78. }
  79.  
  80. static int warn(const char *fn)
  81. {
  82.     savedErrno = errno;
  83.     perror(fn);
  84.     error |= 2;
  85.     return error;
  86. }
  87.  
  88. static int obj_compare(const void *a, const void * b)
  89. {
  90.   objItem *oa, *ob;
  91.  
  92.   oa = (objItem *)a;
  93.   ob = (objItem *)b;
  94.  
  95.   if(oa->dev < ob->dev) return -1;
  96.   if(oa->dev > ob->dev) return 1;
  97.   if(oa->ino < ob->ino) return -1;
  98.   if(oa->ino > ob->ino) return 1;
  99.  
  100.   return 0;
  101. }
  102.  
  103.  
  104. static void add_obj_to_list(dev_t dev, ino_t ino, int obj)
  105. {
  106.     if(n_obj < MAX_OBJECTS)
  107.     {
  108.         obj_list[n_obj].dev = dev;
  109.         obj_list[n_obj].ino = ino;
  110.         obj_list[n_obj].obj = obj;
  111.         n_obj++;
  112.         qsort(obj_list,n_obj,sizeof(objItem),obj_compare);
  113.        
  114.     }
  115.     else
  116.     {
  117.         // oops! not enough space in the object array
  118.         fprintf(stderr,"Not enough space in object array\n");
  119.         exit(1);
  120.     }
  121. }
  122.  
  123.  
  124. static int find_obj_in_list(dev_t dev, ino_t ino)
  125. {
  126.     objItem *i = NULL;
  127.     objItem test;
  128.  
  129.     test.dev = dev;
  130.     test.ino = ino;
  131.    
  132.     if(n_obj > 0)
  133.     {
  134.         i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare);
  135.     }
  136.  
  137.     if(i)
  138.     {
  139.         return i->obj;
  140.     }
  141.     return -1;
  142. }
  143.  
  144. /* This little function converts a little endian tag to a big endian tag.
  145.  * NOTE: The tag is not usable after this other than calculating the CRC
  146.  * with.
  147.  */
  148. static void little_to_big_endian(yaffs_Tags *tagsPtr)
  149. {
  150. #if 0 // FIXME NCB
  151.     yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes.
  152.     yaffs_TagsUnion   temp;
  153.  
  154.     memset(&temp, 0, sizeof(temp));
  155.     // Ick, I hate magic numbers.
  156.     temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4);
  157.     temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4);
  158.     temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6);
  159.     temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6);
  160.     temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2);
  161.     temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2);
  162.     temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F);
  163.     temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6);
  164.  
  165.     // Now copy it back.
  166.     tags->asBytes[0] = temp.asBytes[0];
  167.     tags->asBytes[1] = temp.asBytes[1];
  168.     tags->asBytes[2] = temp.asBytes[2];
  169.     tags->asBytes[3] = temp.asBytes[3];
  170.     tags->asBytes[4] = temp.asBytes[4];
  171.     tags->asBytes[5] = temp.asBytes[5];
  172.     tags->asBytes[6] = temp.asBytes[6];
  173.     tags->asBytes[7] = temp.asBytes[7];
  174. #endif
  175. }
  176.  
  177. static void shuffle_oob(char *spareData, yaffs_PackedTags2 *pt)
  178. {
  179.     int i;
  180.     char rawStuff[sizeof(pt->t)];
  181.     if (sizeof(rawStuff)!=16)
  182.     {
  183.         printf("Packedtags not 16 bytes, but %d bytes!\n",sizeof(rawStuff));
  184.         exit(1);
  185.     }
  186.     memcpy(rawStuff, &pt->t, sizeof(rawStuff));
  187.  
  188.     // NAND LAYOUT: For non-trivial OOB orderings, here would be a good place to shuffle.
  189.  
  190. /*  .oobfree =
  191.     {
  192.         {10, 4},
  193.         {26, 4},
  194.         {42, 4},
  195.         {58, 4},
  196.     }
  197. */
  198.  
  199.     memset(spareData,0xFF,spareSize);
  200.     memcpy(&spareData[10],&rawStuff[0],4);
  201.     memcpy(&spareData[26],&rawStuff[4],4);
  202.     memcpy(&spareData[42],&rawStuff[8],4);
  203.     memcpy(&spareData[58],&rawStuff[12],4);
  204. }
  205.  
  206. static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
  207. {
  208.     yaffs_ExtendedTags t;
  209.     yaffs_PackedTags2 pt;
  210.     char spareData[spareSize];
  211.  
  212.     if (write(outFile,data,chunkSize) != chunkSize)
  213.         fatal("write");
  214.  
  215.     yaffs_InitialiseTags(&t);
  216.    
  217.     t.chunkId = chunkId;
  218. //  t.serialNumber = 0;
  219.     t.serialNumber = 1; // **CHECK**
  220.     t.byteCount = nBytes;
  221.     t.objectId = objId;
  222.    
  223.     t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
  224.  
  225. // added NCB **CHECK**
  226.     t.chunkUsed = 1;
  227.  
  228.     if (convert_endian)
  229.     {
  230.             little_to_big_endian(&t);
  231.     }
  232.  
  233.     nPages++;
  234.  
  235.     memset(&pt, 0, sizeof(pt));
  236.     yaffs_PackTags2(&pt,&t,1);
  237.  
  238.     memset(spareData, 0xff, sizeof(spareData));
  239.     shuffle_oob(spareData, &pt);
  240.  
  241.     if (write(outFile,spareData,sizeof(spareData)) != sizeof(spareData))
  242.         fatal("write");
  243.     return 0;
  244. }
  245.  
  246. #define SWAP32(x)   ((((x) & 0x000000FF) << 24) | \
  247.                      (((x) & 0x0000FF00) << 8 ) | \
  248.                      (((x) & 0x00FF0000) >> 8 ) | \
  249.                      (((x) & 0xFF000000) >> 24))
  250.  
  251. #define SWAP16(x)   ((((x) & 0x00FF) << 8) | \
  252.                      (((x) & 0xFF00) >> 8))
  253.        
  254. // This one is easier, since the types are more standard. No funky shifts here.
  255. static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh)
  256. {
  257.     int i;    
  258.     oh->type = SWAP32(oh->type); // GCC makes enums 32 bits.
  259.     oh->parentObjectId = SWAP32(oh->parentObjectId); // int
  260.     oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness.
  261.     // name = skip. Char array. Not swapped.
  262.     oh->yst_mode = SWAP32(oh->yst_mode);
  263. #ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case.
  264.     // In fact, WinCE would be *THE* place where this would be an issue.
  265.     // Why? WINCE is little-endian only.
  266.  
  267.     {
  268.         int n = sizeof(oh->notForWinCE)/sizeof(oh->notForWinCE[0]);
  269.         for(i = 0; i < n; i++)
  270.             oh->notForWinCE[i] = SWAP32(oh->notForWinCE[i]);
  271.     }
  272. #else
  273.     // Regular POSIX.
  274.     oh->yst_uid = SWAP32(oh->yst_uid);
  275.     oh->yst_gid = SWAP32(oh->yst_gid);
  276.     oh->yst_atime = SWAP32(oh->yst_atime);
  277.     oh->yst_mtime = SWAP32(oh->yst_mtime);
  278.     oh->yst_ctime = SWAP32(oh->yst_ctime);
  279. #endif
  280.  
  281.     oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that!
  282.     oh->equivalentObjectId = SWAP32(oh->equivalentObjectId);
  283.     // alias  - char array.
  284.     oh->yst_rdev = SWAP32(oh->yst_rdev);
  285.  
  286. #ifdef CONFIG_YAFFS_WINCE
  287.     oh->win_ctime[0] = SWAP32(oh->win_ctime[0]);
  288.     oh->win_ctime[1] = SWAP32(oh->win_ctime[1]);
  289.     oh->win_atime[0] = SWAP32(oh->win_atime[0]);
  290.     oh->win_atime[1] = SWAP32(oh->win_atime[1]);
  291.     oh->win_mtime[0] = SWAP32(oh->win_mtime[0]);
  292.     oh->win_mtime[1] = SWAP32(oh->win_mtime[1]);
  293. #else
  294.  
  295.     {
  296.         int n = sizeof(oh->roomToGrow)/sizeof(oh->roomToGrow[0]);
  297.         for(i=0; i < n; i++)
  298.             oh->roomToGrow[i] = SWAP32(oh->roomToGrow[i]);
  299.     }
  300. #endif
  301. }
  302.  
  303. static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
  304. {
  305.     __u8 bytes[chunkSize];
  306.    
  307.    
  308.     yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes;
  309.    
  310.     memset(bytes,0xff,sizeof(bytes));
  311.    
  312.     oh->type = t;
  313.  
  314.     oh->parentObjectId = parent;
  315.    
  316.     if (strlen(name)+1 > sizeof(oh->name))
  317.     {
  318.         errno = ENAMETOOLONG;
  319.         return warn("object name");
  320.     }
  321.     memset(oh->name,0,sizeof(oh->name));
  322.     strcpy(oh->name,name);
  323.    
  324.    
  325.     if(t != YAFFS_OBJECT_TYPE_HARDLINK)
  326.     {
  327.         oh->yst_mode = s->st_mode;
  328.         oh->yst_uid = s->st_uid;
  329. // NCB 12/9/02      oh->yst_gid = s->yst_uid;
  330.         oh->yst_gid = s->st_gid;
  331.         oh->yst_atime = s->st_atime;
  332.         oh->yst_mtime = s->st_mtime;
  333.         oh->yst_ctime = s->st_ctime;
  334.         oh->yst_rdev  = s->st_rdev;
  335.     }
  336.    
  337.     if(t == YAFFS_OBJECT_TYPE_FILE)
  338.     {
  339.         oh->fileSize = s->st_size;
  340.     }
  341.    
  342.     if(t == YAFFS_OBJECT_TYPE_HARDLINK)
  343.     {
  344.         oh->equivalentObjectId = equivalentObj;
  345.     }
  346.    
  347.     if(t == YAFFS_OBJECT_TYPE_SYMLINK)
  348.     {
  349.         if (strlen(alias)+1 > sizeof(oh->alias))
  350.         {
  351.             errno = ENAMETOOLONG;
  352.             return warn("object alias");
  353.         }
  354.         memset(oh->alias,0,sizeof(oh->alias));
  355.         strcpy(oh->alias,alias);
  356.     }
  357.  
  358.     if (convert_endian)
  359.     {
  360.             object_header_little_to_big_endian(oh);
  361.     }
  362.    
  363.     return write_chunk(bytes,objId,0,0xffff);
  364.    
  365. }
  366.  
  367. static void pad_image()
  368. {
  369.     __u8 data[chunkSize + spareSize];
  370.     int padPages = (nPages % pagesPerBlock);
  371.  
  372.     if (padPages)
  373.     {
  374.         memset(data, 0xff, sizeof(data));
  375.         for (padPages = pagesPerBlock-padPages; padPages; padPages--)
  376.         {
  377.             if (write(outFile, data, sizeof(data)) != sizeof(data))
  378.                 fatal("write");
  379.         }
  380.     }
  381. }
  382.  
  383. static int process_directory(int parent, const char *path)
  384. {
  385.  
  386.     DIR *dir;
  387.     struct dirent *entry;
  388.  
  389.     nDirectories++;
  390.    
  391.     dir = opendir(path);
  392.     if(!dir)
  393.     {
  394.         warn("opendir");
  395.     }
  396.     else
  397.     {
  398.         while((entry = readdir(dir)) != NULL)
  399.         {
  400.        
  401.             /* Ignore . and .. */
  402.             if(strcmp(entry->d_name,".") &&
  403.                strcmp(entry->d_name,".."))
  404.             {
  405.                 char full_name[500];
  406.                 struct stat stats;
  407.                 int equivalentObj;
  408.                 int newObj;
  409.                
  410.                 if (snprintf(full_name,sizeof(full_name),"%s/%s",path,entry->d_name) >= (int)sizeof(full_name))
  411.                 {
  412.                     error = -1;
  413.                     continue;
  414.                 }
  415.                
  416.                 if (lstat(full_name,&stats) < 0)
  417.                 {
  418.                     warn("lstat");
  419.                     continue;
  420.                 }
  421.                
  422.                 if(S_ISLNK(stats.st_mode) ||
  423.                     S_ISREG(stats.st_mode) ||
  424.                     S_ISDIR(stats.st_mode) ||
  425.                     S_ISFIFO(stats.st_mode) ||
  426.                     S_ISBLK(stats.st_mode) ||
  427.                     S_ISCHR(stats.st_mode) ||
  428.                     S_ISSOCK(stats.st_mode))
  429.                 {
  430.                
  431.                     newObj = obj_id++;
  432.                     nObjects++;
  433.                    
  434.                     printf("Object %d, %s is a ",newObj,full_name);
  435.                    
  436.                     /* We're going to create an object for it */
  437.                     if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
  438.                     {
  439.                         /* we need to make a hard link */
  440.                         printf("hard link to object %d\n",equivalentObj);
  441.                         write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL);
  442.                     }
  443.                     else
  444.                     {
  445.                        
  446.                         add_obj_to_list(stats.st_dev,stats.st_ino,newObj);
  447.                        
  448.                         if(S_ISLNK(stats.st_mode))
  449.                         {
  450.                    
  451.                             char symname[500];
  452.                        
  453.                             memset(symname,0, sizeof(symname));
  454.                    
  455.                             if (readlink(full_name,symname,sizeof(symname) -1) < 0)
  456.                             {
  457.                                 warn("readlink");
  458.                             }
  459.                             else
  460.                             {
  461.                                 printf("symlink to \"%s\"\n",symname);
  462.                                 write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname);
  463.                             }
  464.                         }
  465.                         else if(S_ISREG(stats.st_mode))
  466.                         {
  467.                             printf("file, ");
  468.                             if(write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL) == 0)
  469.                             {
  470.                                 int h;
  471.                                 __u8 bytes[chunkSize];
  472.                                 int nBytes;
  473.                                 int chunk = 0;
  474.                                
  475.                                 h = open(full_name,O_RDONLY);
  476.                                 if(h >= 0)
  477.                                 {
  478.                                     memset(bytes,0xff,sizeof(bytes));
  479.                                     while((nBytes = read(h,bytes,sizeof(bytes))) > 0)
  480.                                     {
  481.                                         chunk++;
  482.                                         write_chunk(bytes,newObj,chunk,nBytes);
  483.                                         memset(bytes,0xff,sizeof(bytes));
  484.                                     }
  485.                                     if(nBytes < 0)
  486.                                        warn("read");
  487.                                        
  488.                                     printf("%d data chunks written\n",chunk);
  489.                                     close(h);
  490.                                 }
  491.                                 else
  492.                                 {
  493.                                     warn("open");
  494.                                 }
  495.                                
  496.                             }                          
  497.                                                        
  498.                         }
  499.                         else if(S_ISSOCK(stats.st_mode))
  500.                         {
  501.                             printf("socket\n");
  502.                             write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
  503.                         }
  504.                         else if(S_ISFIFO(stats.st_mode))
  505.                         {
  506.                             printf("fifo\n");
  507.                             write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
  508.                         }
  509.                         else if(S_ISCHR(stats.st_mode))
  510.                         {
  511.                             printf("character device\n");
  512.                             write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
  513.                         }
  514.                         else if(S_ISBLK(stats.st_mode))
  515.                         {
  516.                             printf("block device\n");
  517.                             write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
  518.                         }
  519.                         else if(S_ISDIR(stats.st_mode))
  520.                         {
  521.                             printf("directory\n");
  522.                             if (write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL) == 0)
  523.                                 process_directory(newObj,full_name);
  524.                         }
  525.                     }
  526.                 }
  527.                 else
  528.                 {
  529.                     fprintf(stderr, "%s: unhandled type\n", full_name);
  530.                     error |= 2;
  531.                     savedErrno = EINVAL;
  532.                 }
  533.             }
  534.         }
  535.         closedir(dir);
  536.     }
  537.    
  538.     return 0;
  539.  
  540. }
  541.  
  542.  
  543. int main(int argc, char *argv[])
  544. {
  545.     struct stat stats;
  546.    
  547.     printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n");
  548.    
  549.     if(argc < 3)
  550.     {
  551.         printf("usage: mkyaffs2image dir image_file [convert]\n");
  552.         printf("           dir        the directory tree to be converted\n");
  553.         printf("           image_file the output file to hold the image\n");
  554.         printf("           'convert'  produce a big-endian image from a little-endian machine\n");
  555.         exit(1);
  556.     }
  557.  
  558.     if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
  559.     {
  560.         convert_endian = 1;
  561.     }
  562.    
  563.     if(stat(argv[1],&stats) < 0)
  564.     {
  565.         printf("Could not stat %s\n",argv[1]);
  566.         exit(1);
  567.     }
  568.    
  569.     if(!S_ISDIR(stats.st_mode))
  570.     {
  571.         printf(" %s is not a directory\n",argv[1]);
  572.         exit(1);
  573.     }
  574.    
  575.     outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
  576.    
  577.    
  578.     if(outFile < 0)
  579.     {
  580.         printf("Could not open output file %s\n",argv[2]);
  581.         exit(1);
  582.     }
  583.    
  584.     printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
  585.     process_directory(YAFFS_OBJECTID_ROOT,argv[1]);
  586.    
  587.     //pad_image();
  588.  
  589.     close(outFile);
  590.    
  591.     if(error)
  592.     {
  593.         errno = savedErrno;
  594.         perror("operation incomplete");
  595.     }
  596.     else
  597.     {
  598.         printf("Operation complete.\n"
  599.                "%d objects in %d directories\n"
  600.                "%d NAND pages\n",nObjects, nDirectories, nPages);
  601.     }
  602.    
  603.     exit(error);
  604. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement