diff --git a/package/base-files/files/bin/board_detect b/package/base-files/files/bin/board_detect
new file mode 100755
index 0000000000000000000000000000000000000000..ddd17a16337d1159cc05fda4d6ce1c7a0dd34e75
--- /dev/null
+++ b/package/base-files/files/bin/board_detect
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+[ -d "/etc/board.d/" -a ! -f "/etc/board.json" ] || {
+	for a in `ls /etc/board.d/*`; do
+		[ -x $a ] || continue;
+		$(. $a)
+	done
+}
+
+[ -f "/etc/board.json" ] || return 1
+[ -f "/etc/config/network" ] || {
+	touch /etc/config/network
+	/bin/config_generate
+}
diff --git a/package/base-files/files/bin/config_generate b/package/base-files/files/bin/config_generate
new file mode 100755
index 0000000000000000000000000000000000000000..c435e7bb43e72e59b8f6d50a59189c68a07e1aa7
--- /dev/null
+++ b/package/base-files/files/bin/config_generate
@@ -0,0 +1,173 @@
+#!/bin/sh
+
+CFG=/etc/board.json
+
+. /usr/share/libubox/jshn.sh
+
+[ -f $CFG ] || exit 1
+
+generate_static_network() {
+	uci -q batch <<EOF
+delete network.loopback
+set network.loopback='interface'
+set network.loopback.ifname='lo'
+set network.loopback.proto='static'
+set network.loopback.ipaddr='127.0.0.1'
+set network.loopback.netmask='255.0.0.0'
+delete network.globals
+set network.globals='globals'
+set network.globals.ula_prefix='fdb1:a57f:2544::/48'
+EOF
+}
+
+next_vlan=3
+generate_network() {
+	local vlan
+
+	json_select network
+	json_select $1
+	json_get_vars ifname create_vlan macaddr
+	json_select ..
+	json_select ..
+
+	[ -n "$ifname" ] || return
+	[ "$create_vlan" -eq 1 ] && case $1 in
+	lan) vlan=1;;
+	wan) vlan=2;;
+	*)
+		vlan=$next_vlan
+		next_vlan=$((next_vlan + 1))
+		;;
+	esac
+	[ -n "$vlan" ] && ifname=${ifname}.${vlan}
+	uci -q batch <<EOF
+delete network.$1
+set network.$1='interface'
+set network.$1.ifname='$ifname'
+set network.$1.force_link=1
+set network.$1.proto='none'
+set network.$1.macaddr='$macaddr'
+EOF
+
+	case $1 in
+	lan) uci -q batch <<EOF
+set network.$1.type='bridge'
+set network.$1.proto='static'
+set network.$1.ipaddr='192.168.1.1'
+set network.$1.netmask='255.255.255.0'
+set network.$1.ip6assign='60'
+EOF
+		;;
+	wan) uci -q batch <<EOF
+set network.$1.proto='dhcp'
+delete network.wan6
+set network.wan6='interface'
+set network.wan6.ifname='@wan6'
+set network.wan6.proto='dhcpv6'
+EOF
+		;;
+	esac
+}
+
+generate_switch_vlan() {
+	local device=$1
+	local vlan=$2
+	local cpu_port=$3
+
+	case $vlan in
+	lan)	vlan=1;;
+	wan)	vlan=2;;
+	*)	vlan=${vlan##vlan};;
+	esac
+
+	json_select vlans
+	json_select $2
+	json_get_values ports
+	json_select ..
+	json_select ..
+
+	uci -q batch <<EOF
+add network switch_vlan
+set network.@switch_vlan[-1].device='$device'
+set network.@switch_vlan[-1].vlan='$vlan'
+set network.@switch_vlan[-1].ports='$ports ${cpu_port}t'
+EOF
+}
+
+generate_switch() {
+	local key=$1
+	local vlans
+
+	json_select switch
+	json_select $key
+	json_get_vars enable reset blinkrate cpu_port
+
+	[ -n "$cpu_port" ] || return
+
+	uci -q batch <<EOF
+add network switch
+set network.@switch[-1].name='$key'
+set network.@switch[-1].reset='$reset'
+set network.@switch[-1].enable_vlan='$enable'
+set network.@switch[-1].blinkrate='$blinkrate'
+EOF
+
+	json_get_keys vlans vlans
+	for vlan in $vlans; do generate_switch_vlan $1 $vlan $cpu_port; done
+	json_select ..
+	json_select ..
+}
+
+generate_led() {
+	local key=$1
+	local cfg="led_$key"
+
+	json_select led
+	json_select $key
+	json_get_vars name sysfs type trigger device interface default
+	json_select ..
+	json_select ..
+
+	uci -q batch <<EOF
+delete system.$cfg
+set system.$cfg='led'
+set system.$cfg.name='$name'
+set system.$cfg.sysfs='$sysfs'
+set system.$cfg.dev='$device'
+set system.$cfg.trigger='$trigger'
+set system.$cfg.port_mask='$port_mask'
+set system.$cfg.default='$default'
+EOF
+	case $type in
+	netdev)
+		uci -q batch <<EOF
+set system.$cfg.trigger='netdev'
+set system.$cfg.mode='link tx rx'
+EOF
+	;;
+
+	usb)
+		uci -q batch <<EOF
+set system.$cfg.trigger='usbdev'
+set system.$cfg.interval='50'
+EOF
+	;;
+
+	esac
+}
+
+json_init
+json_load "$(cat ${CFG})"
+
+generate_static_network
+
+json_get_keys keys network
+for key in $keys; do generate_network $key; done
+
+json_get_keys keys switch
+for key in $keys; do generate_switch $key; done
+
+json_get_keys keys led
+for key in $keys; do generate_led $key; done
+
+uci commit
diff --git a/package/base-files/files/etc/init.d/boot b/package/base-files/files/etc/init.d/boot
index b1272f401c6c33004c308a489d75b5231a5ad04e..f10db1344f69dc9e08dd28dc68df6e85f054e187 100755
--- a/package/base-files/files/etc/init.d/boot
+++ b/package/base-files/files/etc/init.d/boot
@@ -46,6 +46,7 @@ boot() {
 	}
 	rm -f /tmp/wireless.tmp
 
