modules/admin-full: rewrite firmware upgrade pages
authorJo-Philipp Wich <jow@openwrt.org>
Sat, 9 May 2009 02:06:33 +0000 (02:06 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sat, 9 May 2009 02:06:33 +0000 (02:06 +0000)
modules/admin-full/luasrc/controller/admin/system.lua
modules/admin-full/luasrc/view/admin_system/upgrade.htm

index efd0e9d6a29406c7f2534c797e095bd335f50d72..6031034995b690bb389b3d527ff9e864c9a28fc5 100644 (file)
@@ -187,37 +187,117 @@ end
 function action_upgrade()
        require("luci.model.uci")
 
-       local ret
-       local plat = luci.fs.mtime("/lib/upgrade/platform.sh")
        local tmpfile = "/tmp/firmware.img"
-       local keep_avail = true
+       
+       local function image_supported()
+               -- XXX: yay...
+               return ( 0 == os.execute(
+                       ". /etc/functions.sh; " ..
+                       "include /lib/upgrade; " ..
+                       "platform_check_image %q >/dev/null"
+                               % tmpfile
+               ) )
+       end
+       
+       local function image_checksum()
+               return (luci.sys.exec("md5sum %q" % tmpfile):match("^([^%s]+)"))
+       end
+       
+       local function storage_size()
+               local size = 0
+               if luci.fs.access("/proc/mtd") then
+                       for l in io.lines("/proc/mtd") do
+                               local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
+                               if n == "linux" then
+                                       size = tonumber(s, 16)
+                                       break
+                               end
+                       end
+               end
+               return size
+       end
+
 
+       -- Install upload handler
        local file
        luci.http.setfilehandler(
                function(meta, chunk, eof)
-                       if not file then
+                       if not luci.fs.access(tmpfile) and not file and chunk and #chunk > 0 then
                                file = io.open(tmpfile, "w")
                        end
-                       if chunk then
+                       if file and chunk then
                                file:write(chunk)
                        end
-                       if eof then
+                       if file and eof then
                                file:close()
                        end
                end
        )
 
-       local fname   = luci.http.formvalue("image")
-       local keepcfg = keep_avail and luci.http.formvalue("keepcfg")
 
-       if plat and fname then
-               ret = function()
-                       return luci.sys.flash(tmpfile, keepcfg and _keep_pattern())
+       -- Determine state
+       local keep_avail   = true
+       local step         = tonumber(luci.http.formvalue("step") or 1)
+       local has_image    = luci.fs.access(tmpfile)
+       local has_support  = image_supported()
+       local has_platform = luci.fs.access("/lib/upgrade/platform.sh")
+       local has_upload   = luci.http.formvalue("image")
+       
+       -- This does the actual flashing which is invoked inside an iframe
+       -- so don't produce meaningful errors here because the the 
+       -- previous pages should arrange the stuff as required.
+       if step == 4 then
+               if has_platform and has_image and has_support then
+                       -- Next line is to bypass luci.http layer
+                       luci.http.context.eoh = true
+
+                       -- Now invoke sysupgrade
+                       local keepcfg = keep_avail and luci.http.formvalue("keepcfg") == "1"
+                       os.execute("/sbin/luci-flash %s %q" %{
+                               keepcfg and "-k %q" % _keep_pattern() or "", tmpfile
+                       })
+
+                       -- Make sure the device is rebooted
+                       luci.sys.reboot()
                end
-       end
 
-       luci.http.prepare_content("text/html")
-       luci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail})
+
+       --
+       -- This is step 1-3, which does the user interaction and
+       -- image upload.
+       --
+
+       -- Step 1: file upload, error on unsupported image format
+       elseif not has_image or not has_support or step == 1 then
+               -- If there is an image but user has requested step 1
+               -- or type is not supported, then remove it.
+               if has_image then
+                       luci.fs.unlink(tmpfile)
+               end
+                       
+               luci.template.render("admin_system/upgrade", {
+                       step=1,
+                       bad_image=(has_image and not has_support or false),
+                       keepavail=keep_avail
+               } )
+
+       -- Step 2: present uploaded file, show checksum, confirmation
+       elseif step == 2 then
+               luci.template.render("admin_system/upgrade", {
+                       step=2,
+                       checksum=image_checksum(),
+                       filesize=luci.fs.stat(tmpfile).size,
+                       flashsize=storage_size(),
+                       keepconfig=(keep_avail and luci.http.formvalue("keepcfg") == "1")
+               } )
+       
+       -- Step 3: load iframe which calls the actual flash procedure
+       elseif step == 3 then
+               luci.template.render("admin_system/upgrade", {
+                       step=3,
+                       keepconfig=(keep_avail and luci.http.formvalue("keepcfg") == "1")
+               } )
+       end     
 end
 
 function _keep_pattern()
