From b94e235b0b447f3fdf3b6268851b3b0b9588527d Mon Sep 17 00:00:00 2001
From: Attila Lendvai <attila.lendvai@gmail.com>
Date: Wed, 10 Dec 2014 02:11:30 +0100
Subject: [PATCH] works for me with barrier breaker. added some readme, too.

---
 .gitignore                                   |  1 +
 README.md                                    | 56 ++++++++++++++++++--
 build.sh                                     |  7 ++-
 image-extras/etc/config/fstab                | 12 ++---
 image-extras/root/autoprovision-functions.sh |  8 ++-
 image-extras/root/autoprovision-stage1.sh    | 27 +++++-----
 image-extras/root/autoprovision-stage2.sh    | 17 ++++--
 7 files changed, 98 insertions(+), 30 deletions(-)

diff --git a/.gitignore b/.gitignore
index 567609b..3c49f0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 build/
+notes.txt
diff --git a/README.md b/README.md
index f4fbd25..116a792 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,54 @@
-* This is more of a template than something standalone
+# What
 
-I've extracted this from another project, but I think it's useful
-enough for making it public.
+It's a script to build a customized OpenWRT firmware that will
+automatically set up
+[extroot](http://wiki.openwrt.org/doc/howto/extroot) on any (!)
+storage device plugged into the USB port (`/dev/sda`).
+
+# Why
+
+So that e.g. customers can buy a router on their own, flash our
+firmware, plug in a pendrive, and manage their SIP (telephony) node
+from our webapp.
+
+# Status
+
+This is more of a template than something standalone. You most
+probably want to customize this script here and there; search for
+`CUSTOMIZE` for places of interest.
+
+I've extracted this from a project where OpenWRT nodes auto-provision
+themselves in 3 stages, but I thought it's useful enough for making it
+public (stage 1: extroot setup; stage 2: install packages; stage 3: a
+Python script for app-level sync).
+
+At the time of writing it only supports a few `ar71xx` routers but
+it's easy to extend it.
+
+## Tested with
+
+[OpenWRT Barrier Breaker 14.07](http://downloads.openwrt.org/barrier_breaker/14.07/)
+on a TP-Link WDR4300.
+
+# Building
+
+e.g. `./build.sh TLWDR4300`
+
+Results will be under `build/OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64`.
+
+# Usage
+
+After flashing the firmware the router will have the standard
+`192.168.1.1` IP address, and SSH will listen there using the keys
+specified in `image-extras/etc/dropbear/authorized_keys`.
+
+Once connected, you can read the log with `logread -f`.
+
+The autoprovision script will wait for any `/dev/sda` to show up, then
+erase it and set up a `swap`, an `extroot`, and a `data` filesystem,
+and then reboots.
+
+In stage 2 it will need an internet connection, so you should connect
+to its [LuCI interface](http://192.168.1.1) to set up an Internet
+upstream, and then it will automatically continue installing packages,
+finishing the whole process, and then do a final reboot.
diff --git a/build.sh b/build.sh
index d24060c..d7d486a 100755
--- a/build.sh
+++ b/build.sh
@@ -20,6 +20,11 @@ IMGTEMPDIR="${BUILD}/openwrt-build-image-extras"
 IMGBUILDERDIR="${BUILD}/OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64"
 IMGBUILDERURL="https://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/OpenWrt-ImageBuilder-ar71xx_generic-for-linux-x86_64.tar.bz2"
 
+PREINSTALLED_PACKAGES="wireless-tools firewall iptables"
+PREINSTALLED_PACKAGES+=" ppp ppp-mod-pppoe ppp-mod-pppol2tp ppp-mod-pptp kmod-ppp kmod-pppoe"
+PREINSTALLED_PACKAGES+=" fdisk blkid swap-utils mount-utils block-mount e2fsprogs kmod-fs-ext4 kmod-usb2 kmod-usb-uhci kmod-usb-ohci kmod-usb-storage kmod-usb-storage-extras kmod-mmc"
+PREINSTALLED_PACKAGES+=" luci"
+
 mkdir --parents ${BUILD}
 
 rm -rf $IMGTEMPDIR
@@ -37,7 +42,7 @@ fi
 
 pushd ${IMGBUILDERDIR}
 
-make image PROFILE=$TARGET_PLATFORM PACKAGES="wireless-tools firewall iptables fdisk blkid block-mount e2fsprogs kmod-fs-ext4 kmod-usb2 kmod-usb-uhci kmod-usb-ohci kmod-usb-storage kmod-usb-storage-extras luci kmod-mmc mount-utils ppp ppp-mod-pppoe ppp-mod-pppol2tp ppp-mod-pptp kmod-ppp kmod-pppoe" FILES=${IMGTEMPDIR}
+make image PROFILE=${TARGET_PLATFORM} PACKAGES="${PREINSTALLED_PACKAGES}" FILES=${IMGTEMPDIR}
 
 pushd bin/ar71xx/
 ln -s ../../packages .
diff --git a/image-extras/etc/config/fstab b/image-extras/etc/config/fstab
index ea1d80c..720e0f7 100644
--- a/image-extras/etc/config/fstab
+++ b/image-extras/etc/config/fstab
@@ -1,10 +1,10 @@
-config global 'automount'
-      option from_fstab '0'
-      option anon_mount '0'
-
-config global 'autoswap'
-      option from_fstab '0'
+config global
       option anon_swap '0'
+      option anon_mount '0'
+      option auto_swap '0'
+      option auto_mount '0'
+      option delay_root '3'
+      option check_fs '0'
 
 config swap
       option uuid '05d615b3-bef8-460c-9a23-52db8d09e002'
diff --git a/image-extras/root/autoprovision-functions.sh b/image-extras/root/autoprovision-functions.sh
index bab2819..e2a438b 100755
--- a/image-extras/root/autoprovision-functions.sh
+++ b/image-extras/root/autoprovision-functions.sh
@@ -2,6 +2,9 @@
 
 # utility functions for the various stages of autoprovisioning
 
+# make sure that installed packages take precedence over busybox. see https://dev.openwrt.org/ticket/18523
+PATH="/usr/bin:/usr/sbin:/bin:/sbin"
+
 # these are also copy-pasted into other scripts and config files!
 rootUUID=05d615b3-bef8-460c-9a23-52db8d09e000
 dataUUID=05d615b3-bef8-460c-9a23-52db8d09e001
@@ -13,6 +16,7 @@ swapUUID=05d615b3-bef8-460c-9a23-52db8d09e002
 autoprovisionUSBLed="tp-link:green:usb"
 autoprovisionStatusLed="tp-link:green:qss"
 
+# CUSTOMIZE
 case $(ar71xx_board_name) in
 "tl-wr1043nd")
         autoprovisionUSBLed="tp-link:green:usb"
@@ -27,7 +31,7 @@ case $(ar71xx_board_name) in
         autoprovisionStatusLed="tp-link:green:wlan5g"
 	;;
 "tl-wdr4300")
-        autoprovisionUSBLed="tp-link:green:usb1"
+        autoprovisionUSBLed="tp-link:blue:wan"
         autoprovisionStatusLed="tp-link:blue:qss"
 	;;
 esac
@@ -76,6 +80,8 @@ signalFormatting()
 
 stopSignallingAnything()
 {
+    # TODO this is wrong, they should be restored to their original state.
+    # but then leds are only touched in the setup stage, which is ephemeral when things work as expected...
     setLedAttribute ${autoprovisionStatusLed} trigger none
     setLedAttribute ${autoprovisionUSBLed} trigger usbdev
 }
diff --git a/image-extras/root/autoprovision-stage1.sh b/image-extras/root/autoprovision-stage1.sh
index 7bcdb0f..1dcaa31 100755
--- a/image-extras/root/autoprovision-stage1.sh
+++ b/image-extras/root/autoprovision-stage1.sh
@@ -36,9 +36,9 @@ setupPendrivePartitions()
     # erase partition table
     dd if=/dev/zero of=/dev/sda bs=1M count=1
 
-    # first is 'swap'
-    # second is 'root'
-    # the rest is 'data'
+    # sda1 is 'swap'
+    # sda2 is 'root'
+    # sda3 is 'data'
     fdisk /dev/sda <<EOF
 o
 n
@@ -64,15 +64,14 @@ q
 EOF
     log "Finished partitioning /dev/sda using fdisk"
 
+    sleep 2
+
     until [ -e /dev/sda1 ]
     do
-        echo "Waiting for a partitions to show up in /dev"
+        echo "Waiting for partitions to show up in /dev"
         sleep 1
     done
 
-    # just to be sure we wait a bit more (i've seen once that mkswap worked on /dev/sda1, but then mkfs errored that there's no /dev/sda2 (?!))
-    sleep 3
-
     mkswap -L swap -U $swapUUID /dev/sda1
     mkfs.ext4 -L root -U $rootUUID /dev/sda2
     mkfs.ext4 -L data -U $dataUUID /dev/sda3
@@ -83,17 +82,18 @@ EOF
 setupExtroot()
 {
     mkdir -p /mnt/extroot
+    # TODO they said on the wiki that it's optional, an empty overlay also works...
     # we need to make the internal overlay read-only, otherwise the two md5's may be different
     # due to writing to the internal overlay from this point until the reboot.
     # files: /.extroot.md5sum (extroot) and /etc/extroot.md5sum (internal)
-    mount -o remount,ro /
+    #mount -o remount,ro /
+    #log "Remounted / as read-only"
 
-    log "Remounted / as read-only"
-
-    mount UUID=$rootUUID /mnt/extroot
-    tar -C /overlay -cvf - . | tar -C /mnt/extroot -xf -
+    mount -U $rootUUID /mnt/extroot
+    #tar -C /overlay -cvf - . | tar -C /mnt/extroot -xf -
 
     # let's write a new rc.local on extroot which will shadow the one which is in the rom and runs stage1
+    mkdir -p /mnt/extroot/etc/
     cat >/mnt/extroot/etc/rc.local <<EOF
 /root/autoprovision-stage2.sh
 exit 0
@@ -113,9 +113,6 @@ autoprovisionStage1()
 {
     signalAutoprovisionWorking
 
-    # this way it will set a random password and only ssh key based login will work
-    setRootPassword ""
-
     signalAutoprovisionWaitingForUser
     signalWaitingForPendrive
 
diff --git a/image-extras/root/autoprovision-stage2.sh b/image-extras/root/autoprovision-stage2.sh
index 3d06768..d5474bc 100755
--- a/image-extras/root/autoprovision-stage2.sh
+++ b/image-extras/root/autoprovision-stage2.sh
@@ -28,6 +28,7 @@ installPackages()
     #mv /etc/dropbear/authorized_keys /root/.ssh/
     #rm -rf /etc/dropbear
 
+    # CUSTOMIZE
     # install some more packages that don't need any extra steps
     opkg install lua luci ppp-mod-pppoe screen mc zip unzip logrotate
 
@@ -41,13 +42,20 @@ installPackages()
 autoprovisionStage2()
 {
     log "Autoprovisioning stage2 speaking"
-    signalAutoprovisionWorking
 
-    # it's not the nicest way to test whether stage2 has been done already, but this is a shell script...
+    # TODO this is a rather sloppy way to test whether stage2 has been done already, but this is a shell script...
     if [ $(uci get system.@system[0].log_type) == "file" ]; then
         log "Seems like autoprovisioning stage2 has been done already. Running stage3."
         #/root/autoprovision-stage3.py
     else
+        signalAutoprovisionWorking
+
+        # CUSTOMIZE: with an empty argument it will set a random password and only ssh key based login will work.
+        # please note that stage2 requires internet connection to install packages and you most probably want to log in
+        # on the GUI to set up a WAN connection. but on the other hand you don't want to end up using a publically
+        # available default password anywhere, therefore the random here...
+        setRootPassword ""
+
         installPackages
 
         crontab - <<EOF
@@ -57,6 +65,9 @@ EOF
 
         mkdir -p /var/log/archive
 
+        # logrotate is complaining without this directory
+        mkdir -p /var/lib
+
         uci set system.@system[0].log_type=file
         uci set system.@system[0].log_file=/var/log/syslog
         uci set system.@system[0].log_size=0
@@ -65,8 +76,6 @@ EOF
         sync
         reboot
     fi
-
-    stopSignallingAnything
 }
 
 autoprovisionStage2