Index: utils/ap51-flash/files/ap51-flash.init
===================================================================
--- utils/ap51-flash/files/ap51-flash.init	(revision 21552)
+++ utils/ap51-flash/files/ap51-flash.init	(working copy)
@@ -1,45 +1,68 @@
 #!/bin/sh /etc/rc.common
 # Copyright (C) 2010 OpenWrt.org
 
-START=20
+START=45
 
 NAME=ap51-flash
+PIPE_PATH="/tmp/ap51-flash-pipe"
 
 start_daemon() {
 	local cfg="$1"
+	local ifname="$1"
 
+	if [ -z "`ifconfig | grep "^$cfg`" ]; then
+		ifname="`echo $cfg | sed 's/_/./'`"
+	fi
+
 	config_get_bool loop "$cfg" loop
-	config_get ifname "$cfg" ifname
 	config_get rootfs "$cfg" rootfs
 	config_get kernel "$cfg" kernel
 	config_get ubnt "$cfg" ubnt
+	
+	[ -n "$rootfs" ] && rootfs="--rootfs $rootfs"
+	[ -n "$kernel" ] && kernel="--kernel $kernel"
+	[ -n "$ubnt" ] && ubnt="--ubnt $ubnt"
+
 	[ "$loop" != "1" ] && loop=0
 	if [ -n "$ifname" -a -n "$rootfs" -a -n "$kernel" ] || \
 	   [ -n "$ifname" -a -n "$ubnt" ]; then
-	   	PID="`cat /var/run/$NAME.sh-$ifname.pid 2> /dev/null`"
+	   	PID="`cat /var/run/$NAME-$ifname.pid 2> /dev/null`"
 	   	[ -z "`ps | grep "^.[ ]*$PID "`" ] && \
-	   		rm /var/run/$NAME.sh-$ifname.pid
-		[ -n "`ls /var/run/$NAME.sh-$ifname.pid 2> /dev/null`" ] && {
+	   		rm /var/run/$NAME-$ifname.pid
+		[ -n "`ls /var/run/$NAME-$ifname.pid 2> /dev/null`" ] && {
 			echo "Can't start more than one ap51-flash for interface $ifname!"
 			return 0
 		}
-		start-stop-daemon -S -b -m -p /var/run/$NAME.sh-$ifname.pid -n $NAME.sh \
-			-x /usr/lib/ap51-flash/$NAME.sh -- "$loop" "$ifname" "$rootfs" "$kernel" "$ubnt"
+		start-stop-daemon -S -b -m -p /var/run/$NAME-$ifname.pid -n $NAME \
+			-x /usr/sbin/$NAME -- --flash-from-file --pipe $PIPE_PATH $rootfs $kernel $ubnt $ifname
 	fi
 }
 
+start_loop_script() {
+	PID="`cat /var/run/$NAME.sh-$ifname.pid 2> /dev/null`"
+	[ -z "`ps | grep "^.[ ]*$PID "`" ] && \
+		rm /var/run/$NAME.sh.pid
+	[ -n "`ls /var/run/$NAME.sh.pid 2> /dev/null`" ] && {
+		echo "Can't start more than one ap51-flash loop script!"
+		return 0
+	}
+	start-stop-daemon -S -b -m -p /var/run/$NAME.sh.pid -n $NAME.sh \
+		-x /usr/lib/ap51-flash/ap51-flash.sh
+}
+
 start() {
+	mount -a
+	[ -e "$PIPE_PATH" ] || mkfifo $PIPE_PATH
 	config_load ap51-flash
 	config_foreach start_daemon flash
+	sleep 1
+	[ -e "$PIPE_PATH" ] && start_loop_script
 }
 
 stop() {
-	# Terminating all ap51-flash processes
-	echo "WARNING: Going to teminate all ap51-flash processes! (hope you made sure that they're not flashing right now)"
-	echo "OR you can stop this with Ctrl+c within 10 seconds"
-	sleep 10
+	# Terminating all ap51-flash processes (if they are not flashing anymore)
 	local pidfile
-	for pidfile in `ls /var/run/${NAME}.sh-*.pid 2> /dev/null`; do
+	for pidfile in `ls /var/run/${NAME}.sh.pid 2> /dev/null`; do
 		start-stop-daemon -K -s TERM -p "${pidfile}" -n "${NAME}.sh" >/dev/null
 		rm -f "${pidfile}"
 	done
@@ -47,4 +70,19 @@
 		start-stop-daemon -K -s TERM -p "${pidfile}" -n "${NAME}" >/dev/null
 		rm -f "${pidfile}"
 	done
+	[ -e "$PIPE_PATH" ] && rm $PIPE_PATH
 }
+
+forcestop() {
+	# Kill all ap51-flash processes
+	local pidfile
+	for pidfile in `ls /var/run/${NAME}.sh.pid 2> /dev/null`; do
+		start-stop-daemon -K -s KILL -p "${pidfile}" -n "${NAME}.sh" >/dev/null
+		rm -f "${pidfile}"
+	done
+	for pidfile in `ls /var/run/${NAME}.pid 2> /dev/null`; do
+		start-stop-daemon -K -s KILL -p "${pidfile}" -n "${NAME}" >/dev/null
+		rm -f "${pidfile}"
+	done
+	[ -e "$PIPE_PATH" ] && rm $PIPE_PATH
+}
Index: utils/ap51-flash/files/ap51-flash.sh
===================================================================
--- utils/ap51-flash/files/ap51-flash.sh	(revision 21552)
+++ utils/ap51-flash/files/ap51-flash.sh	(working copy)
@@ -1,21 +1,47 @@
-#!/bin/sh
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010 OpenWrt.org
 
 NAME=ap51-flash
-rootfs=""
-kernel=""
-ubnt=""
+PIPE_PATH="/tmp/ap51-flash-pipe"
 
-[ $1 -eq "1" ] && loop="1"
-ifname="$2"
-[ -n "$3" ] && rootfs="--rootfs $3"
-[ -n "$4" ] && kernel="--kernel $4"
-[ -n "$5" ] && ubnt="--ubnt $5"
+config_load ap51-flash
+[ -e "$PIPE_PATH" ] || mkfifo $PIPE_PATH
 
-while [ 1 ]; do
-	start-stop-daemon -S -m -p /var/run/$NAME-$ifname.pid -n $NAME \
-		-x /usr/sbin/$NAME -- --flash-from-file $rootfs $kernel $ubnt $ifname
+while true; do
+	read ifname evtype msg < $PIPE_PATH
+	echo "iface: $ifname, evtype: $evtype, msg: $msg" >> /tmp/ap51-flash.log
 	
+	[ "$evtype" != "SUCCESS" ] && continue
+	
+	PID="`cat /var/run/$NAME-$ifname.pid 2> /dev/null`"
 	rm /var/run/$NAME-$ifname.pid
-	[ "$loop" != "1" ] && break
-	sleep 15
+
+	local cfg="$ifname"
+	[ -z "`grep \"^$ifname\"`" ] && \
+		cfg="`echo $cfg | sed 's/\./_/'`"
+
+	config_get_bool loop "$cfg" loop
+	config_get rootfs "$cfg" rootfs
+	config_get kernel "$cfg" kernel
+	config_get ubnt "$cfg" ubnt
+	
+	[ "$loop" != "1" ] && continue
+
+	[ -n "$rootfs" ] && rootfs="--rootfs $rootfs"
+	[ -n "$kernel" ] && kernel="--kernel $kernel"
+	[ -n "$ubnt" ] && ubnt="--ubnt $ubnt"
+
+	wait $PID
+
+	if [ -n "$ifname" -a -n "$rootfs" -a -n "$kernel" ] || \
+	   [ -n "$ifname" -a -n "$ubnt" ]; then
+		[ -z "`ps | grep "^.[ ]*$PID "`" ] && \
+			rm /var/run/$NAME.sh-$ifname.pid
+		[ -n "`ls /var/run/$NAME.sh-$ifname.pid 2> /dev/null`" ] && {
+			echo "Can't start more than one ap51-flash for interface $ifname!"
+			return 0
+		}
+		start-stop-daemon -S -b -m -p /var/run/$NAME-$ifname.pid -n $NAME \
+			-x /usr/sbin/$NAME -- --flash-from-file --pipe $PIPE_PATH $rootfs $kernel $ubnt $ifname
+	fi
 done
Index: utils/ap51-flash/patches/0007-ap51-flash-Add-countdown-waits-for-flash-from-file-m.patch
===================================================================
--- utils/ap51-flash/patches/0007-ap51-flash-Add-countdown-waits-for-flash-from-file-m.patch	(revision 0)
+++ utils/ap51-flash/patches/0007-ap51-flash-Add-countdown-waits-for-flash-from-file-m.patch	(revision 0)
@@ -0,0 +1,71 @@
+From 1a7b22d7fa6d83105748a459fe88b521ef7cf209 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Sun, 25 Apr 2010 13:33:50 +0200
+Subject: [PATCH 7/7] ap51-flash: Add countdown/waits for flash-from-file mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is safer to add some time in between informing applications/users of
+a starting flash-procedure and the actual start of the flash-procedure
+itself. A user might unplug a router which is just going to be flashed.
+This patch shell avoid this "human-machine" race condition by giving
+him/her a 5 seconds reaction/noticing time.
+Also adding a 15 seconds wait after flashing procedure (after the reboot
+detection) to make sure to only terminate ap51-flash when the just
+flashed device is no more in its flashing-critical section.
+
+Signed-off-by: Linus Lüssing <linus.luessing@web.de>
+---
+ ap51-flash.c |   11 +++++++++++
+ ap51-flash.h |    5 +++++
+ 2 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index 891fe44..7307064 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -438,6 +438,12 @@ sanity_check:
+ 			goto err_close;
+ 		}
+ 
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++		/* Some time (for the UI) to react/notice */
++		printf("Starting flash procedure in %d seconds!\n", COUNTDOWN_TIMER);
++		sleep(COUNTDOWN_TIMER);
++#endif
++
+ 		if (device_info->kernel_part_size < kernel_size)
+ 			device_info->kernel_part_size = kernel_size;
+ 
+@@ -1122,6 +1128,11 @@ init_socket:
+ 		goto sock_close;
+ 
+ 	ret = detect_reboot(flash_mode, &srcipaddr, &dstipaddr, &srcmac, &dstmac);
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++		/* Avoid reflashing the same device (in looping scripts i.e.),
++		 * wait until a device left its critical flashing section */
++		sleep(COUNTDOWN_TIMER);
++#endif
+ 	if (ret != 0)
+ 		pipe_msg("ERROR", "could not detect the reboot of the same device");
+ 	else
+diff --git a/ap51-flash.h b/ap51-flash.h
+index 6e064de..cbc2875 100644
+--- a/ap51-flash.h
++++ b/ap51-flash.h
+@@ -67,6 +67,11 @@
+ #error Unsupported PLATFORM
+ #endif
+ 
++#if defined(FLASH_FROM_FILE)
++#define COUNTDOWN_TIMER 5
++#define BOOTWAIT_TIMER 15
++#endif
++
+ typedef struct ap51_flash_state {
+ 	struct psock p;
+ 	char inputbuffer[4096];
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0002-print-status-to-pipe.patch
===================================================================
--- utils/ap51-flash/patches/0002-print-status-to-pipe.patch	(revision 0)
+++ utils/ap51-flash/patches/0002-print-status-to-pipe.patch	(revision 0)
@@ -0,0 +1,276 @@
+From 32644d1de0e70c0d3a6d091b7fcc09dbf7fbe615 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Sun, 25 Apr 2010 12:54:20 +0200
+Subject: [PATCH 2/7] print status to pipe
+
+from Marek
+---
+ ap51-flash.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ ap51-flash.h |    4 +++
+ main.c       |    8 +++++-
+ packet.c     |    2 +
+ 4 files changed, 92 insertions(+), 3 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index 3244620..a1072ab 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -39,6 +39,11 @@ static int uncomp_loader = 0;
+ static int nvram_part_size = 0x00000000;
+ static int rootfs_part_size = 0x00000000;
+ 
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++static char *ap51_iface = NULL;
++char *pipe_path = NULL;
++#endif
++
+ char flash_mode = MODE_NONE;
+ int flash_from_file = 0;
+ struct flash_from_file fff_data[FFF_NUM];
+@@ -86,6 +91,40 @@ void uip_log(char *m)
+ #endif
+ }
+ 
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++void pipe_msg(char *event_type, char *msg)
++{
++	int fd, ret;
++
++	if (!flash_from_file)
++		return;
++
++	if (!pipe_path)
++		return;
++
++	if (!ap51_iface)
++		return;
++
++	fd = open(pipe_path, O_WRONLY);
++	if (fd < 0)
++		return;
++
++	ret = flock(fd, LOCK_EX);
++	if (ret < 0)
++		goto out;
++
++	dprintf(fd, "%s %s %s\n", ap51_iface, event_type, msg);
++	flock(fd, LOCK_UN);
++
++out:
++	close(fd);
++}
++#else
++void pipe_msg(char *event_type, char *msg)
++{
++}
++#endif
++
+ static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac, struct uip_eth_addr* dmac, int special)
+ {
+ 	int ret, len, arp_replies = 0, arp_grat_packets = 0;
+@@ -348,6 +387,11 @@ sanity_check:
+ 		       rootfs_part_size, device_info->kernel_part_size, nvram_part_size,
+ 		       rootfs_part_size + device_info->kernel_part_size + nvram_part_size);
+ 
++		if (device_info == &flash_8mb_info)
++			pipe_msg("FLASHING", "redboot_8MB");
++		else
++			pipe_msg("FLASHING", "redboot_4MB");
++
+ 		sprintf(str, "ip_addr -l %d.%d.%d.%d/8 -h %d.%d.%d.%d\n",
+ 			P(&dstipaddr)[0], P(&dstipaddr)[1], P(&dstipaddr)[2], P(&dstipaddr)[3],
+ 			P(&srcipaddr)[0], P(&srcipaddr)[1], P(&srcipaddr)[2], P(&srcipaddr)[3]);
+@@ -687,6 +731,7 @@ int ap51_flash(char *iface, char *rootfs_filename, char *kernel_filename, int nv
+ 		nvram_part_size = FLASH_PAGE_SIZE;
+ 
+ #if defined(FLASH_FROM_FILE)
++	char *fff_desc;
+ 	int i;
+ 
+ 	if (flash_from_file) {
+@@ -700,9 +745,24 @@ int ap51_flash(char *iface, char *rootfs_filename, char *kernel_filename, int nv
+ 			if (ret != 0)
+ 				return ret;
+ 
++			switch (i) {
++			case 0:
++				fff_desc = "rootfs";
++				break;
++			case 1:
++				fff_desc = "kernel";
++				break;
++			case 2:
++				fff_desc = "ubnt";
++				break;
++			case 3:
++			default:
++				fff_desc = "uboot";
++				break;
++			}
++
+ 			printf("Reading %s file %s with %d bytes ...\n",
+-			       (i == 0 ? "rootfs" : (i == 1 ? "kernel" : "ubnt")),
+-			       fff_data[i].fname, fff_data[i].flash_size);
++			       fff_desc, fff_data[i].fname, fff_data[i].flash_size);
+ 		}
+ 
+ 		goto init_socket;
+@@ -822,6 +882,10 @@ init_socket:
+ 	if (!socket_dev)
+ 		socket_dev = iface;
+ 
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++	ap51_iface = socket_dev;
++#endif
++
+ 	ret = ap51_init(socket_dev, &srcipaddr, &dstipaddr, &srcmac, &dstmac, special);
+ 
+ 	if (ret != 0)
+@@ -849,6 +913,7 @@ init_socket:
+ 			if ((!fff_data[FFF_ROOTFS].fname) ||
+ 			    (!fff_data[FFF_KERNEL].fname)) {
+ 				fprintf(stderr, "Error - redboot enabled device detected but rootfs & kernel file not available\n");
++				pipe_msg("ERROR", "no kernel and rootfs for redboot available");
+ 				goto sock_close;
+ 			}
+ 		} else {
+@@ -908,6 +973,7 @@ init_socket:
+ 		if (flash_from_file) {
+ 			if (!fff_data[FFF_UBNT].fname) {
+ 				fprintf(stderr, "Error - ubiquiti device detected but ubiquiti file not available\n");
++				pipe_msg("ERROR", "no image for ubiquiti available");
+ 				goto sock_close;
+ 			}
+ 		} else {
+@@ -924,6 +990,7 @@ init_socket:
+ 		tftp_xfer_buff = (flash_from_file ? (unsigned char *)&fff_data[FFF_UBNT] : rootfs_buf);
+ 		tftp_xfer_size = (flash_from_file ? fff_data[FFF_UBNT].flash_size : rootfs_size);
+ 		printf("Ubiquiti device detected - using TFTP client to flash\n");
++		pipe_msg("FLASHING", "ubiquiti");
+ 		break;
+ 	case MODE_TFTP_SERVER:
+ #if defined(EMBEDDED_DATA)
+@@ -962,6 +1029,7 @@ init_socket:
+ 		if (flash_from_file) {
+ 			if (!fff_data[FFF_UBOOT].fname) {
+ 				fprintf(stderr, "Error - uboot device detected but uboot file not available\n");
++				pipe_msg("ERROR", "no image for uboot available");
+ 				goto sock_close;
+ 			}
+ 		} else {
+@@ -976,14 +1044,23 @@ init_socket:
+ 		}
+ 
+ 		printf("Uboot device detected - using TFTP server to flash\n");
++		pipe_msg("FLASHING", "uboot");
+ 		break;
+ 	default:
+ 		fprintf(stderr, "Error - could not auto-detect flash mode!\n");
++		pipe_msg("ERROR", "could not auto-detect flash mode");
+ 		goto sock_close;
+ 	}
+ 
++#if defined(LINUX) && defined(FLASH_FROM_FILE)
++	signal(SIGTERM, SIG_IGN);
++#endif
++
+ 	ret = fw_upload();
+ 
++	if (ret == 0)
++		pipe_msg("SUCCESS", "");
++
+ sock_close:
+ 	socket_close(socket_dev);
+ 	return ret;
+diff --git a/ap51-flash.h b/ap51-flash.h
+index 2e59519..4dec003 100644
+--- a/ap51-flash.h
++++ b/ap51-flash.h
+@@ -57,6 +57,8 @@
+ #include <netinet/tcp.h>
+ #include <netinet/udp.h>
+ #include <arpa/inet.h>
++#include <signal.h>
++#include <sys/file.h>
+ #define PCAP_TIMEOUT_MS 200
+ #if !defined(NO_LIBPCAP)
+ #include <pcap.h>
+@@ -138,6 +140,7 @@ enum {
+ typedef int uip_udp_appstate_t;
+ void ap51_flash_tftp_appcall(void);
+ 
++void pipe_msg(char *event_type, char *msg);
+ int ap51_flash(char* device, char* rootfs_filename, char* kernel_filename, int nvram, int uncomp, int special);
+ void ap51_flash_appcall(void);
+ void handle_uip_tcp(const unsigned char *packet_buff, unsigned int packet_len);
+@@ -153,6 +156,7 @@ extern int rootfs_size;
+ extern int kernel_size;
+ extern char flash_mode;
+ extern int flash_from_file;
++extern char *pipe_path;
+ extern struct flash_from_file fff_data[];
+ 
+ #endif /* __ap51_FLASH_H__ */
+diff --git a/main.c b/main.c
+index 44f0386..9e5c0da 100644
+--- a/main.c
++++ b/main.c
+@@ -48,6 +48,7 @@ void usage(char *prgname)
+ 	fprintf(stderr, "  --kernel   path to kernel file\n");
+ 	fprintf(stderr, "  --ubnt     path to ubiquiti image\n");
+ 	fprintf(stderr, "  --uboot    path to uboot image\n");
++	fprintf(stderr, "  --pipe     write status messages to pipe\n");
+ #endif
+ 
+ 	fprintf(stderr, "\nThe 'ethdevice' has to be one of the devices that are part of the supported device list which follows.\nYou can either specify its name or the interface number.\n");
+@@ -66,6 +67,7 @@ int main(int argc, char* argv[])
+ 	{
+ 		{"uboot", required_argument, 0, 'b'},
+ 		{"flash-from-file", no_argument, 0, 'f'},
++		{"pipe", required_argument, 0, 'p'},
+ 		{"rootfs", required_argument, 0, 'r'},
+ 		{"kernel", required_argument, 0, 'k'},
+ 		{"ubnt", required_argument, 0, 'u'},
+@@ -118,7 +120,7 @@ int main(int argc, char* argv[])
+ 	for (i = 0; i < FFF_NUM; i++)
+ 		fff_data[i].fname = NULL;
+ 
+-	while ((optchar = getopt_long(argc, argv, "fb:k:r:u:", long_options, &option_index)) != -1) {
++	while ((optchar = getopt_long(argc, argv, "fb:k:p:r:u:", long_options, &option_index)) != -1) {
+ 		switch (optchar) {
+ 		case 'b':
+ 			fff_data[FFF_UBOOT].fname = optarg;
+@@ -132,6 +134,10 @@ int main(int argc, char* argv[])
+ 			fff_data[FFF_KERNEL].fname = optarg;
+ 			found_args += 2;
+ 			break;
++		case 'p':
++			pipe_path = optarg;
++			found_args += 2;
++			break;
+ 		case 'r':
+ 			fff_data[FFF_ROOTFS].fname = optarg;
+ 			found_args += 2;
+diff --git a/packet.c b/packet.c
+index 61ea04b..a932098 100644
+--- a/packet.c
++++ b/packet.c
+@@ -184,6 +184,7 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 			       ((tftp_xfer_size + 511) / 512));
+ 		} else {
+ 			fprintf(stderr, "Unknown file name: %s\n", file_name);
++			pipe_msg("ERROR", "unknown TFTP file name requested");
+ 			return -1;
+ 		}
+ 
+@@ -256,6 +257,7 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 		else
+ 			fprintf(stderr, "Received TFTP error code: %d\n", block);
+ 
++		pipe_msg("ERROR", "received TFTP error");
+ 		return -1;
+ 		break;
+ 	default:
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0006-ap51-flash-Return-SUCCESS-exit-only-if-reboot-detect.patch
===================================================================
--- utils/ap51-flash/patches/0006-ap51-flash-Return-SUCCESS-exit-only-if-reboot-detect.patch	(revision 0)
+++ utils/ap51-flash/patches/0006-ap51-flash-Return-SUCCESS-exit-only-if-reboot-detect.patch	(revision 0)
@@ -0,0 +1,88 @@
+From 4730a17161f08dfe86bf6d888027cb702a760726 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Tue, 4 May 2010 02:55:45 +0200
+Subject: [PATCH 6/7] ap51-flash: Return SUCCESS / exit only if reboot detected
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+At least for devices using uboot or redboot, the reboot can be
+determined very reliably by just starting and waiting for the device
+detection of the same one again. This is informing the ap51-flash user
+more reliably too, in that this user can be sure that the flashing
+procedure for the uboot/redboot devices has really finished.
+
+Signed-off-by: Linus Lüssing <linus.luessing@web.de>
+---
+ ap51-flash.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 46 insertions(+), 1 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index 9b4028b..891fe44 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -246,6 +246,46 @@ read_packet:
+ 	return flash_mode;
+ }
+ 
++/* Returns 0 if the same device is being detected again */
++static int detect_reboot(const char flash_mode, uip_ipaddr_t* sip, uip_ipaddr_t* dip,
++			 struct uip_eth_addr* smac, struct uip_eth_addr* dmac)
++{
++	char new_flash_mode;
++	struct ether_header *recv_ethhdr = NULL;
++	uip_ipaddr_t new_sip, new_dip;
++	struct uip_eth_addr new_dmac;
++
++	// We are not able to detect a ubnt-devices reboot reliably, therefore
++	// ignoring it and returning true anyway (as it had been done before).
++	if (flash_mode == MODE_TFTP_SERVER)
++		return 0;
++
++	arp_packet_init();
++
++	arphdr->ea_hdr.ar_op = htons(ARPOP_REQUEST);
++	memcpy(arphdr->arp_sha, smac->addr, ETH_ALEN);
++	// Resetting arp-target mac, got somehow set somewhere?
++	memset(arphdr->arp_tha, 0, ETH_ALEN);
++	*((unsigned int *)arphdr->arp_spa) = htonl(ubnt_local_ip);
++	*((unsigned int *)arphdr->arp_tpa) = htonl(ubnt_remote_ip);
++
++	new_flash_mode = detect_mode(&recv_ethhdr);
++	extract_ethhdr_info(recv_ethhdr, &new_sip, &new_dip, &new_dmac);
++
++	if ((flash_mode == MODE_REDBOOT) || (flash_mode == MODE_MAYBE_REDBOOT))
++		P(new_sip)[3] = 0 == P(new_sip)[3] ? 1 : 0;
++
++	if (flash_mode != new_flash_mode)
++		return 1;
++
++	if (memcmp(sip, &new_sip, sizeof(new_sip)) ||
++	    memcmp(dip, &new_dip, sizeof(new_dip)) ||
++	    memcmp(dmac, &new_dmac, sizeof(new_dmac)) )
++		return 1;
++	
++	return 0;
++}
++
+ static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac,
+ 		     struct uip_eth_addr* dmac, int special, char *flash_mode)
+ {
+@@ -1078,8 +1118,13 @@ init_socket:
+ #endif
+ 
+ 	ret = fw_upload(flash_mode);
++	if (ret != 0)
++		goto sock_close;
+ 
+-	if (ret == 0)
++	ret = detect_reboot(flash_mode, &srcipaddr, &dstipaddr, &srcmac, &dstmac);
++	if (ret != 0)
++		pipe_msg("ERROR", "could not detect the reboot of the same device");
++	else
+ 		pipe_msg("SUCCESS", "");
+ 
+ sock_close:
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0003-ap51-flash-Convert-flash_mode-to-local-variable.patch
===================================================================
--- utils/ap51-flash/patches/0003-ap51-flash-Convert-flash_mode-to-local-variable.patch	(revision 0)
+++ utils/ap51-flash/patches/0003-ap51-flash-Convert-flash_mode-to-local-variable.patch	(revision 0)
@@ -0,0 +1,167 @@
+From 478b06d9dad452fe4d74b18601da171f4f57754c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Sun, 25 Apr 2010 13:41:01 +0200
+Subject: [PATCH 3/7] ap51-flash: Convert flash_mode to local variable
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Not all functions (will) need the flash_mode information. Therefore
+making it a local variable to achieve a little more tight cohesion.
+
+Signed-off-by: Linus Lüssing <linus.luessing@web.de>
+---
+ ap51-flash.c |   19 ++++++++++---------
+ ap51-flash.h |    1 -
+ packet.c     |    6 +++---
+ packet.h     |    2 +-
+ 4 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index a1072ab..f7be682 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -44,7 +44,6 @@ static char *ap51_iface = NULL;
+ char *pipe_path = NULL;
+ #endif
+ 
+-char flash_mode = MODE_NONE;
+ int flash_from_file = 0;
+ struct flash_from_file fff_data[FFF_NUM];
+ unsigned int remote_ip;
+@@ -125,7 +124,8 @@ void pipe_msg(char *event_type, char *msg)
+ }
+ #endif
+ 
+-static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac, struct uip_eth_addr* dmac, int special)
++static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac,
++		     struct uip_eth_addr* dmac, int special, char *flash_mode)
+ {
+ 	int ret, len, arp_replies = 0, arp_grat_packets = 0;
+ 	const unsigned char *packet;
+@@ -211,7 +211,7 @@ read_packet:
+ 				continue;
+ 			}
+ 
+-			flash_mode = MODE_TFTP_CLIENT;
++			*flash_mode = MODE_TFTP_CLIENT;
+ 			break;
+ 		}
+ 
+@@ -223,7 +223,7 @@ read_packet:
+ 		}
+ 
+ 		if (*((unsigned int *)recv_arphdr->arp_tpa) == htonl(mr500_local_ip)) {
+-			flash_mode = MODE_TFTP_SERVER;
++			*flash_mode = MODE_TFTP_SERVER;
+ 			break;
+ 		}
+ 
+@@ -241,14 +241,14 @@ read_packet:
+ 				continue;
+ 			}
+ 
+-			flash_mode = MODE_MAYBE_REDBOOT;
++			*flash_mode = MODE_MAYBE_REDBOOT;
+ 			break;
+ 		}
+ 
+ #if defined(DEBUG)
+ 			fprintf(stderr, "device detection: redboot detected\n");
+ #endif
+-		flash_mode = MODE_REDBOOT;
++		*flash_mode = MODE_REDBOOT;
+ 		break;
+ 	}
+ 
+@@ -259,7 +259,7 @@ read_packet:
+ 	memmove(dip, recv_arphdr->arp_spa, 4);
+ 	memmove(sip, recv_arphdr->arp_tpa, 4);
+ 
+-	if ((flash_mode == MODE_REDBOOT) || (flash_mode == MODE_MAYBE_REDBOOT))
++	if ((*flash_mode == MODE_REDBOOT) || (*flash_mode == MODE_MAYBE_REDBOOT))
+ 		P(*sip)[3] = 0 == P(*sip)[3] ? 1 : 0;
+ 
+ 	memcpy(&remote_ip, dip, 4);
+@@ -715,6 +715,7 @@ int ap51_flash(char *iface, char *rootfs_filename, char *kernel_filename, int nv
+ 	uip_ipaddr_t netmask;
+ 	struct uip_eth_addr srcmac, dstmac, brcmac;
+ 	int ret, img_type = IMG_REDBOOT, fd, size = 0;
++	char flash_mode = MODE_NONE;
+ 	unsigned char *buf = 0;
+ 	char *socket_dev;
+ 
+@@ -886,7 +887,7 @@ init_socket:
+ 	ap51_iface = socket_dev;
+ #endif
+ 
+-	ret = ap51_init(socket_dev, &srcipaddr, &dstipaddr, &srcmac, &dstmac, special);
++	ret = ap51_init(socket_dev, &srcipaddr, &dstipaddr, &srcmac, &dstmac, special, &flash_mode);
+ 
+ 	if (ret != 0)
+ 		return ret;
+@@ -1056,7 +1057,7 @@ init_socket:
+ 	signal(SIGTERM, SIG_IGN);
+ #endif
+ 
+-	ret = fw_upload();
++	ret = fw_upload(flash_mode);
+ 
+ 	if (ret == 0)
+ 		pipe_msg("SUCCESS", "");
+diff --git a/ap51-flash.h b/ap51-flash.h
+index 4dec003..6e064de 100644
+--- a/ap51-flash.h
++++ b/ap51-flash.h
+@@ -154,7 +154,6 @@ extern unsigned char *rootfs_buf;
+ extern unsigned char *kernel_buf;
+ extern int rootfs_size;
+ extern int kernel_size;
+-extern char flash_mode;
+ extern int flash_from_file;
+ extern char *pipe_path;
+ extern struct flash_from_file fff_data[];
+diff --git a/packet.c b/packet.c
+index a932098..3ec07d1 100644
+--- a/packet.c
++++ b/packet.c
+@@ -144,7 +144,7 @@ static int read_from_file(void *target_buff, void *data, int len, int seek_pos)
+ 	return 0;
+ }
+ 
+-static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_len)
++static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_len, char flash_mode)
+ {
+ 	struct udphdr *rcv_udphdr = (struct udphdr *)packet_buff;
+ 	unsigned short opcode, block;
+@@ -269,7 +269,7 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 	return 1;
+ }
+ 
+-int fw_upload(void)
++int fw_upload(char flash_mode)
+ {
+ 	const unsigned char *packet;
+ 	struct ether_arp *rcv_arphdr;
+@@ -393,7 +393,7 @@ int fw_upload(void)
+ 			switch (rcv_iphdr->protocol) {
+ 			case IPPROTO_UDP:
+ 				ret = tftp_transfer(packet + ETH_HLEN + (rcv_iphdr->ihl * 4),
+-						    len - ETH_HLEN - (rcv_iphdr->ihl * 4));
++						    len - ETH_HLEN - (rcv_iphdr->ihl * 4), flash_mode);
+ 
+ 				if (ret < 0)
+ 					return 1;  /* error */
+diff --git a/packet.h b/packet.h
+index 3e06a43..a19b378 100644
+--- a/packet.h
++++ b/packet.h
+@@ -36,4 +36,4 @@ extern char tcp_status;
+ 
+ void arp_packet_init(void);
+ int arp_packet_send(void);
+-int fw_upload(void);
++int fw_upload(char flash_mode);
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0004-ap51-flash-Export-device-detection-to-seperate-funct.patch
===================================================================
--- utils/ap51-flash/patches/0004-ap51-flash-Export-device-detection-to-seperate-funct.patch	(revision 0)
+++ utils/ap51-flash/patches/0004-ap51-flash-Export-device-detection-to-seperate-funct.patch	(revision 0)
@@ -0,0 +1,153 @@
+From f5ba2ea8b085aa4d865083824c5571844a2273e0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Tue, 4 May 2010 02:54:05 +0200
+Subject: [PATCH 4/7] ap51-flash: Export device detection to seperate function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This will shrink the ap51_init() method to make its scope clearer and to
+enhance its readability. The device detection could then also be called
+in several places (if someone would like to detect the reboot of a
+device for verifying the flashing-procedure for instance).
+
+Signed-off-by: Linus Lüssing <linus.luessing@web.de>
+---
+ ap51-flash.c |   79 +++++++++++++++++++++++++++++++++------------------------
+ 1 files changed, 46 insertions(+), 33 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index f7be682..3c6b495 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -124,37 +124,13 @@ void pipe_msg(char *event_type, char *msg)
+ }
+ #endif
+ 
+-static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac,
+-		     struct uip_eth_addr* dmac, int special, char *flash_mode)
++/* Returns the detected flash-mode and sets recv_ethhdr */
++static char detect_mode(struct ether_header **recv_ethhdr)
+ {
+ 	int ret, len, arp_replies = 0, arp_grat_packets = 0;
++	char flash_mode = MODE_NONE;
+ 	const unsigned char *packet;
+-	struct ether_header *recv_ethhdr;
+ 	struct ether_arp *recv_arphdr;
+-#if defined(DEBUG)
+-	int i;
+-#endif
+-
+-	/* Open the output adapter */
+-	ret = socket_open(dev);
+-	if (ret != 0)
+-		return ret;
+-
+-	arp_packet_init();
+-	memset(ethhdr->ether_dhost, 0xff, ETH_ALEN);
+-	memcpy(ethhdr->ether_shost, smac->addr, ETH_ALEN);
+-
+-	arphdr->ea_hdr.ar_op = htons(ARPOP_REQUEST);
+-	memcpy(arphdr->arp_sha, smac->addr, ETH_ALEN);
+-	*((unsigned int *)arphdr->arp_spa) = htonl(ubnt_local_ip);
+-	*((unsigned int *)arphdr->arp_tpa) = htonl(ubnt_remote_ip);
+-
+-#if !defined(OSX)
+-	// TODO: This is a seeming bug in OSX - won't work if we turn on non blocking - Lokkju
+-	ret = socket_setnonblock();
+-	if (ret != 0)
+-		return ret;
+-#endif
+ 
+ 	fprintf(stderr, "Waiting for device to run auto-detection.\nMake sure the device is connected directly!\n");
+ 
+@@ -175,9 +151,9 @@ read_packet:
+ 				return ret;
+ 		}
+ 
+-		recv_ethhdr = (struct ether_header *)packet;
++		*recv_ethhdr = (struct ether_header *)packet;
+ 
+-		if (recv_ethhdr->ether_type != htons(ETHERTYPE_ARP)) {
++		if ((*recv_ethhdr)->ether_type != htons(ETHERTYPE_ARP)) {
+ #if defined(DEBUG)
+ 			fprintf(stderr, "device detection: non-arp packet received\n");
+ #endif
+@@ -211,7 +187,7 @@ read_packet:
+ 				continue;
+ 			}
+ 
+-			*flash_mode = MODE_TFTP_CLIENT;
++			flash_mode = MODE_TFTP_CLIENT;
+ 			break;
+ 		}
+ 
+@@ -223,7 +199,7 @@ read_packet:
+ 		}
+ 
+ 		if (*((unsigned int *)recv_arphdr->arp_tpa) == htonl(mr500_local_ip)) {
+-			*flash_mode = MODE_TFTP_SERVER;
++			flash_mode = MODE_TFTP_SERVER;
+ 			break;
+ 		}
+ 
+@@ -241,17 +217,54 @@ read_packet:
+ 				continue;
+ 			}
+ 
+-			*flash_mode = MODE_MAYBE_REDBOOT;
++			flash_mode = MODE_MAYBE_REDBOOT;
+ 			break;
+ 		}
+ 
+ #if defined(DEBUG)
+ 			fprintf(stderr, "device detection: redboot detected\n");
+ #endif
+-		*flash_mode = MODE_REDBOOT;
++		flash_mode = MODE_REDBOOT;
+ 		break;
+ 	}
+ 
++	return flash_mode;
++}
++
++static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip_eth_addr* smac,
++		     struct uip_eth_addr* dmac, int special, char *flash_mode)
++{
++	int ret = 0;
++	struct ether_header *recv_ethhdr = NULL;
++	struct ether_arp *recv_arphdr;
++#if defined(DEBUG)
++	int i;
++#endif
++
++	/* Open the output adapter */
++	ret = socket_open(dev);
++	if (ret != 0)
++		return ret;
++
++	arp_packet_init();
++	memset(ethhdr->ether_dhost, 0xff, ETH_ALEN);
++	memcpy(ethhdr->ether_shost, smac->addr, ETH_ALEN);
++
++	arphdr->ea_hdr.ar_op = htons(ARPOP_REQUEST);
++	memcpy(arphdr->arp_sha, smac->addr, ETH_ALEN);
++	*((unsigned int *)arphdr->arp_spa) = htonl(ubnt_local_ip);
++	*((unsigned int *)arphdr->arp_tpa) = htonl(ubnt_remote_ip);
++
++#if !defined(OSX)
++	// TODO: This is a seeming bug in OSX - won't work if we turn on non blocking - Lokkju
++	ret = socket_setnonblock();
++	if (ret != 0)
++		return ret;
++#endif
++
++	*flash_mode = detect_mode(&recv_ethhdr);
++	recv_arphdr = (struct ether_arp *)(recv_ethhdr + 1);
++
+ 	/* Grab MAC adress of device */
+ 	memmove(dmac, recv_ethhdr->ether_shost, ETH_ALEN);
+ 	memcpy(ethhdr->ether_dhost, recv_ethhdr->ether_shost, ETH_ALEN);
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0005-ap51-flash-Exporting-ip-mac-determination-to-helper-.patch
===================================================================
--- utils/ap51-flash/patches/0005-ap51-flash-Exporting-ip-mac-determination-to-helper-.patch	(revision 0)
+++ utils/ap51-flash/patches/0005-ap51-flash-Exporting-ip-mac-determination-to-helper-.patch	(revision 0)
@@ -0,0 +1,70 @@
+From 437a6e0b6f5cf6f26c7be1c21fe1b48ea9dd153c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Tue, 4 May 2010 02:54:58 +0200
+Subject: [PATCH 5/7] ap51-flash: Exporting ip/mac determination to helper-function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This makes ap51_init() even smaller and abstracts the ip/mac
+determination/extraction in the ap51_init() method, leaving the task
+to the new helper function.
+
+Signed-off-by: Linus Lüssing <linus.luessing@web.de>
+---
+ ap51-flash.c |   25 ++++++++++++++++---------
+ 1 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/ap51-flash.c b/ap51-flash.c
+index 3c6b495..9b4028b 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -124,6 +124,21 @@ void pipe_msg(char *event_type, char *msg)
+ }
+ #endif
+ 
++static void extract_ethhdr_info(const struct ether_header *recv_ethhdr,
++				uip_ipaddr_t *sip, uip_ipaddr_t *dip,
++				struct uip_eth_addr *dmac)
++{
++	struct ether_arp *recv_arphdr =
++		(struct ether_arp *)(recv_ethhdr + 1);
++
++	/* Grab MAC adress of device */
++	memmove(dmac, recv_ethhdr->ether_shost, ETH_ALEN);
++	memcpy(ethhdr->ether_dhost, recv_ethhdr->ether_shost, ETH_ALEN);
++	/* Grab IP adress of device */
++	memmove(dip, recv_arphdr->arp_spa, 4);
++	memmove(sip, recv_arphdr->arp_tpa, 4);
++}
++
+ /* Returns the detected flash-mode and sets recv_ethhdr */
+ static char detect_mode(struct ether_header **recv_ethhdr)
+ {
+@@ -236,7 +251,6 @@ static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip
+ {
+ 	int ret = 0;
+ 	struct ether_header *recv_ethhdr = NULL;
+-	struct ether_arp *recv_arphdr;
+ #if defined(DEBUG)
+ 	int i;
+ #endif
+@@ -263,14 +277,7 @@ static int ap51_init(char *dev, uip_ipaddr_t* sip, uip_ipaddr_t* dip, struct uip
+ #endif
+ 
+ 	*flash_mode = detect_mode(&recv_ethhdr);
+-	recv_arphdr = (struct ether_arp *)(recv_ethhdr + 1);
+-
+-	/* Grab MAC adress of device */
+-	memmove(dmac, recv_ethhdr->ether_shost, ETH_ALEN);
+-	memcpy(ethhdr->ether_dhost, recv_ethhdr->ether_shost, ETH_ALEN);
+-	/* Grab IP adress of device */
+-	memmove(dip, recv_arphdr->arp_spa, 4);
+-	memmove(sip, recv_arphdr->arp_tpa, 4);
++	extract_ethhdr_info(recv_ethhdr, dip, sip, dmac);
+ 
+ 	if ((*flash_mode == MODE_REDBOOT) || (*flash_mode == MODE_MAYBE_REDBOOT))
+ 		P(*sip)[3] = 0 == P(*sip)[3] ? 1 : 0;
+-- 
+1.7.1
+
Index: utils/ap51-flash/patches/0001-add-mr500-support-flash-via-uboot.patch
===================================================================
--- utils/ap51-flash/patches/0001-add-mr500-support-flash-via-uboot.patch	(revision 0)
+++ utils/ap51-flash/patches/0001-add-mr500-support-flash-via-uboot.patch	(revision 0)
@@ -0,0 +1,360 @@
+From aa62616897c3ca43b758b4c29c106c7018920ebf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@web.de>
+Date: Sun, 25 Apr 2010 12:53:43 +0200
+Subject: [PATCH 1/7] add mr500 support (flash via uboot)
+
+from Marek
+---
+ Makefile         |   13 ++++++--
+ ap51-flash-res.h |    1 +
+ ap51-flash.c     |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++----
+ ap51-flash.h     |    9 +++++
+ main.c           |   18 ++++++++---
+ packet.c         |   10 +++++-
+ 6 files changed, 121 insertions(+), 16 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index ba4d742..e710ab7 100644
+--- a/Makefile
++++ b/Makefile
+@@ -40,24 +40,28 @@ AP51_RC = ap51-flash-res
+ EMBED_KERNEL = openwrt-atheros-vmlinux.lzma
+ EMBED_ROOTFS = openwrt-atheros-root.squashfs
+ EMBED_UBNT_IMG = openwrt-atheros-ubnt2-squashfs.bin
++EMBED_UBOOT_IMG = openwrt-ralink-mr500-squashfs.bin
+ 
+ ifneq ($(wildcard $(EMBED_KERNEL)),)
+ ifneq ($(wildcard $(EMBED_ROOTFS)),)
+ ifneq ($(wildcard $(EMBED_UBNT_IMG)),)
++ifneq ($(wildcard $(EMBED_UBOOT_IMG)),)
+ CFLAGS += -DEMBEDDED_DATA
+-LIN_OBJS = kernel.o rootfs.o ubnt_img.o
++LIN_OBJS = kernel.o rootfs.o ubnt_img.o uboot_img.o
+ WIN_OBJS = $(AP51_RC).o
+ OSX_OBJ =
+ $(shell echo '#include "ap51-flash-res.h"' > $(AP51_RC))
+ $(shell echo 'IDR_KERNEL RCDATA DISCARDABLE "$(EMBED_KERNEL)"' >> $(AP51_RC))
+ $(shell echo 'IDR_ROOTFS RCDATA DISCARDABLE "$(EMBED_ROOTFS)"' >> $(AP51_RC))
+ $(shell echo 'IDR_UBNT_IMG RCDATA DISCARDABLE "$(EMBED_UBNT_IMG)"' >> $(AP51_RC))
++$(shell echo 'IDR_UBNT_IMG RCDATA DISCARDABLE "$(EMBED_UBOOT_IMG)"' >> $(AP51_RC))
+ ifneq ($(DESC),)
+ CFLAGS += -DEMBEDDED_DESC=\"$(DESC)\"
+ endif
+ endif
+ endif
+ endif
++endif
+ 
+ ifeq ($(MAKECMDGOALS),ap51-flash.exe)
+ PLATFORM = WIN32
+@@ -128,11 +132,14 @@ rootfs.o: $(EMBED_ROOTFS)
+ ubnt_img.o: $(EMBED_UBNT_IMG)
+ 	$(OBJCOPY) -B i386 -I binary $(EMBED_UBNT_IMG) -O elf32-i386 $@
+ 
+-$(AP51_RC).o: $(EMBED_KERNEL) $(EMBED_ROOTFS) $(EMBED_UBNT_IMG)
++uboot_img.o: $(EMBED_UBOOT_IMG)
++	$(OBJCOPY) -B i386 -I binary $(EMBED_UBOOT_IMG) -O elf32-i386 $@
++
++$(AP51_RC).o: $(EMBED_KERNEL) $(EMBED_ROOTFS) $(EMBED_UBNT_IMG) $(EMBED_UBOOT_IMG)
+ 	$(WINDRES) -i $(AP51_RC) -I. -o $@
+ 
+ clean:
+ 	rm -rf *.o *~ *.plg *.ncb libap51-flash.a ap51-flash ap51-flash-static ap51-flash.exe ap51-flash-osx $(AP51_RC)
+ 
+ distclean: clean
+-	rm -rf $(EMBED_ROOTFS) $(EMBED_KERNEL) $(EMBED_UBNT_IMG)
++	rm -rf $(EMBED_ROOTFS) $(EMBED_KERNEL) $(EMBED_UBNT_IMG) $(EMBED_UBOOT_IMG)
+diff --git a/ap51-flash-res.h b/ap51-flash-res.h
+index 30b83d6..7d9a36d 100644
+--- a/ap51-flash-res.h
++++ b/ap51-flash-res.h
+@@ -19,3 +19,4 @@
+ #define IDR_KERNEL 101
+ #define IDR_ROOTFS 102
+ #define IDR_UBNT_IMG 103
++#define IDR_UBOOT_IMG 104
+diff --git a/ap51-flash.c b/ap51-flash.c
+index 256b010..3244620 100644
+--- a/ap51-flash.c
++++ b/ap51-flash.c
+@@ -46,6 +46,7 @@ unsigned int remote_ip;
+ unsigned int local_ip;
+ static unsigned int ubnt_remote_ip = 3232235796UL; /* 192.168.1.20 */
+ static unsigned int ubnt_local_ip = 3232235801UL; /* 192.168.1.25 */
++static unsigned int mr500_local_ip = 3232260872UL; /* 192.168.99.8 */
+ unsigned char *tftp_xfer_buff = NULL;
+ unsigned long tftp_xfer_size = 0;
+ 
+@@ -66,6 +67,10 @@ extern unsigned long _binary_openwrt_atheros_root_squashfs_size;
+ extern unsigned long _binary_openwrt_atheros_ubnt2_squashfs_bin_start;
+ extern unsigned long _binary_openwrt_atheros_ubnt2_squashfs_bin_end;
+ extern unsigned long _binary_openwrt_atheros_ubnt2_squashfs_bin_size;
++
++extern unsigned long _binary_openwrt_ralink_mr500_squashfs_bin_start;
++extern unsigned long _binary_openwrt_ralink_mr500_squashfs_bin_end;
++extern unsigned long _binary_openwrt_ralink_mr500_squashfs_bin_size;
+ #endif
+ 
+ static uip_ipaddr_t srcipaddr;
+@@ -178,6 +183,11 @@ read_packet:
+ 			continue;
+ 		}
+ 
++		if (*((unsigned int *)recv_arphdr->arp_tpa) == htonl(mr500_local_ip)) {
++			flash_mode = MODE_TFTP_SERVER;
++			break;
++		}
++
+ 		/* we are waiting for gratuitous requests */
+ 		if (*((unsigned int *)recv_arphdr->arp_spa) != *((unsigned int *)recv_arphdr->arp_tpa))
+ 			continue;
+@@ -660,7 +670,7 @@ int ap51_flash(char *iface, char *rootfs_filename, char *kernel_filename, int nv
+ {
+ 	uip_ipaddr_t netmask;
+ 	struct uip_eth_addr srcmac, dstmac, brcmac;
+-	int ret, ubnt_img = 0, fd, size = 0;
++	int ret, img_type = IMG_REDBOOT, fd, size = 0;
+ 	unsigned char *buf = 0;
+ 	char *socket_dev;
+ 
+@@ -777,9 +787,13 @@ int ap51_flash(char *iface, char *rootfs_filename, char *kernel_filename, int nv
+ 	/* ubnt magic header */
+ 	if ((strncmp((char *)rootfs_buf, "UBNT", 4) == 0) ||
+ 	    (strncmp((char *)rootfs_buf, "OPEN", 4) == 0))
+-		ubnt_img = 1;
++		img_type = IMG_UBNT;
++
++	/* uboot magic header */
++	if (*((unsigned int *)rootfs_buf) == htonl(0x27051956))
++		img_type = IMG_UBOOT;
+ 
+-	if ((FLASH_PAGE_SIZE > kernel_size) && (!ubnt_img)) {
++	if ((FLASH_PAGE_SIZE > kernel_size) && (img_type == IMG_REDBOOT)) {
+ 		fprintf(stderr, "kernel implausible small: %d bytes\n", kernel_size);
+ 		return 1;
+ 	}
+@@ -838,9 +852,13 @@ init_socket:
+ 				goto sock_close;
+ 			}
+ 		} else {
+-			if (ubnt_img) {
++			switch (img_type) {
++			case IMG_UBNT:
+ 				fprintf(stderr, "Error - you are trying to flash a redboot device with a ubiquiti image!\n");
+ 				goto sock_close;
++			case IMG_UBOOT:
++				fprintf(stderr, "Error - you are trying to flash a redboot device with a uboot image!\n");
++				goto sock_close;
+ 			}
+ 		}
+ 
+@@ -884,7 +902,7 @@ init_socket:
+ 				}
+ 			}
+ 
+-			ubnt_img = 1;
++			img_type = IMG_UBNT;
+ 		}
+ #endif /* EMBEDDED_DATA */
+ 		if (flash_from_file) {
+@@ -893,9 +911,13 @@ init_socket:
+ 				goto sock_close;
+ 			}
+ 		} else {
+-			if (!ubnt_img) {
++			switch (img_type) {
++			case IMG_REDBOOT:
+ 				fprintf(stderr, "Error - you are trying to flash a ubiquiti device with redboot images!\n");
+ 				goto sock_close;
++			case IMG_UBOOT:
++				fprintf(stderr, "Error - you are trying to flash a ubiquiti device with a uboot image!\n");
++				goto sock_close;
+ 			}
+ 		}
+ 
+@@ -903,6 +925,58 @@ init_socket:
+ 		tftp_xfer_size = (flash_from_file ? fff_data[FFF_UBNT].flash_size : rootfs_size);
+ 		printf("Ubiquiti device detected - using TFTP client to flash\n");
+ 		break;
++	case MODE_TFTP_SERVER:
++#if defined(EMBEDDED_DATA)
++		if ((!rootfs_filename) && (!flash_from_file)) {
++
++			/* free the rootfs and replace it by the uboot image */
++			free(rootfs_buf);
++
++#if defined(WIN32)
++			HRSRC hRsrc;
++			hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_UBOOT_IMG), RT_RCDATA);
++			if (NULL != hRsrc) {
++				HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
++				buf = LockResource(hGlobal);
++				size = SizeofResource(NULL, hRsrc);
++			}
++#else
++			buf = (unsigned char*)&_binary_openwrt_ralink_mr500_squashfs_bin_start;
++			size = (int)&_binary_openwrt_ralink_mr500_squashfs_bin_size;
++#endif
++
++			if (0 != buf) {
++				rootfs_size = ((size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE;
++				if (0 != (rootfs_buf = malloc(rootfs_size))) {
++					memset(rootfs_buf, 0xff, rootfs_size);
++					memmove(rootfs_buf, buf, size);
++				} else {
++					perror("no mem");
++					goto sock_close;
++				}
++			}
++
++			img_type = IMG_UBOOT;
++		}
++#endif /* EMBEDDED_DATA */
++		if (flash_from_file) {
++			if (!fff_data[FFF_UBOOT].fname) {
++				fprintf(stderr, "Error - uboot device detected but uboot file not available\n");
++				goto sock_close;
++			}
++		} else {
++			switch (img_type) {
++			case IMG_REDBOOT:
++				fprintf(stderr, "Error - you are trying to flash a uboot device with redboot images!\n");
++				goto sock_close;
++			case IMG_UBNT:
++				fprintf(stderr, "Error - you are trying to flash a uboot device with a ubiquiti image!\n");
++				goto sock_close;
++			}
++		}
++
++		printf("Uboot device detected - using TFTP server to flash\n");
++		break;
+ 	default:
+ 		fprintf(stderr, "Error - could not auto-detect flash mode!\n");
+ 		goto sock_close;
+diff --git a/ap51-flash.h b/ap51-flash.h
+index 1049661..2e59519 100644
+--- a/ap51-flash.h
++++ b/ap51-flash.h
+@@ -94,6 +94,14 @@ enum {
+ 	MODE_REDBOOT,
+ 	MODE_MAYBE_REDBOOT,
+ 	MODE_TFTP_CLIENT,
++	MODE_TFTP_SERVER,
++};
++
++/* image type */
++enum {
++	IMG_REDBOOT,
++	IMG_UBNT,
++	IMG_UBOOT,
+ };
+ 
+ /* flash from file data */
+@@ -101,6 +109,7 @@ enum {
+ 	FFF_ROOTFS = 0,
+ 	FFF_KERNEL,
+ 	FFF_UBNT,
++	FFF_UBOOT,
+ 	FFF_NUM,
+ };
+ 
+diff --git a/main.c b/main.c
+index 9589d00..44f0386 100644
+--- a/main.c
++++ b/main.c
+@@ -31,11 +31,12 @@ void usage(char *prgname)
+ 	fprintf(stderr, "Usage:\n");
+ 
+ #if defined(EMBEDDED_DATA)
+-	fprintf(stderr, "%s [ethdevice]   flashes embedded kernel + rootfs or ubquiti image: %s\n", prgname, EMBEDDED_DESC_STR);
++	fprintf(stderr, "%s [ethdevice]   flashes embedded kernel + rootfs or ubquiti or uboot image: %s\n", prgname, EMBEDDED_DESC_STR);
+ #endif
+ 
+ 	fprintf(stderr, "%s [ethdevice] rootfs.bin kernel.lzma   flashes your rootfs and kernel\n", prgname);
+ 	fprintf(stderr, "%s [ethdevice] ubnt.bin   flashes your ubiquiti image\n", prgname);
++	fprintf(stderr, "%s [ethdevice] uboot.bin   flashes your uboot image\n", prgname);
+ 	fprintf(stderr, "%s -v   prints version information\n", prgname);
+ 
+ #if defined(FLASH_FROM_FILE)
+@@ -45,7 +46,8 @@ void usage(char *prgname)
+ 	fprintf(stderr, "  --flash-from-file   enable 'flash from file' mode\n");
+ 	fprintf(stderr, "  --rootfs   path to rootfs file\n");
+ 	fprintf(stderr, "  --kernel   path to kernel file\n");
+-	fprintf(stderr, "  --ubnt   path to ubiquiti image\n");
++	fprintf(stderr, "  --ubnt     path to ubiquiti image\n");
++	fprintf(stderr, "  --uboot    path to uboot image\n");
+ #endif
+ 
+ 	fprintf(stderr, "\nThe 'ethdevice' has to be one of the devices that are part of the supported device list which follows.\nYou can either specify its name or the interface number.\n");
+@@ -62,6 +64,7 @@ int main(int argc, char* argv[])
+ 	int i, found_args = 1, optchar, option_index;
+ 	struct option long_options[] =
+ 	{
++		{"uboot", required_argument, 0, 'b'},
+ 		{"flash-from-file", no_argument, 0, 'f'},
+ 		{"rootfs", required_argument, 0, 'r'},
+ 		{"kernel", required_argument, 0, 'k'},
+@@ -115,8 +118,12 @@ int main(int argc, char* argv[])
+ 	for (i = 0; i < FFF_NUM; i++)
+ 		fff_data[i].fname = NULL;
+ 
+-	while ((optchar = getopt_long(argc, argv, "fk:r:u:", long_options, &option_index)) != -1) {
++	while ((optchar = getopt_long(argc, argv, "fb:k:r:u:", long_options, &option_index)) != -1) {
+ 		switch (optchar) {
++		case 'b':
++			fff_data[FFF_UBOOT].fname = optarg;
++			found_args += 2;
++			break;
+ 		case 'f':
+ 			flash_from_file = 1;
+ 			found_args++;
+@@ -146,8 +153,9 @@ int main(int argc, char* argv[])
+ 			return 1;
+ 		}
+ 
+-		if (!fff_data[FFF_ROOTFS].fname && !fff_data[FFF_KERNEL].fname && !fff_data[FFF_UBNT].fname) {
+-			fprintf(stderr, "Error - you need to specify at least kernel and rootfs or ubiquiti image file\n");
++		if (!fff_data[FFF_ROOTFS].fname && !fff_data[FFF_KERNEL].fname &&
++		    !fff_data[FFF_UBNT].fname && !fff_data[FFF_UBOOT].fname) {
++			fprintf(stderr, "Error - you need to specify at least kernel and rootfs or ubiquiti or uboot image file\n");
+ 			return 1;
+ 		}
+ 
+diff --git a/packet.c b/packet.c
+index 47bb6ad..61ea04b 100644
+--- a/packet.c
++++ b/packet.c
+@@ -151,7 +151,8 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 	char *file_name;
+ 	int tftp_data_len, ret;
+ 
+-	if ((flash_mode == MODE_REDBOOT) && (rcv_udphdr->dest != htons(IPPORT_TFTP)))
++	if (((flash_mode == MODE_REDBOOT) || (flash_mode == MODE_TFTP_SERVER)) &&
++	    (rcv_udphdr->dest != htons(IPPORT_TFTP)))
+ 		return 1;
+ 
+ 	if ((flash_mode == MODE_TFTP_CLIENT) && (rcv_udphdr->source != htons(IPPORT_TFTP)))
+@@ -176,6 +177,11 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 			tftp_xfer_size = (flash_from_file ? fff_data[FFF_ROOTFS].flash_size : rootfs_size);
+ 			printf("Sending rootfs, %ld blocks...\n",
+ 			       ((tftp_xfer_size + 511) / 512));
++		} else if (strcmp(file_name, "mr500.bin") == 0) {
++			tftp_xfer_buff = (flash_from_file ? (unsigned char *)&fff_data[FFF_UBOOT] : rootfs_buf);
++			tftp_xfer_size = (flash_from_file ? fff_data[FFF_UBOOT].flash_size : rootfs_size);
++			printf("Sending uboot image, %ld blocks...\n",
++			       ((tftp_xfer_size + 511) / 512));
+ 		} else {
+ 			fprintf(stderr, "Unknown file name: %s\n", file_name);
+ 			return -1;
+@@ -204,7 +210,7 @@ static int tftp_transfer(const unsigned char *packet_buff, unsigned int packet_l
+ 			block = tftp_ack_block;
+ 		} else {
+ 			if (block * 512 > tftp_xfer_size) {
+-				if (flash_mode == MODE_TFTP_CLIENT) {
++				if ((flash_mode == MODE_TFTP_CLIENT) || (flash_mode == MODE_TFTP_SERVER)) {
+ 					printf("Image successfully transmitted.\n");
+ 					printf("Please give the device a couple of minutes to install the new image into the flash.\n");
+ 					return 0;
+-- 
+1.7.1
+
