diff --git a/scripts/qemustart b/scripts/qemustart
new file mode 100755
index 0000000000000000000000000000000000000000..5cadd7d6a8198eaab38784e5e410ad56abf6a3c8
--- /dev/null
+++ b/scripts/qemustart
@@ -0,0 +1,281 @@
+#!/usr/bin/env bash
+
+SELF="$0"
+
+# Linux bridge for connecting lan and wan network of guest machines
+BR_LAN="${BR_LAN:-br-lan}"
+BR_WAN="${BR_WAN:-br-wan}"
+
+# Host network interface providing internet access for guest machines
+IF_INET="${IF_INET:-eth0}"
+
+# qemu-bridge-helper does two things here
+#
+# - create tap interface
+# - add the tap interface to bridge
+#
+# as such it requires CAP_NET_ADMIN to do its job.  It will be convenient to
+# have it as a root setuid program.  Be aware of the security risks implied
+#
+# the helper has an acl list which defaults to deny all bridge.  we need to add
+# $BR_LAN and $BR_WAN to its allow list
+#
+#	# sudo vim /etc/qemu/bridge.conf
+#	allow br-lan
+#	allow br-wan
+#
+# Other allowed directives can be 'allow all', 'deny all', 'include xxx',  See
+# qemu-bridge-helper.c of qemu source code for details.
+#
+# The helper can be provided by package qemu-system-common on debian, or
+# qemu-kvm-common on rhel
+#
+HELPER="${HELPER:-/usr/libexec/qemu-bridge-helper}"
+
+### end of global settings
+
+__errmsg() {
+	echo "$*" >&2
+}
+
+do_setup() {
+	# setup bridge for LAN network
+	sudo ip link add dev "$BR_LAN" type bridge
+	sudo ip link set dev "$BR_LAN" up
+	sudo ip addr add 192.168.1.3/24 dev "$BR_LAN"
+
+	# setup bridge for WAN network
+	#
+	# minimal dnsmasq config for configuring guest wan network with dhcp
+	#
+	#	# sudo apt-get install dnsmasq
+	#	# sudo vi /etc/dnsmasq.conf
+	#	interface=br-wan
+	#	dhcp-range=192.168.7.50,192.168.7.150,255.255.255.0,30m
+	#
+	sudo ip link add dev "$BR_WAN" type bridge
+	sudo ip link set dev "$BR_WAN" up
+	sudo ip addr add 192.168.7.1/24 dev "$BR_WAN"
+
+	# guest internet access
+	sudo sysctl -w "net.ipv4.ip_forward=1"
+	sudo sysctl -w "net.ipv4.conf.$BR_WAN.proxy_arp=1"
+	while sudo iptables -t nat -D POSTROUTING -o "$IF_INET" -j MASQUERADE 2>/dev/null; do true; done
+	      sudo iptables -t nat -A POSTROUTING -o "$IF_INET" -j MASQUERADE
+}
+
+check_setup_() {
+	ip link show "$BR_LAN" >/dev/null || return 1
+	ip link show "$BR_WAN" >/dev/null || return 1
+	[ -x "$HELPER" ] || {
+		__errmsg "helper $HELPER is not an executable"
+		return 1
+	}
+}
+
+check_setup() {
+	check_setup_ || {
+		__errmsg "please check the script content to see the environment requirement"
+		return 1
+	}
+}
+#do_setup; check_setup; exit $?
+
+usage() {
+	cat >&2 <<EOF
+Usage: $SELF [-h|--help]
+       $SELF <target>
+         [<subtarget> [<extra-qemu-options>]]
+         [--kernel <kernel>]
+         [--rootfs <rootfs>]
+
+<subtarget> will default to "generic" and must be specified if
+<extra-qemu-options> are present
+
+e.g. <subtarget> for malta can be le, be, le64, be64, le-glibc, le64-glibc, etc
+
+<kernel>, <rootfs> can be required or optional arguments to qemu depending on
+the actual <target> in use.  They will default to files under bin/targets/
+
+Examples
+
+  $SELF x86 64
+  $SELF x86 64 -enable-kvm -device virtio-balloon-pci
+  $SELF x86 64 -incoming tcp:0:4444
+  $SELF x86 64-glibc
+  $SELF malta be -m 64
+  $SELF malta le64
+  $SELF malta be-glibc
+  $SELF armvirt 32 \\
+                --kernel bin/targets/armvirt/32/lede-armvirt-32-zImage \\
+                --rootfs bin/targets/armvirt/32/lede-armvirt-32-root.ext4
+EOF
+}
+
+rand_mac() {
+	hexdump -n 3 -e '"52:54:00:" 2/1 "%02x:" 1/1 "%02x"' /dev/urandom
+}
+
+parse_args() {
+	while [ "$#" -gt 0 ]; do
+		case "$1" in
+			--kernel) o_kernel="$2"; shift 2 ;;
+			--rootfs) o_rootfs="$2"; shift 2 ;;
+			--help|-h)
+				usage
+				exit 0
+				;;
+			*)
+				if [ -z "$o_target" ]; then
+					o_target="$1"
+				elif [ -z "$o_subtarget" ]; then
+					o_subtarget="$1"
+				else
+					o_qemu_extra=("${o_qemu_extra[@]}" "$1")
+				fi
+				shift
+				;;
+		esac
+	done
+
+	MAC_LAN="$(rand_mac)"
+	MAC_WAN="$(rand_mac)"
+	[ -n "$o_target" ] || {
+		usage
+		return 1
+	}
+	[ -n "$o_subtarget" ] || o_subtarget="generic"
+	o_bindir="bin/targets/$o_target/$o_subtarget"
+}
+
+start_qemu_armvirt() {
+	local kernel="$o_kernel"
+	local rootfs="$o_rootfs"
+	local cpu
+	local qemu_exe
+
+	case "${o_subtarget%-*}" in
+		32)
+			qemu_exe="qemu-system-arm"
+			cpu="cortex-a15"
+			[ -n "$kernel" ] || kernel="$o_bindir/lede-$o_target-${o_subtarget%-*}-zImage-initramfs"
+			;;
+		64)
+			qemu_exe="qemu-system-aarch64"
+			cpu="cortex-a57"
+			[ -n "$kernel" ] || kernel="$o_bindir/lede-$o_target-${o_subtarget%-*}-Image-initramfs"
+			;;
+		*)
+			__errmsg "target $o_target: unknown subtarget $o_subtarget"
+			return 1
+			;;
+	esac
+	[ -z "$rootfs" ] || {
+		if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
+			gunzip "$rootfs.gz"
+		fi
+		o_qemu_extra=( \
+			"-drive" "file=$rootfs,format=raw,if=virtio" \
+			"-append" "root=/dev/vda rootwait" \
+			"${o_qemu_extra[@]}" \
+		 )
+	}
+
+	"$qemu_exe" -machine virt -cpu "$cpu" -nographic \
+		-netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \
+		-netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \
+		-kernel "$kernel" \
+		"${o_qemu_extra[@]}"
+}
+
+start_qemu_malta() {
+	local is64
+	local isel
+	local qemu_exe
+	local kernel="$o_kernel"
+
+	# o_subtarget can be le, be, le64, be64, le-glibc, le64-glibc, etc..
+	is64="$(echo $o_subtarget | grep -o 64)"
+	[ "$(echo "$o_subtarget" | grep -o '^..')" = "le" ] && isel="el"
+	qemu_exe="qemu-system-mips$is64$isel"
+
+	[ -n "$kernel" ] || kernel="$o_bindir/lede-malta-${o_subtarget%-*}-vmlinux-initramfs.elf"
+
+	# NOTE: order of wan, lan -device arguments matters as it will affect which
+	# one will be actually used as the wan, lan network interface inside the
+	# guest machine
+	"$qemu_exe" -machine malta -nographic \
+		-netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device pcnet,netdev=wan,mac="$MAC_WAN" \
+		-netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device pcnet,netdev=lan,mac="$MAC_LAN" \
+		-kernel "$kernel" \
+		"${o_qemu_extra[@]}"
+}
+
+start_qemu_x86() {
+	local rootfs="$o_rootfs"
+	local qemu_exe
+
+	[ -n "$rootfs" ] || {
+		rootfs="$o_bindir/lede-$o_target-${o_subtarget%-*}-combined-ext4.img"
+		if [ ! -f "$rootfs" -a -s "$rootfs.gz" ]; then
+			gunzip "$rootfs.gz"
+		fi
+	}
+	#
+	# generic: 32-bit, pentium4 (CONFIG_MPENTIUM4), kvm guest, virtio
+	# legacy: 32-bit, i486 (CONFIG_M486)
+	# 64: 64-bit, kvm guest, virtio
+	#
+	case "${o_subtarget%-*}" in
+		legacy)			qemu_exe="qemu-system-i386"		;;
+		generic|64)		qemu_exe="qemu-system-x86_64"	;;
+		*)
+			__errmsg "target $o_target: unknown subtarget $o_subtarget"
+			return 1
+			;;
+	esac
+
+	case "${o_subtarget%-*}" in
+		legacy)
+			# use IDE (PATA) disk instead of AHCI (SATA).  Refer to link
+			# [1] for related discussions
+			#
+			# To use AHCI interface
+			#
+			#	-device ich9-ahci,id=ahci \
+			#	-device ide-drive,drive=drv0,bus=ahci.0 \
+			#	-drive "file=$rootfs,format=raw,id=drv0,if=none" \
+			#
+			# [1] https://dev.openwrt.org/ticket/17947
+			"$qemu_exe" -nographic \
+				-netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device e1000,id=devlan,netdev=lan,mac="$MAC_LAN" \
+				-netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device e1000,id=devwan,netdev=wan,mac="$MAC_WAN" \
+				-device ide-drive,drive=drv0 \
+				-drive "file=$rootfs,format=raw,id=drv0,if=none" \
+				"${o_qemu_extra[@]}"
+			;;
+		generic|64)
+			"$qemu_exe" -nographic \
+				-netdev bridge,id=lan,br="$BR_LAN,helper=$HELPER" -device virtio-net-pci,id=devlan,netdev=lan,mac="$MAC_LAN" \
+				-netdev bridge,id=wan,br="$BR_WAN,helper=$HELPER" -device virtio-net-pci,id=devwan,netdev=wan,mac="$MAC_WAN" \
+				-drive "file=$rootfs,format=raw,if=virtio" \
+				"${o_qemu_extra[@]}"
+			;;
+	esac
+}
+
+start_qemu() {
+	case "$o_target" in
+		armvirt)	start_qemu_armvirt	;;
+		malta)		start_qemu_malta	;;
+		x86)		start_qemu_x86		;;
+		*)
+			__errmsg "target $o_target is not supported yet"
+			return 1
+			;;
+	esac
+}
+
+check_setup \
+	&& parse_args "$@" \
+	&& start_qemu