uflashfs.c 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086
  1. /*
  2. * Copyright (C) 2010 by egnite GmbH
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. #include <fs/fs.h>
  35. #include <sys/nutdebug.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <fcntl.h>
  39. #include <sys/stat.h>
  40. #include <string.h>
  41. #include <errno.h>
  42. #include <dirent.h>
  43. #include <dev/spi_at45dib.h>
  44. #include <fs/uflashfs.h>
  45. #if 0
  46. /* Use for local debugging. */
  47. #define NUTDEBUG
  48. #include <stdio.h>
  49. #endif
  50. /*!
  51. * \file fs/uflashfs.c
  52. * \brief UFLASH File System.
  53. *
  54. * The UFLASH file system has been specifically designed for serial
  55. * flash memory chips used on tiny embedded systems.
  56. *
  57. * Such memory chips do not allow to program single bytes. Instead,
  58. * only full pages can be programmed. On the other hand, these chips
  59. * provide one or two integrated RAM buffers. They allow to modify
  60. * single bytes without transfering full pages between the memory
  61. * chip and the microcontroller's RAM.
  62. *
  63. * Although no mechanism has been implemented to replace worn out pages,
  64. * the file system maintains a very well balanced wear levelling. This
  65. * includes regular movement of static files.
  66. *
  67. * Furthermore, previously unfinished write accesses are automatically
  68. * detected and reverted when mounting a volume. However, this features
  69. * still needs to be tested more thoroughly.
  70. *
  71. * Note, that directories do not really exist in the UFLASH file system.
  72. * They are mimicked in a limited way. When scanning a directory, all
  73. * subdirectories will appear again for each file they contain.
  74. *
  75. * \verbatim
  76. * $Id$
  77. * \endverbatim
  78. */
  79. /*!
  80. * \addtogroup xgUFlash
  81. */
  82. /*@{*/
  83. /* Wheter to use time stamps. Requires, that the system time had been set. */
  84. //#define UFLASH_USE_TIMESTAMP
  85. /* Wheter to use IDs instead of file names. Not implemented. */
  86. //#define UFLASH_ID_NAMES
  87. /*
  88. * File system configuration.
  89. */
  90. #ifndef UFLASH_MAX_BLOCKS
  91. /*! \brief Max. number of blocks per file system. */
  92. #define UFLASH_MAX_BLOCKS 8192
  93. #endif
  94. #ifndef UFLASH_BLOCK_UNITS
  95. /*! \brief Number of units per block. */
  96. #define UFLASH_BLOCK_UNITS 4
  97. #endif
  98. #ifndef UFLASH_ENTRIES
  99. /*! \brief Number of file system entries. */
  100. #define UFLASH_ENTRIES 128
  101. #endif
  102. #ifndef UFLASH_USAGE_CACHE
  103. /*! \brief Size of the least used buffer. */
  104. #define UFLASH_USAGE_CACHE 32
  105. #endif
  106. #if UFLASH_MAX_BLOCKS <= 255
  107. typedef uint8_t blknum_t;
  108. typedef uint_fast8_t blknum_fast_t;
  109. #elif UFLASH_MAX_BLOCKS <= 65535
  110. typedef uint16_t blknum_t;
  111. typedef uint_fast16_t blknum_fast_t;
  112. #else
  113. typedef uint32_t blknum_t;
  114. typedef uint_fast32_t blknum_fast_t;
  115. #endif
  116. #ifndef UFLASH_MAX_PATH
  117. /*! \brief Maximum lenght of a full absolute path.
  118. *
  119. * If not defined, a variable path name length is used. Note, that
  120. * the total size of the name is still limited, because the block
  121. * header and the entry header must fit into the first unit of the
  122. * file system block.
  123. */
  124. #define UFLASH_MAX_PATH 0
  125. #endif
  126. #define UFLASH_BLOCK_INVALID ((blknum_t)-1)
  127. /*!
  128. * \brief Internal block usage cache structure.
  129. */
  130. typedef struct _BLOCK_USAGE {
  131. uint8_t use_cnt;
  132. blknum_t use_phyblk;
  133. } BLOCK_USAGE;
  134. /*!
  135. * \brief Internal block usage cache.
  136. */
  137. static BLOCK_USAGE min_used[UFLASH_USAGE_CACHE];
  138. /*!
  139. * \brief UFLASH block header.
  140. *
  141. * Each used block starts with a BLOCKHEAD structure.
  142. */
  143. typedef struct NUT_PACKED_TYPE _BLOCKHEAD {
  144. blknum_t bh_logblk; /*!< \brief Logical block number. */
  145. blknum_t bh_version; /*!< \brief Logical block version. */
  146. blknum_t bh_entblk; /*!< \brief Logical entry block number. */
  147. blknum_t bh_entseq; /*!< \brief Block sequence. */
  148. } BLOCKHEAD;
  149. /*!
  150. * \brief UFLASH block footer.
  151. *
  152. * Each block ends with a BLOCKFOOT structure.
  153. */
  154. typedef struct NUT_PACKED_TYPE _BLOCKFOOT {
  155. #ifdef UFLASH_USE_TIMESTAMP
  156. time_t bf_time; /*!< \brief Last update time. */
  157. #endif
  158. uint8_t bf_wear; /*!< \brief Erase counter. */
  159. } BLOCKFOOT;
  160. /*
  161. * UFLASH entry header.
  162. *
  163. * On each entry block an ENTRYHEAD structure follows the BLOCKHEAD.
  164. * The ENTRYHEAD is followed by the variable length name of this entry.
  165. * After the name comes the data, immediatly followed by an optional
  166. * timestamp.
  167. */
  168. typedef struct NUT_PACKED_TYPE _ENTRYHEAD {
  169. /* Entry attributes. */
  170. uint8_t eh_attr;
  171. /* Name length. */
  172. uint8_t eh_nlen;
  173. } ENTRYHEAD;
  174. /*!
  175. * \brief File system entry descriptor.
  176. */
  177. typedef struct _UFLASHENTRY {
  178. /*! \brief Logical block number of the entry. */
  179. blknum_t ent_id;
  180. /*! \brief Current data pointer position. */
  181. uint32_t ent_pos;
  182. /*! \brief Current logical block number. */
  183. blknum_t ent_bidx;
  184. /*! \brief Current sequence. */
  185. uint16_t ent_sidx;
  186. /*! \brief Current unit index within the current block. */
  187. uint16_t ent_uidx;
  188. /*! \brief Current position within the current unit. */
  189. uint16_t ent_upos;
  190. /*! \brief File open mode flags. */
  191. uint32_t ent_mode;
  192. /*! \brief Entry attributes. */
  193. uint8_t ent_attr;
  194. /*! \brief Name length. */
  195. uint8_t ent_namlen;
  196. /*! \brief Total data size. */
  197. uint32_t ent_size;
  198. /*! \brief Total file data offset of the entry block. */
  199. uint16_t ent_eoff;
  200. } UFLASHENTRY;
  201. #define UFLASH_VOLF_FIXED 0x80
  202. /*! \brief Volume info structure type. */
  203. typedef struct _UFLASHVOLUME UFLASHVOLUME;
  204. /*!
  205. * \brief Volume info structure.
  206. */
  207. struct _UFLASHVOLUME {
  208. /*! \brief I/O interface. */
  209. NUTSERIALFLASH *vol_ifc;
  210. /*! \brief Exclusive access queue. */
  211. HANDLE vol_mutex;
  212. /*! \brief Attribute flags. */
  213. uint8_t vol_attrib;
  214. /*! \brief Number of blocks in this volume. */
  215. blknum_t vol_blocks;
  216. /*! \brief Block translation table. */
  217. blknum_t *vol_l2p;
  218. };
  219. /*!
  220. * \brief Entry search structure.
  221. */
  222. typedef struct _UFLASHFIND {
  223. blknum_t uff_lbe;
  224. char *uff_path;
  225. } UFLASHFIND;
  226. /*!
  227. * \brief Copy a given unit from one block to another.
  228. */
  229. static int FlashUnitCopy(NUTSERIALFLASH * ifc, blknum_t b_src, blknum_t b_dst, sf_unit_t unit)
  230. {
  231. unit += ifc->sf_rsvbot;
  232. return (*ifc->sf_copy) (ifc, b_src * UFLASH_BLOCK_UNITS + unit, b_dst * UFLASH_BLOCK_UNITS + unit);
  233. }
  234. /*!
  235. * \brief Commit changes of a given unit.
  236. */
  237. static void FlashUnitCommit(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit)
  238. {
  239. (*ifc->sf_commit) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot);
  240. }
  241. /*!
  242. * \brief Read unit.
  243. */
  244. static int FlashUnitRead(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit, int upos, void *data, int len)
  245. {
  246. int rc = ifc->sf_unit_size - upos;
  247. if (unit == UFLASH_BLOCK_UNITS - 1) {
  248. rc -= sizeof(BLOCKFOOT);
  249. }
  250. if (rc > len) {
  251. rc = len;
  252. }
  253. (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot, upos, data, rc);
  254. return rc;
  255. }
  256. /*!
  257. * \brief Write unit.
  258. */
  259. static int FlashUnitWrite(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit, int upos, const void *data, int len)
  260. {
  261. int rc = ifc->sf_unit_size - upos;
  262. if (unit == UFLASH_BLOCK_UNITS - 1) {
  263. rc -= sizeof(BLOCKFOOT);
  264. }
  265. if (rc > len) {
  266. rc = len;
  267. }
  268. (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot, upos, data, rc);
  269. return rc;
  270. }
  271. /*!
  272. * \brief Verify CRC of a given block.
  273. */
  274. static int FlashCheckBlock(NUTSERIALFLASH * ifc, blknum_t b)
  275. {
  276. return (*ifc->sf_check) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, UFLASH_BLOCK_UNITS);
  277. }
  278. /*!
  279. * \brief Read header of a given block.
  280. */
  281. static int FlashReadBlockHead(NUTSERIALFLASH * ifc, blknum_t b, BLOCKHEAD * bh)
  282. {
  283. return (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 0, bh, sizeof(BLOCKHEAD));
  284. }
  285. /*!
  286. * \brief Write header of a given block.
  287. */
  288. static int FlashWriteBlockHead(NUTSERIALFLASH * ifc, blknum_t b, BLOCKHEAD * bh)
  289. {
  290. /* Update the block's version number. */
  291. bh->bh_version++;
  292. return (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 0, bh, sizeof(BLOCKHEAD));
  293. }
  294. /*!
  295. * \brief Read entry of a given block.
  296. */
  297. static int FlashReadEntry(NUTSERIALFLASH * ifc, blknum_t b, ENTRYHEAD * eh, char **name)
  298. {
  299. int rc;
  300. /* Read the entry header, which contains the name length. */
  301. rc = (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD), eh, sizeof(ENTRYHEAD));
  302. if (rc == 0 && name) {
  303. *name = malloc(eh->eh_nlen + 1);
  304. if (*name == NULL) {
  305. rc = -1;
  306. } else {
  307. *(*name + eh->eh_nlen) = '\0';
  308. rc = (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), *name,
  309. eh->eh_nlen);
  310. }
  311. }
  312. return rc;
  313. }
  314. /*!
  315. * \brief Compare entry name of a given block.
  316. */
  317. static int FlashBlockCmpEntryName(NUTSERIALFLASH * ifc, blknum_t b, const char *name, uint8_t len)
  318. {
  319. return (*ifc->sf_compare) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), name, len);
  320. }
  321. /*!
  322. * \brief Write entry of a given block.
  323. */
  324. static int FlashWriteEntry(NUTSERIALFLASH * ifc, blknum_t b, const ENTRYHEAD * eh, const char *name)
  325. {
  326. int rc;
  327. rc = (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD), eh, sizeof(ENTRYHEAD));
  328. if (rc == 0) {
  329. rc = (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), name,
  330. eh->eh_nlen);
  331. }
  332. return rc;
  333. }
  334. /*!
  335. * \brief Read footer of a given block.
  336. */
  337. static int FlashReadBlockFoot(NUTSERIALFLASH * ifc, blknum_t b, BLOCKFOOT * bf)
  338. {
  339. return (*ifc->sf_read) (ifc, (b + 1) * UFLASH_BLOCK_UNITS - 1 + ifc->sf_rsvbot, -(int) sizeof(BLOCKFOOT), bf,
  340. sizeof(BLOCKFOOT));
  341. }
  342. /*!
  343. * \brief Write footer of a given block.
  344. */
  345. static int FlashWriteBlockFoot(NUTSERIALFLASH * ifc, blknum_t b, BLOCKFOOT * bf)
  346. {
  347. bf->bf_wear++;
  348. #ifdef UFLASH_USE_TIMESTAMP
  349. bf->bf_time = time(NULL);
  350. #endif
  351. return (*ifc->sf_write) (ifc, (b + 1) * UFLASH_BLOCK_UNITS - 1 + ifc->sf_rsvbot, -(int) sizeof(BLOCKFOOT), bf,
  352. sizeof(BLOCKFOOT));
  353. }
  354. /*!
  355. * \brief Erase first unit of a given block.
  356. */
  357. static int FlashEraseEntry(NUTSERIALFLASH * ifc, blknum_t b)
  358. {
  359. return (*ifc->sf_erase) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 1);
  360. }
  361. /*!
  362. * \brief Erase data units of a given block.
  363. */
  364. static int FlashEraseBlockData(NUTSERIALFLASH * ifc, blknum_t b)
  365. {
  366. return (*ifc->sf_erase) (ifc, b * UFLASH_BLOCK_UNITS + 1 + ifc->sf_rsvbot, UFLASH_BLOCK_UNITS - 1);
  367. }
  368. /*!
  369. * \brief Erase a given number of blocks.
  370. */
  371. static int FlashEraseBlocks(NUTSERIALFLASH * ifc, int n)
  372. {
  373. return (*ifc->sf_erase) (ifc, ifc->sf_rsvbot, n * UFLASH_BLOCK_UNITS);
  374. }
  375. /*!
  376. * \brief Collect least used blocks.
  377. *
  378. * \param vol Pointer to the information structure of a mounted volume.
  379. *
  380. * TODO: We may optionally exclude static files from recycling.
  381. */
  382. static void CollectLeastUsed(UFLASHVOLUME * vol, uint8_t * usage)
  383. {
  384. uint8_t rmin;
  385. uint8_t rmax;
  386. blknum_t b;
  387. /* Determine the range of values. */
  388. rmin = usage[0];
  389. rmax = rmin;
  390. for (b = 1; b < vol->vol_blocks; b++) {
  391. if (usage[b] < rmin) {
  392. rmin = usage[b];
  393. if (rmax - rmin >= 128) {
  394. break;
  395. }
  396. } else if (usage[b] > rmax) {
  397. rmax = usage[b];
  398. if (rmax - rmin >= 128) {
  399. break;
  400. }
  401. }
  402. }
  403. /*
  404. ** If the range of values is equal or greater than half of the full
  405. ** range, then some values overflowed. In this case we shift all
  406. ** values by half of the full range to get a consecutive sequence.
  407. */
  408. if (b < vol->vol_blocks) {
  409. rmax = 0;
  410. for (b = 0; b < vol->vol_blocks; b++) {
  411. usage[b] += 128;
  412. if (usage[b] > rmax) {
  413. rmax = usage[b];
  414. }
  415. }
  416. }
  417. /*
  418. ** Collect a sorted table of minimums.
  419. */
  420. memset(min_used, 0xff, sizeof(min_used));
  421. for (b = 0; b < vol->vol_blocks; b++) {
  422. int j = UFLASH_USAGE_CACHE - 1;
  423. if (min_used[j].use_phyblk > vol->vol_blocks || min_used[j].use_cnt > usage[b]) {
  424. while (--j >= 0) {
  425. if (usage[b] >= min_used[j].use_cnt && min_used[j].use_phyblk < vol->vol_blocks) {
  426. break;
  427. }
  428. min_used[j + 1] = min_used[j];
  429. }
  430. min_used[j + 1].use_cnt = usage[b];
  431. min_used[j + 1].use_phyblk = b;
  432. }
  433. }
  434. }
  435. static blknum_t PhysBlkAllocate(UFLASHVOLUME * vol, int level);
  436. /*!
  437. * \brief Move a physical block.
  438. *
  439. * \param vol Pointer to the information structure of a mounted volume.
  440. * \param src Physical source block number. On return, this block will
  441. * be available again.
  442. * \param dst Physical destination block number.
  443. */
  444. static int PhysBlkMove(UFLASHVOLUME * vol, blknum_t src, blknum_t dst)
  445. {
  446. int rc = 0;
  447. BLOCKHEAD bh;
  448. BLOCKFOOT bf;
  449. uint_fast8_t u;
  450. /* Read the header of the source block. */
  451. FlashReadBlockHead(vol->vol_ifc, src, &bh);
  452. /* Read the footer of the destination block. */
  453. FlashReadBlockFoot(vol->vol_ifc, dst, &bf);
  454. /* Erase the tail of the destination. */
  455. FlashEraseBlockData(vol->vol_ifc, dst);
  456. /* Copy unit by unit. */
  457. for (u = 0; rc == 0 && u < UFLASH_BLOCK_UNITS; u++) {
  458. FlashUnitCopy(vol->vol_ifc, src, dst, u);
  459. /* If this is the first unit, write a new version of the header. */
  460. if (u == 0) {
  461. FlashWriteBlockHead(vol->vol_ifc, dst, &bh);
  462. }
  463. /* If this is the last unit, write back an updated footer. */
  464. else if (u == UFLASH_BLOCK_UNITS - 1) {
  465. FlashWriteBlockFoot(vol->vol_ifc, dst, &bf);
  466. }
  467. /* Commit the unit. */
  468. FlashUnitCommit(vol->vol_ifc, dst, u);
  469. }
  470. /* If all done, erase the first unit of the source block. This will
  471. ** make the block available again. */
  472. FlashEraseEntry(vol->vol_ifc, src);
  473. return 0;
  474. }
  475. /*!
  476. * \brief Get the first unused block.
  477. *
  478. * \param vol Pointer to the information structure of a mounted volume.
  479. */
  480. static blknum_t PhysBlkUnused(UFLASHVOLUME * vol)
  481. {
  482. BLOCKHEAD bh;
  483. blknum_t b;
  484. for (b = 0; b < vol->vol_blocks; b++) {
  485. FlashReadBlockHead(vol->vol_ifc, b, &bh);
  486. if (bh.bh_logblk >= vol->vol_blocks) {
  487. break;
  488. }
  489. }
  490. return b;
  491. }
  492. /*!
  493. * \brief Reallocate an unused physical block.
  494. *
  495. * \param vol Pointer to the information structure of a mounted volume.
  496. */
  497. static int PhysBlkRequest(UFLASHVOLUME * vol, int level, blknum_t n)
  498. {
  499. blknum_t b;
  500. /* Check if this block is in use. */
  501. for (b = 0; b < vol->vol_blocks; b++) {
  502. if (vol->vol_l2p[b] == n) {
  503. blknum_t nn;
  504. nn = PhysBlkAllocate(vol, level + 1);
  505. if (nn >= vol->vol_blocks) {
  506. return -1;
  507. }
  508. vol->vol_l2p[b] = nn;
  509. PhysBlkMove(vol, n, nn);
  510. break;
  511. }
  512. }
  513. return 0;
  514. }
  515. /*!
  516. * \brief Allocate an unused physical block.
  517. *
  518. * \param vol Pointer to the information structure of a mounted volume.
  519. */
  520. static blknum_t PhysBlkAllocate(UFLASHVOLUME * vol, int level)
  521. {
  522. uint8_t *phy_use;
  523. int i;
  524. for (;;) {
  525. if (level || min_used[UFLASH_USAGE_CACHE - (UFLASH_USAGE_CACHE / 4)].use_phyblk < vol->vol_blocks) {
  526. for (i = 0; i < UFLASH_USAGE_CACHE; i++) {
  527. blknum_t n = min_used[i].use_phyblk;
  528. if (n < vol->vol_blocks) {
  529. min_used[i].use_phyblk = UFLASH_BLOCK_INVALID;
  530. if (PhysBlkRequest(vol, level, n)) {
  531. return UFLASH_BLOCK_INVALID;
  532. }
  533. return n;
  534. }
  535. }
  536. }
  537. /* Cache exhausted. */
  538. phy_use = calloc(vol->vol_blocks, 1);
  539. if (phy_use == NULL) {
  540. break;
  541. }
  542. for (i = 0; i < vol->vol_blocks; i++) {
  543. BLOCKFOOT bf;
  544. FlashReadBlockFoot(vol->vol_ifc, i, &bf);
  545. phy_use[i] = bf.bf_wear;
  546. }
  547. for (i = 0; i < vol->vol_blocks; i++) {
  548. if (vol->vol_l2p[i] < vol->vol_blocks) {
  549. phy_use[vol->vol_l2p[i]] += UFLASH_USAGE_CACHE - 1;
  550. }
  551. }
  552. CollectLeastUsed(vol, phy_use);
  553. free(phy_use);
  554. if (level) {
  555. break;
  556. }
  557. }
  558. return PhysBlkUnused(vol);
  559. }
  560. /*!
  561. * \brief Allocate a new logical block.
  562. *
  563. * \param vol Pointer to the information structure of a mounted volume.
  564. */
  565. static blknum_t LogBlkAllocate(UFLASHVOLUME * vol, blknum_t lb)
  566. {
  567. int lb_last = lb ? vol->vol_blocks : UFLASH_ENTRIES;
  568. /* Find an unused logical block. */
  569. for (; lb < lb_last; lb++) {
  570. if (vol->vol_l2p[lb] >= vol->vol_blocks) {
  571. /* Found, assign a physical block. */
  572. vol->vol_l2p[lb] = PhysBlkAllocate(vol, 0);
  573. break;
  574. }
  575. }
  576. return lb;
  577. }
  578. /*!
  579. * \brief Reallocate a logical block.
  580. *
  581. * \param vol Pointer to the information structure of a mounted volume.
  582. */
  583. static blknum_t LogBlkReallocate(UFLASHVOLUME * vol, blknum_t lb)
  584. {
  585. blknum_t b_old;
  586. blknum_t b_new;
  587. /* Allocate a new physical block. Note, that the currently assigned
  588. ** physical block may move during this allocation. */
  589. b_new = PhysBlkAllocate(vol, 0);
  590. if (b_new >= vol->vol_blocks) {
  591. b_old = b_new;
  592. } else {
  593. b_old = vol->vol_l2p[lb];
  594. vol->vol_l2p[lb] = b_new;
  595. }
  596. return b_old;
  597. }
  598. /*!
  599. * \brief Find existing data block by sequence.
  600. *
  601. * \param vol Pointer to the information structure of a mounted volume.
  602. */
  603. static int LogBlkRelease(UFLASHVOLUME * vol, blknum_t lb)
  604. {
  605. blknum_t b;
  606. b = vol->vol_l2p[lb];
  607. vol->vol_l2p[lb] = UFLASH_BLOCK_INVALID;
  608. return FlashEraseEntry(vol->vol_ifc, b);
  609. }
  610. /*!
  611. * \brief Find existing data block by sequence.
  612. *
  613. * \param vol Pointer to the information structure of a mounted volume.
  614. * \param lbe Logical block of the entry.
  615. * \param seq Sequence number to search.
  616. *
  617. * \return Logical block number of the requested data block. If this is
  618. * equal to the number of blocks available, then the sequence
  619. * doesn't exist.
  620. */
  621. static blknum_t EntrySeek(UFLASHVOLUME * vol, blknum_t lbe, blknum_t seq)
  622. {
  623. blknum_t lb = lbe;
  624. /* Data block sequence 0 is the same as the entry block. No need to
  625. ** search for it. */
  626. if (seq) {
  627. /* Walking through the translation table requires exclusive access. */
  628. NutEventWait(&vol->vol_mutex, 0);
  629. /* No need to search the entry blocks. */
  630. for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
  631. blknum_t b = vol->vol_l2p[lb];
  632. /* If this block is allocated, read its header. */
  633. if (b < vol->vol_blocks) {
  634. BLOCKHEAD bh;
  635. FlashReadBlockHead(vol->vol_ifc, b, &bh);
  636. if (bh.bh_entblk == lbe && bh.bh_entseq == seq) {
  637. /* Block found. */
  638. break;
  639. }
  640. }
  641. }
  642. /* Release the exclusive access. */
  643. NutEventPost(&vol->vol_mutex);
  644. }
  645. return lb;
  646. }
  647. /*!
  648. * \brief Update the position indices.
  649. */
  650. static void EntryPosSet(NUTFILE * nfp, long pos)
  651. {
  652. uint16_t seq;
  653. uint32_t off;
  654. UFLASHENTRY *ent;
  655. UFLASHVOLUME *vol;
  656. ent = (UFLASHENTRY *) nfp->nf_fcb;
  657. vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
  658. /* Current position within this entry. */
  659. ent->ent_pos = pos;
  660. off = ent->ent_eoff + ent->ent_pos;
  661. /* Current block sequence within this entry. */
  662. seq = (uint16_t) (off / (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT))));
  663. if (seq != ent->ent_sidx) {
  664. ent->ent_sidx = seq;
  665. ent->ent_bidx = UFLASH_BLOCK_INVALID;
  666. }
  667. off -= ent->ent_sidx * (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT)));
  668. /* Page number within the current block. */
  669. ent->ent_uidx = (uint16_t) ((off + sizeof(BLOCKHEAD)) / vol->vol_ifc->sf_unit_size);
  670. off -= ent->ent_uidx * vol->vol_ifc->sf_unit_size;
  671. /* Position with the current page. */
  672. ent->ent_upos = (uint16_t) off + sizeof(BLOCKHEAD);
  673. }
  674. static void EntryPosInc(NUTFILE * nfp, int step)
  675. {
  676. UFLASHENTRY *ent;
  677. UFLASHVOLUME *vol;
  678. ent = (UFLASHENTRY *) nfp->nf_fcb;
  679. vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
  680. ent->ent_pos += step;
  681. ent->ent_upos += step;
  682. if (ent->ent_uidx < UFLASH_BLOCK_UNITS - 1) {
  683. step = vol->vol_ifc->sf_unit_size - ent->ent_upos;
  684. } else {
  685. step = vol->vol_ifc->sf_unit_size - sizeof(BLOCKFOOT) - ent->ent_upos;
  686. }
  687. if (step == 0) {
  688. ent->ent_uidx++;
  689. if (ent->ent_uidx >= UFLASH_BLOCK_UNITS) {
  690. ent->ent_upos = sizeof(BLOCKHEAD);
  691. ent->ent_uidx = 0;
  692. ent->ent_sidx++;
  693. ent->ent_bidx = UFLASH_BLOCK_INVALID;
  694. } else {
  695. ent->ent_upos = 0;
  696. }
  697. }
  698. }
  699. /*!
  700. * \brief Scan for all blocks associated to a given entry.
  701. *
  702. * \param vol Pointer to the information structure of a mounted volume.
  703. */
  704. static long EntryScan(UFLASHVOLUME * vol, blknum_t lbe, time_t * mod)
  705. {
  706. long siz;
  707. int p;
  708. int i;
  709. int off;
  710. BLOCKHEAD bh;
  711. blknum_t lb;
  712. blknum_t lbs = lbe;
  713. blknum_t seq = 0;
  714. #ifdef UFLASH_USE_TIMESTAMP
  715. if (mod) {
  716. BLOCKFOOT bf;
  717. FlashReadBlockFoot(vol->vol_ifc, vol->vol_l2p[lbe] / UFLASH_BLOCK_UNITS, &bf);
  718. *mod = bf.bf_time;
  719. }
  720. #endif
  721. /* Find the highest sequence block. */
  722. for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
  723. p = vol->vol_l2p[lb];
  724. if (p < vol->vol_blocks) {
  725. p *= UFLASH_BLOCK_UNITS;
  726. FlashReadBlockHead(vol->vol_ifc, p / UFLASH_BLOCK_UNITS, &bh);
  727. if (bh.bh_entblk == lbe) {
  728. if (seq < bh.bh_entseq) {
  729. seq = bh.bh_entseq;
  730. lbs = lb;
  731. }
  732. #ifdef UFLASH_USE_TIMESTAMP
  733. if (mod) {
  734. BLOCKFOOT bf;
  735. FlashReadBlockFoot(vol->vol_ifc, p / UFLASH_BLOCK_UNITS, &bf);
  736. if (*mod < bf.bf_time) {
  737. *mod = bf.bf_time;
  738. }
  739. }
  740. #endif
  741. }
  742. }
  743. }
  744. /* Size of full blocks. */
  745. siz = seq * (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT)));
  746. /* Number of bytes in the highest sequence block. */
  747. p = vol->vol_l2p[lbs] * UFLASH_BLOCK_UNITS;
  748. off = -(int) sizeof(BLOCKFOOT);
  749. for (i = UFLASH_BLOCK_UNITS; --i >= 0;) {
  750. int s = (*vol->vol_ifc->sf_used) (vol->vol_ifc, p + i + vol->vol_ifc->sf_rsvbot, off);
  751. off = 0;
  752. if (s) {
  753. siz += s + i * vol->vol_ifc->sf_unit_size - sizeof(BLOCKHEAD);
  754. break;
  755. }
  756. }
  757. return siz;
  758. }
  759. /*!
  760. * \brief Find entry by name.
  761. *
  762. * This routine can be either used to find an exact match or to find
  763. * the next entry that starts with the given name.
  764. *
  765. * \param vol Pointer to the volume information structure.
  766. * \param name Full path name of the requested entry. A leading slash
  767. * will be ignored.
  768. * \param eh Pointer to the entry header.
  769. * \param lbs Logical block to start searching. If set to UFLASH_ENTRIES,
  770. * all entry blocks will be searched for an exact match.
  771. * Otherwise the search starts at the specified block for the
  772. * next entry that starts with the given name.
  773. */
  774. static int EntrySearchNext(UFLASHVOLUME * vol, const char *name, ENTRYHEAD * eh, blknum_t lbs)
  775. {
  776. blknum_t lbe;
  777. blknum_t b;
  778. int nlen;
  779. nlen = strlen(name);
  780. /* Walking through the translation table requires exclusive access. */
  781. NutEventWait(&vol->vol_mutex, 0);
  782. for (lbe = lbs == UFLASH_ENTRIES ? 0 : lbs; lbe < UFLASH_ENTRIES; lbe++) {
  783. b = vol->vol_l2p[lbe];
  784. if (b < vol->vol_blocks) {
  785. /* Read the entry header, which contains the path length. */
  786. if (FlashReadEntry(vol->vol_ifc, b, eh, NULL) == 0) {
  787. /* If the path lengths are equal, then compare the names. */
  788. if (eh->eh_nlen == nlen || (lbs != UFLASH_ENTRIES && eh->eh_nlen >= nlen)) {
  789. if (FlashBlockCmpEntryName(vol->vol_ifc, b, name, nlen) == 0) {
  790. NutEventPost(&vol->vol_mutex);
  791. return lbe;
  792. }
  793. }
  794. }
  795. }
  796. }
  797. NutEventPost(&vol->vol_mutex);
  798. return UFLASH_ENTRIES;
  799. }
  800. /*!
  801. * \brief Find existing entry by name.
  802. *
  803. * \param vol Pointer to the information structure of a mounted volume.
  804. */
  805. static int EntrySearch(UFLASHVOLUME * vol, const char *name, ENTRYHEAD * eh)
  806. {
  807. return EntrySearchNext(vol, name, eh, UFLASH_ENTRIES);
  808. }
  809. /*!
  810. * \brief Erase all data blocks of a given entry.
  811. *
  812. * \param vol Pointer to the information structure of a mounted volume.
  813. */
  814. static int EntryTruncateSeq(UFLASHVOLUME * vol, int lbe)
  815. {
  816. blknum_t lb;
  817. BLOCKHEAD bh;
  818. for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
  819. if (vol->vol_l2p[lb] < vol->vol_blocks) {
  820. FlashReadBlockHead(vol->vol_ifc, vol->vol_l2p[lb], &bh);
  821. if (bh.bh_entblk == lbe) {
  822. LogBlkRelease(vol, lb);
  823. }
  824. }
  825. }
  826. return 0;
  827. }
  828. /*!
  829. * \brief Truncate an entry.
  830. *
  831. * \param vol Pointer to the information structure of a mounted volume.
  832. */
  833. static int EntryTruncate(UFLASHVOLUME * vol, blknum_t lbe)
  834. {
  835. BLOCKHEAD bh;
  836. ENTRYHEAD eh;
  837. BLOCKFOOT bf;
  838. blknum_t b;
  839. blknum_t b_old;
  840. char *name = NULL;
  841. EntryTruncateSeq(vol, lbe);
  842. /* Allocate a new entry block. */
  843. b = PhysBlkAllocate(vol, 0);
  844. if (b >= vol->vol_blocks) {
  845. return -1;
  846. }
  847. b_old = vol->vol_l2p[lbe];
  848. vol->vol_l2p[lbe] = b;
  849. /* Read the block footer and erase the remaining units. */
  850. FlashReadBlockFoot(vol->vol_ifc, b, &bf);
  851. FlashEraseBlockData(vol->vol_ifc, b);
  852. /* Copy block and entry headers, incrementing the version.
  853. * Note, that we cannot use a unit copy, because we also must
  854. * get rid of the data in the first block. */
  855. FlashReadBlockHead(vol->vol_ifc, b_old, &bh);
  856. FlashReadEntry(vol->vol_ifc, b_old, &eh, &name);
  857. FlashWriteBlockHead(vol->vol_ifc, b, &bh);
  858. FlashWriteEntry(vol->vol_ifc, b, &eh, name);
  859. free(name);
  860. FlashUnitCommit(vol->vol_ifc, b, 0);
  861. /* Update block footer in the last unit. */
  862. FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
  863. FlashUnitCommit(vol->vol_ifc, b, UFLASH_BLOCK_UNITS - 1);
  864. /* Remove the old entry. */
  865. FlashEraseEntry(vol->vol_ifc, b_old);
  866. return 0;
  867. }
  868. /*!
  869. * \brief Create a new entry.
  870. *
  871. * \param vol Pointer to the information structure of a mounted volume.
  872. */
  873. static int EntryCreate(UFLASHVOLUME * vol, blknum_t lbe, ENTRYHEAD * eh, const char *name)
  874. {
  875. BLOCKHEAD bh;
  876. BLOCKFOOT bf;
  877. blknum_t b;
  878. b = vol->vol_l2p[lbe];
  879. /* Read the footer before erasing the block. */
  880. FlashReadBlockFoot(vol->vol_ifc, b, &bf);
  881. FlashEraseBlockData(vol->vol_ifc, b);
  882. /* Write block header. */
  883. bh.bh_logblk = lbe;
  884. bh.bh_version = UFLASH_BLOCK_INVALID;
  885. bh.bh_entblk = lbe;
  886. bh.bh_entseq = 0;
  887. FlashWriteBlockHead(vol->vol_ifc, b, &bh);
  888. /* Write the entry header and name. */
  889. FlashWriteEntry(vol->vol_ifc, b, eh, name);
  890. FlashUnitCommit(vol->vol_ifc, b, 0);
  891. /* Update block footer. */
  892. FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
  893. FlashUnitCommit(vol->vol_ifc, b, UFLASH_BLOCK_UNITS - 1);
  894. return 0;
  895. }
  896. /*!
  897. * \brief Remove an entry.
  898. */
  899. static int UFlashFileRemove(NUTDEVICE * dev, const char *name)
  900. {
  901. blknum_t lbe;
  902. ENTRYHEAD eh;
  903. UFLASHVOLUME *vol;
  904. vol = (UFLASHVOLUME *) dev->dev_dcb;
  905. while (*name == '/') {
  906. name++;
  907. }
  908. lbe = EntrySearch(vol, name, &eh);
  909. if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
  910. return -1;
  911. }
  912. NutEventWait(&vol->vol_mutex, 0);
  913. EntryTruncateSeq(vol, lbe);
  914. LogBlkRelease(vol, lbe);
  915. NutEventPost(&vol->vol_mutex);
  916. return 0;
  917. }
  918. /*!
  919. * \brief Retrieve the status of an entry.
  920. */
  921. static int UFlashFileStatus(NUTDEVICE * dev, const char *name, struct stat *st)
  922. {
  923. blknum_t lbe;
  924. ENTRYHEAD eh;
  925. UFLASHVOLUME *vol;
  926. uint_fast8_t partial = 0;
  927. vol = (UFLASHVOLUME *) dev->dev_dcb;
  928. while (*name == '/') {
  929. name++;
  930. }
  931. lbe = EntrySearch(vol, name, &eh);
  932. if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
  933. lbe = EntrySearchNext(vol, name, &eh, 0);
  934. if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
  935. return -1;
  936. }
  937. partial = 1;
  938. }
  939. memset(st, 0, sizeof(struct stat));
  940. if (partial) {
  941. st->st_mode = 1;
  942. #ifdef UFLASH_USE_TIMESTAMP
  943. EntryScan(vol, lbe, &st->st_mtime);
  944. #endif
  945. } else {
  946. NutEventWait(&vol->vol_mutex, 0);
  947. #ifdef UFLASH_USE_TIMESTAMP
  948. st->st_size = EntryScan(vol, lbe, &st->st_mtime);
  949. #else
  950. st->st_size = EntryScan(vol, lbe, NULL);
  951. #endif
  952. NutEventPost(&vol->vol_mutex);
  953. #if UFLASH_MAX_PATH
  954. st->st_size -= sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
  955. #else
  956. st->st_size -= sizeof(ENTRYHEAD) + eh.eh_nlen;
  957. #endif
  958. }
  959. return 0;
  960. }
  961. /*!
  962. * \brief Open a directory.
  963. *
  964. * \param dev Specifies the file system device.
  965. * \param dpath Full absolute pathname of the directory to open.
  966. *
  967. * \return Pointer to a NUTFILE structure if successful or NUTFILE_EOF otherwise.
  968. */
  969. static NUTFILE *UFlashDirOpen(NUTDEVICE * dev, const char *dpath)
  970. {
  971. NUTFILE *ndp;
  972. UFLASHFIND *uff;
  973. ndp = malloc(sizeof(NUTFILE));
  974. if (ndp) {
  975. uff = malloc(sizeof(UFLASHFIND));
  976. if (uff) {
  977. uff->uff_lbe = 0;
  978. uff->uff_path = strdup(dpath + (*dpath == '/'));
  979. if (uff->uff_path) {
  980. ndp->nf_dev = dev;
  981. ndp->nf_fcb = uff;
  982. return ndp;
  983. }
  984. free(uff);
  985. }
  986. free(ndp);
  987. }
  988. return NUTFILE_EOF;
  989. }
  990. /*!
  991. * \brief Close a directory.
  992. */
  993. static int UFlashDirClose(NUTFILE * ndp)
  994. {
  995. UFLASHFIND *uff;
  996. uff = (UFLASHFIND *) ndp->nf_fcb;
  997. free(uff->uff_path);
  998. free(uff);
  999. free(ndp);
  1000. return 0;
  1001. }
  1002. /*!
  1003. * \brief Read next entry of a directory.
  1004. */
  1005. static int UFlashDirRead(DIR * dir)
  1006. {
  1007. struct dirent *ent;
  1008. NUTFILE *ndp;
  1009. NUTDEVICE *dev;
  1010. UFLASHFIND *uff;
  1011. UFLASHVOLUME *vol;
  1012. ENTRYHEAD eh;
  1013. char *name = NULL;
  1014. char *cp;
  1015. ndp = dir->dd_fd;
  1016. uff = (UFLASHFIND *) ndp->nf_fcb;
  1017. dev = ndp->nf_dev;
  1018. vol = (UFLASHVOLUME *) dev->dev_dcb;
  1019. uff->uff_lbe = EntrySearchNext(vol, uff->uff_path, &eh, uff->uff_lbe);
  1020. if (uff->uff_lbe >= UFLASH_ENTRIES) {
  1021. return -1;
  1022. }
  1023. ent = (struct dirent *) dir->dd_buf;
  1024. memset(dir->dd_buf, 0, sizeof(struct dirent));
  1025. FlashReadEntry(vol->vol_ifc, vol->vol_l2p[uff->uff_lbe], &eh, &name);
  1026. cp = strchr(name + strlen(uff->uff_path), '/');
  1027. if (cp) {
  1028. *cp = '\0';
  1029. ent->d_type = 1;
  1030. } else {
  1031. ent->d_type = 0;
  1032. }
  1033. strcpy(ent->d_name, name + strlen(uff->uff_path));
  1034. ent->d_namlen = strlen(name + strlen(uff->uff_path));
  1035. free(name);
  1036. uff->uff_lbe++;
  1037. return 0;
  1038. }
  1039. /*!
  1040. * \brief Rename an entry.
  1041. *
  1042. * \param dev Specifies the file system device.
  1043. * \param old_path Old name and path of the file.
  1044. * \param new_path New name and path of the file.
  1045. *
  1046. * \return 0 on success, -1 otherwise.
  1047. */
  1048. static int UFlashFileRename(NUTDEVICE * dev, const char *old_path, const char *new_path)
  1049. {
  1050. blknum_t lbe;
  1051. blknum_t b;
  1052. blknum_t b_old;
  1053. uint_fast8_t u;
  1054. ENTRYHEAD eh;
  1055. UFLASHVOLUME *vol;
  1056. BLOCKHEAD bh;
  1057. BLOCKFOOT bf;
  1058. NUTASSERT(dev != NULL);
  1059. NUTASSERT(old_path != NULL);
  1060. #if UFLASH_MAX_PATH
  1061. NUTASSERT(strlen(old_path) <= UFLASH_MAX_PATH);
  1062. #endif
  1063. NUTASSERT(new_path != NULL);
  1064. #if UFLASH_MAX_PATH
  1065. NUTASSERT(strlen(new_path) <= UFLASH_MAX_PATH);
  1066. #endif
  1067. vol = (UFLASHVOLUME *) dev->dev_dcb;
  1068. NUTASSERT(vol != NULL);
  1069. vol = (UFLASHVOLUME *) dev->dev_dcb;
  1070. while (*old_path == '/') {
  1071. old_path++;
  1072. }
  1073. while (*new_path == '/') {
  1074. new_path++;
  1075. }
  1076. lbe = EntrySearch(vol, old_path, &eh);
  1077. if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
  1078. return -1;
  1079. }
  1080. #if UFLASH_MAX_PATH == 0
  1081. if (eh.eh_nlen < strlen(new_path)) {
  1082. return -1;
  1083. }
  1084. #endif
  1085. eh.eh_nlen = strlen(new_path);
  1086. /* Exclusive access from here. */
  1087. NutEventWait(&vol->vol_mutex, 0);
  1088. /* Allocate a new entry block. */
  1089. b = PhysBlkAllocate(vol, 0);
  1090. if (b >= vol->vol_blocks) {
  1091. /* No more blocks available. */
  1092. NutEventPost(&vol->vol_mutex);
  1093. return -1;
  1094. }
  1095. /* Replace the physical block in the translation table. */
  1096. b_old = vol->vol_l2p[lbe];
  1097. vol->vol_l2p[lbe] = b;
  1098. /* Keep the footer and erase the pages of the new block, except the
  1099. first. The first page of unallocated blocks is already erased. */
  1100. FlashReadBlockFoot(vol->vol_ifc, b, &bf);
  1101. FlashEraseBlockData(vol->vol_ifc, b);
  1102. /* Copy all pages of the entry block. */
  1103. for (u = 0; u < UFLASH_BLOCK_UNITS; u++) {
  1104. FlashUnitCopy(vol->vol_ifc, b_old, b, u);
  1105. /* If this is the first unit, write a new version of the header. */
  1106. if (u == 0) {
  1107. /* Separately copy the block header, because this will
  1108. increment the block's version number. */
  1109. FlashReadBlockHead(vol->vol_ifc, b, &bh);
  1110. FlashWriteBlockHead(vol->vol_ifc, b, &bh);
  1111. /* Fill in the new path name. */
  1112. FlashWriteEntry(vol->vol_ifc, b, &eh, new_path);
  1113. }
  1114. /* If this is the last unit, write back an updated footer. */
  1115. else if (u == UFLASH_BLOCK_UNITS - 1) {
  1116. FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
  1117. }
  1118. /* Commit the unit. */
  1119. FlashUnitCommit(vol->vol_ifc, b, u);
  1120. }
  1121. /* Finally remove the old entry. */
  1122. FlashEraseEntry(vol->vol_ifc, b_old);
  1123. /* Release exclusive access. */
  1124. NutEventPost(&vol->vol_mutex);
  1125. return 0;
  1126. }
  1127. /*!
  1128. * \brief Retrieve the size of a previously opened UFLASH file.
  1129. *
  1130. * This function is called by the low level size routine of the C runtime
  1131. * library, using the _NUTDEVICE::dev_size entry.
  1132. *
  1133. * \param nfp Pointer to a \ref _NUTFILE structure, obtained by a
  1134. * previous call to UFlashFileOpen().
  1135. *
  1136. * \return Size of the file.
  1137. */
  1138. static long UFlashFileSize(NUTFILE * nfp)
  1139. {
  1140. NUTASSERT(nfp != NULL);
  1141. NUTASSERT(nfp->nf_fcb != NULL);
  1142. return ((UFLASHENTRY *) nfp->nf_fcb)->ent_size;
  1143. }
  1144. /*!
  1145. * \brief Open a UFLASH file.
  1146. *
  1147. * This function is called by the low level open routine of the C runtime
  1148. * library, using the _NUTDEVICE::dev_open entry.
  1149. *
  1150. * \param dev Specifies the file system device.
  1151. * \param path Pathname of the file to open.
  1152. * \param mode Operation mode.
  1153. * \param acc File attribute, currently ignored.
  1154. *
  1155. * \return Pointer to a NUTFILE structure if successful or NUTFILE_EOF otherwise.
  1156. */
  1157. static NUTFILE *UFlashFileOpen(NUTDEVICE * dev, const char *path, int mode, int acc)
  1158. {
  1159. int rc = -1;
  1160. NUTFILE *nfp = NUTFILE_EOF;
  1161. UFLASHENTRY *ent;
  1162. UFLASHVOLUME *vol;
  1163. blknum_t lbe;
  1164. ENTRYHEAD eh;
  1165. long datsiz = 0;
  1166. NUTASSERT(dev != NULL);
  1167. NUTASSERT(path != NULL);
  1168. vol = (UFLASHVOLUME *) dev->dev_dcb;
  1169. NUTASSERT(vol != NULL);
  1170. while (*path == '/') {
  1171. path++;
  1172. }
  1173. /* Allocate a private entry information structure. */
  1174. ent = calloc(1, sizeof(UFLASHENTRY));
  1175. if (ent == NULL) {
  1176. return NUTFILE_EOF;
  1177. }
  1178. ent->ent_mode = mode;
  1179. lbe = EntrySearch(vol, path, &eh);
  1180. NutEventWait(&vol->vol_mutex, 0);
  1181. /*
  1182. ** Entry exists.
  1183. */
  1184. if (lbe < UFLASH_ENTRIES) {
  1185. if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
  1186. errno = EEXIST;
  1187. } else {
  1188. /* Truncate. */
  1189. if ((mode & _O_TRUNC) == _O_TRUNC) {
  1190. rc = EntryTruncate(vol, lbe);
  1191. }
  1192. /* Do not truncate. */
  1193. else {
  1194. rc = 0;
  1195. datsiz = EntryScan(vol, lbe, NULL);
  1196. #if UFLASH_MAX_PATH
  1197. datsiz -= sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
  1198. #else
  1199. datsiz -= sizeof(ENTRYHEAD) + eh.eh_nlen;
  1200. #endif
  1201. }
  1202. }
  1203. }
  1204. /*
  1205. ** Entry doesn't exist.
  1206. */
  1207. else {
  1208. if ((mode & _O_CREAT) == _O_CREAT) {
  1209. lbe = LogBlkAllocate(vol, 0);
  1210. if (lbe < UFLASH_ENTRIES) {
  1211. eh.eh_nlen = strlen(path);
  1212. eh.eh_attr = 0;
  1213. rc = EntryCreate(vol, lbe, &eh, path);
  1214. }
  1215. } else {
  1216. errno = ENOENT;
  1217. }
  1218. }
  1219. if (rc) {
  1220. free(ent);
  1221. } else {
  1222. ent->ent_attr = eh.eh_attr;
  1223. ent->ent_namlen = eh.eh_nlen;
  1224. #if UFLASH_MAX_PATH
  1225. ent->ent_eoff = sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
  1226. #else
  1227. ent->ent_eoff = sizeof(ENTRYHEAD) + eh.eh_nlen;
  1228. #endif
  1229. ent->ent_id = lbe;
  1230. ent->ent_size = datsiz;
  1231. /* Allocate a file information structure. */
  1232. nfp = malloc(sizeof(NUTFILE));
  1233. if (nfp == NULL) {
  1234. free(ent);
  1235. NutEventPost(&vol->vol_mutex);
  1236. return NUTFILE_EOF;
  1237. }
  1238. nfp->nf_dev = dev;
  1239. nfp->nf_fcb = ent;
  1240. if ((mode & _O_APPEND) == _O_APPEND) {
  1241. ent->ent_bidx = UFLASH_BLOCK_INVALID;
  1242. EntryPosSet(nfp, datsiz);
  1243. } else {
  1244. ent->ent_bidx = lbe;
  1245. EntryPosSet(nfp, 0);
  1246. }
  1247. }
  1248. NutEventPost(&vol->vol_mutex);
  1249. return nfp;
  1250. }
  1251. /*!
  1252. * \brief Close a UFLASH file.
  1253. *
  1254. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  1255. * call to UFlashFileOpen().
  1256. *
  1257. * \return Always 0.
  1258. */
  1259. static int UFlashFileClose(NUTFILE * nfp)
  1260. {
  1261. NUTASSERT(nfp != NULL);
  1262. NUTASSERT(nfp->nf_dev != NULL);
  1263. NUTASSERT(nfp->nf_fcb != NULL);
  1264. free(nfp->nf_fcb);
  1265. free(nfp);
  1266. return 0;
  1267. }
  1268. /*!
  1269. * \brief Read data from a UFLASH file.
  1270. *
  1271. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  1272. * call to UFlashFileOpen().
  1273. * \param data Pointer to the data buffer to fill.
  1274. * \param size Maximum number of bytes to read.
  1275. *
  1276. * \return The number of bytes actually read. A return value of -1 indicates
  1277. * an error.
  1278. */
  1279. static int UFlashFileRead(NUTFILE * nfp, void *data, int size)
  1280. {
  1281. int u;
  1282. int step;
  1283. int rc;
  1284. uint8_t *dptr;
  1285. UFLASHENTRY *ent;
  1286. UFLASHVOLUME *vol;
  1287. /* Ignore input flush. */
  1288. if (data == NULL || size == 0) {
  1289. return 0;
  1290. }
  1291. dptr = (uint8_t *) data;
  1292. NUTASSERT(nfp != NULL);
  1293. NUTASSERT(nfp->nf_dev != NULL);
  1294. ent = (UFLASHENTRY *) nfp->nf_fcb;
  1295. NUTASSERT(ent != NULL);
  1296. vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
  1297. NUTASSERT(vol != NULL);
  1298. /* Do not read beyond the file end. */
  1299. if (size > (int) (ent->ent_size - ent->ent_pos)) {
  1300. size = (int) (ent->ent_size - ent->ent_pos);
  1301. }
  1302. /*
  1303. ** Loop until we read the requested size.
  1304. */
  1305. for (rc = 0; rc < size;) {
  1306. /* Is the current logical block number still valid? */
  1307. if (ent->ent_bidx >= vol->vol_blocks) {
  1308. /* If not, seek for the right block. */
  1309. ent->ent_bidx = EntrySeek(vol, ent->ent_id, ent->ent_sidx);
  1310. if (ent->ent_bidx >= vol->vol_blocks) {
  1311. /* Seek failed. */
  1312. errno = EIO;
  1313. return -1;
  1314. }
  1315. }
  1316. /* Read unit by unit. */
  1317. for (u = ent->ent_uidx; rc < size && u < UFLASH_BLOCK_UNITS; u++) {
  1318. NutEventWait(&vol->vol_mutex, 0);
  1319. step = FlashUnitRead(vol->vol_ifc, vol->vol_l2p[ent->ent_bidx], u, ent->ent_upos, dptr, size - rc);
  1320. NutEventPost(&vol->vol_mutex);
  1321. if (step < 0) {
  1322. /* Read failed. */
  1323. errno = EIO;
  1324. return -1;
  1325. }
  1326. /* Increment pointers and indices. */
  1327. rc += step;
  1328. dptr += step;
  1329. EntryPosInc(nfp, step);
  1330. }
  1331. }
  1332. return rc;
  1333. }
  1334. /*!
  1335. * \brief Write data to a UFLASH file.
  1336. *
  1337. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  1338. * call to UFlashFileOpen().
  1339. * \param buffer Pointer to the data to be written. If zero, then the
  1340. * output buffer will be flushed.
  1341. * \param len Number of bytes to write.
  1342. *
  1343. * \return The number of bytes written. A return value of -1 indicates an
  1344. * error.
  1345. */
  1346. static int UFlashFileWrite(NUTFILE * nfp, const void *data, int len)
  1347. {
  1348. int u;
  1349. blknum_t b;
  1350. blknum_t b_old;
  1351. int step;
  1352. int siz = len;
  1353. uint8_t *dptr;
  1354. BLOCKHEAD bh;
  1355. BLOCKFOOT bf;
  1356. UFLASHENTRY *ent;
  1357. UFLASHVOLUME *vol;
  1358. /* Ignore output flush. */
  1359. if (data == NULL || len == 0) {
  1360. return 0;
  1361. }
  1362. dptr = (uint8_t *) data;
  1363. /* Sanity check. */
  1364. NUTASSERT(nfp != NULL);
  1365. NUTASSERT(nfp->nf_fcb != NULL);
  1366. NUTASSERT(nfp->nf_dev != NULL);
  1367. NUTASSERT(nfp->nf_dev->dev_dcb != NULL);
  1368. ent = (UFLASHENTRY *) nfp->nf_fcb;
  1369. vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
  1370. /*
  1371. ** Loop until all data has been written.
  1372. */
  1373. while (len) {
  1374. /* Is the current logical block number still valid? */
  1375. if (ent->ent_bidx >= vol->vol_blocks) {
  1376. /* If not, seek for the right block. The routine will return an
  1377. ** invalid block number, if we need a new block. */
  1378. ent->ent_bidx = EntrySeek(vol, ent->ent_id, ent->ent_sidx);
  1379. }
  1380. /*
  1381. ** If the current logical block exists, then we reallocate a
  1382. ** physical block.
  1383. */
  1384. NutEventWait(&vol->vol_mutex, 0);
  1385. if (ent->ent_bidx < vol->vol_blocks) {
  1386. b_old = LogBlkReallocate(vol, ent->ent_bidx);
  1387. if (b_old >= vol->vol_blocks) {
  1388. /* No more blocks available. */
  1389. NutEventPost(&vol->vol_mutex);
  1390. return -1;
  1391. }
  1392. /* Read header of old block and increment the version number. */
  1393. FlashReadBlockHead(vol->vol_ifc, b_old, &bh);
  1394. }
  1395. /*
  1396. ** If the current logical block doesn't exists, then we allocate
  1397. ** a new one.
  1398. */
  1399. else {
  1400. ent->ent_bidx = LogBlkAllocate(vol, UFLASH_ENTRIES);
  1401. if (ent->ent_bidx >= vol->vol_blocks) {
  1402. /* No more blocks available. */
  1403. NutEventPost(&vol->vol_mutex);
  1404. return -1;
  1405. }
  1406. /* No reallocation, old and new are the same block. */
  1407. b_old = vol->vol_l2p[ent->ent_bidx];
  1408. /* Initial block header. */
  1409. bh.bh_logblk = ent->ent_bidx;
  1410. bh.bh_entblk = ent->ent_id;
  1411. bh.bh_entseq = ent->ent_sidx;
  1412. bh.bh_version = UFLASH_BLOCK_INVALID;
  1413. }
  1414. /* Current physical block. */
  1415. b = vol->vol_l2p[ent->ent_bidx];
  1416. /* Read the block footer. */
  1417. FlashReadBlockFoot(vol->vol_ifc, b, &bf);
  1418. /* The first unit had been erased when the block was released.
  1419. ** Now erase the remaining units. */
  1420. FlashEraseBlockData(vol->vol_ifc, b);
  1421. /*
  1422. ** Write unit by unit.
  1423. */
  1424. for (u = 0; u < UFLASH_BLOCK_UNITS; u++) {
  1425. /* Make a copy of the old unit. If old and new are
  1426. ** the same, this won't hurt. */
  1427. FlashUnitCopy(vol->vol_ifc, b_old, b, u);
  1428. /* Write the block header to the first unit. */
  1429. if (u == 0) {
  1430. FlashWriteBlockHead(vol->vol_ifc, b, &bh);
  1431. }
  1432. /* If this is the current unit to write to, fill it with data. */
  1433. if (len && u == ent->ent_uidx) {
  1434. step = FlashUnitWrite(vol->vol_ifc, b, u, ent->ent_upos, dptr, len);
  1435. /* Increment pointers and indices. */
  1436. len -= step;
  1437. dptr += step;
  1438. EntryPosInc(nfp, step);
  1439. if (ent->ent_size < ent->ent_pos) {
  1440. ent->ent_size = ent->ent_pos;
  1441. }
  1442. }
  1443. /* Write the block footer to the last unit. */
  1444. if (u == UFLASH_BLOCK_UNITS - 1) {
  1445. FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
  1446. }
  1447. FlashUnitCommit(vol->vol_ifc, b, u);
  1448. }
  1449. /* If we reallocated the block, then release the old one now.
  1450. ** It is essential to do this after having successfully written
  1451. ** the new block. If the new block with a higher version number
  1452. ** remains incomplete, then the old version still exists and the
  1453. ** incomplete block will be removed during mounting. */
  1454. if (b != b_old) {
  1455. FlashEraseEntry(vol->vol_ifc, b_old);
  1456. }
  1457. NutEventPost(&vol->vol_mutex);
  1458. }
  1459. return siz;
  1460. }
  1461. #ifdef __HARVARD_ARCH__
  1462. /*!
  1463. * \brief Write data from program space to a file.
  1464. *
  1465. * This function is not yet implemented and will always return -1.
  1466. *
  1467. * Similar to UFlashFileWrite() except that the data is located in
  1468. * program memory.
  1469. *
  1470. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  1471. * call to RawFsFileOpen().
  1472. * \param buffer Pointer to the data in program space. If zero, then the
  1473. * output buffer will be flushed.
  1474. * \param len Number of bytes to write.
  1475. *
  1476. * \return The number of bytes written. A return value of -1 indicates an
  1477. * error.
  1478. */
  1479. static int UFlashFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
  1480. {
  1481. return -1;
  1482. }
  1483. #endif
  1484. /*!
  1485. * \brief Move file pointer to a specified position.
  1486. *
  1487. * Moving beyond the current file size is not supported.
  1488. *
  1489. * \param nfp File descriptor.
  1490. * \param pos Requested file position.
  1491. * \param whence Positioning directive.
  1492. *
  1493. * \return 0 on success, -1 otherwise. In the latter case the position
  1494. * is unspecified.
  1495. */
  1496. static int UFlashFileSeek(NUTFILE * nfp, long *pos, int whence)
  1497. {
  1498. int rc = 0;
  1499. long npos;
  1500. UFLASHENTRY *ent;
  1501. NUTASSERT(nfp != NULL);
  1502. NUTASSERT(nfp->nf_fcb != NULL);
  1503. ent = (UFLASHENTRY *) nfp->nf_fcb;
  1504. NUTASSERT(pos != NULL);
  1505. npos = *pos;
  1506. switch (whence) {
  1507. case SEEK_CUR:
  1508. /* Relative to current position. */
  1509. npos += ent->ent_pos;
  1510. break;
  1511. case SEEK_END:
  1512. /* Relative to file end. */
  1513. npos += ent->ent_size;
  1514. break;
  1515. }
  1516. /* Make sure that we are within limits. */
  1517. if (npos < 0 || npos > (long) ent->ent_size) {
  1518. errno = EINVAL;
  1519. rc = -1;
  1520. } else {
  1521. EntryPosSet(nfp, npos);
  1522. *pos = npos;
  1523. }
  1524. return rc;
  1525. }
  1526. /*!
  1527. * \brief Mount a UFLASH volume.
  1528. *
  1529. * \param dev Specifies the file system device.
  1530. *
  1531. * \return 0 on success or -1 in case of an error.
  1532. */
  1533. static int UFlashMount(NUTDEVICE * dev)
  1534. {
  1535. int b;
  1536. BLOCKHEAD bh;
  1537. UFLASHVOLUME *vol;
  1538. NUTASSERT(dev != NULL);
  1539. NUTASSERT(dev->dev_icb != NULL);
  1540. NUTASSERT(dev->dev_dcb == NULL);
  1541. /* Allocate the volume information structure */
  1542. vol = calloc(1, sizeof(UFLASHVOLUME));
  1543. if (vol == NULL) {
  1544. return -1;
  1545. }
  1546. dev->dev_dcb = vol;
  1547. vol->vol_ifc = (NUTSERIALFLASH *) dev->dev_icb;
  1548. /* Determine the total number of blocks. Honor any reserved units. */
  1549. vol->vol_blocks =
  1550. (blknum_t) ((vol->vol_ifc->sf_units - vol->vol_ifc->sf_rsvbot - vol->vol_ifc->sf_rsvtop) / UFLASH_BLOCK_UNITS);
  1551. if (vol->vol_blocks > UFLASH_MAX_BLOCKS) {
  1552. vol->vol_blocks = UFLASH_MAX_BLOCKS;
  1553. }
  1554. /* Allocate the block translation table. */
  1555. vol->vol_l2p = malloc(vol->vol_blocks * sizeof(blknum_t));
  1556. if (vol->vol_l2p == NULL) {
  1557. free(vol);
  1558. return -1;
  1559. }
  1560. memset(vol->vol_l2p, 0xff, vol->vol_blocks * sizeof(blknum_t));
  1561. memset(min_used, 0xff, sizeof(min_used));
  1562. /*
  1563. ** Fill the block translation table.
  1564. */
  1565. for (b = 0; b < vol->vol_blocks; b++) {
  1566. FlashReadBlockHead(vol->vol_ifc, b, &bh);
  1567. /* Check if this is a logical block. */
  1568. if (bh.bh_logblk < vol->vol_blocks) {
  1569. /* Verify the CRC. */
  1570. if (FlashCheckBlock(vol->vol_ifc, b)) {
  1571. /* Bad block, remove it. */
  1572. FlashEraseEntry(vol->vol_ifc, b);
  1573. /* Mark the volume fixed. */
  1574. vol->vol_attrib |= UFLASH_VOLF_FIXED;
  1575. } else {
  1576. /* Check if we already found another version. */
  1577. if (vol->vol_l2p[bh.bh_logblk] < vol->vol_blocks) {
  1578. BLOCKHEAD bho;
  1579. /* Read the previous entry. */
  1580. FlashReadBlockHead(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk], &bho);
  1581. /* Compare versions. */
  1582. if (bho.bh_version > bh.bh_version) {
  1583. if (bho.bh_version - bh.bh_version > vol->vol_blocks) {
  1584. /* The current version overflowed. */
  1585. FlashEraseEntry(vol->vol_ifc, b);
  1586. } else {
  1587. FlashEraseEntry(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk]);
  1588. vol->vol_l2p[bh.bh_logblk] = b;
  1589. }
  1590. } else if (bh.bh_version - bho.bh_version < vol->vol_blocks) {
  1591. /* The current version is higher. */
  1592. FlashEraseEntry(vol->vol_ifc, b);
  1593. } else {
  1594. FlashEraseEntry(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk]);
  1595. vol->vol_l2p[bh.bh_logblk] = b;
  1596. }
  1597. /* Mark the volume fixed. */
  1598. vol->vol_attrib |= UFLASH_VOLF_FIXED;
  1599. } else {
  1600. /* First version of this block. */
  1601. vol->vol_l2p[bh.bh_logblk] = b;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. /* Initialize the mutex. */
  1607. NutEventPost(&vol->vol_mutex);
  1608. return 0;
  1609. }
  1610. /*!
  1611. * \brief Unmount a UFLASH volume.
  1612. *
  1613. * \param dev Specifies the file system device.
  1614. *
  1615. * \return Always 0.
  1616. */
  1617. static int UFlashUnmount(NUTDEVICE * dev)
  1618. {
  1619. UFLASHVOLUME *vol;
  1620. /* Sanity check. */
  1621. NUTASSERT(dev != NULL);
  1622. /* Get the volume information structure. */
  1623. NUTASSERT(dev->dev_dcb != NULL);
  1624. vol = (UFLASHVOLUME *) dev->dev_dcb;
  1625. /* Release allocated heap space. */
  1626. NUTASSERT(vol->vol_l2p != NULL);
  1627. free(vol->vol_l2p);
  1628. free(vol);
  1629. /* Mark the file system driver unmounted. */
  1630. dev->dev_dcb = NULL;
  1631. return 0;
  1632. }
  1633. /*!
  1634. * \brief Attach an UFLASH file system to a serial flash device.
  1635. *
  1636. * This function will initialize the hardware and mount the
  1637. * volume.
  1638. *
  1639. * \param dev Specifies the file system device.
  1640. * \param sfi Specifies the serial flash interface.
  1641. * \param bus Specifies the SPI bus driver.
  1642. *
  1643. * \return 0 on success, -1 on errors.
  1644. */
  1645. int UFlashAttach(NUTDEVICE * dev, NUTSERIALFLASH * sfi, NUTSPIBUS * bus)
  1646. {
  1647. /* Sanity checks. */
  1648. NUTASSERT(dev != NULL);
  1649. NUTASSERT(sfi != NULL);
  1650. NUTASSERT(sfi->sf_node != NULL);
  1651. NUTASSERT(sfi->sf_init != NULL);
  1652. NUTASSERT(bus != NULL);
  1653. NUTASSERT(bus->bus_initnode != NULL);
  1654. sfi->sf_node->node_bus = bus;
  1655. if ((*bus->bus_initnode) (sfi->sf_node)) {
  1656. return -1;
  1657. }
  1658. NutEventPost(&sfi->sf_node->node_bus->bus_mutex);
  1659. if ((*sfi->sf_init) (sfi) == 0) {
  1660. dev->dev_icb = (void *) sfi;
  1661. if (UFlashMount(dev) == 0) {
  1662. return 0;
  1663. }
  1664. dev->dev_icb = NULL;
  1665. }
  1666. return -1;
  1667. }
  1668. /*!
  1669. * \brief Detach an UFLASH file system from a serial flash device.
  1670. *
  1671. * This function will unmount the volume and release all occupied resources.
  1672. *
  1673. * \param dev Specifies the file system device.
  1674. *
  1675. * \return 0 on success, -1 on errors.
  1676. */
  1677. void UFlashDetach(NUTDEVICE * dev)
  1678. {
  1679. NUTSERIALFLASH *sfi;
  1680. UFlashUnmount(dev);
  1681. /* Release and detach the serial flash interface. */
  1682. sfi = (NUTSERIALFLASH *) dev->dev_icb;
  1683. NUTASSERT(sfi != NULL);
  1684. NUTASSERT(sfi->sf_exit != NULL);
  1685. (*sfi->sf_exit) (sfi);
  1686. dev->dev_icb = NULL;
  1687. }
  1688. /*!
  1689. * \brief Format an UFLASH volume.
  1690. *
  1691. * Formatting an UFLASH volume is easy: All blocks are simply erased.
  1692. * Therefore, formatting is required only to remove existing contents,
  1693. * which is incompatible with the current format options. The caller
  1694. * must make sure, that the volume is not mounted.
  1695. *
  1696. * \param dev Specifies the file system device.
  1697. * \param sfi Specifies the serial flash interface.
  1698. * \param bus Specifies the SPI bus driver.
  1699. *
  1700. * \return 0 on success, -1 on errors.
  1701. */
  1702. int UFlashFormat(NUTDEVICE * dev, NUTSERIALFLASH * sfi, NUTSPIBUS * bus)
  1703. {
  1704. int rc;
  1705. blknum_t n;
  1706. /* Sanity checks. */
  1707. NUTASSERT(dev != NULL);
  1708. NUTASSERT(sfi != NULL);
  1709. NUTASSERT(dev->dev_dcb == NULL);
  1710. sfi->sf_node->node_bus = bus;
  1711. if ((*sfi->sf_node->node_bus->bus_initnode) (sfi->sf_node)) {
  1712. return -1;
  1713. }
  1714. NutEventPost(&sfi->sf_node->node_bus->bus_mutex);
  1715. rc = (*sfi->sf_init) (sfi);
  1716. if (rc == 0) {
  1717. n = (blknum_t) ((sfi->sf_units - sfi->sf_rsvbot - sfi->sf_rsvtop) / UFLASH_BLOCK_UNITS);
  1718. if (n > UFLASH_MAX_BLOCKS) {
  1719. n = UFLASH_MAX_BLOCKS;
  1720. }
  1721. FlashEraseBlocks(sfi, n);
  1722. (*sfi->sf_exit) (sfi);
  1723. }
  1724. return 0;
  1725. }
  1726. /*!
  1727. * \brief UFLASH specific functions.
  1728. *
  1729. * \param dev Identifies the file system device that receives the
  1730. * control function.
  1731. * \param req Requested control function. May be set to one of the
  1732. * following constants:
  1733. * - FS_STATUS
  1734. * - FS_DIR_CREATE, ignored
  1735. * - FS_DIR_REMOVE, ignored
  1736. * - FS_DIR_OPEN
  1737. * - FS_DIR_CLOSE
  1738. * - FS_DIR_READ
  1739. * - FS_FILE_DELETE
  1740. * - FS_FILE_SEEK
  1741. * - FS_RENAME
  1742. * - FS_VOL_MOUNT
  1743. * - FS_VOL_UNMOUNT
  1744. * \param conf Points to a buffer that contains any data required for
  1745. * the given control function or receives data from that
  1746. * function.
  1747. *
  1748. * \return 0 on success, -1 otherwise.
  1749. */
  1750. static int UFlashIOCtl(NUTDEVICE * dev, int req, void *conf)
  1751. {
  1752. int rc = -1;
  1753. switch (req) {
  1754. case FS_STATUS:
  1755. NUTASSERT(conf != NULL);
  1756. {
  1757. FSCP_STATUS *par = (FSCP_STATUS *) conf;
  1758. rc = UFlashFileStatus(dev, par->par_path, par->par_stp);
  1759. }
  1760. break;
  1761. case FS_DIR_CREATE:
  1762. rc = 0;
  1763. break;
  1764. case FS_DIR_REMOVE:
  1765. rc = 0;
  1766. break;
  1767. case FS_DIR_OPEN:
  1768. /* Open a directory for reading entries. */
  1769. NUTASSERT(conf != NULL);
  1770. {
  1771. DIR *dir = (DIR *) conf;
  1772. if ((dir->dd_fd = UFlashDirOpen(dev, dir->dd_buf)) != NUTFILE_EOF) {
  1773. rc = 0;
  1774. }
  1775. }
  1776. break;
  1777. case FS_DIR_CLOSE:
  1778. NUTASSERT(conf != NULL);
  1779. rc = UFlashDirClose(((DIR *) conf)->dd_fd);
  1780. break;
  1781. case FS_DIR_READ:
  1782. rc = UFlashDirRead((DIR *) conf);
  1783. break;
  1784. case FS_FILE_DELETE:
  1785. rc = UFlashFileRemove(dev, (char *) conf);
  1786. break;
  1787. case FS_FILE_SEEK:
  1788. NUTASSERT(conf != NULL);
  1789. UFlashFileSeek((NUTFILE *) ((IOCTL_ARG3 *) conf)->arg1, /* */
  1790. (long *) ((IOCTL_ARG3 *) conf)->arg2, /* */
  1791. (int) ((IOCTL_ARG3 *) conf)->arg3);
  1792. break;
  1793. case FS_RENAME:
  1794. /* Rename an existing file. */
  1795. NUTASSERT(conf != NULL);
  1796. {
  1797. FSCP_RENAME *par = (FSCP_RENAME *) conf;
  1798. rc = UFlashFileRename(dev, par->par_old, par->par_new);
  1799. }
  1800. break;
  1801. case FS_VOL_MOUNT:
  1802. /* Mount a volume. */
  1803. rc = UFlashMount(dev);
  1804. break;
  1805. case FS_VOL_UNMOUNT:
  1806. /* Unmount a volume. */
  1807. rc = UFlashUnmount(dev);
  1808. break;
  1809. }
  1810. return rc;
  1811. }
  1812. /*!
  1813. * \brief Initialize the UFLASH device file system driver.
  1814. *
  1815. * This routine is called during device registration.
  1816. *
  1817. * \param dev Specifies the file system device.
  1818. *
  1819. * \return Zero on success. Otherwise an error code is returned.
  1820. */
  1821. static int UFlashInit(NUTDEVICE * dev)
  1822. {
  1823. return 0;
  1824. }
  1825. /*!
  1826. * \brief UFLASH0 file system device.
  1827. */
  1828. NUTDEVICE devUFlash0 = {
  1829. 0, /*!< \brief Pointer to next device, dev_next. */
  1830. {'U', 'F', 'L', 'A', 'S', 'H', '0', 0, 0}
  1831. , /*!< \brief Unique device name, dev_name. */
  1832. IFTYP_FS, /*!< \brief Type of device, dev_type. Obsolete. */
  1833. 0, /*!< \brief Chip select, dev_base. */
  1834. 0, /*!< \brief First interrupt number, dev_irq. Unused. */
  1835. NULL, /*!< \brief Attached serial flash interface, dev_icb. */
  1836. NULL, /*!< \brief Mounted volume information, dev_dcb. */
  1837. UFlashInit, /*!< \brief Driver initialization routine, dev_init. */
  1838. UFlashIOCtl, /*!< \brief Driver specific control function, dev_ioctl. */
  1839. UFlashFileRead, /*!< \brief Read data from a file, dev_read. */
  1840. UFlashFileWrite, /*!< \brief Write data to a file, dev_write. */
  1841. #ifdef __HARVARD_ARCH__
  1842. UFlashFileWrite_P, /*!< \brief Write data from program space to a file, dev_write_P. */
  1843. #endif
  1844. UFlashFileOpen, /*!< \brief Open a file, dev_open. */
  1845. UFlashFileClose, /*!< \brief Close a file, dev_close. */
  1846. UFlashFileSize, /*!< \brief Return file size, dev_size. */
  1847. NULL, /*!< \brief Select function, optional, not yet implemented */
  1848. };
  1849. /*!
  1850. * \brief UFLASH1 file system device.
  1851. */
  1852. NUTDEVICE devUFlash1 = {
  1853. 0, /*!< \brief Pointer to next device, dev_next. */
  1854. {'U', 'F', 'L', 'A', 'S', 'H', '1', 0, 0}
  1855. , /*!< \brief Unique device name, dev_name. */
  1856. IFTYP_FS, /*!< \brief Type of device, dev_type. Obsolete. */
  1857. 1, /*!< \brief Chip select, dev_base. */
  1858. 0, /*!< \brief First interrupt number, dev_irq. Unused. */
  1859. NULL, /*!< \brief Attached serial flash interface, dev_icb. */
  1860. NULL, /*!< \brief Mounted volume information, dev_dcb. */
  1861. UFlashInit, /*!< \brief Driver initialization routine, dev_init. */
  1862. UFlashIOCtl, /*!< \brief Driver specific control function, dev_ioctl. */
  1863. UFlashFileRead, /*!< \brief Read data from a file, dev_read. */
  1864. UFlashFileWrite, /*!< \brief Write data to a file, dev_write. */
  1865. #ifdef __HARVARD_ARCH__
  1866. UFlashFileWrite_P, /*!< \brief Write data from program space to a file, dev_write_P. */
  1867. #endif
  1868. UFlashFileOpen, /*!< \brief Open a file, dev_open. */
  1869. UFlashFileClose, /*!< \brief Close a file, dev_close. */
  1870. UFlashFileSize, /*!< \brief Return file size, dev_size. */
  1871. NULL, /*!< \brief Select function, optional, not yet implemented */
  1872. };
  1873. /*@}*/