>From 6c158d0bd323a6686de433290779132008ff8bbf Mon Sep 17 00:00:00 2001
From: Matthew Fatheree <matthew.fathe...@belkin.com>
Date: Sun, 4 May 2014 20:06:39 +0700
Subject: [PATCH 17/30] mamba mvebu: support factory reset on syscfg partition

Mamba use the syscfg partition formatted in ubifs type as the
overlay partition to store the router configuration. This overlay style
is different from OpenWRT. We created a jffs2reset_mamba script to
support resetting this overlay partition. The original jffs2reset on the
rootfs is  a symbolic link to /sbin/mount_root, we cannot overwrite the
symbolic link directly. We created the script with a different name
jffs2reset_mamba. During the Image/mkfs/prepare/default, we try to
overwrite the jffs2reset with jffs2reset_mamba

system.lua_mamba file is added to support the factory reset from UI, it only
changes the default IP address to 192.168.200.1 and checking condition
on the overlay partition to enable the "Perform reset" button.
system.lua is installed by luci, we overwrite system.lua with
system.lua_mamba

Signed-off-by: Matthew Fatheree <matthew.fathe...@belkin.com>
---
 .../linksys-base-files/files/sbin/jffs2reset_mamba |   95 +++++
 .../lib/lua/luci/controller/admin/system.lua_mamba |  393 ++++++++++++++++++++
 target/linux/mvebu/image/Makefile                  |   15 +
 3 files changed, 503 insertions(+)
 create mode 100755 package/linksys-base-files/files/sbin/jffs2reset_mamba
 create mode 100644 
package/linksys-base-files/files/usr/lib/lua/luci/controller/admin/system.lua_mamba