index bbc5215c4579c1c1fd016ee21227d6df35e78032..b4c9d1241be6e8ee38692b2216a7775e2b752826 100644 (file)
@@ -1,7 +1,7 @@
 <%#
 LuCI - Lua Configuration Interface
 Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
+Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -12,41 +12,89 @@ You may obtain a copy of the License at
 $Id$
 
 -%>
+
 <%+header%>
+
 <h2><a id="content" name="content"><%:system%></a></h2>
 <h3><%:a_s_flash%></h3>
-<p><%:a_s_flash_upgrade1%></p>
-<br />
-<% if sysupgrade and not ret then %>
-<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
-       <div class="left"><%:a_s_flash_fwimage%>:</div>
+
+<% if step == 1 then %>
+       <form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
+       <p>
+               <%:admin_upgrade Upload an OpenWrt image file to reflash the device.%>
+               <% if bad_image then %>
+                       <br /><br />
+                       <div class="error"><%:admin_upgrade_badimage The uploaded image file does not
+                               contain a supported format. Make sure that you choose the generic
+                               image format for your platform. %></div>
+               <% end %>
+       </p>
        <div>
+               <%:admin_upgrade_fwimage Firmware image%>:<br />
+               <input type="hidden" name="step" value="2" />
                <input type="file" size="30" name="image" />
                <br />
                <br />
-               <% if keep_avail then -%>
+               <% if keepavail then -%>
                <input type="checkbox" name="keepcfg" value="1" checked="checked" />
                <span class="bold"><%:a_s_flash_keepcfg%></span>
                <% end -%>
+
+               <br />
+               <input class="cbi-button cbi-button-apply" type="submit" value="<%:admin_upgrade_upload Upload image%>" />
        </div>
-       <div>
-               <input type="submit" value="<%:a_s_flash_fwupgrade%>" />
-       </div>
-</form>
-<% elseif ret then %>
-       <p><%:a_s_flash_received%></p>
-       <p><%:a_s_flash_inprogress%></p>
+       </form>
+<% elseif step == 2 then %>
+       <p>
+               <%:admin_upgrade_uploaded The flash image was uploaded.
+                       Below is the checksum and file size listed,
+                       compare them with the original file to ensure data integrity.<br />
+                       Click "Proceed" below to start the flash procedure. %>
+
+               <% if filesize > flashsize then %>
+                       <br /><br />
+                       <div class="error"><%:admin_upgrade_toolarge It appears that you try to
+                               flash an image that does not fit in the flash memory, please verify
+                               the image file! %></div>
+               <% end %>
+
+               <br />
+               <ul>
+                       <li><%:admin_upgrade_checksum Checksum%>: <code><%=checksum%></code></li>
+                       <li><%:admin_upgrade_filesize Size%>: <%
+                               local w = require "luci.tools.webadmin"
+                               write(w.byte_format(filesize))
        
-<!-- <%=string.rep(" ", 2048)%> -->
-       <% %>
-       <% local ret = ret() 
-       if ret == 0 then %>
-<div class="ok"><%:a_s_flash_flashed%></div>
-       <% else %>
-<div class="error"><%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)</div> 
-       <% end %>
-<% else %>
-<div class="error"><%:a_s_flash_notimplemented%></div>
+                               if flashsize > 0 then
+                                       write(luci.i18n.translatef(
+                                               "admin_upgrade_spaceavil",
+                                               " (%s available)",
+                                               w.byte_format(flashsize)
+                                       ))
+                               end
+                       %></li>
+               </ul>
+       </p>
+       <div class="cbi-page-actions right">
+               <form style="display:inline">
+                       <input type="hidden" name="step" value="3" />
+                       <input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
+                       <input class="cbi-button cbi-button-apply" type="submit" value="<%:proceed Proceed%>" />        
+               </form>
+               <form style="display:inline">
+                       <input type="hidden" name="step" value="1" />
+                       <input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
+                       <input class="cbi-button cbi-button-reset" type="submit" value="<%:cancel Cancel%>" />
+               </form>
+       </div>
+<% elseif step == 3 then %>
+       <p><%:admin_upgrade_running The system is flashing now.<br />
+               DO NOT POWER OFF THE DEVICE!<br />
+               Wait a few minutes until you try to reconnect.
+               It might be necessary to renew the address of your computer to reach the device
+               again, depending on your settings. %></p>
+               
+       <iframe src="<%=REQUEST_URI%>?step=4&#38;keepcfg=<%=keepconfig and "1" or "0"%>" style="border:1px solid black; width:100%; height:150px"></iframe>
 <% end %>
 <%+footer%>
-<% if ret == 0 then luci.sys.reboot() end %>
+