Browse Source

Lfs fix (#131)

* added
- usage info for LFS targets
- lfs.img build rule (requires luac.cross from nodemcu-firmware)
- basic autodetection for USB serial device

* updated LFS code for recent nodemcu versions

* safe default (SOFTAP)

* Revert "safe default (SOFTAP)"

This reverts commit a76db2a153f421cc81e9c1caf0903d550043b1d6.

* removed compatibility code

* updated nodemcu-firmware requirement

Co-authored-by: langausd <langausd@github.com>
Siggi 3 years ago
parent
commit
ca836f1944
4 changed files with 64 additions and 62 deletions
  1. 8 4
      Makefile
  2. 1 1
      README.md
  3. 3 2
      init.lua
  4. 52 55
      srv/_init.lua

+ 8 - 4
Makefile

@@ -5,8 +5,11 @@
 # Path to nodemcu-uploader (https://github.com/kmpm/nodemcu-uploader)
 NODEMCU-UPLOADER?=python ../nodemcu-uploader/nodemcu-uploader.py
 
+# Path to LUA cross compiler (part of the nodemcu firmware; only needed to compile the LFS image yourself)
+LUACC?=../nodemcu-firmware/luac.cross
+
 # Serial port
-PORT?=/dev/cu.SLAB_USBtoUART
+PORT?=$(shell ls /dev/cu.SLAB_USBtoUART /dev/ttyUSB* 2>/dev/null|head -n1)
 SPEED?=115200
 
 define _upload
@@ -28,8 +31,10 @@ usage:
 	@echo "make upload_http          to upload files to be served"
 	@echo "make upload_server        to upload the server code and init.lua"
 	@echo "make upload_all           to upload all"
+	@echo "make upload_lfs           to upload lfs based server code"
+	@echo "make upload_all_lfs       to upload all (LFS based)"
 
-# Upload one files only
+# Upload one file only
 upload: $(FILE)
 	$(_upload)
 
@@ -49,9 +54,8 @@ upload_wifi_config: $(WIFI_CONFIG)
 upload_lfs: $(LFS_FILES)
 	$(_upload)
 
-# Throw error if lfs file not found
 $(LFS_IMAGE):
-	$(error File $(LFS_IMAGE) not found)
+	$(LUACC) -f -o $(LFS_IMAGE) srv/*.lua
 
 # Upload all non-lfs files
 upload_all: $(HTTP_FILES) $(SERVER_FILES) $(WIFI_CONFIG)

+ 1 - 1
README.md

@@ -154,7 +154,7 @@ Let the abuse begin.
 
 * Other methods: HEAD, DELETE, TRACE, OPTIONS, CONNECT, PATCH
 * Encryption / SSL
-* Old nodemcu-firmware versions prior to January 2017) because I don't bother to test them.
+* Old nodemcu-firmware versions prior to January 2021) because I don't bother to test them.
 
 ## Contributing
 

+ 3 - 2
init.lua

@@ -1,4 +1,4 @@
--- Compile freshly uploaded nodemcu-httpserver lua files.
+-- check/flash/use LFS support, if possible
 if node.getpartitiontable().lfs_size > 0 then
    if file.exists("lfs.img") then
       if file.exists("lfs_lock") then
@@ -9,12 +9,13 @@ if node.getpartitiontable().lfs_size > 0 then
 	 f:flush()
 	 f:close()
 	 file.remove("httpserver-compile.lua")
-	 node.flashreload("lfs.img")
+	 node.LFS.reload("lfs.img")
       end
    end
    pcall(node.flashindex("_init"))
 end
 
+-- Compile freshly uploaded nodemcu-httpserver lua files.
 if file.exists("httpserver-compile.lua") then
    dofile("httpserver-compile.lua")
    file.remove("httpserver-compile.lua")

+ 52 - 55
srv/_init.lua

@@ -8,10 +8,10 @@
   module related initialisaion in this. This example uses standard Lua features to
   simplify the LFS API.
 
-  The first section adds a 'LFS' table to _G and uses the __index metamethod to
-  resolve functions in the LFS, so you can execute the main function of module
-  'fred' by executing LFS.fred(params), etc. It also implements some standard
-  readonly properties:
+  For Lua 5.1, the first section adds a 'LFS' table to _G and uses the __index
+  metamethod to resolve functions in the LFS, so you can execute the main
+  function of module 'fred' by executing LFS.fred(params), etc.
+  It also implements some standard readonly properties:
 
   LFS._time    The Unix Timestamp when the luac.cross was executed.  This can be
                used as a version identifier.
@@ -24,36 +24,44 @@
                  print(table.concat(LFS._list,'\n'))
                gives you a single column listing of all modules in the LFS.
 
+   For Lua 5.3 LFS table is populated by the LFS implementation in C so this part
+   of the code is skipped.
 ---------------------------------------------------------------------------------]]
 
-local index = node.flashindex
-
-local lfs_t = {
-  __index = function(_, name)
-      local fn_ut, ba, ma, size, modules = index(name)
-      if not ba then
-        return fn_ut
-      elseif name == '_time' then
-        return fn_ut
-      elseif name == '_config' then
-        local fs_ma, fs_size = file.fscfg()
-        return {lfs_base = ba, lfs_mapped = ma, lfs_size = size,
-                fs_mapped = fs_ma, fs_size = fs_size}
-      elseif name == '_list' then
-        return modules
-      else
-        return nil
-      end
-    end,
-
-  __newindex = function(_, name, value)
-      error("LFS is readonly. Invalid write to LFS." .. name, 2)
-    end,
-
-  }
-
-local G=getfenv()
-G.LFS = setmetatable(lfs_t,lfs_t)
+local lfsindex = node.LFS and node.LFS.get or node.flashindex
+local G=_ENV or getfenv()
+local lfs_t
+if _VERSION == 'Lua 5.1' then
+    lfs_t = {
+    __index = function(_, name)
+        local fn_ut, ba, ma, size, modules = lfsindex(name)
+        if not ba then
+          return fn_ut
+        elseif name == '_time' then
+          return fn_ut
+        elseif name == '_config' then
+          local fs_ma, fs_size = file.fscfg()
+          return {lfs_base = ba, lfs_mapped = ma, lfs_size = size,
+                  fs_mapped = fs_ma, fs_size = fs_size}
+        elseif name == '_list' then
+          return modules
+        else
+          return nil
+        end
+      end,
+
+    __newindex = function(_, name, value) -- luacheck: no unused
+        error("LFS is readonly. Invalid write to LFS." .. name, 2)
+      end,
+    }
+
+    setmetatable(lfs_t,lfs_t)
+    G.module       = nil    -- disable Lua 5.0 style modules to save RAM
+    package.seeall = nil
+else
+    lfs_t = node.LFS
+end
+G.LFS = lfs_t
 
 --[[-------------------------------------------------------------------------------
   The second section adds the LFS to the require searchlist, so that you can
@@ -67,33 +75,22 @@ G.LFS = setmetatable(lfs_t,lfs_t)
 ---------------------------------------------------------------------------------]]
 
 package.loaders[3] = function(module) -- loader_flash
-  local fn, ba = index(module)
-  return ba and "Module not in LFS" or fn
+  return lfs_t[module]
 end
 
---[[-------------------------------------------------------------------------------
-  You can add any other initialisation here, for example a couple of the globals
-  are never used, so setting them to nil saves a couple of global entries
----------------------------------------------------------------------------------]]
-
-G.module       = nil    -- disable Lua 5.0 style modules to save RAM
-package.seeall = nil
-
---[[-------------------------------------------------------------------------------
-  These replaces the builtins loadfile & dofile with ones which preferentially
-  loads the corresponding module from LFS if present.  Flipping the search order
+--[[----------------------------------------------------------------------------
+  These replace the builtins loadfile & dofile with ones which preferentially
+  load from the filesystem and fall back to LFS.  Flipping the search order
   is an exercise left to the reader.-
----------------------------------------------------------------------------------]]
+------------------------------------------------------------------------------]]
 
-local lf, df = loadfile, dofile
+local lf = loadfile
 G.loadfile = function(n)
-  local mod, ext = n:match("(.*)%.(l[uc]a?)");
-  local fn, ba   = index(mod)
-  if ba or (ext ~= 'lc' and ext ~= 'lua') then return lf(n) else return fn end
+  if file.exists(n) then return lf(n) end
+  local mod = n:match("(.*)%.l[uc]a?$")
+  local fn  = mod and lfsindex(mod)
+  return (fn or error (("Cannot find '%s' in FS or LFS"):format(n))) and fn
 end
 
-G.dofile = function(n)
-  local mod, ext = n:match("(.*)%.(l[uc]a?)");
-  local fn, ba   = index(mod)
-  if ba or (ext ~= 'lc' and ext ~= 'lua') then return df(n) else return fn() end
-end
+-- Lua's dofile (luaB_dofile) reaches directly for luaL_loadfile; shim instead
+G.dofile = function(n) return assert(loadfile(n))() end