>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