lflash.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. ** $Id: lflash.c
  3. ** See Copyright Notice in lua.h
  4. */
  5. #define lflash_c
  6. #define LUA_CORE
  7. #define LUAC_CROSS_FILE
  8. #include "lua.h"
  9. #ifdef LUA_FLASH_STORE
  10. #include "lobject.h"
  11. #include "lauxlib.h"
  12. #include "lstate.h"
  13. #include "lfunc.h"
  14. #include "lflash.h"
  15. #include "platform.h"
  16. #include "vfs.h"
  17. #include "c_fcntl.h"
  18. #include "c_stdio.h"
  19. #include "c_stdlib.h"
  20. #include "c_string.h"
  21. /*
  22. * Flash memory is a fixed memory addressable block that is serially allocated by the
  23. * luac build process and the out image can be downloaded into SPIFSS and loaded into
  24. * flash with a node.flash.load() command. See luac_cross/lflashimg.c for the build
  25. * process.
  26. */
  27. static char *flashAddr;
  28. static uint32_t flashAddrPhys;
  29. static uint32_t flashSector;
  30. static uint32_t curOffset;
  31. #define ALIGN(s) (((s)+sizeof(size_t)-1) & ((size_t) (- (signed) sizeof(size_t))))
  32. #define ALIGN_BITS(s) (((uint32_t)s) & (sizeof(size_t)-1))
  33. #define ALL_SET cast(uint32_t, -1)
  34. #define FLASH_SIZE LUA_FLASH_STORE
  35. #define FLASH_PAGE_SIZE INTERNAL_FLASH_SECTOR_SIZE
  36. #define FLASH_PAGES (FLASH_SIZE/FLASH_PAGE_SIZE)
  37. char flash_region_base[FLASH_SIZE] ICACHE_FLASH_RESERVED_ATTR;
  38. #ifdef NODE_DEBUG
  39. extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
  40. void dumpStrt(stringtable *tb, const char *type) {
  41. int i,j;
  42. GCObject *o;
  43. NODE_DBG("\nDumping %s String table\n\n========================\n", type);
  44. NODE_DBG("No of elements: %d\nSize of table: %d\n", tb->nuse, tb->size);
  45. for (i=0; i<tb->size; i++)
  46. for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
  47. TString *ts =cast(TString *, o);
  48. NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n",
  49. i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len,
  50. ts_isreadonly(ts) ? "R" : " ", getstr(ts));
  51. }
  52. }
  53. LUA_API void dumpStrings(lua_State *L) {
  54. dumpStrt(&G(L)->strt, "RAM");
  55. if (G(L)->ROstrt.hash)
  56. dumpStrt(&G(L)->ROstrt, "ROM");
  57. }
  58. #endif
  59. /* =====================================================================================
  60. * The next 4 functions: flashPosition, flashSetPosition, flashBlock and flashErase
  61. * wrap writing to flash. The last two are platform dependent. Also note that any
  62. * writes are suppressed if the global writeToFlash is false. This is used in
  63. * phase I where the pass is used to size the structures in flash.
  64. */
  65. static char *flashPosition(void){
  66. return flashAddr + curOffset;
  67. }
  68. static char *flashSetPosition(uint32_t offset){
  69. NODE_DBG("flashSetPosition(%04x)\n", offset);
  70. curOffset = offset;
  71. return flashPosition();
  72. }
  73. static char *flashBlock(const void* b, size_t size) {
  74. void *cur = flashPosition();
  75. NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,b,size);
  76. lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0);
  77. platform_flash_write(b, flashAddrPhys+curOffset, size);
  78. curOffset += size;
  79. return cur;
  80. }
  81. static void flashErase(uint32_t start, uint32_t end){
  82. int i;
  83. if (start == -1) start = FLASH_PAGES - 1;
  84. if (end == -1) end = FLASH_PAGES - 1;
  85. NODE_DBG("flashErase(%04x,%04x)\n", flashSector+start, flashSector+end);
  86. for (i = start; i<=end; i++)
  87. platform_flash_erase_sector( flashSector + i );
  88. }
  89. /*
  90. * Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
  91. */
  92. LUAI_FUNC void luaN_init (lua_State *L) {
  93. // luaL_dbgbreak();
  94. curOffset = 0;
  95. flashAddr = flash_region_base;
  96. flashAddrPhys = platform_flash_mapped2phys((uint32_t)flashAddr);
  97. flashSector = platform_flash_get_sector_of_address(flashAddrPhys);
  98. FlashHeader *fh = cast(FlashHeader *, flashAddr);
  99. /*
  100. * For the LFS to be valid, its signature has to be correct for this build variant,
  101. * thr ROhash and main proto fields must be defined and the main proto address
  102. * be within the LFS address bounds. (This last check is primarily to detect the
  103. * direct imaging of an absolute LFS with the wrong base address.
  104. */
  105. if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
  106. NODE_ERR("Flash sig not correct: %p vs %p\n",
  107. fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
  108. return;
  109. }
  110. if (fh->pROhash == ALL_SET ||
  111. ((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
  112. NODE_ERR("Flash size check failed: %p vs 0xFFFFFFFF; %p >= %p\n",
  113. fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
  114. return;
  115. }
  116. G(L)->ROstrt.hash = cast(GCObject **, fh->pROhash);
  117. G(L)->ROstrt.nuse = fh->nROuse ;
  118. G(L)->ROstrt.size = fh->nROsize;
  119. G(L)->ROpvmain = cast(Proto *,fh->mainProto);
  120. }
  121. #define BYTE_OFFSET(t,f) cast(size_t, &(cast(t *, NULL)->f))
  122. /*
  123. * Rehook address chain to correct Flash byte addressed within the mapped adress space
  124. * Note that on input each 32-bit address field is split into 2×16-bit subfields
  125. * - the lu_int16 offset of the target address being referenced
  126. * - the lu_int16 offset of the next address pointer.
  127. */
  128. static int rebuild_core (int fd, uint32_t size, lu_int32 *buf, int is_absolute) {
  129. int bi; /* byte offset into memory mapped LFS of current buffer */
  130. int wNextOffset = BYTE_OFFSET(FlashHeader,mainProto)/sizeof(lu_int32);
  131. int wj; /* word offset into current input buffer */
  132. for (bi = 0; bi < size; bi += FLASH_PAGE_SIZE) {
  133. int wi = bi / sizeof(lu_int32);
  134. int blen = ((bi + FLASH_PAGE_SIZE) < size) ? FLASH_PAGE_SIZE : size - bi;
  135. int wlen = blen / sizeof(lu_int32);
  136. if (vfs_read(fd, buf , blen) != blen)
  137. return 0;
  138. if (!is_absolute) {
  139. for (wj = 0; wj < wlen; wj++) {
  140. if ((wi + wj) == wNextOffset) { /* this word is the next linked address */
  141. int wTargetOffset = buf[wj]&0xFFFF;
  142. wNextOffset = buf[wj]>>16;
  143. lua_assert(!wNextOffset || (wNextOffset>(wi+wj) && wNextOffset<size/sizeof(lu_int32)));
  144. buf[wj] = cast(lu_int32, flashAddr + wTargetOffset*sizeof(lu_int32));
  145. }
  146. }
  147. }
  148. flashBlock(buf, blen);
  149. }
  150. return size;
  151. }
  152. /*
  153. * Library function called by node.flash.load(filename).
  154. */
  155. LUALIB_API int luaN_reload_reboot (lua_State *L) {
  156. int fd, status, is_absolute;
  157. FlashHeader fh;
  158. const char *fn = lua_tostring(L, 1);
  159. if (!fn || !(fd = vfs_open(fn, "r")))
  160. return 0;
  161. if (vfs_read(fd, &fh, sizeof(fh)) != sizeof(fh) ||
  162. (fh.flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG)
  163. return 0;
  164. if (vfs_lseek(fd, -1, VFS_SEEK_END) != fh.flash_size-1 ||
  165. vfs_lseek(fd, 0, VFS_SEEK_SET) != 0)
  166. return 0;
  167. is_absolute = fh.flash_sig & FLASH_SIG_ABSOLUTE;
  168. lu_int32 *buffer = luaM_newvector(L, FLASH_PAGE_SIZE / sizeof(lu_int32), lu_int32);
  169. /*
  170. * This is the point of no return. We attempt to rebuild the flash. If there
  171. * are any problems them the Flash is going to be corrupt, so the only fallback
  172. * is to erase it and reboot with a clean but blank flash. Otherwise the reboot
  173. * will load the new LFS.
  174. *
  175. * Note that the Lua state is not passed into the lua core because from this
  176. * point on, we make no calls on the Lua RTS.
  177. */
  178. flashErase(0,-1);
  179. if (rebuild_core(fd, fh.flash_size, buffer, is_absolute) != fh.flash_size)
  180. flashErase(0,-1);
  181. /*
  182. * Issue a break 0,0. This will either enter the debugger or force a restart if
  183. * not installed. Follow this by a H/W timeout is a robust way to insure that
  184. * other interrupts / callbacks don't fire and reference THE old LFS context.
  185. */
  186. asm("break 0,0" ::);
  187. while (1) {}
  188. return 0;
  189. }
  190. /*
  191. * In the arg is a valid LFS module name then return the LClosure pointing to it.
  192. * Otherwise return:
  193. * - The Unix time that the LFS was built
  194. * - The base address and length of the LFS
  195. * - An array of the module names in the the LFS
  196. */
  197. LUAI_FUNC int luaN_index (lua_State *L) {
  198. int i;
  199. int n = lua_gettop(L);
  200. /* Return nil + the LFS base address if the LFS isn't loaded */
  201. if(!(G(L)->ROpvmain)) {
  202. lua_settop(L, 0);
  203. lua_pushnil(L);
  204. lua_pushinteger(L, (lua_Integer) flashAddr);
  205. lua_pushinteger(L, flashAddrPhys);
  206. return 3;
  207. }
  208. /* Push the LClosure of the LFS index function */
  209. Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
  210. cl->l.p = G(L)->ROpvmain;
  211. lua_settop(L, n+1);
  212. setclvalue(L, L->top-1, cl);
  213. /* Move it infront of the arguments and call the index function */
  214. lua_insert(L, 1);
  215. lua_call(L, n, LUA_MULTRET);
  216. /* Return it if the response if a single value (the function) */
  217. if (lua_gettop(L) == 1)
  218. return 1;
  219. lua_assert(lua_gettop(L) == 2);
  220. /* Otherwise add the base address of the LFS, and its size bewteen the */
  221. /* Unix time and the module list, then return all 4 params. */
  222. lua_pushinteger(L, (lua_Integer) flashAddr);
  223. lua_insert(L, 2);
  224. lua_pushinteger(L, flashAddrPhys);
  225. lua_insert(L, 3);
  226. lua_pushinteger(L, cast(FlashHeader *, flashAddr)->flash_size);
  227. lua_insert(L, 4);
  228. return 5;
  229. }
  230. #endif