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