2 LuCI - Lua Configuration Interface
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
16 local io = require "io"
17 local os = require "os"
18 local fs = require "luci.fs"
19 local util = require "luci.util"
20 local ltn12 = require "luci.ltn12"
21 local posix = require "posix"
23 local type, assert, error, ipairs = type, assert, error, ipairs
25 module "luci.sys.mtdow"
42 EmulatedWriter = util.class(Writer)
43 EmulatedWriter.blocks = {
47 write = WRITE_EMULATED
51 function EmulatedWriter.write_block(self, name, imagestream, appendpattern)
53 os.execute("grep rootfs /proc/mtd >/dev/null || "
54 .. "{ echo /dev/hda2,65536,rootfs > "
55 .. "/sys/module/block2mtd/parameters/block2mtd }")
57 return Writer.write_block(self, name, imagestream, appendpattern)
61 CFEWriter = util.class(Writer)
64 magic = {"4844", "5735"},
72 CommonWriter = util.class(Writer)
73 CommonWriter.blocks = {
76 write = WRITE_COMBINED,
82 RedWriter = util.class(Writer)
85 device = "vmlinux.bin.l7",
90 write = WRITE_COMBINED,
96 function native_writer()
100 local x86 = {"x86_64", "i386", "i486", "i586", "i686"}
101 if util.contains(x86, posix.uname("%m")) then
102 return EmulatedWriter()
106 if w:_find_mtdblock("cfe") and w:_find_mtdblock("linux") then
111 if w:_find_mtdblock("RedBoot") and w:_find_mtdblock("vmlinux.bin.l7") then
116 if fs.readfile("/proc/cpuinfo"):find("MagicBox") then
117 return CommonWriter()
123 Writer.COPY = {"/sbin/mtd"}
124 Writer.MTD = "/tmp/mtd"
125 Writer.IMAGEFIFO = "/tmp/mtdimage.fifo"
128 function Writer.write_block(self, name, imagestream, appendfile)
129 assert(self.blocks[name], ERROR_NOTFOUND)
130 local block = self.blocks[name]
131 local device = block.device
132 device = fs.stat(device) and device or self:_find_mtdblock(device)
133 assert(device, ERROR_NODETECT)
135 imagestream = self:_check_magic(imagestream, block.magic)
137 assert(imagestream, ERROR_INVMAGIC)
142 if block.write == WRITE_COMBINED then
143 return (self:_write_combined(device, imagestream, appendfile) == 0)
144 elseif block.write == WRITE_EMULATED then
145 return (self:_write_emulated(device, imagestream, appendfile) == 0)
147 error(ERROR_NOTAVAIL)
150 return (self:_write_memory(device, imagestream) == 0)
154 function Writer._prepare_env(self)
155 if self._prepared then
159 for k, app in ipairs(self.COPY) do
160 local target = "/tmp/"..fs.basename(app)
163 fs.chmod(target, "rwx------")
166 self._prepared = true
169 function Writer._check_magic(self, imagestream, magic)
170 magic = type(magic) == "table" and magic or {magic}
172 local block = imagestream()
173 assert(block, ERROR_NOSTREAM)
174 local cm = "%x%x" % {block:byte(1), block:byte(2)}
176 if util.contains(magic, cm) then
177 return ltn12.source.cat(ltn12.source.string(block), imagestream)
181 function Writer._find_mtdblock(self, mtdname)
183 local prefix = "/dev/mtd"
184 prefix = prefix .. (fs.stat(prefix) and "/" or "")
186 for l in io.lines("/proc/mtd") do
187 local k = l:match('mtd([%%w-_]+):.*"%s"' % mtdname)
188 if k then return prefix..k end
192 function Writer._write_emulated(self, devicename, imagestream, appendfile)
193 local stat = (self:_write_memory(device, imagestream) == 0)
194 stat = stat and (self:_refresh_block("rootfs") == 0)
195 local squash = self:_find_mtdblock("rootfs_data")
197 stat = stat and (self:_append("rootfs_data", imagestream, true) == 0)
199 stat = stat and (self:_append("rootfs", imagestream) == 0)
204 function Writer._write_memory(self, devicename, imagestream)
205 local imageproc = posix.fork()
206 assert(imageproc ~= -1, ERROR_RESOURCE)
207 if imageproc == 0 then
208 fs.unlink(self.IMAGEFIFO)
209 assert(posix.mkfifo(self.IMAGEFIFO), ERROR_RESOURCE)
210 local imagefifo = io.open(self.IMAGEFIFO, "w")
211 assert(imagefifo, ERROR_RESOURCE)
212 ltn12.pump.all(imagestream, ltn12.sink.file(imagefifo))
217 "%s write '%s' '%s' >/dev/null 2>&1" % {
218 self.MTD, self.IMAGEFIFO, devicename
223 function Writer._write_combined(self, devicename, imagestream, appendfile)
224 local imageproc = posix.fork()
225 assert(imageproc ~= -1, ERROR_RESOURCE)
226 if imageproc == 0 then
227 fs.unlink(self.IMAGEFIFO)
228 assert(posix.mkfifo(self.IMAGEFIFO), ERROR_RESOURCE)
229 local imagefifo = io.open(self.IMAGEFIFO, "w")
230 assert(imagefifo, ERROR_RESOURCE)
231 ltn12.pump.all(imagestream, ltn12.sink.file(imagefifo))
236 "%s -j '%s' write '%s' '%s' >/dev/null 2>&1" % {
237 self.MTD, appendfile, self.IMAGEFIFO, devicename
242 function Writer._refresh_block(self, devicename)
243 return os.execute("%s refresh '%s' >/dev/null 2>&1" % {self.MTD, devicename})
246 function Writer._append(self, devicename, appendfile, erase)
247 erase = erase and ("-e '%s' " % devicename) or ''
250 "%s %s jffs2write '%s' '%s' >/dev/null 2>&1" % {
251 self.MTD, erase, appendfile, devicename