aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lua/test/automenu.lua
diff options
context:
space:
mode:
authorFerenc Wágner <wferi@niif.hu>2014-02-25 19:18:27 +0100
committerFerenc Wágner <wferi@niif.hu>2014-03-02 09:16:32 +0100
commita562f1c87424a58daea16dc0bd8801211817c116 (patch)
treeb6cc91f72e8cbf7008a7ba876b3f21cb47120afc /com32/lua/test/automenu.lua
parentea804356f1dea456524807d809673c7f27ec9b00 (diff)
downloadsyslinux-a562f1c87424a58daea16dc0bd8801211817c116.tar.gz
syslinux-a562f1c87424a58daea16dc0bd8801211817c116.tar.xz
syslinux-a562f1c87424a58daea16dc0bd8801211817c116.zip
lua: replace the syslinux module test with an automatic boot menu generatorsyslinux-6.03-pre6
Diffstat (limited to 'com32/lua/test/automenu.lua')
-rw-r--r--com32/lua/test/automenu.lua152
1 files changed, 152 insertions, 0 deletions
diff --git a/com32/lua/test/automenu.lua b/com32/lua/test/automenu.lua
new file mode 100644
index 00000000..1e66cca1
--- /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
+}