[syslinux:master] lua: replace the syslinux module test with an automatic boot menu generator

syslinux-bot for Ferenc Wágner wferi at niif.hu
Sun Mar 2 13:48:31 PST 2014


Commit-ID:  a562f1c87424a58daea16dc0bd8801211817c116
Gitweb:     http://www.syslinux.org/commit/a562f1c87424a58daea16dc0bd8801211817c116
Author:     Ferenc Wágner <wferi at niif.hu>
AuthorDate: Tue, 25 Feb 2014 19:18:27 +0100
Committer:  Ferenc Wágner <wferi at niif.hu>
CommitDate: Sun, 2 Mar 2014 09:16:32 +0100

lua: replace the syslinux module test with an automatic boot menu generator


---
 com32/lua/test/automenu.lua | 152 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/com32/lua/test/automenu.lua b/com32/lua/test/automenu.lua
new file mode 100644
index 0000000..1e66cca
--- /dev/null
+++ b/com32/lua/test/automenu.lua
@@ -0,0 +1,152 @@
+--[[
+Automatically generated boot menu of the installed Linux kernels
+
+Example:
+
+m = require "automenu"
+m.run { dir = "/",
+        default = 1,
+        timeout = 5,
+        append = "root=/dev/hda2 ro",
+}
+
+TODO:
+- add hooks
+- demo adding break options from user config
+- kernel flavor preference (pae/rt)
+]]
+
+local lfs = require "lfs"
+local sl = require "syslinux"
+
+local single = false
+local verbosity = 2
+
+local function modifiers ()
+   return (single and " single" or "") .. ({" quiet",""," debug"})[verbosity]
+end
+
+local function scan (params)
+   local sep = string.sub (params.dir, -1) == "/" and "" or "/"
+   if not params.items then params.items = {} end
+   for name in lfs.dir (params.dir) do
+      local path = params.dir .. sep .. name
+      if lfs.attributes (path, "mode") == "file" then
+         local from,to,version = string.find (name, "^vmlinuz%-(.*)")
+         if from then
+            local initrd = params.dir .. sep .. "initrd.img-" .. version
+            local initrd_param = ""
+            if lfs.attributes (initrd, "size") then
+               initrd_param = "initrd=" .. initrd .. " "
+            end
+            table.insert (params.items, {
+                             show = function () return name end,
+                             version = version,
+                             execute = function () sl.boot_linux (path, initrd_param .. params.append .. modifiers ()) end
+                          })
+         end
+      end
+   end
+end
+
+local function version_gt (v1, v2)
+   local negatives = {"rc", "pre"}
+   local m1, r1 = string.match (v1, "^(%D*)(.*)")
+   local m2, r2 = string.match (v2, "^(%D*)(.*)")
+   if m1 ~= m2 then
+      for _, suffix in ipairs (negatives) do
+         suffix = "-" .. suffix
+         if m1 == suffix and m2 ~= suffix then
+            return false
+         elseif m1 ~= suffix and m2 == suffix then
+            return true
+         end
+      end
+      return m1 > m2
+   end
+   m1, r1 = string.match (r1, "^(%d*)(.*)")
+   m2, r2 = string.match (r2, "^(%d*)(.*)")
+   m1 = tonumber (m1) or 0
+   m2 = tonumber (m2) or 0
+   if m1 ~= m2 then
+      return m1 > m2
+   end
+   if r1 == "" and r2 == "" then
+      return false
+   end
+   return version_gt (r1, r2)
+end
+
+local function kernel_gt (k1, k2)
+   return version_gt (k1.version, k2.version)
+end
+
+local function print_or_call (x, def)
+   local t = type (x)
+   if t == "nil" then
+      if def then print (def) end
+   elseif t == "function" then
+      x ()
+   else
+      print (x)
+   end
+end
+
+local function draw (params)
+   print_or_call (params.title, "\n=== Boot menu ===")
+   for i, item in ipairs (params.items) do
+      print ((i == params.default and " > " or "   ") .. i .. "  " .. item.show ())
+   end
+   print ("\nKernel arguments:\n  " .. params.append .. modifiers ())
+   print ("\nHit a number to select from the menu,\n    ENTER to accept default,\n    ESC to exit\n or any other key to print menu again")
+end
+
+local function choose (params)
+   draw (params)
+   print ("\nBooting in " .. params.timeout .. " s...")
+   while true do
+      local i = sl.get_key (params.timeout * 1000)
+      if i == sl.KEY.ESC then
+         break
+      else
+         if i == sl.KEY.NONE or i == sl.KEY.ENTER then
+            i = params.default
+         elseif i == sl.KEY.DOWN then
+            params.default = params.default < #params.items and params.default + 1 or #params.items
+         elseif i == sl.KEY.UP then
+            params.default = params.default > 1 and params.default - 1 or 1
+         else
+            i = i - string.byte "0"
+         end
+         if params.items[i] then
+            params.items[i].execute ()
+         end
+         params.timeout = 0
+         draw (params)
+      end
+   end
+end
+
+local function run (params)
+   scan (params)
+   if not next (params.items) then
+      print ("No kernels found in directory " .. params.dir)
+      os.exit (false)
+   end
+   table.sort (params.items, kernel_gt)
+   table.insert (params.items, {
+                    show = function () return "Single user: " .. (single and "true" or "false") end,
+                    execute = function () single = not single end
+                 })
+   table.insert (params.items, {
+                    show = function () return "Verbosity: " .. ({"quiet","normal","debug"})[verbosity] end,
+                    execute = function () verbosity = verbosity < 3 and verbosity + 1 or 1 end
+                 })
+   choose (params)
+end
+
+return {
+   scan = scan,
+   choose = choose,
+   run = run
+}


More information about the Syslinux-commits mailing list