Author: titmuss
Date: Fri Nov 28 08:55:25 2008
New Revision: 3465

URL: http://svn.slimdevices.com?rev=3465&root=Jive&view=rev
Log:
Bug: N/A
Description:
Add support for upgrades when using a UBI flash filesystem.


Added:
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeMTD.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeUBI.lua
Modified:
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeApplet.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeMeta.lua
    
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/Upgrade.lua

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeApplet.lua?rev=3465&root=Jive&r1=3464&r2=3465&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeApplet.lua
 Fri Nov 28 08:55:25 2008
@@ -97,7 +97,7 @@
 
        local help = Textarea("help", "")
 
-       if url then
+       if url and string.match(url, machine) then
                local version = self:_firmwareVersion(url)
                local networkUpdateItem = {
                        text = self:string("BEGIN_UPDATE"),
@@ -260,12 +260,15 @@
 function _t_upgrade(self)
        Task:yield(true)
 
-       local t, err = self.upgrade:start(function(...)
-                                                 self:_t_setText(...)
-                                         end)
-
-       if t == nil then
+       local upgrade = Upgrade()
+       local t, err = upgrade:start(self.url,
+               function(...)
+                       self:_t_setText(...)
+               end)
+
+       if not t then
                -- error
+               log:error("Upgrade failed: ", err)
                self:_upgradeFailed():showInstead()
 
                if self.popup then
@@ -315,7 +318,6 @@
        appletManager:callService("disconnectPlayer")
 
        -- start the upgrade
-       self.upgrade = Upgrade(self.url)
        Task("upgrade", self, _t_upgrade, _upgradeFailed):addTask()
 
        self:tieAndShowWindow(self.popup)

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeMeta.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeMeta.lua?rev=3465&root=Jive&r1=3464&r2=3465&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeMeta.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/SetupFirmwareUpgradeMeta.lua
 Fri Nov 28 08:55:25 2008
@@ -4,6 +4,8 @@
 local oo            = require("loop.simple")
 
 local AppletMeta    = require("jive.AppletMeta")
+local System        = require("jive.System")
+
 local jul           = require("jive.utils.log")
 local log           = require("jive.utils.log").logger("applets.setup")
 local debug         = require("jive.utils.debug")
@@ -98,7 +100,12 @@
 
                end
 
-       local fwcmd = { 'firmwareupgrade', 'firmwareVersion:' .. JIVE_VERSION, 
'subscribe:0' }
+       local fwcmd = {
+               'firmwareupgrade',
+               'firmwareVersion:' .. JIVE_VERSION,
+               'machine:' .. System:getMachine(),
+               'subscribe:0'
+       }
        player:subscribe(
                         '/slim/firmwarestatus/' .. player:getId(),
                         firmwareUpgradeSink,

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/Upgrade.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/Upgrade.lua?rev=3465&root=Jive&r1=3464&r2=3465&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/Upgrade.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/Upgrade.lua
 Fri Nov 28 08:55:25 2008
@@ -1,48 +1,27 @@
-
-
-local ipairs, pairs, tonumber, tostring, type = ipairs, pairs, tonumber, 
tostring, type
 
 local oo          = require("loop.base")
 local io          = require("io")
-local os          = require("os")
-local math        = require("math")
-local table       = require("jive.utils.table")
-local zip         = require("zipfilter")
-local ltn12       = require("ltn12")
 local string      = require("string")
-local url         = require("socket.url")
-local http        = require("socket.http")
 
-local RequestHttp = require("jive.net.RequestHttp")
-local SocketHttp  = require("jive.net.SocketHttp")
-local Process     = require("jive.net.Process")
-local Framework   = require("jive.ui.Framework")
 local Task        = require("jive.ui.Task")
+
+local UpgradeMTD  = require("applets.SetupFirmwareUpgrade.UpgradeMTD")
+local UpgradeUBI  = require("applets.SetupFirmwareUpgrade.UpgradeUBI")
 
 local debug       = require("jive.utils.debug")
 local log         = require("jive.utils.log").logger("applets.setup")
 
-local jnt = jnt
 
 module(..., oo.class)
 
 
-function __init(self, url)
-       local obj = oo.rawnew(self, {
-                                     url = url,
-                                     _mtd = {},
-                                     _size = {},
-                                     _checksum = "",
-                             })
-
-       return obj
+function __init(self)
+       return oo.rawnew(self, {})
 end
 
 
 -- perform the upgrade
-function start(self, callback)
-       local t, err
-
+function start(self, url, callback)
        if not callback then
                callback = function() end
        end
@@ -50,448 +29,46 @@
        callback(false, "UPDATE_DOWNLOAD", "")
 
        -- parse the flash devices
-       t, err = self:parseMtd()
-       if not t then
-               log:warn("parseMtd failed")
-               return nil, err
-       end
-                           
-       -- parse the kernel version
-       self._zImageExtraVersion = "zImage-P7"
-       self._mtd[self._zImageExtraVersion] = self._mtd["zImage"]
-       t, err = self:parseVersion()
-       if not t then
-               log:warn("parseVersion failed")
+       local mtd, err = self:parseMtd()
+       if not mtd then
+               log:error("parseMtd failed")
                return nil, err
        end
 
-       -- disable VOL+ on boot
-       t, err = self:fw_setenv({ sw7 = "" })
-       if not t then
-               log:warn("fw_setenv failed")
-               return nil, err
+       Task:yield(true)
+
+       local class
+       if mtd.ubi then
+               class = UpgradeUBI
+       else
+               class = UpgradeMTD
        end
 
-       -- erase flash
-       t, err = self:flashErase(self._zImageExtraVersion)
-       if not t then
-               log:warn("flash kernel failed")
-               return nil, err
-       end
-
-       t, err = self:flashErase("root.cramfs")
-       if not t then
-               log:warn("flash filesystem failed")
-               return nil, err
-       end
-                           
-       -- stream the firmware, and update the flash
-       t, err = self:download(callback)
-       if not t then
-               log:warn("download Failed err=", err)
-               return nil, err
-       end
-
-       callback(false, "UPDATE_VERIFY")
-
-       -- checksum kernel
-       t, err = self:checksum(self._zImageExtraVersion)
-       if not t then
-               log:warn("flash checksum failed")
-               return nil, err
-       end
-
-       -- checksum cramfs
-       t, err = self:checksum("root.cramfs")
-       if not t then
-               log:warn("flash checksum failed")
-               return nil, err
-       end
-
-       -- switch running kernel and filesystem and enable VOL+ on boot
-       t, err = self:fw_setenv({ kernelblock = self.nextKernelblock,
-                                 mtdset = self.nextMtdset,
-                                 sw7 = "echo Booting last image; blink; setenv 
kernelblock " .. self.thisKernelblock .. "; setenv mtdset " .. self.thisMtdset 
.. "; boot",
-                                 -- fix for bug 6322
-                                 sw6 = "echo Factory reset; blink; nande b00 
1400000; blink"
-                         })
-       if not t then
-               log:warn("fw_setenv failed")
-               return nil, err
-       end
-
-       callback(true, "UPDATE_REBOOT")
-
-       -- two second delay
-       local t = Framework:getTicks()
-       while (t + 2000) > Framework:getTicks() do
-               Task:yield(true)
-       end
-
-       log:warn("REBOOTING ...")
-       os.execute("/bin/busybox reboot -f")
-
-       return true
-end
-
-
-function processSink(self, prog)
-       local fh, err = io.popen(prog, "w")
-
-       if fh == nil then
-               return function()
-                       return false, err
-               end
-       end
-
-       return function(chunk, err)
-               if chunk then
-                       return fh:write(chunk)
-               else
-                       fh:close()
-                       return false
-               end
-       end
-end
-
-
--- zip filter sink to process upgrade zip file
-function upgradeSink(self)
-       local fhsink = nil
-       local action = nil
-       local length = 0
-       local part = nil
-
-       return function(chunk, err)
-                      if err then
-                              log:info("sinkErr=", err)
-                              self.sinkErr = err
-                              return 0
-                      end
-
-                      Task:yield(true)
-
-                      if type(chunk) == "string" then
-                              self.downloadBytes = self.downloadBytes + #chunk
-
-                              if action == "store" then
-                                      -- write content to fhsink
-                                      local t, err = fhsink(chunk)
-                                      if not t then
-                                              log:warn("FLASH err=", err)
-                                              return nil
-                                      end
-
-                                      length = length + #chunk
-
-                              elseif action == "checksum" then
-                                      -- store checksum
-                                      self._checksum = self._checksum .. chunk
-                              end
-
-                              return 1
-                      end
-
-                      if fhsink then
-                              -- end of file, close the sink
-                              self._size[part] = length
-                              part = nil
-
-                              fhsink(nil)
-                              fhsink = nil
-                      end
-
-                      if chunk == nil then
-                              -- end of zip file
-                              self.downloadClose = true
-                              return nil
-                      end
-
-                      if type(chunk) == "table" then
-                              -- new file
-                              if chunk.filename == self._zImageExtraVersion 
then
-                                      -- kernel
-                                      part = self._zImageExtraVersion
-
-                              elseif chunk.filename == "root.cramfs" then
-                                      -- cramfs
-                                      part = "root.cramfs"
-
-                              elseif chunk.filename == "upgrade.md5" then
-                                      -- md5 checksums
-                                      action = "checksum"
-
-                              else
-                                      action = nil
-                              end
-
-
-                              -- open file handle
-                              if part ~= nil then
-                                      action = "store"
-                                      length = 0
-
-                                      -- open file handle
-                                       local cmd = "/usr/sbin/nandwrite -qp " 
.. self._mtd[part] .. " -"
-                                       log:info("flash: ", cmd)
-
-                                       fhsink = self:processSink(cmd)
-                              end
-
-                              return 1
-                      end
-
-                      -- should never get here
-                      return nil
-              end
+       local obj = (class)()
+       return obj:start(url, mtd, callback)
 end
 
 
 -- utility function to parse /dev/mtd
-function parseMtd(self)
+function parseMtd()
+       local mtd = {}
+
        -- parse mtd to work out what partitions to use
        local fh, err = io.open("/proc/mtd")
        if fh == nil then
                return fh, err
        end
 
-       local mtd = string.lower(fh:read("*all"))
-       fh:close()
-
-       self._mtd["zImage"] = string.match(mtd, "mtd(%d+):[^\n]*zimage[^\n]*\n")
-       self._mtd["root.cramfs"] = string.match(mtd, 
"mtd(%d+):[^\n]*cramfs[^\n]*\n")
-       self._mtd["jffs2"] = string.match(mtd, "mtd(%d+):[^\n]*jffs2[^\n]*\n")
-       self._mtd["env"] = string.match(mtd, "mtd(%d+):[^\n]*env[^\n]*\n")
-
-       for _, part in ipairs({"zImage", "root.cramfs", "jffs2", "env"}) do
-               if self._mtd[part] == nil then
-                       return nil, "PROBLEM_PARSE_MTD"
-               else
-                       self._mtd[part] = "/dev/mtd/" .. self._mtd[part]
+       for line in fh:lines() do
+               local partno, name = string.match(line, 
"mtd(%d+):.*\"([^\"]+)\"")
+               if partno then
+                       mtd[name] = "/dev/mtd/" .. partno
                end
        end
 
-       -- parse cmdline to work out which image is running
-       local fh, err = io.open("/proc/cmdline")
-       if fh == nil then
-               return fh, err
-       end
-
-       local cmdline = string.lower(fh:read("*all"))
        fh:close()
 
-       local mtdset = string.match(cmdline, "mtdset=(%d+)")
-       mtdset = tonumber(mtdset) or 0
-
-       if mtdset == 0 then
-               self.thisKernelblock = "c"
-               self.thisMtdset = "0"
-               self.nextKernelblock = "580"
-               self.nextMtdset = "1"
-       else
-               self.thisKernelblock = "580"
-               self.thisMtdset = "1"
-               self.nextKernelblock = "c"
-               self.nextMtdset = "0"
-       end
-
-       log:info("mtdset=", mtdset, " nextKernelblock=", self.nextKernelblock, 
" nextMtdset=", self.nextMtdset)
-
-       Task:yield(true)
-
-       return 1
-end
-
-
--- parse kernel extraversion
-function parseVersion(self)
-
-       local fh, err = io.open("/proc/version")
-       if fh == nil then
-               return fh, err
-       end
-
-       local version = fh:read("*all")
-       fh:close()
-
-       local extraversion = string.match(version, "Linux version 
[%d%.]+(%-[^%s]+)") or ""
-
-       -- backwards compatibility
-       if extraversion == "-P4" then
-               extraversion = ""
-       end
-
-       log:info("extraversion=", extraversion)
-
-       -- select kernel to use
-       self._zImageExtraVersion = "zImage" .. extraversion
-       self._mtd[self._zImageExtraVersion] = self._mtd["zImage"]
-
-       Task:yield(true)
-
-       return 1
-end
-
-
--- update bootloader environment
-function fw_setenv(self, variables)
-       local cmd = { "/usr/sbin/fw_setenv" }
-
-       for k,v in pairs(variables) do
-               cmd[#cmd + 1] = k
-
-               if v == nil then
-                       cmd[#cmd + 1] = '""'
-               else
-                       cmd[#cmd + 1] = '"' .. v .. '"'
-               end
-       end
-
-       local str = table.concat(cmd, " ")
-
-       log:info("fw_setenv: ", str)
-       if os.execute(str) ~= 0 then
-               return nil, "fw_setenv failed"
-       end
-
-       Task:yield(true)
-
-       return 1
-end
-
-
--- open the zip file or stream for processing
-function download(self, callback)
-       log:info("self.url=", self.url)
-
-       -- unzip the stream, and store the contents
-       local sink = ltn12.sink.chain(zip.filter(), self:upgradeSink())
-
-       local parsedUrl = url.parse(self.url)
-       self.downloadBytes = 0
-       self.sinkErr = false
-
-       local t, err
-       if parsedUrl.scheme == "file" then
-               local file = io.open(parsedUrl.path)
-
-               local totalBytes = file:seek("end")
-               file:seek("set", 0)
-
-               local source = function()
-                                   local chunk = file:read(0x16000)
-                                   if not chunk then file:close() end
-                                   return chunk
-                               end
-
-               while true do
-                       local t, err = ltn12.pump.step(source, sink)
-                       callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
-
-                       Task:yield()
-                       if not t then
-                               return not err, err
-                       end
-               end 
-
-       elseif parsedUrl.scheme == "http" then
-               self.downloadClose = false
-
-               local req = RequestHttp(sink, 'GET', self.url, { stream = true 
})
-               local uri  = req:getURI()
-
-               local http = SocketHttp(jnt, uri.host, uri.port, uri.host)
-               http:fetch(req)
-
-               while not self.sinkErr and not self.downloadClose do
-                       local totalBytes = 
req:t_getResponseHeader("Content-Length")
-                       if totalBytes then
-                               callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
-                       end
-                       Task:yield(true)
-               end
-
-               if self.sinkErr then
-                       log:info("sinkErr=", self.sinkErr)
-                       return false, self.sinkErr
-               end
-
-               return true
-       else
-               return false, "Unsupported url scheme"
-       end
-end
-
-
-function nullProcessSink(chunk, err)
-       if err then
-               log:warn("process error:", err)
-               return nil
-       end
-       return 1
-end
-
-
--- flash the image from tmp file
-function flashErase(self, part)
-       local cmd, proc
-
-       -- erase flash
-       cmd = "/usr/sbin/flash_eraseall -q " .. self._mtd[part]
-       log:info("flash: ", cmd)
-
-       proc = Process(jnt, cmd)
-       proc:read(nullProcessSink)
-       while proc:status() ~= "dead" do
-               -- wait for the process to complete
-               Task:yield()
-       end
-
-       return 1
-end
-
-
--- checksum flash partition
-function checksum(self, part, dir)
-       if self._checksum == "" then
-               log:error("Firmware checksum not found")
-               return nil, "PROBLEM_NO_CHECKSUM"
-       end
-
-       local md5check = string.match(self._checksum,
-                                     "(%x+)%s+" .. string.gsub(part, "[%-]", 
"%%%1"))
-
-       local cmd
-       if dir then
-               cmd = "md5sum " .. dir .. part
-       else
-               cmd = "/usr/sbin/nanddump -obl " .. self._size[part] .. " " .. 
self._mtd[part] .. " | md5sum"
-       end
-       log:info("checksum cmd: ", cmd)
-
-       local md5flash = {}
-
-       local proc = Process(jnt, cmd)
-       proc:read(
-               function(chunk, err)
-                       if err then
-                               log:warn("md5sum error ", err)
-                               return nil
-                       end
-                       if chunk ~= nil then
-                               table.insert(md5flash, chunk)
-                       end
-                       return 1                        
-               end)
-
-       while proc:status() ~= "dead" do
-               -- wait for the process to complete
-               Task:yield()
-       end
-       md5flash = string.match(table.concat(md5flash), "(%x+)%s+.+")
-
-       log:info("md5check=", md5check, " md5flash=", md5flash, " ", md5check 
== md5flash)
-       return md5check == md5flash, "PROBLEM_CHECKSUM_FAILED"
+       return mtd
 end
 
 

Added: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeMTD.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeMTD.lua?rev=3465&root=Jive&view=auto
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeMTD.lua
 (added)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeMTD.lua
 Fri Nov 28 08:55:25 2008
@@ -1,0 +1,507 @@
+
+
+local ipairs, pairs, tonumber, tostring, type = ipairs, pairs, tonumber, 
tostring, type
+
+local oo          = require("loop.base")
+local io          = require("io")
+local os          = require("os")
+local math        = require("math")
+local table       = require("jive.utils.table")
+local zip         = require("zipfilter")
+local ltn12       = require("ltn12")
+local string      = require("string")
+local url         = require("socket.url")
+local http        = require("socket.http")
+
+local RequestHttp = require("jive.net.RequestHttp")
+local SocketHttp  = require("jive.net.SocketHttp")
+local Process     = require("jive.net.Process")
+local Framework   = require("jive.ui.Framework")
+local Task        = require("jive.ui.Task")
+
+local debug       = require("jive.utils.debug")
+local log         = require("jive.utils.log").logger("applets.setup")
+
+local jnt = jnt
+
+module(..., oo.class)
+
+
+function __init(self)
+       local obj = oo.rawnew(self, {
+                                     _mtd = {},
+                                     _size = {},
+                                     _checksum = "",
+                             })
+
+       return obj
+end
+
+
+-- perform the upgrade
+function start(self, url, mtd, callback)
+       local t, err
+
+       self.url = url
+
+       if not callback then
+               callback = function() end
+       end
+
+       callback(false, "UPDATE_DOWNLOAD", "")
+
+       -- parse the flash devices
+       t, err = self:parseMtd()
+       if not t then
+               log:warn("parseMtd failed")
+               return nil, err
+       end
+                           
+       -- parse the kernel version
+       self._zImageExtraVersion = "zImage-P7"
+       self._mtd[self._zImageExtraVersion] = self._mtd["zImage"]
+       t, err = self:parseVersion()
+       if not t then
+               log:warn("parseVersion failed")
+               return nil, err
+       end
+
+       -- disable VOL+ on boot
+       t, err = self:fw_setenv({ sw7 = "" })
+       if not t then
+               log:warn("fw_setenv failed")
+               return nil, err
+       end
+
+       -- erase flash
+       t, err = self:flashErase(self._zImageExtraVersion)
+       if not t then
+               log:warn("flash kernel failed")
+               return nil, err
+       end
+
+       t, err = self:flashErase("root.cramfs")
+       if not t then
+               log:warn("flash filesystem failed")
+               return nil, err
+       end
+                           
+       -- stream the firmware, and update the flash
+       t, err = self:download(callback)
+       if not t then
+               log:warn("download Failed err=", err)
+               return nil, err
+       end
+
+       callback(false, "UPDATE_VERIFY")
+
+       -- checksum kernel
+       t, err = self:checksum(self._zImageExtraVersion)
+       if not t then
+               log:warn("flash checksum failed")
+               return nil, err
+       end
+
+       -- checksum cramfs
+       t, err = self:checksum("root.cramfs")
+       if not t then
+               log:warn("flash checksum failed")
+               return nil, err
+       end
+
+       -- switch running kernel and filesystem and enable VOL+ on boot
+       t, err = self:fw_setenv({ kernelblock = self.nextKernelblock,
+                                 mtdset = self.nextMtdset,
+                                 sw7 = "echo Booting last image; blink; setenv 
kernelblock " .. self.thisKernelblock .. "; setenv mtdset " .. self.thisMtdset 
.. "; boot",
+                                 -- fix for bug 6322
+                                 sw6 = "echo Factory reset; blink; nande b00 
1400000; blink"
+                         })
+       if not t then
+               log:warn("fw_setenv failed")
+               return nil, err
+       end
+
+       callback(true, "UPDATE_REBOOT")
+
+       -- two second delay
+       local t = Framework:getTicks()
+       while (t + 2000) > Framework:getTicks() do
+               Task:yield(true)
+       end
+
+       os.execute("/bin/busybox reboot -f")
+
+       return true
+end
+
+
+function processSink(self, prog)
+       local fh, err = io.popen(prog, "w")
+
+       if fh == nil then
+               return function()
+                       return false, err
+               end
+       end
+
+       return function(chunk, err)
+               if chunk then
+                       return fh:write(chunk)
+               else
+                       fh:close()
+                       return false
+               end
+       end
+end
+
+
+-- zip filter sink to process upgrade zip file
+function upgradeSink(self)
+       local fhsink = nil
+       local action = nil
+       local length = 0
+       local part = nil
+
+       return function(chunk, err)
+                      if err then
+                              log:info("sinkErr=", err)
+                              self.sinkErr = err
+                              return 0
+                      end
+
+                      Task:yield(true)
+
+                      if type(chunk) == "string" then
+                              self.downloadBytes = self.downloadBytes + #chunk
+
+                              if action == "store" then
+                                      -- write content to fhsink
+                                      local t, err = fhsink(chunk)
+                                      if not t then
+                                              log:warn("FLASH err=", err)
+                                              return nil
+                                      end
+
+                                      length = length + #chunk
+
+                              elseif action == "checksum" then
+                                      -- store checksum
+                                      self._checksum = self._checksum .. chunk
+                              end
+
+                              return 1
+                      end
+
+                      if fhsink then
+                              -- end of file, close the sink
+                              self._size[part] = length
+                              part = nil
+
+                              fhsink(nil)
+                              fhsink = nil
+                      end
+
+                      if chunk == nil then
+                              -- end of zip file
+                              self.downloadClose = true
+                              return nil
+                      end
+
+                      if type(chunk) == "table" then
+                              -- new file
+                              if chunk.filename == self._zImageExtraVersion 
then
+                                      -- kernel
+                                      part = self._zImageExtraVersion
+
+                              elseif chunk.filename == "root.cramfs" then
+                                      -- cramfs
+                                      part = "root.cramfs"
+
+                              elseif chunk.filename == "upgrade.md5" then
+                                      -- md5 checksums
+                                      action = "checksum"
+
+                              else
+                                      action = nil
+                              end
+
+
+                              -- open file handle
+                              if part ~= nil then
+                                      action = "store"
+                                      length = 0
+
+                                      -- open file handle
+                                       local cmd = "/usr/sbin/nandwrite -qp " 
.. self._mtd[part] .. " -"
+                                       log:info("flash: ", cmd)
+
+                                       fhsink = self:processSink(cmd)
+                              end
+
+                              return 1
+                      end
+
+                      -- should never get here
+                      return nil
+              end
+end
+
+
+-- utility function to parse /dev/mtd
+function parseMtd(self)
+       -- parse mtd to work out what partitions to use
+       local fh, err = io.open("/proc/mtd")
+       if fh == nil then
+               return fh, err
+       end
+
+       local mtd = string.lower(fh:read("*all"))
+       fh:close()
+
+       self._mtd["zImage"] = string.match(mtd, "mtd(%d+):[^\n]*zimage[^\n]*\n")
+       self._mtd["root.cramfs"] = string.match(mtd, 
"mtd(%d+):[^\n]*cramfs[^\n]*\n")
+       self._mtd["jffs2"] = string.match(mtd, "mtd(%d+):[^\n]*jffs2[^\n]*\n")
+       self._mtd["env"] = string.match(mtd, "mtd(%d+):[^\n]*env[^\n]*\n")
+
+       for _, part in ipairs({"zImage", "root.cramfs", "jffs2", "env"}) do
+               if self._mtd[part] == nil then
+                       return nil, "PROBLEM_PARSE_MTD"
+               else
+                       self._mtd[part] = "/dev/mtd/" .. self._mtd[part]
+               end
+       end
+
+       -- parse cmdline to work out which image is running
+       local fh, err = io.open("/proc/cmdline")
+       if fh == nil then
+               return fh, err
+       end
+
+       local cmdline = string.lower(fh:read("*all"))
+       fh:close()
+
+       local mtdset = string.match(cmdline, "mtdset=(%d+)")
+       mtdset = tonumber(mtdset) or 0
+
+       if mtdset == 0 then
+               self.thisKernelblock = "c"
+               self.thisMtdset = "0"
+               self.nextKernelblock = "580"
+               self.nextMtdset = "1"
+       else
+               self.thisKernelblock = "580"
+               self.thisMtdset = "1"
+               self.nextKernelblock = "c"
+               self.nextMtdset = "0"
+       end
+
+       log:info("mtdset=", mtdset, " nextKernelblock=", self.nextKernelblock, 
" nextMtdset=", self.nextMtdset)
+
+       Task:yield(true)
+
+       return 1
+end
+
+
+-- parse kernel extraversion
+function parseVersion(self)
+
+       local fh, err = io.open("/proc/version")
+       if fh == nil then
+               return fh, err
+       end
+
+       local version = fh:read("*all")
+       fh:close()
+
+       local extraversion = string.match(version, "Linux version 
[%d%.]+(%-[^%s]+)") or ""
+
+       -- backwards compatibility
+       if extraversion == "-P4" then
+               extraversion = ""
+       end
+
+       log:info("extraversion=", extraversion)
+
+       -- select kernel to use
+       self._zImageExtraVersion = "zImage" .. extraversion
+       self._mtd[self._zImageExtraVersion] = self._mtd["zImage"]
+
+       Task:yield(true)
+
+       return 1
+end
+
+
+-- update bootloader environment
+function fw_setenv(self, variables)
+       local cmd = { "/usr/sbin/fw_setenv" }
+
+       for k,v in pairs(variables) do
+               cmd[#cmd + 1] = k
+
+               if v == nil then
+                       cmd[#cmd + 1] = '""'
+               else
+                       cmd[#cmd + 1] = '"' .. v .. '"'
+               end
+       end
+
+       local str = table.concat(cmd, " ")
+
+       log:info("fw_setenv: ", str)
+       if os.execute(str) ~= 0 then
+               return nil, "fw_setenv failed"
+       end
+
+       Task:yield(true)
+
+       return 1
+end
+
+
+-- open the zip file or stream for processing
+function download(self, callback)
+       log:info("self.url=", self.url)
+
+       -- unzip the stream, and store the contents
+       local sink = ltn12.sink.chain(zip.filter(), self:upgradeSink())
+
+       local parsedUrl = url.parse(self.url)
+       self.downloadBytes = 0
+       self.sinkErr = false
+
+       local t, err
+       if parsedUrl.scheme == "file" then
+               local file = io.open(parsedUrl.path)
+
+               local totalBytes = file:seek("end")
+               file:seek("set", 0)
+
+               local source = function()
+                                   local chunk = file:read(0x16000)
+                                   if not chunk then file:close() end
+                                   return chunk
+                               end
+
+               while true do
+                       local t, err = ltn12.pump.step(source, sink)
+                       callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
+
+                       Task:yield()
+                       if not t then
+                               return not err, err
+                       end
+               end 
+
+       elseif parsedUrl.scheme == "http" then
+               self.downloadClose = false
+
+               local req = RequestHttp(sink, 'GET', self.url, { stream = true 
})
+               local uri  = req:getURI()
+
+               local http = SocketHttp(jnt, uri.host, uri.port, uri.host)
+               http:fetch(req)
+
+               while not self.sinkErr and not self.downloadClose do
+                       local totalBytes = 
req:t_getResponseHeader("Content-Length")
+                       if totalBytes then
+                               callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
+                       end
+                       Task:yield(true)
+               end
+
+               if self.sinkErr then
+                       log:info("sinkErr=", self.sinkErr)
+                       return false, self.sinkErr
+               end
+
+               return true
+       else
+               return false, "Unsupported url scheme"
+       end
+end
+
+
+function nullProcessSink(chunk, err)
+       if err then
+               log:warn("process error:", err)
+               return nil
+       end
+       return 1
+end
+
+
+-- flash the image from tmp file
+function flashErase(self, part)
+       local cmd, proc
+
+       -- erase flash
+       cmd = "/usr/sbin/flash_eraseall -q " .. self._mtd[part]
+       log:info("flash: ", cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+
+       return 1
+end
+
+
+-- checksum flash partition
+function checksum(self, part, dir)
+       if self._checksum == "" then
+               log:error("Firmware checksum not found")
+               return nil, "PROBLEM_NO_CHECKSUM"
+       end
+
+       local md5check = string.match(self._checksum,
+                                     "(%x+)%s+" .. string.gsub(part, "[%-]", 
"%%%1"))
+
+       local cmd
+       if dir then
+               cmd = "md5sum " .. dir .. part
+       else
+               cmd = "/usr/sbin/nanddump -obl " .. self._size[part] .. " " .. 
self._mtd[part] .. " | md5sum"
+       end
+       log:info("checksum cmd: ", cmd)
+
+       local md5flash = {}
+
+       local proc = Process(jnt, cmd)
+       proc:read(
+               function(chunk, err)
+                       if err then
+                               log:warn("md5sum error ", err)
+                               return nil
+                       end
+                       if chunk ~= nil then
+                               table.insert(md5flash, chunk)
+                       end
+                       return 1                        
+               end)
+
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+       md5flash = string.match(table.concat(md5flash), "(%x+)%s+.+")
+
+       log:info("md5check=", md5check, " md5flash=", md5flash, " ", md5check 
== md5flash)
+       return md5check == md5flash, "PROBLEM_CHECKSUM_FAILED"
+end
+
+
+--[[
+
+=head1 LICENSE
+
+Copyright 2007 Logitech. All Rights Reserved.
+
+This file is subject to the Logitech Public Source License Version 1.0. Please 
see the LICENCE file for details.
+
+=cut
+--]]

Added: 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeUBI.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeUBI.lua?rev=3465&root=Jive&view=auto
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeUBI.lua
 (added)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay_squeezeos/share/applets/SetupFirmwareUpgrade/UpgradeUBI.lua
 Fri Nov 28 08:55:25 2008
@@ -1,0 +1,435 @@
+
+
+local assert, error, pairs, type, pcall = assert, error, pairs, type, pcall
+
+local oo          = require("loop.base")
+local io          = require("io")
+local os          = require("os")
+local math        = require("math")
+local table       = require("jive.utils.table")
+local zip         = require("zipfilter")
+local ltn12       = require("ltn12")
+local string      = require("string")
+local url         = require("socket.url")
+
+local RequestHttp = require("jive.net.RequestHttp")
+local SocketHttp  = require("jive.net.SocketHttp")
+local Process     = require("jive.net.Process")
+local Framework   = require("jive.ui.Framework")
+local Task        = require("jive.ui.Task")
+
+local debug       = require("jive.utils.debug")
+local log         = require("jive.utils.log").logger("applets.setup")
+
+local jnt = jnt
+
+module(..., oo.class)
+
+
+function __init(self)
+       local obj = oo.rawnew(self, {
+               _mtd = mtd,
+               _file = {},
+               _size = {},
+               _checksum = "",
+       })
+
+       return obj
+end
+
+
+-- perform the upgrade
+function start(self, url, mtd, callback)
+       self._url = url
+       self._mtd = mtd
+       self._callback = callback
+
+       return Task:pcall(_upgrade, self)
+end
+
+
+function _upgrade(self)
+
+       self._callback(false, "UPDATE_DOWNLOAD", "")
+
+       -- remove old image
+       self:rmvol("kernel_bak")
+       self:rmvol("cramfs_bak")
+
+       -- remove any failed upgrades
+       self:rmvol("kernel_upg")
+       self:rmvol("cramfs_upg")
+
+       -- wait for udev
+       self:udevtrigger()
+
+       -- write new volume contents
+       self:download()
+
+       self._callback(false, "UPDATE_VERIFY")
+
+       -- verify new volumes
+       self:parseMtd()
+       self:checksum("kernel_upg")
+       self:checksum("cramfs_upg")
+
+       -- automically rename volumes
+       self:renamevol({
+               ["kernel"] = "kernel_bak",
+               ["kernel_upg"] = "kernel",
+               ["cramfs"] = "cramfs_bak",
+               ["cramfs_upg"] = "cramfs",
+       })
+
+       -- reboot
+       self._callback(true, "UPDATE_REBOOT")
+
+       -- two second delay
+       local t = Framework:getTicks()
+       while (t + 2000) > Framework:getTicks() do
+               Task:yield(true)
+       end
+
+       os.execute("/bin/busybox reboot -f")
+
+       return true
+end
+
+
+-- utility function to parse /dev/mtd
+function parseMtd(self)
+       local mtd = {}
+
+       -- parse mtd to work out what partitions to use
+       local fh, err = io.open("/proc/mtd")
+       if fh == nil then
+               error(err, 0)
+       end
+
+       for line in fh:lines() do
+               local partno, name = string.match(line, 
"mtd(%d+):.*\"([^\"]+)\"")
+               if partno then
+                       mtd[name] = "/dev/mtd/" .. partno
+               end
+       end
+
+       fh:close()
+
+       self._mtd = mtd
+end
+
+
+-- wait for udev to create device nodes
+function udevtrigger(self)
+       -- sometimes the devices nodes are not created correctly,
+       -- manually triggering udev corrects this
+       local cmd = "/sbin/udevtrigger --subsystem-match=ubi"
+       log:info(cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+
+       -- wait for udev to settle before continuing
+       local cmd = "/sbin/udevsettle"
+       log:info(cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+end
+
+
+-- zip filter sink to process upgrade zip file
+function upgradeSink(self)
+       local _fhsink = nil
+       local _action = nil
+
+       return function(chunk, err)
+               if err then
+                       log:error("upgrade sink: ", err)
+                       self.sinkErr = err
+                       return 0
+               end
+
+               Task:yield(true)
+
+               if type(chunk) == "string" then
+                       self.downloadBytes = self.downloadBytes + #chunk
+
+                       if _action == "store" then
+                               -- write content to fhsink
+                               local t, err = _fhsink(chunk)
+                               if not t then
+                                       log:error("FLASH err=", err)
+                                       return nil, err
+                               end
+
+                       elseif _action == "checksum" then
+                               -- store checksum
+                               self._checksum = self._checksum .. chunk
+                       end
+                       return 1
+               end
+
+               if _fhsink then
+                       -- end of file, close the sink
+                       _fhsink(nil)
+                       _fhsink = nil
+               end
+
+               if chunk == nil then
+                       -- end of zip file
+                       self.downloadClose = true
+                       return nil
+               end
+
+               if type(chunk) == "table" then
+                       -- new file
+                       local filename = chunk.filename
+
+                       if string.match(filename, "^zImage") then
+                               _action = "store"
+                               _fhsink, err = self:updatevol("kernel_upg", 
filename, chunk.uncompressed_size)
+                               if not _fhsink then
+                                       return nil, err
+                               end
+
+                       elseif filename == "root.cramfs" then
+                               _action = "store"
+                               _fhsink = self:updatevol("cramfs_upg", 
filename, chunk.uncompressed_size)
+                               if not _fhsink then
+                                       return nil, err
+                               end
+
+                       elseif filename == "upgrade.md5" then
+                               _action = "checksum"
+
+                       else
+                               -- ignore file
+                               _action = nil
+                       end
+
+                       return 1
+               end
+
+               -- should never get here
+               return nil
+       end
+end
+
+
+-- open the zip file or stream for processing
+function download(self)
+       log:info("Firmware url=", self._url)
+
+       -- unzip the stream, and store the contents
+       local sink = ltn12.sink.chain(zip.filter(), self:upgradeSink())
+
+       local parsedUrl = url.parse(self._url)
+       self.downloadBytes = 0
+       self.sinkErr = false
+
+       local t, err
+       if parsedUrl.scheme == "file" then
+               local file = io.open(parsedUrl.path)
+
+               local totalBytes = file:seek("end")
+               file:seek("set", 0)
+
+               local source = function()
+                                   local chunk = file:read(0x16000)
+                                   if not chunk then file:close() end
+                                   return chunk
+                               end
+
+               while true do
+                       local t, err = ltn12.pump.step(source, sink)
+                       self._callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
+
+                       Task:yield()
+                       if not t then
+                               if err then
+                                       error(err, 0)
+                               else
+                                       return
+                               end
+                       end
+               end 
+
+       elseif parsedUrl.scheme == "http" then
+               self.downloadClose = false
+
+               local req = RequestHttp(sink, 'GET', self._url, { stream = true 
})
+               local uri  = req:getURI()
+
+               local http = SocketHttp(jnt, uri.host, uri.port, uri.host)
+               http:fetch(req)
+
+               while not self.sinkErr and not self.downloadClose do
+                       local totalBytes = 
req:t_getResponseHeader("Content-Length")
+                       if totalBytes then
+                               self._callback(false, "UPDATE_DOWNLOAD", 
math.floor((self.downloadBytes / totalBytes) * 100) .. "%")
+                       end
+                       Task:yield(true)
+               end
+
+               if self.sinkErr then
+                       error(self.sinkErr, 0)
+               end
+       else
+               error("Unsupported url scheme", 0)
+       end
+end
+
+
+-- create and update a ubi volume. returns a sink to the ubi volume.
+function updatevol(self, volume, filename, size)
+
+       self._file[volume] = filename
+       self._size[volume] = size
+
+       -- make volume
+       local cmd = "/usr/sbin/ubimkvol /dev/ubi0 -N " .. volume .. " -s " .. 
size
+       log:info(cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+
+       -- wait for udev
+       self:udevtrigger()
+
+       -- update volume
+       local cmd = "/usr/sbin/ubiupdatevol /dev/ubi/" .. volume .. "/vol -s " 
.. size .. " -"
+       log:info(cmd)
+
+       local fh, err = io.popen(cmd, "w")
+       if fh == nil then
+               error(err, 0)
+       end
+       
+       return function(chunk, err)
+               if chunk then
+                       return fh:write(chunk)
+               else
+                       fh:close()
+                       return false
+               end
+       end
+end
+
+
+function renamevol(self, volumes)
+       local cmd = { "/usr/sbin/ubirename /dev/ubi0 " }
+       for old, new in pairs(volumes) do
+               table.insert(cmd, old)
+               table.insert(cmd, new)
+       end
+       cmd = table.concat(cmd, " ")
+       log:info(cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+end
+
+
+function nullProcessSink(chunk, err)
+       if err then
+               log:warn("process error:", err)
+               return nil
+       end
+       return 1
+end
+
+
+-- remove a ubi volume
+function rmvol(self, volume)
+       if not self._mtd[volume] then
+               return true
+       end
+
+       -- remove volume
+       local cmd = "/usr/sbin/ubirmvol /dev/ubi0 -N " .. volume
+       log:info(cmd)
+
+       proc = Process(jnt, cmd)
+       proc:read(nullProcessSink)
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+
+       return true
+end
+
+
+-- checksum flash partition
+function checksum(self, volume)
+       local checksum = {}
+       for md5, file in string.gmatch(self._checksum, "(%x+)%s+([^%s]+)") do   
+                checksum[file] = md5
+       end
+
+       local filename = self._file[volume]
+       local size = self._size[volume]
+
+       local md5check = checksum[filename]
+
+       assert(filename)
+       assert(size)
+       assert(md5check)
+
+       local cmd = "/usr/bin/head -c " .. size .. " " .. self._mtd[volume] .. 
" | md5sum"
+       log:info(cmd)
+
+       local md5flash = {}
+
+       local proc = Process(jnt, cmd)
+       proc:read(
+               function(chunk, err)
+                       if err then
+                               log:warn("md5sum error ", err)
+                               return nil
+                       end
+                       if chunk ~= nil then
+                               table.insert(md5flash, chunk)
+                       end
+                       return 1                        
+               end)
+
+       while proc:status() ~= "dead" do
+               -- wait for the process to complete
+               Task:yield()
+       end
+
+       md5flash = string.match(table.concat(md5flash), "(%x+)%s+.+")
+
+       log:info("md5check=", md5check, " md5flash=", md5flash, " ", md5check 
== md5flash)
+       assert(md5check == md5flash, "Firmware checksum failed for " .. volume)
+end
+
+
+--[[
+
+=head1 LICENSE
+
+Copyright 2007 Logitech. All Rights Reserved.
+
+This file is subject to the Logitech Public Source License Version 1.0. Please 
see the LICENCE file for details.
+
+=cut
+--]]

_______________________________________________
Jive-checkins mailing list
[email protected]
http://lists.slimdevices.com/cgi-bin/mailman/listinfo/jive-checkins

Reply via email to