diff --git a/package/linksys-base-files/files/sbin/jffs2reset_mamba 
b/package/linksys-base-files/files/sbin/jffs2reset_mamba
new file mode 100755
index 0000000..abca57d
--- /dev/null
+++ b/package/linksys-base-files/files/sbin/jffs2reset_mamba
@@ -0,0 +1,95 @@
+#!/bin/sh
+SYSCFG_UBIFS_MNT=/tmp/syscfg
+. /lib/functions.sh
+
+# mtdpart: the ubifs syscfg partition
+# rom: the read-only rootfs mount point
+# overlay: the overlay upper directory
+pre_check() {
+       # return 1 on failed
+       grep -qs ubifs /proc/filesystems ||  return 1
+       grep -qs overlayfs /proc/filesystems ||  return 1
+       [ ! -e $SYSCFG_UBIFS_MNT ] && mkdir -p $SYSCFG_UBIFS_MNT
+
+       mtdpart="$(find_mtd_part syscfg)"
+       [ -z "$mtdpart" ] && return 1
+       mtdpart_idx="$(echo $mtdpart | tr -d "/dev/mtdblock")"
+
+    rom=$(awk '/jffs2 ro/ {print $2}' /proc/mounts)
+    overlay=$(awk '/ubifs/ {print $2}' /proc/mounts | tail -n 1)
+       return 0
+}
+
+clean_mounted_overlayfs(){
+       if [ ! -z "$overlay" ]
+       then
+               echo -n "delete all file under $overlay/ ... "
+               rm -rf $overlay/*
+               echo "done"
+       fi
+}
+
+try_ubifs_syscfg_mount() {
+       overlay_mountpoint=$1
+       if [ -z $overlay_mountpoint ]
+       then
+               overlay_mountpoint=/overlay
+       fi
+       recover_ubifs=0
+       [ ! -e /dev/ubi0 ] && ubiattach -m $mtdpart_idx /dev/ubi_ctrl || 
recover_ubifs=1
+       if [ $recover_ubifs -eq 0 ]
+       then
+               ubi0_nod_id=`cat /sys/class/ubi/ubi0/dev | tr -s ":" " "`
+               [ ! -e /dev/ubi0 ] && mknod /dev/ubi0 c ${ubi0_nod_id}
+               if [ ! -e /sys/class/ubi/ubi0_0/dev ]
+               then
+                       # no volume
+                       recover_ubifs=1
+               else
+                       # check for "syscfg" volume
+                       ubi0_0_nod_id=`cat /sys/class/ubi/ubi0_0/dev | tr -s 
":" " "`
+                       [ ! -e /dev/ubi0_0 ] && mknod /dev/ubi0_0 c 
${ubi0_0_nod_id}
+                       { ubinfo /dev/ubi0_0 | grep Name  | grep -qs "syscfg" ; 
} || \
+                       recover_ubifs=1
+               fi
+       fi
+       if [ $recover_ubifs -eq 1 ]
+       then
+               echo "ubifs syscfg partition is damaged"
+               echo "try to recover by formatting $mtdpart..."
+               [ -e /dev/ubi0 ] && ubidetach -m $mtdpart_idx
+               ubiformat -y -q /dev/mtd$mtdpart_idx
+               ubiattach -m $mtdpart_idx /dev/ubi_ctrl
+               ubi0_nod_id=`cat /sys/class/ubi/ubi0/dev | tr -s ":" " "`
+               [ ! -e /dev/ubi0 ] && mknod /dev/ubi0 c ${ubi0_nod_id}
+               ubimkvol /dev/ubi0 -n 0 -N syscfg -t dynamic --maxavsize
+       fi
+       # finally mount the ubifs
+       mount -t ubifs -o noatime ubi0:syscfg $SYSCFG_UBIFS_MNT || return 1
+       [ ! -d $SYSCFG_UBIFS_MNT/openwrt_overlay ] && mkdir -p 
$SYSCFG_UBIFS_MNT/openwrt_overlay
+       mount -o bind $SYSCFG_UBIFS_MNT/openwrt_overlay $overlay_mountpoint
+       return 0
+}
+
+if [ "$1" != "-y" ]
+then
+read -p "This will erase all settings and remove any installed packages. Are 
you sure? [N/y]" answer
+case $answer in
+       [Yy]* ) break;;
+       [Nn]* ) exit 0;;
+       * )     exit 0;;
+esac
+fi
+
+pre_check
+if [ ! -z "$overlay" ]
+then
+       echo "overlayfs is mounted"
+       clean_mounted_overlayfs
+else
+       echo "try to mount overlayfs"
+       try_ubifs_syscfg_mount || exit 1
+    overlay=$(awk '/ubifs/ {print $2}' /proc/mounts | tail -n 1)
+       clean_mounted_overlayfs
+fi
+
diff --git 
a/package/linksys-base-files/files/usr/lib/lua/luci/controller/admin/system.lua_mamba
 
b/package/linksys-base-files/files/usr/lib/lua/luci/controller/admin/system.lua_mamba
new file mode 100644
index 0000000..7154e41
--- /dev/null
+++ 
b/package/linksys-base-files/files/usr/lib/lua/luci/controller/admin/system.lua_mamba
@@ -0,0 +1,393 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright 2008 Steven Barth <ste...@midlink.org>
+Copyright 2008-2011 Jo-Philipp Wich <x...@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+
+module("luci.controller.admin.system", package.seeall)
+
+function index()
+       entry({"admin", "system"}, alias("admin", "system", "system"), 
_("System"), 30).index = true
+       entry({"admin", "system", "system"}, cbi("admin_system/system"), 
_("System"), 1)
+       entry({"admin", "system", "clock_status"}, call("action_clock_status"))
+
+       entry({"admin", "system", "admin"}, cbi("admin_system/admin"), 
_("Administration"), 2)
+
+       if nixio.fs.access("/bin/opkg") then
+               entry({"admin", "system", "packages"}, call("action_packages"), 
_("Software"), 10)
+               entry({"admin", "system", "packages", "ipkg"}, 
form("admin_system/ipkg"))
+       end
+
+       entry({"admin", "system", "startup"}, form("admin_system/startup"), 
_("Startup"), 45)
+       entry({"admin", "system", "crontab"}, form("admin_system/crontab"), 
_("Scheduled Tasks"), 46)
+
+       if nixio.fs.access("/etc/config/fstab") then
+               entry({"admin", "system", "fstab"}, cbi("admin_system/fstab"), 
_("Mount Points"), 50)
+               entry({"admin", "system", "fstab", "mount"}, 
cbi("admin_system/fstab/mount"), nil).leaf = true
+               entry({"admin", "system", "fstab", "swap"},  
cbi("admin_system/fstab/swap"),  nil).leaf = true
+       end
+
+       if nixio.fs.access("/sys/class/leds") then
+               entry({"admin", "system", "leds"}, cbi("admin_system/leds"), 
_("<abbr title=\"Light Emitting Diode\">LED</abbr> Configuration"), 60)
+       end
+
+       entry({"admin", "system", "flashops"}, call("action_flashops"), 
_("Backup / Flash Firmware"), 70)
+       entry({"admin", "system", "flashops", "backupfiles"}, 
form("admin_system/backupfiles"))
+
+       entry({"admin", "system", "reboot"}, call("action_reboot"), 
_("Reboot"), 90)
+end
+
+function action_clock_status()
+       local set = tonumber(luci.http.formvalue("set"))
+       if set ~= nil and set > 0 then
+               local date = os.date("*t", set)
+               if date then
+                       luci.sys.call("date -s '%04d-%02d-%02d %02d:%02d:%02d'" 
%{
+                               date.year, date.month, date.day, date.hour, 
date.min, date.sec
+                       })
+               end
+       end
+
+       luci.http.prepare_content("application/json")
+       luci.http.write_json({ timestring = os.date("%c") })
+end
+
+function action_packages()
+       local ipkg = require("luci.model.ipkg")
+       local submit = luci.http.formvalue("submit")
+       local changes = false
+       local install = { }
+       local remove  = { }
+       local stdout  = { "" }
+       local stderr  = { "" }
+       local out, err
+
+       -- Display
+       local display = luci.http.formvalue("display") or "installed"
+
+       -- Letter
+       local letter = string.byte(luci.http.formvalue("letter") or "A", 1)
+       letter = (letter == 35 or (letter >= 65 and letter <= 90)) and letter 
or 65
+
+       -- Search query
+       local query = luci.http.formvalue("query")
+       query = (query ~= '') and query or nil
+
+
+       -- Packets to be installed
+       local ninst = submit and luci.http.formvalue("install")
+       local uinst = nil
+
+       -- Install from URL
+       local url = luci.http.formvalue("url")
+       if url and url ~= '' and submit then
+               uinst = url
+       end
+
+       -- Do install
+       if ninst then
+               install[ninst], out, err = ipkg.install(ninst)
+               stdout[#stdout+1] = out
+               stderr[#stderr+1] = err
+               changes = true
+       end
+
+       if uinst then
+               local pkg
+               for pkg in luci.util.imatch(uinst) do
+                       install[uinst], out, err = ipkg.install(pkg)
+                       stdout[#stdout+1] = out
+                       stderr[#stderr+1] = err
+                       changes = true
+               end
+       end
+
+       -- Remove packets
+       local rem = submit and luci.http.formvalue("remove")
+       if rem then
+               remove[rem], out, err = ipkg.remove(rem)
+               stdout[#stdout+1] = out
+               stderr[#stderr+1] = err
+               changes = true
+       end
+
+
+       -- Update all packets
+       local update = luci.http.formvalue("update")
+       if update then
+               update, out, err = ipkg.update()
+               stdout[#stdout+1] = out
+               stderr[#stderr+1] = err
+       end
+
+
+       -- Upgrade all packets
+       local upgrade = luci.http.formvalue("upgrade")
+       if upgrade then
+               upgrade, out, err = ipkg.upgrade()
+               stdout[#stdout+1] = out
+               stderr[#stderr+1] = err
+       end
+
+
+       -- List state
+       local no_lists = true
+       local old_lists = false
+       local tmp = nixio.fs.dir("/var/opkg-lists/")
+       if tmp then
+               for tmp in tmp do
+                       no_lists = false
+                       tmp = nixio.fs.stat("/var/opkg-lists/"..tmp)
+                       if tmp and tmp.mtime < (os.time() - (24 * 60 * 60)) then
+                               old_lists = true
+                               break
+                       end
+               end
+       end
+
+
+       luci.template.render("admin_system/packages", {
+               display   = display,
+               letter    = letter,
+               query     = query,
+               install   = install,
+               remove    = remove,
+               update    = update,
+               upgrade   = upgrade,
+               no_lists  = no_lists,
+               old_lists = old_lists,
+               stdout    = table.concat(stdout, ""),
+               stderr    = table.concat(stderr, "")
+       })
+
+       -- Remove index cache
+       if changes then
+               nixio.fs.unlink("/tmp/luci-indexcache")
+       end
+end
+
+function action_flashops()
+       local sys = require "luci.sys"
+       local fs  = require "luci.fs"
+
+       local upgrade_avail = nixio.fs.access("/lib/upgrade/platform.sh")
+       local reset_avail   = os.execute([[grep '"syscfg"' /proc/mtd >/dev/null 
2>&1]]) == 0
+
+       local restore_cmd = "tar -xzC/ >/dev/null 2>&1"
+       local backup_cmd  = "sysupgrade --create-backup - 2>/dev/null"
+       local image_tmp   = "/tmp/firmware.img"
+
+       local function image_supported()
+               -- XXX: yay...
+               return ( 0 == os.execute(
+                       ". /lib/functions.sh; " ..
+                       "include /lib/upgrade; " ..
+                       "platform_check_image %q >/dev/null"
+                               % image_tmp
+               ) )
+       end
+
+       local function image_checksum()
+               return (luci.sys.exec("md5sum %q" % 
image_tmp):match("^([^%s]+)"))
+       end
+
+       local function storage_size()
+               local size = 0
+               if nixio.fs.access("/proc/mtd") then
+                       for l in io.lines("/proc/mtd") do
+                               local d, s, e, n = 
l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
+                               if n == "linux" or n == "firmware" then
+                                       size = tonumber(s, 16)
+                                       break
+                               end
+                       end
+               elseif nixio.fs.access("/proc/partitions") then
+                       for l in io.lines("/proc/partitions") do
+                               local x, y, b, n = 
l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
+                               if b and n and not n:match('[0-9]') then
+                                       size = tonumber(b) * 1024
+                                       break
+                               end
+                       end
+               end
+               return size
+       end
+
+
+       local fp
+       luci.http.setfilehandler(
+               function(meta, chunk, eof)
+                       if not fp then
+                               if meta and meta.name == "image" then
+                                       fp = io.open(image_tmp, "w")
+                               else
+                                       fp = io.popen(restore_cmd, "w")
+                               end
+                       end
+                       if chunk then
+                               fp:write(chunk)
+                       end
+                       if eof then
+                               fp:close()
+                       end
+               end
+       )
+
+       if luci.http.formvalue("backup") then
+               --
+               -- Assemble file list, generate backup
+               --
+               local reader = ltn12_popen(backup_cmd)
+               luci.http.header('Content-Disposition', 'attachment; 
filename="backup-%s-%s.tar.gz"' % {
+                       luci.sys.hostname(), os.date("%Y-%m-%d")})
+               luci.http.prepare_content("application/x-targz")
+               luci.ltn12.pump.all(reader, luci.http.write)
+       elseif luci.http.formvalue("restore") then
+               --
+               -- Unpack received .tar.gz
+               --
+               local upload = luci.http.formvalue("archive")
+               if upload and #upload > 0 then
+                       luci.template.render("admin_system/applyreboot")
+                       luci.sys.reboot()
+               end
+       elseif luci.http.formvalue("image") or luci.http.formvalue("step") then
+               --
+               -- Initiate firmware flash
+               --
+               local step = tonumber(luci.http.formvalue("step") or 1)
+               if step == 1 then
+                       if image_supported() then
+                               luci.template.render("admin_system/upgrade", {
+                                       checksum = image_checksum(),
+                                       storage  = storage_size(),
+                                       size     = 
nixio.fs.stat(image_tmp).size,
+                                       keep     = (not not 
luci.http.formvalue("keep"))
+                               })
+                       else
+                               nixio.fs.unlink(image_tmp)
+                               luci.template.render("admin_system/flashops", {
+                                       reset_avail   = reset_avail,
+                                       upgrade_avail = upgrade_avail,
+                                       image_invalid = true
+                               })
+                       end
+               --
+               -- Start sysupgrade flash
+               --
+               elseif step == 2 then
+                       local keep = (luci.http.formvalue("keep") == "1") and 
"" or "-n"
+                       luci.template.render("admin_system/applyreboot", {
+                               title = luci.i18n.translate("Flashing..."),
+                               msg   = luci.i18n.translate("The system is 
flashing now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes until 
you try to reconnect. It might be necessary to renew the address of your 
computer to reach the device again, depending on your settings."),
+                               addr  = (#keep > 0) and "192.168.200.1" or nil
+                       })
+                       fork_exec("killall dropbear uhttpd; sleep 1; 
/sbin/sysupgrade %s %q" %{ keep, image_tmp })
+               end
+       elseif reset_avail and luci.http.formvalue("reset") then
+               --
+               -- Reset system
+               --
+               luci.template.render("admin_system/applyreboot", {
+                       title = luci.i18n.translate("Erasing..."),
+                       msg   = luci.i18n.translate("The system is erasing the 
configuration partition now and will reboot itself when finished."),
+                       addr  = "192.168.200.1"
+               })
+               fork_exec("killall dropbear uhttpd; sleep 1; /sbin/jffs2reset 
-y ; reboot")
+       else
+               --
+               -- Overview
+               --
+               luci.template.render("admin_system/flashops", {
+                       reset_avail   = reset_avail,
+                       upgrade_avail = upgrade_avail
+               })
+       end
+end
+
+function action_passwd()
+       local p1 = luci.http.formvalue("pwd1")
+       local p2 = luci.http.formvalue("pwd2")
+       local stat = nil
+
+       if p1 or p2 then
+               if p1 == p2 then
+                       stat = luci.sys.user.setpasswd("root", p1)
+               else
+                       stat = 10
+               end
+       end
+
+       luci.template.render("admin_system/passwd", {stat=stat})
+end
+
+function action_reboot()
+       local reboot = luci.http.formvalue("reboot")
+       luci.template.render("admin_system/reboot", {reboot=reboot})
+       if reboot then
+               luci.sys.reboot()
+       end
+end
+
+function fork_exec(command)
+       local pid = nixio.fork()
+       if pid > 0 then
+               return
+       elseif pid == 0 then
+               -- change to root dir
+               nixio.chdir("/")
+
+               -- patch stdin, out, err to /dev/null
+               local null = nixio.open("/dev/null", "w+")
+               if null then
+                       nixio.dup(null, nixio.stderr)
+                       nixio.dup(null, nixio.stdout)
+                       nixio.dup(null, nixio.stdin)
+                       if null:fileno() > 2 then
+                               null:close()
+                       end
+               end
+
+               -- replace with target command
+               nixio.exec("/bin/sh", "-c", command)
+       end
+end
+
+function ltn12_popen(command)
+
+       local fdi, fdo = nixio.pipe()
+       local pid = nixio.fork()
+
+       if pid > 0 then
+               fdo:close()
+               local close
+               return function()
+                       local buffer = fdi:read(2048)
+                       local wpid, stat = nixio.waitpid(pid, "nohang")
+                       if not close and wpid and stat == "exited" then
+                               close = true
+                       end
+
+                       if buffer and #buffer > 0 then
+                               return buffer
+                       elseif close then
+                               fdi:close()
+                               return nil
+                       end
+               end
+       elseif pid == 0 then
+               nixio.dup(fdo, nixio.stdout)
+               fdi:close()
+               fdo:close()
+               nixio.exec("/bin/sh", "-c", command)
+       end
+end
diff --git a/target/linux/mvebu/image/Makefile 
b/target/linux/mvebu/image/Makefile
index 736fb9d..63ed2ac 100644
--- a/target/linux/mvebu/image/Makefile
+++ b/target/linux/mvebu/image/Makefile
@@ -17,6 +17,21 @@ JFFS2OPTS += --no-cleanmarkers
 define add_jffs2_mark
        echo "do nothing"
 endef
+
+# override Image/mkfs/prepare/default
+define Image/mkfs/prepare/default
+       # Use symbolic permissions to avoid clobbering SUID/SGID/sticky bits
+       - $(FIND) $(TARGET_DIR) -type f -not -perm +0100 -not -name 'ssh_host*' 
-not -name 'shadow' -print0 | $(XARGS) -0 chmod u+rw,g+r,o+r
+       - $(FIND) $(TARGET_DIR) -type f -perm +0100 -print0 | $(XARGS) -0 chmod 
u+rwx,g+rx,o+rx
+       - $(FIND) $(TARGET_DIR) -type d -print0 | $(XARGS) -0 chmod 
u+rwx,g+rx,o+rx
+       $(INSTALL_DIR) $(TARGET_DIR)/tmp
+       chmod 1777 $(TARGET_DIR)/tmp
+       rm -f $(TARGET_DIR)/sbin/jffs2reset
+       rm -f $(TARGET_DIR)/usr/lib/lua/luci/controller/admin/system.lua
+       mv $(TARGET_DIR)/sbin/jffs2reset_mamba $(TARGET_DIR)/sbin/jffs2reset
+       mv $(TARGET_DIR)/usr/lib/lua/luci/controller/admin/system.lua_mamba 
$(TARGET_DIR)/usr/lib/lua/luci/controller/admin/system.lua
+endef
+
 endif # PROFILE == Mamba

 LOADADDR:=0x00008000
--
1.7.9.5



__________________________________________________________________ Confidential 
This e-mail and any files transmitted with it are the property of Belkin 
International, Inc. and/or its affiliates, are confidential, and are intended 
solely for the use of the individual or entity to whom this e-mail is 
addressed. If you are not one of the named recipients or otherwise have reason 
to believe that you have received this e-mail in error, please notify the 
sender and delete this message immediately from your computer. Any other use, 
retention, dissemination, forwarding, printing or copying of this e-mail is 
strictly prohibited. Pour la version française: 
http://www.belkin.com/email-notice/French.html Für die deutsche Übersetzung: 
http://www.belkin.com/email-notice/German.html 
__________________________________________________________________
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to