+	/bin/board_detect
 	uci_apply_defaults
 	
 	# temporary hack until configd exists
diff --git a/package/base-files/files/lib/functions/uci-defaults-new.sh b/package/base-files/files/lib/functions/uci-defaults-new.sh
new file mode 100755
index 0000000000000000000000000000000000000000..528835bb7ffa8ba3801c3f1ba898e7a9855e67fa
--- /dev/null
+++ b/package/base-files/files/lib/functions/uci-defaults-new.sh
@@ -0,0 +1,302 @@
+#!/bin/ash
+
+CFG=/etc/board.json
+
+. /usr/share/libubox/jshn.sh
+
+json_select_array() {
+	local _json_no_warning=1
+
+	json_select "$1"
+	[ $? = 0 ] && return
+
+	json_add_array $1
+	json_close_array
+
+        json_select "$1"
+}
+
+json_select_object() {
+	local _json_no_warning=1
+
+	json_select "$1"
+	[ $? = 0 ] && return
+
+	json_add_object $1
+	json_close_object
+
+        json_select "$1"
+}
+
+_ucidef_set_interface() {
+	local name=$1
+	local iface=$2
+
+	json_select_object $name
+	json_add_string ifname "${iface%%.*}"
+	[ "$iface" == "${iface%%.*}" ] || json_add_boolean create_vlan 1 
+	json_select ..
+}
+
+ucidef_set_interface_loopback()
+{
+	# stub
+	local a=$1
+}
+
+ucidef_set_interface_lan() {
+	local lan_if=$1
+
+	json_select_object network
+	_ucidef_set_interface lan $lan_if
+	json_select ..
+}
+
+ucidef_set_interfaces_lan_wan() {
+	local lan_if=$1
+	local wan_if=$2
+
+	json_select_object network
+	_ucidef_set_interface lan $lan_if
+	_ucidef_set_interface wan $wan_if
+	json_select ..
+}
+
+ucidef_add_switch() {
+	local name=$1
+	local reset=$2
+	local enable=$3
+
+	json_select_object switch
+
+        json_select_object $name
+	[ "$enable" -eq 1 ] && json_add_boolean enable 1
+	[ "$reset" -eq 1 ] && json_add_boolean reset 1
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_add_switch_attr() {
+	local name=$1
+	local key=$2
+	local val=$3
+
+	json_select_object switch
+
+        json_select_object $name
+	json_add_string $key $val
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_add_switch_vlan() {
+	local name=$1
+	local vlan=$2
+	local ports=$3
+	local cpu_port=''
+
+	case $vlan in
+	1)	vlan=lan;;
+	2)	vlan=wan;;
+	*)	vlan=vlan$vlan;;
+	esac
+
+	json_select_object switch
+	json_select_object $name
+	json_select_object vlans
+
+	json_add_array $vlan
+	for p in $ports; do
+		if [ ${p%t} != $p ]; then
+			cpu_port=$p
+		else
+			json_add_int "" $p
+		fi
+	done
+	json_close_array
+
+	json_select ..
+	[ -n "$cpu_port" ] && json_add_int cpu_port $cpu_port
+	json_select ..
+	json_select ..
+}
+
+ucidef_set_interface_macaddr() {
+	local network=$1
+	local macaddr=$2
+
+	json_select_object network
+
+	json_select $network
+	[ $? -eq 0 ] || {
+		json_select ..
+		return
+	}
+
+	json_add_string macaddr $macaddr
+	json_select ..
+	
+	json_select ..
+}
+
+ucidef_set_led_netdev() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local dev=$4
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name
+	json_add_string type netdev
+	json_add_string sysfs $sysfs
+	json_add_string device $dev
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_interface() {
+	local name=$1
+	local sysfs=$2
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name
+	json_add_string type interface
+	json_add_string sysfs $sysfs
+	json_add_string interface $name
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_usbdev() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local dev=$4
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name	
+	json_add_string type usb
+	json_add_string sysfs $sysfs
+	json_add_string device $dev
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_wlan() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local trigger=$4
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name
+	json_add_string type trigger
+	json_add_string sysfs $sysfs
+	json_add_string trigger $trigger
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_switch() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local trigger=$4
+	local port_mask=$5
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name
+	json_add_string type switch
+	json_add_string sysfs $sysfs
+	json_add_string trigger $trigger
+	json_add_string port_mask $port_mask
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_default() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local default=$4
+
+	json_select_object led
+	
+	json_select_object $1
+	json_add_string name $name
+	json_add_string sysfs $sysfs
+	json_add_string default $default
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_led_rssi() {
+	local cfg="led_$1"
+	local name=$2
+	local sysfs=$3
+	local iface=$4
+	local minq=$5
+	local maxq=$6
+	local offset=$7
+	local factor=$8
+
+	json_select_object led
+	
+	json_select_object rssi
+	json_select_object $1
+	json_add_string name $name
+	json_add_string sysfs $sysfs
+	json_add_string minq $minq
+	json_add_string maxq $maxq
+	json_add_string offset $offset
+	json_add_string factor $factor
+	json_select ..
+	json_select ..
+
+	json_select ..
+}
+
+ucidef_set_rssimon() {
+	local dev="$1"
+	local refresh="$2"
+	local threshold="$3"
+
+	json_select_object led
+	
+	json_select_object rssi
+	json_add_string type rssi
+	json_add_string dev $dev
+	json_add_string threshold $threshold
+	json_select ..
+
+	json_select ..
+	
+}
+
+board_config_update() {
+	json_init
+	[ -f ${CFG} ] && json_load "$(cat ${CFG})"
+}
+
+board_config_flush() {
+	json_dump -i > /tmp/.board.json
+	mv /tmp/.board.json ${CFG}
+}