luat_main.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. #ifdef LUA_USE_WINDOWS
  10. #include <stdlib.h>
  11. extern int win32_argc;
  12. extern char** win32_argv;
  13. #endif
  14. static int report (lua_State *L, int status);
  15. lua_State *L;
  16. static uint8_t boot_mode = 1;
  17. void stopboot(void) {
  18. boot_mode = 0;
  19. }
  20. lua_State * luat_get_state() {
  21. return L;
  22. }
  23. int luat_search_module(const char* name, char* filename);
  24. void luat_os_print_heapinfo(const char* tag);
  25. static int pmain(lua_State *L) {
  26. int re = -2;
  27. #ifdef LUA_32BITS
  28. //LLOGD("Lua complied with LUA_32BITS");
  29. #endif
  30. luat_os_print_heapinfo("boot");
  31. // 加载内置库
  32. luat_openlibs(L);
  33. luat_os_print_heapinfo("loadlibs");
  34. lua_gc(L, LUA_GCSETPAUSE, 90); // 设置`垃圾收集器间歇率`要低于100%
  35. // 加载main.lua
  36. #ifdef LUA_USE_WINDOWS
  37. if (win32_argc > 1) {
  38. int slen = strlen(win32_argv[1]);
  39. if (slen > 4 && !strcmp(".lua", win32_argv[1] + (slen - 4)))
  40. re = luaL_dofile(L, win32_argv[1]);
  41. }
  42. #endif
  43. if (re == -2) {
  44. char filename[32] = {0};
  45. if (luat_search_module("main", filename) == 0) {
  46. re = luaL_dofile(L, filename);
  47. }
  48. else {
  49. re = -1;
  50. luaL_error(L, "module '%s' not found", "main");
  51. }
  52. }
  53. report(L, re);
  54. lua_pushboolean(L, re == LUA_OK); /* signal no errors */
  55. return 1;
  56. }
  57. /*
  58. ** Prints an error message, adding the program name in front of it
  59. ** (if present)
  60. */
  61. static void l_message (const char *pname, const char *msg) {
  62. if (pname) lua_writestringerror("%s: ", pname);
  63. lua_writestringerror("%s\n", msg);
  64. }
  65. /*
  66. ** Check whether 'status' is not OK and, if so, prints the error
  67. ** message on the top of the stack. It assumes that the error object
  68. ** is a string, as it was either generated by Lua or by 'msghandler'.
  69. */
  70. static int report (lua_State *L, int status) {
  71. if (status != LUA_OK) {
  72. const char *msg = lua_tostring(L, -1);
  73. l_message("LUAT", msg);
  74. lua_pop(L, 1); /* remove message */
  75. }
  76. return status;
  77. }
  78. static int panic (lua_State *L) {
  79. lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
  80. lua_tostring(L, -1));
  81. return 0; /* return to Lua to abort */
  82. }
  83. #define UPDATE_BIN_PATH "/update.bin"
  84. #define ROLLBACK_MARK_PATH "/rollback_mark"
  85. #define UPDATE_MARK "/update_mark"
  86. #define FLASHX_PATH "/flashx.bin"
  87. #ifndef LUAT_OTA_MODE
  88. #define LUAT_OTA_MODE 1
  89. #endif
  90. #ifndef LUAT_EXIT_REBOOT_DELAY
  91. #define LUAT_EXIT_REBOOT_DELAY 15000
  92. #endif
  93. int luat_bin_unpack(const char* path, int writeOut);
  94. int luat_ota_need_update(void) {
  95. return (luat_fs_fexist(UPDATE_BIN_PATH)) ? 1 : 0;
  96. }
  97. int luat_ota_need_rollback(void) {
  98. return (luat_fs_fexist(ROLLBACK_MARK_PATH)) ? 1 : 0;
  99. }
  100. int luat_ota_mark_rollback(void) {
  101. // 既然是异常退出,那肯定出错了!!!
  102. // 如果升级过, 那么就写入标志文件
  103. {
  104. if (luat_fs_fexist(UPDATE_MARK)) {
  105. FILE* fd = luat_fs_fopen("/rollback_mark", "wb");
  106. if (fd) {
  107. luat_fs_fclose(fd);
  108. }
  109. }
  110. else {
  111. // 没升级过, 那就是线刷, 不存在回滚
  112. }
  113. }
  114. return 0;
  115. }
  116. static void luat_bin_exec_update(void);
  117. static void luat_bin_exec_rollback(void);
  118. LUAT_WEAK void luat_ota_reboot(int timeout) {
  119. if (timeout > 0)
  120. luat_timer_mdelay(timeout * 1000);
  121. luat_os_reboot(1);
  122. }
  123. void luat_ota_exec_update(void) {
  124. #if LUAT_OTA_MODE == 1
  125. luat_bin_exec_update();
  126. #elif LUAT_OTA_MODE == 2
  127. luat_db_exec_update();
  128. #endif
  129. }
  130. void luat_ota_exec_rollback(void) {
  131. #if LUAT_OTA_MODE == 1
  132. luat_bin_exec_rollback();
  133. #elif LUAT_OTA_MODE == 2
  134. luat_db_exec_rollback();
  135. #endif
  136. }
  137. int luat_ota_update_or_rollback(void) {
  138. if (luat_ota_need_update()) {
  139. luat_ota_exec_update();
  140. LLOGW("update: reboot at 5 secs");
  141. luat_ota_reboot(5);
  142. return 1;
  143. }
  144. if (luat_ota_need_rollback()) {
  145. luat_ota_exec_rollback();
  146. LLOGW("rollback: reboot at 5 secs");
  147. luat_ota_reboot(5);
  148. return 1;
  149. }
  150. return 0;
  151. }
  152. static void luat_bin_exec_update(void) {
  153. // 找到了, 检查一下大小
  154. LLOGI("found " UPDATE_BIN_PATH " ...");
  155. size_t fsize = luat_fs_fsize(UPDATE_BIN_PATH);
  156. if (fsize < 256) {
  157. // 太小了, 肯定不合法, 直接移除, 正常启动
  158. LLOGW(UPDATE_BIN_PATH " is too small, delete it");
  159. luat_fs_remove(UPDATE_BIN_PATH);
  160. return;
  161. }
  162. // 写入标志文件.
  163. // 必须提前写入, 即使解包失败, 仍标记为升级过,这样报错就能回滚
  164. LLOGI("write " UPDATE_MARK " first");
  165. FILE* fd = luat_fs_fopen(UPDATE_MARK, "wb");
  166. if (fd) {
  167. luat_fs_fclose(fd);
  168. // TODO 连标志文件都写入失败,怎么办?
  169. }
  170. // 检测升级包合法性
  171. if (luat_bin_unpack(UPDATE_BIN_PATH, 0) != LUA_OK) {
  172. LLOGE("%s is invaild!!", UPDATE_BIN_PATH);
  173. }
  174. else {
  175. // 开始解包升级文件
  176. if (luat_bin_unpack(UPDATE_BIN_PATH, 1) == LUA_OK) {
  177. LLOGI("update OK, remove " UPDATE_BIN_PATH);
  178. }
  179. else {
  180. LLOGW("update FAIL, remove " UPDATE_BIN_PATH);
  181. }
  182. }
  183. // 无论是否成功,都一定要删除升级文件, 防止升级死循环
  184. luat_fs_remove(UPDATE_BIN_PATH);
  185. }
  186. static void luat_bin_exec_rollback(void) {
  187. // 回滚文件存在,
  188. LLOGW("Found " ROLLBACK_MARK_PATH ", check rollback");
  189. // 首先,移除回滚标志, 防止重复N次的回滚
  190. luat_fs_remove("/rollback_mark"); // TODO 如果删除也失败呢?
  191. // 然后检查原始文件, flashx.bin
  192. if (!luat_fs_fexist(FLASHX_PATH)) {
  193. LLOGW("NOT " FLASHX_PATH " , can't rollback");
  194. return;
  195. }
  196. // 存在原始flashx.bin
  197. LLOGD("found " FLASHX_PATH ", unpack it");
  198. // 开始回滚操作
  199. if (luat_bin_unpack(FLASHX_PATH, 1) == LUA_OK) {
  200. LLOGI("rollback complete!");
  201. }
  202. else {
  203. LLOGE("rollback FAIL");
  204. }
  205. // 执行完成, 准备重启
  206. LLOGW("rollback: reboot at 5 secs");
  207. // 延迟5秒后,重启
  208. luat_timer_mdelay(5*1000);
  209. luat_os_reboot(0); // 重启
  210. }
  211. int luat_main_call(void) {
  212. // 4. init Lua State
  213. int status = 0;
  214. int result = 0;
  215. L = lua_newstate(luat_heap_alloc, NULL);
  216. if (L == NULL) {
  217. l_message("lua", "cannot create state: not enough memory\n");
  218. goto _exit;
  219. }
  220. if (L) lua_atpanic(L, &panic);
  221. //print_list_mem("after lua_newstate");
  222. lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
  223. //lua_pushinteger(L, argc); /* 1st argument */
  224. //lua_pushlightuserdata(L, argv); /* 2nd argument */
  225. status = lua_pcall(L, 0, 1, 0); /* do the call */
  226. result = lua_toboolean(L, -1); /* get result */
  227. report(L, status);
  228. //lua_close(L);
  229. _exit:
  230. #ifdef LUA_USE_WINDOWS
  231. result = !result;
  232. LLOGE("Lua VM exit!! result:%d",result);
  233. exit(result);
  234. #endif
  235. }
  236. int luat_main (void) {
  237. if (boot_mode == 0) {
  238. return 0; // just nop
  239. }
  240. LLOGI("LuatOS@%s %s, Build: " __DATE__ " " __TIME__, luat_os_bsp(), LUAT_VERSION);
  241. #if LUAT_VERSION_BETA
  242. LLOGD("This is a beta version, for testing");
  243. #endif
  244. // 1. 初始化文件系统
  245. luat_fs_init();
  246. // 是否需要升级或者回滚
  247. luat_ota_update_or_rollback();
  248. int result = luat_main_call();
  249. LLOGE("Lua VM exit!! reboot in %dms", LUAT_EXIT_REBOOT_DELAY);
  250. luat_ota_reboot(LUAT_EXIT_REBOOT_DELAY);
  251. // 往下是肯定不会被执行的
  252. return 0;
  253. }
  254. #include "rotable.h"
  255. void luat_newlib(lua_State* l, const rotable_Reg* reg) {
  256. #ifdef LUAT_CONF_DISABLE_ROTABLE
  257. luaL_newlibtable(l,reg);
  258. int i;
  259. int nup = 0;
  260. luaL_checkstack(l, nup, "too many upvalues");
  261. for (; reg->name != NULL; reg++) { /* fill the table with given functions */
  262. for (i = 0; i < nup; i++) /* copy upvalues to the top */
  263. lua_pushvalue(l, -nup);
  264. if (reg->func)
  265. lua_pushcclosure(l, reg->func, nup); /* closure with those upvalues */
  266. else
  267. lua_pushinteger(l, reg->value);
  268. lua_setfield(l, -(nup + 2), reg->name);
  269. }
  270. lua_pop(l, nup); /* remove upvalues */
  271. #else
  272. rotable_newlib(l, reg);
  273. #endif
  274. }
  275. void luat_os_print_heapinfo(const char* tag) {
  276. size_t total; size_t used; size_t max_used;
  277. luat_meminfo_luavm(&total, &used, &max_used);
  278. LLOGD("%s luavm %ld %ld %ld", tag, total, used, max_used);
  279. luat_meminfo_sys(&total, &used, &max_used);
  280. LLOGD("%s sys %ld %ld %ld", tag, total, used, max_used);
  281. }