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 = type, assert, error
25 module "luci.sys.mtdow"
28 local WRITE_COMBINED = 1
29 local WRITE_EMULATED = 2
34 EmulatedWriter = util.class(Writer)
35 EmulatedWriter.blocks = {
39 write = WRITE_SEPARATELY
44 TRXWriter = util.class(Writer)
47 magic = {"4844", "5735"},
49 write = WRITE_COMBINED
54 CommonWriter = util.class(Writer)
55 CommonWriter.blocks = {
58 write = WRITE_COMBINED
63 RedWriter = util.class(Writer)
66 device = "vmlinux.bin.l7",
71 write = WRITE_COMBINED
75 function EmulatedWriter.write_block(self, name, imagestream, appendpattern)
77 os.execute("grep rootfs /proc/mtd >/dev/null || "
78 .. "{ echo /dev/hda2,65536,rootfs > "
79 .. "/sys/module/block2mtd/parameters/block2mtd }")
81 return Writer.write_block(self, name, imagestream, appendpattern)
85 Writer.MTD = "/sbin/mtd"
86 Writer.SAFEMTD = "/tmp/mtd"
87 Writer.IMAGEFIFO = "/tmp/mtdimage.fifo"
89 function Writer.write_block(self, name, imagestream, appendfile)
90 assert(self.blocks[name], "Undefined block: " % name)
91 local block = self.blocks[name]
92 local device = block.device
93 device = fs.stat(device) and device or self:_find_mtdblock(device)
94 assert(device, "Unable to determine device file")
96 imagestream = self:_check_magic(imagestream, block.magic)
98 assert(imagestream, "Invalid image file")
101 if block.write == WRITE_COMBINED then
102 return (self:_write_combined(device, imagestream, appendfile) == 0)
103 elseif block.write == WRITE_EMULATED then
104 return (self:_write_emulated(device, imagestream, appendfile) == 0)
106 error("Appending is not supported for selected platform.")
109 return (self:_write_memory(device, imagestream) == 0)
113 function Writer._check_magic(self, imagestream, magic)
114 magic = type(magic) == "table" and magic or {magic}
116 local block = imagestream()
117 assert(block, "Invalid image stream")
118 local cm = "%x%x" % {block:byte(1), block:byte(2)}
120 if util.contains(magic, cm) then
121 return ltn12.source.cat(ltn12.source.string(block), imagestream)
125 function Writer._find_mtdblock(self, mtdname)
127 local prefix = "/dev/mtdblock"
128 prefix = prefix .. (fs.stat(prefix) and "/" or "")
130 for l in io.lines("/proc/mtd") do
131 local k = l:match('([%w-_]+):.*-"%s"' % mtdname)
132 if k then return prefix..k end
136 function Write._write_emulated(self, devicename, imagestream, appendfile)
137 local stat = (self:_write_memory(device, imagestream) == 0)
138 stat = stat and (self:_refresh_block("rootfs") == 0)
139 local squash = self:_find_mtdblock("rootfs_data")
141 stat = stat and (self:_append("rootfs_data", imagestream, true) == 0)
143 stat = stat and (self:_append("rootfs", imagestream) == 0)
148 function Writer._write_memory(self, devicename, imagestream)
149 local devicestream = ltn12.sink.file(io.open(devicename, "w"))
150 local stat, err = ltn12.pump.all(imagestream, devicestream)
152 return os.execute("sync")
156 function Writer._write_combined(self, devicename, imagestream, appendfile)
157 assert(fs.copy(self.MTD, self.SAFEMTD), "Unable to copy mtd writer")
158 assert(posix.mkfifo(self.IMAGEFIFO), "Unable to create image pipe")
160 local imagefifo = io.open(self.IMAGEFIFO, "w")
162 assert(imagefifo, "Unable to open image pipe")
164 local imageproc = posix.fork()
165 assert(imageproc ~= -1, "Unable to fork()")
166 if imageproc == 0 then
167 ltn12.pump.all(imagestream, ltn12.sink.file(imagefifo))
172 "%s -j '%s' write '%s' '%s'" % {
173 self.SAFEMTD, appendfile, devicename, self.IMAGEFIFO
178 function Writer._refresh_block(self, devicename)
179 assert(fs.copy(self.MTD, self.SAFEMTD), "Unable to copy mtd writer")
180 return os.execute("%s refresh '%s'" % {self.SAFEMTD, devicename})
183 function Writer._append(self, devicename, appendfile, erase)
184 assert(fs.copy(self.MTD, self.SAFEMTD), "Unable to copy mtd writer")
185 erase = erase and ("-e '%s' " % devicename) or ''
188 "%s %s jffs2write '%s' '%s'" % {
189 self.SAFEMTD, erase, appendfile, devicename