luat_main.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "luat_base.h"
  2. #include "luat_malloc.h"
  3. #include "luat_fs.h"
  4. #include "stdio.h"
  5. #include "luat_msgbus.h"
  6. #include "luat_timer.h"
  7. #define LUAT_LOG_TAG "luat.main"
  8. #include "luat_log.h"
  9. static int report (lua_State *L, int status);
  10. lua_State *L;
  11. static uint8_t boot_mode = 1;
  12. void stopboot(void) {
  13. boot_mode = 0;
  14. }
  15. lua_State * luat_get_state() {
  16. return L;
  17. }
  18. static int pmain(lua_State *L) {
  19. int re = 0;
  20. #ifdef LUA_32BITS
  21. LLOGD("Lua complied with LUA_32BITS");
  22. #endif
  23. // 加载内置库
  24. luat_openlibs(L);
  25. size_t total; size_t used; size_t max_used;
  26. luat_meminfo_luavm(&total, &used, &max_used);
  27. LLOGD("luavm %ld %ld %ld", total, used, max_used);
  28. luat_meminfo_sys(&total, &used, &max_used);
  29. LLOGD("sys %ld %ld %ld", total, used, max_used);
  30. lua_gc(L, LUA_GCSETPAUSE, 90); // 设置`垃圾收集器间歇率`要低于100%
  31. // 加载main.lua
  32. //re = luaL_dofile(L, "/main.lua");
  33. re = luaL_dostring(L, "require(\"main\")");
  34. report(L, re);
  35. lua_pushboolean(L, 1); /* signal no errors */
  36. return 1;
  37. }
  38. /*
  39. ** Prints an error message, adding the program name in front of it
  40. ** (if present)
  41. */
  42. static void l_message (const char *pname, const char *msg) {
  43. if (pname) lua_writestringerror("%s: ", pname);
  44. lua_writestringerror("%s\n", msg);
  45. }
  46. /*
  47. ** Check whether 'status' is not OK and, if so, prints the error
  48. ** message on the top of the stack. It assumes that the error object
  49. ** is a string, as it was either generated by Lua or by 'msghandler'.
  50. */
  51. static int report (lua_State *L, int status) {
  52. if (status != LUA_OK) {
  53. const char *msg = lua_tostring(L, -1);
  54. l_message("LUAT", msg);
  55. lua_pop(L, 1); /* remove message */
  56. }
  57. return status;
  58. }
  59. static int panic (lua_State *L) {
  60. lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
  61. lua_tostring(L, -1));
  62. return 0; /* return to Lua to abort */
  63. }
  64. #define UPDATE_BIN_PATH "/update.bin"
  65. #define ROLLBACK_MARK_PATH "/rollback_mark"
  66. #define UPDATE_MARK "/update_mark"
  67. #define FLASHX_PATH "/flashx.bin"
  68. int luat_bin_unpack(const char* path);
  69. static void check_update(void) {
  70. // 首先, 升级文件是否存在呢?
  71. if (!luat_fs_fexist(UPDATE_BIN_PATH)) {
  72. // 不存在, 正常启动
  73. return;
  74. }
  75. // 找到了, 检查一下大小
  76. LLOGI("found " UPDATE_BIN_PATH " ...");
  77. size_t fsize = luat_fs_fsize(UPDATE_BIN_PATH);
  78. if (fsize < 256) {
  79. // 太小了, 肯定不合法, 直接移除, 正常启动
  80. LLOGW(UPDATE_BIN_PATH " is too small, delete it");
  81. luat_fs_remove(UPDATE_BIN_PATH);
  82. return;
  83. }
  84. // 写入标志文件.
  85. // 必须提前写入, 即使解包失败, 仍标记为升级过,这样报错就能回滚
  86. LLOGI("write " UPDATE_MARK " first");
  87. FILE* fd = luat_fs_fopen(UPDATE_MARK, "wb");
  88. if (fd) {
  89. luat_fs_fclose(fd);
  90. // TODO 连标志文件都写入失败,怎么办?
  91. }
  92. // 开始解包升级文件
  93. if (luat_bin_unpack(UPDATE_BIN_PATH) == LUA_OK) {
  94. LLOGI("update OK, remove " UPDATE_BIN_PATH);
  95. }
  96. else {
  97. LLOGW("update FAIL, remove " UPDATE_BIN_PATH);
  98. }
  99. // 无论是否成功,都一定要删除升级文件, 防止升级死循环
  100. luat_fs_remove(UPDATE_BIN_PATH);
  101. // 延迟5秒,重启
  102. LLOGW("update: reboot at 5 secs");
  103. luat_timer_mdelay(5*1000);
  104. luat_os_reboot(0); // 重启
  105. }
  106. static void check_rollback(void) {
  107. // 首先, 查一下是否有回滚文件
  108. if (!luat_fs_fexist(ROLLBACK_MARK_PATH)) {
  109. return; // 没有回滚标志文件, 正常启动
  110. }
  111. // 回滚文件存在,
  112. LLOGW("Found " ROLLBACK_MARK_PATH ", check rollback");
  113. // 首先,移除回滚标志, 防止重复N次的回滚
  114. luat_fs_remove("/rollback_mark"); // TODO 如果删除也失败呢?
  115. // 然后检查原始文件, flashx.bin
  116. if (!luat_fs_fexist(FLASHX_PATH)) {
  117. LLOGW("NOT " FLASHX_PATH " , can't rollback");
  118. return;
  119. }
  120. // 存在原始flashx.bin
  121. LLOGD("found " FLASHX_PATH ", unpack it");
  122. // 开始回滚操作
  123. if (luat_bin_unpack(FLASHX_PATH) == LUA_OK) {
  124. LLOGI("rollback complete!");
  125. }
  126. else {
  127. LLOGE("rollback FAIL");
  128. }
  129. // 执行完成, 准备重启
  130. LLOGW("rollback: reboot at 5 secs");
  131. // 延迟5秒后,重启
  132. luat_timer_mdelay(5*1000);
  133. luat_os_reboot(0); // 重启
  134. }
  135. int luat_main (void) {
  136. if (boot_mode == 0) {
  137. return 0; // just nop
  138. }
  139. LLOGI("LuatOS@%s %s, build at: " __DATE__ " " __TIME__, luat_os_bsp(), LUAT_VERSION);
  140. // 1. 初始化文件系统
  141. luat_fs_init();
  142. // 2. 是否需要升级?
  143. check_update();
  144. // 3. 是否需要回滚呢?
  145. check_rollback();
  146. // 4. init Lua State
  147. int status, result;
  148. L = lua_newstate(luat_heap_alloc, NULL);
  149. if (L == NULL) {
  150. l_message("LUAVM", "cannot create state: not enough memory\n");
  151. goto _exit;
  152. }
  153. if (L) lua_atpanic(L, &panic);
  154. //print_list_mem("after lua_newstate");
  155. lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
  156. //lua_pushinteger(L, argc); /* 1st argument */
  157. //lua_pushlightuserdata(L, argv); /* 2nd argument */
  158. status = lua_pcall(L, 0, 1, 0); /* do the call */
  159. result = lua_toboolean(L, -1); /* get result */
  160. report(L, status);
  161. lua_close(L);
  162. _exit:
  163. LLOGE("Lua VM exit!! reboot in 30s");
  164. // 既然是异常退出,那肯定出错了!!!
  165. // 如果升级过, 那么就写入标志文件
  166. {
  167. if (luat_fs_fexist(UPDATE_MARK)) {
  168. FILE* fd = luat_fs_fopen("/rollback_mark", "wb");
  169. if (fd) {
  170. luat_fs_fclose(fd);
  171. }
  172. }
  173. else {
  174. // 没升级过, 那就是线刷, 不存在回滚
  175. }
  176. }
  177. // 等30秒,就重启吧
  178. luat_timer_mdelay(30*1000);
  179. luat_os_reboot(result);
  180. // 往下是肯定不会被执行的
  181. return (result && status == LUA_OK) ? 0 : 2;
  182. }
  183. //#include "vsprintf.h"
  184. #include "printf.h"
  185. __attribute__((weak)) int l_sprintf(char *buf, size_t size, const char *fmt, ...) {
  186. int32_t n;
  187. va_list args;
  188. va_start(args, fmt);
  189. //n = custom_vsprintf(buf, /*size,*/ fmt, args);
  190. n = vsnprintf_(buf, size, fmt, args);
  191. va_end(args);
  192. return n;
  193. }