| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- #include "luat_base.h"
- #include "luat_malloc.h"
- #include "luat_fs.h"
- #include "stdio.h"
- #include "luat_msgbus.h"
- #include "luat_timer.h"
- #define LUAT_LOG_TAG "luat.main"
- #include "luat_log.h"
- static int report (lua_State *L, int status);
- lua_State *L;
- static uint8_t boot_mode = 1;
- void stopboot(void) {
- boot_mode = 0;
- }
- lua_State * luat_get_state() {
- return L;
- }
- static int pmain(lua_State *L) {
- int re = 0;
- #ifdef LUA_32BITS
- LLOGD("Lua complied with LUA_32BITS");
- #endif
- // 加载内置库
- luat_openlibs(L);
- size_t total; size_t used; size_t max_used;
- luat_meminfo_luavm(&total, &used, &max_used);
- LLOGD("luavm %ld %ld %ld", total, used, max_used);
- luat_meminfo_sys(&total, &used, &max_used);
- LLOGD("sys %ld %ld %ld", total, used, max_used);
- lua_gc(L, LUA_GCSETPAUSE, 90); // 设置`垃圾收集器间歇率`要低于100%
-
- // 加载main.lua
- //re = luaL_dofile(L, "/main.lua");
- re = luaL_dostring(L, "require(\"main\")");
- report(L, re);
- lua_pushboolean(L, 1); /* signal no errors */
- return 1;
- }
- /*
- ** Prints an error message, adding the program name in front of it
- ** (if present)
- */
- static void l_message (const char *pname, const char *msg) {
- if (pname) lua_writestringerror("%s: ", pname);
- lua_writestringerror("%s\n", msg);
- }
- /*
- ** Check whether 'status' is not OK and, if so, prints the error
- ** message on the top of the stack. It assumes that the error object
- ** is a string, as it was either generated by Lua or by 'msghandler'.
- */
- static int report (lua_State *L, int status) {
- if (status != LUA_OK) {
- const char *msg = lua_tostring(L, -1);
- l_message("LUAT", msg);
- lua_pop(L, 1); /* remove message */
- }
- return status;
- }
- static int panic (lua_State *L) {
- lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
- lua_tostring(L, -1));
- return 0; /* return to Lua to abort */
- }
- #define UPDATE_BIN_PATH "/update.bin"
- #define ROLLBACK_MARK_PATH "/rollback_mark"
- #define UPDATE_MARK "/update_mark"
- #define FLASHX_PATH "/flashx.bin"
- int luat_bin_unpack(const char* path);
- static void check_update(void) {
- // 首先, 升级文件是否存在呢?
- if (!luat_fs_fexist(UPDATE_BIN_PATH)) {
- // 不存在, 正常启动
- return;
- }
- // 找到了, 检查一下大小
- LLOGI("found " UPDATE_BIN_PATH " ...");
- size_t fsize = luat_fs_fsize(UPDATE_BIN_PATH);
- if (fsize < 256) {
- // 太小了, 肯定不合法, 直接移除, 正常启动
- LLOGW(UPDATE_BIN_PATH " is too small, delete it");
- luat_fs_remove(UPDATE_BIN_PATH);
- return;
- }
- // 写入标志文件.
- // 必须提前写入, 即使解包失败, 仍标记为升级过,这样报错就能回滚
- LLOGI("write " UPDATE_MARK " first");
- FILE* fd = luat_fs_fopen(UPDATE_MARK, "wb");
- if (fd) {
- luat_fs_fclose(fd);
- // TODO 连标志文件都写入失败,怎么办?
- }
- // 开始解包升级文件
- if (luat_bin_unpack(UPDATE_BIN_PATH) == LUA_OK) {
- LLOGI("update OK, remove " UPDATE_BIN_PATH);
- }
- else {
- LLOGW("update FAIL, remove " UPDATE_BIN_PATH);
- }
- // 无论是否成功,都一定要删除升级文件, 防止升级死循环
- luat_fs_remove(UPDATE_BIN_PATH);
- // 延迟5秒,重启
- LLOGW("update: reboot at 5 secs");
- luat_timer_mdelay(5*1000);
- luat_os_reboot(0); // 重启
- }
- static void check_rollback(void) {
- // 首先, 查一下是否有回滚文件
- if (!luat_fs_fexist(ROLLBACK_MARK_PATH)) {
- return; // 没有回滚标志文件, 正常启动
- }
- // 回滚文件存在,
- LLOGW("Found " ROLLBACK_MARK_PATH ", check rollback");
- // 首先,移除回滚标志, 防止重复N次的回滚
- luat_fs_remove("/rollback_mark"); // TODO 如果删除也失败呢?
- // 然后检查原始文件, flashx.bin
- if (!luat_fs_fexist(FLASHX_PATH)) {
- LLOGW("NOT " FLASHX_PATH " , can't rollback");
- return;
- }
- // 存在原始flashx.bin
- LLOGD("found " FLASHX_PATH ", unpack it");
- // 开始回滚操作
- if (luat_bin_unpack(FLASHX_PATH) == LUA_OK) {
- LLOGI("rollback complete!");
- }
- else {
- LLOGE("rollback FAIL");
- }
- // 执行完成, 准备重启
- LLOGW("rollback: reboot at 5 secs");
- // 延迟5秒后,重启
- luat_timer_mdelay(5*1000);
- luat_os_reboot(0); // 重启
- }
- int luat_main (void) {
- if (boot_mode == 0) {
- return 0; // just nop
- }
- LLOGI("LuatOS@%s %s, build at: " __DATE__ " " __TIME__, luat_os_bsp(), LUAT_VERSION);
- // 1. 初始化文件系统
- luat_fs_init();
- // 2. 是否需要升级?
- check_update();
- // 3. 是否需要回滚呢?
- check_rollback();
- // 4. init Lua State
- int status, result;
- L = lua_newstate(luat_heap_alloc, NULL);
- if (L == NULL) {
- l_message("LUAVM", "cannot create state: not enough memory\n");
- goto _exit;
- }
- if (L) lua_atpanic(L, &panic);
- //print_list_mem("after lua_newstate");
- lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
- //lua_pushinteger(L, argc); /* 1st argument */
- //lua_pushlightuserdata(L, argv); /* 2nd argument */
- status = lua_pcall(L, 0, 1, 0); /* do the call */
- result = lua_toboolean(L, -1); /* get result */
- report(L, status);
- lua_close(L);
- _exit:
- LLOGE("Lua VM exit!! reboot in 30s");
- // 既然是异常退出,那肯定出错了!!!
- // 如果升级过, 那么就写入标志文件
- {
- if (luat_fs_fexist(UPDATE_MARK)) {
- FILE* fd = luat_fs_fopen("/rollback_mark", "wb");
- if (fd) {
- luat_fs_fclose(fd);
- }
- }
- else {
- // 没升级过, 那就是线刷, 不存在回滚
- }
- }
- // 等30秒,就重启吧
- luat_timer_mdelay(30*1000);
- luat_os_reboot(result);
- // 往下是肯定不会被执行的
- return (result && status == LUA_OK) ? 0 : 2;
- }
- //#include "vsprintf.h"
- #include "printf.h"
- __attribute__((weak)) int l_sprintf(char *buf, size_t size, const char *fmt, ...) {
- int32_t n;
- va_list args;
- va_start(args, fmt);
- //n = custom_vsprintf(buf, /*size,*/ fmt, args);
- n = vsnprintf_(buf, size, fmt, args);
- va_end(args);
- return n;
- }
|