diff --git a/mote/sgtools/GNUmakefile b/mote/sgtools/GNUmakefile
new file mode 100644
index 0000000000000000000000000000000000000000..fc27debdae4ef1c6091a9d6a93569e4d54819a9e
--- /dev/null
+++ b/mote/sgtools/GNUmakefile
@@ -0,0 +1,31 @@
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2004 University of Utah and the Flux Group.
+# All rights reserved.
+#
+
+#
+# These are the paths to the ARM cross-compiler on ibapah.flux.utah.edu -
+# should put something more general here
+#
+CXX=/usr/local/arm/3.4.1/bin/arm-linux-g++
+CXXFLAGS=-static
+STRIP=/usr/local/arm/3.4.1/bin/arm-linux-strip
+CC=/usr/local/arm/3.4.1/bin/arm-linux-gcc
+
+OBJS=SGGPIO.o
+
+all: motepower moteleds
+
+motepower: motepower.C $(OBJS)
+	$(CXX) $(CXXFLAGS) -o motepower motepower.C $(OBJS)
+	$(STRIP) motepower
+
+moteleds: moteleds.C $(OBJS)
+	$(CXX) $(CXXFLAGS) -o moteleds moteleds.C $(OBJS)
+	$(STRIP) moteleds
+
+
+
+clean:
+	rm -f $(OBJS) motepower moteleds
diff --git a/mote/sgtools/SGGPIO.C b/mote/sgtools/SGGPIO.C
new file mode 100644
index 0000000000000000000000000000000000000000..2a9d863ec297a3f4de962aa5dab3780d842a7a38
--- /dev/null
+++ b/mote/sgtools/SGGPIO.C
@@ -0,0 +1,154 @@
+/*
+ * $Id: SGGPIO.C,v 1.1 2004-12-16 17:53:32 ricci Exp $
+ *
+ ****************************************************************************
+ *
+ * uisp - The Micro In-System Programmer for Atmel AVR microcontrollers.
+ * Copyright (C) 2003 University of Utah and The Flux Group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ****************************************************************************
+ */
+
+/*
+  SGGPIO.C
+  
+  Direct Stargate/PXA GPIO Access
+  
+*/
+
+
+#include "SGGPIO.h"
+
+char *pxa_reg_names[] = {"GPLR", "GPDR", "GPSR", "GPCR"};
+
+int 
+SGGPIO_PORT::setDir(int pin, unsigned int indir) {
+  
+  unsigned int val = readGPIO(PXA_GPDR, GPIO_nr(pin));
+  
+  if (indir) {
+    val = val | GPIO_bit(pin);
+  } else {
+    val = val & ~(GPIO_bit(pin));
+  }
+  
+  writeGPIO(PXA_GPDR, GPIO_nr(pin), val);
+  
+  return 0;
+}
+
+int 
+SGGPIO_PORT::setPin(int pin, unsigned int inval) {
+  if (inval) {
+    writeGPIO(PXA_GPSR, GPIO_nr(pin), GPIO_bit(pin));
+  } else {
+    writeGPIO(PXA_GPCR, GPIO_nr(pin), GPIO_bit(pin));
+  }
+  return 0;
+}
+
+int 
+SGGPIO_PORT::readPin(int pin) {
+  return ((readGPIO(PXA_GPLR, GPIO_nr(pin)) & GPIO_bit(pin)) >> (0x1f & pin));
+}
+
+unsigned int 
+SGGPIO_PORT::readGPIO(PXA_REG reg,  int regnum) {
+  int fdesc = getGPIO(reg, regnum);
+  char buf[16];
+  int cnt = 0;
+  unsigned int retval = 0;
+
+  
+  if (! fdesc) {
+    printf("Couldn't get GPIO handle\n");
+    return 0;
+  }
+
+  if ((cnt = pread(fdesc, buf, sizeof(buf)-1, 0)) <= 0) {
+    printf("Error reading GPIO register\n");
+    return 0;
+  }
+
+  buf[cnt] = '\0';
+  retval = strtoul(buf, NULL, 0);
+  return retval;
+}
+
+int 
+SGGPIO_PORT::writeGPIO(PXA_REG reg, int regnum, unsigned int value) {
+  int fdesc = getGPIO(reg, regnum);
+  char buf[16];
+  int len;
+  
+  if (! fdesc) {
+    printf("Couldn't get GPIO handle\n");
+    return -1;
+  }
+  
+  len = sprintf(buf, "0x%08X\n", value);
+  
+  if (pwrite(fdesc, buf, len, 0) < 0) {
+    perror("Problem setting GPIO register");
+    printf("Register: %s%d\n", PXA_REG_NAME(reg), regnum);
+    printf("fdesc: %d\n", fdesc);
+    printf("Data: %s\n", buf);
+    return -1;
+  }
+
+  return 0;
+}
+
+SGGPIO_PORT::SGGPIO_PORT() {
+  int i, j;
+  
+  for (i = 0; i < NUM_REGS; ++i) {
+    for (j = 0; j < NUM_REGNUMS; ++j) {
+      GPIO_fds[i][j] = 0;
+    }
+  }
+}
+
+SGGPIO_PORT::~SGGPIO_PORT() {
+  int i, j;
+
+  for (i = 0; i < NUM_REGS; ++i) {
+    for (j = 0; j < NUM_REGNUMS; ++j) {
+      if (GPIO_fds[i][j]) {
+        close(GPIO_fds[i][j]);
+        GPIO_fds[i][j] = 0;
+      }
+    }
+  }
+}
+
+
+int 
+SGGPIO_PORT::getGPIO(PXA_REG reg, int regnum) {
+  char gpioPath[256];
+  
+  if (! GPIO_fds[reg][regnum]) {
+    sprintf(gpioPath, "%s/%s%d", PROC_REG_PREFIX, PXA_REG_NAME(reg), regnum);
+    if ((GPIO_fds[reg][regnum] = open(gpioPath, O_RDWR | O_FSYNC, 0)) < 0) {
+      printf("Error opening %s proc file: %s\n", PXA_REG_NAME(reg), 
+             strerror(errno));
+      return -1;
+    }
+  }
+  
+  return GPIO_fds[reg][regnum];
+}
diff --git a/mote/sgtools/SGGPIO.h b/mote/sgtools/SGGPIO.h
new file mode 100644
index 0000000000000000000000000000000000000000..f235725702e37e4eaa3886bd6dad144b4f52c347
--- /dev/null
+++ b/mote/sgtools/SGGPIO.h
@@ -0,0 +1,82 @@
+/*
+ * $Id: SGGPIO.h,v 1.1 2004-12-16 17:53:32 ricci Exp $
+ *
+ ****************************************************************************
+ *
+ * uisp - The Micro In-System Programmer for Atmel AVR microcontrollers.
+ * Copyright (C) 2003 University of Utah and The Flux Group
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ ****************************************************************************
+ */
+
+/*
+  SGGPIO.h
+  
+  Direct Stargate/PXA GPIO Access
+  
+*/
+
+#ifndef __SGGPIO_H
+#define __SGGPIO_H
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+#define GPIO_nr(x)      ((x) >> 5)
+
+enum PXA_REG {
+  PXA_GPLR = 0,
+  PXA_GPDR = 1,
+  PXA_GPSR = 2,
+  PXA_GPCR = 3
+};
+#define NUM_REGS 4
+#define NUM_REGNUMS 3
+
+extern char *pxa_reg_names[];
+
+#define PXA_REG_NAME(reg) pxa_reg_names[(reg)]
+
+#define PROC_REG_PREFIX "/proc/cpu/registers"
+
+class SGGPIO_PORT {
+
+public:
+
+  int setDir(int pin, unsigned int indir);
+  int setPin(int pin, unsigned int inval);
+  int readPin(int pin);
+  unsigned int readGPIO(PXA_REG reg,  int regnum);
+  int writeGPIO(PXA_REG reg, int regnum, unsigned int value);
+  SGGPIO_PORT();
+  ~SGGPIO_PORT();
+
+private:
+
+  int getGPIO(PXA_REG reg, int regnum);
+  int GPIO_fds[NUM_REGS][NUM_REGNUMS];
+};
+
+#endif /* __SGGPIO_H */
diff --git a/mote/sgtools/moteleds.C b/mote/sgtools/moteleds.C
new file mode 100644
index 0000000000000000000000000000000000000000..37e4cf14d8e12ba3b3f73c53965f459637f29119
--- /dev/null
+++ b/mote/sgtools/moteleds.C
@@ -0,0 +1,318 @@
+/*
+ * EMULAB-COPYRIGHT
+ * Copyright (c) 2004 University of Utah and the Flux Group.
+ * All rights reserved.
+ */
+
+/*
+ * moteleds.C - program to read the mote LED pins on a Stargate, and display
+ * them: on the stargate's LEDs, on the command line, or out a TCP socket
+ */
+
+
+/*
+ * These seem to make things happier when compiling on Linux
+ */
+#ifdef __linux__
+#define __PREFER_BSD
+#define __USE_BSD
+#define __FAVOR_BSD
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <signal.h>
+#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#ifdef __linux__
+#include <linux/sockios.h>
+#else
+#include <sys/sockio.h>
+#endif
+
+#include "SGGPIO.h"
+
+/*
+ * Mote LEDs
+ */
+#define MOTELED_RED_PIN    24
+#define MOTELED_GREEN_PIN  28
+#define MOTELED_YELLOW_PIN 29
+
+/*
+ * Stargate LEDs
+ */
+#define SGLED_YELLOW_PIN 62
+#define SGLED_GREEN_PIN  63
+#define SGLED_RED_PIN    64
+
+/*
+ * LED IOCTL constants - derived from linux/led.h
+ */
+#define LED_DEV "/dev/platx/led" 
+#define CONSUS_LED_IOCTL_MAGIG 'g'
+#define CLED_IOSET          _IO (CONSUS_LED_IOCTL_MAGIG, 1)
+#define CLED_IOGET          _IOR(CONSUS_LED_IOCTL_MAGIG, 2, int*)
+#define CLED_IOSTARTAUTO    _IO (CONSUS_LED_IOCTL_MAGIG, 3)
+#define CLED_IOSTOPAUTO     _IO (CONSUS_LED_IOCTL_MAGIG, 4)
+#define CLED_IOAUTOSTATUS   _IOR(CONSUS_LED_IOCTL_MAGIG, 5, int*)
+#define CLED_RADIO_RESET    _IO (CONSUS_LED_IOCTL_MAGIG, 6)
+
+#define LED_GREEN      (1 << 13)
+#define LED_RED        (1 << 15)
+#define LED_YELLOW     (1 << 14)
+#define LED_MASK       (LED_RED|LED_GREEN|LED_YELLOW)
+
+// Port to listen on
+#define PORT 1812
+
+// How many clients we can handle at once
+#define MAX_CLIENTS 64
+
+// Which mode we're in
+enum modes {
+    MODE_NONE   = 0x0,
+    MODE_MIRROR = 0x1,
+    MODE_PRINT  = 0x2,
+    MODE_EVENT  = 0x4,
+    MODE_SOCKET = 0x8
+};
+
+void usage() {
+	fprintf(stderr,"Usage: moteleds <-m | -p | -e | -s> [-t sleeptime]\n");
+	fprintf(stderr,"  -m  Mirror mode - set stargate LEDs\n");
+	fprintf(stderr,"  -p  Print mode - print LED status to stdout\n");
+	//fprintf(stderr,"  -e  Event mode - set events on LED state change\n");
+	fprintf(stderr,"  -s  Socket mode - open up a socket\n");
+	fprintf(stderr,"  -d  daemonize\n");
+	fprintf(stderr,"  -t  Sleep time in microseconds\n");
+	exit(1);
+}
+
+int main(int argc, char **argv) {
+
+    unsigned int mode = MODE_NONE;
+    int naptime = 0;
+
+    // Process command-line args
+    int ch;
+    bool daemonize = false;
+    while ((ch = getopt(argc, argv, "mpesdt:")) != -1)
+	switch (ch) {
+	    case 'm':
+		mode |= MODE_MIRROR;
+		break;
+	    case 'p':
+		mode |= MODE_PRINT;
+		break;
+	    case 'e':
+		mode |= MODE_EVENT;
+		break;
+	    case 's':
+		mode |= MODE_SOCKET;
+		break;
+	    case 'd':
+		daemonize = true;
+		break;
+	    case 't':
+		if (!sscanf(optarg,"%i",&naptime)) {
+		    usage();
+		}
+		break;
+	    case '?':
+	    default:
+		usage();
+	}
+    argc -= optind;
+    argv += optind;
+
+    if (argc) {
+	usage();
+    }
+
+    if (mode == MODE_NONE) {
+	usage();
+    }
+
+
+    // Set the GPIO pins to read from the mote LEDs
+    SGGPIO_PORT sggpio;
+    sggpio.setDir(MOTELED_YELLOW_PIN,0);
+    sggpio.setDir(MOTELED_GREEN_PIN,0);
+    sggpio.setDir(MOTELED_RED_PIN,0);
+
+    if (!naptime) {
+	naptime = 10 * 1000; // 100Hz
+    }
+
+    // We're going to mirror the mote LEDs to the stargate LEDs, so open up
+    // a file to control the SG LEDs
+    int ledfd = -1;
+    if (mode & MODE_MIRROR) {
+	ledfd = open(LED_DEV, O_RDWR);
+	if (ledfd < 0) {
+	    fprintf(stderr, "Open error: %s\n", LED_DEV);
+	    return 1;
+	}
+	// Turn off the automatic LED pattern
+	if (ioctl (ledfd, CLED_IOSTOPAUTO) < 0) {
+	    fprintf (stderr, "ioctl stop auto error: %s\n", LED_DEV);
+	    return 1;
+	}
+    }
+
+    // If we're supposed to write LED state change events to a socket, open
+    // that up now
+    int sockfd = -1;
+    if (mode & MODE_SOCKET) {
+	struct protoent *proto = getprotobyname("TCP");
+	sockfd = socket(AF_INET,SOCK_STREAM,proto->p_proto);
+	if (sockfd < 0) {     
+	    perror("Creating socket");
+	    exit(1);
+	}                               
+
+	// Set SO_RESEADDUR to make it easier to kill and restart this daemon
+        int opt = 1;
+        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0)
+                perror("SO_REUSEADDR");
+	
+	// Make the socket non-blocking
+        if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
+                perror("O_NONBLOCK");
+
+	struct sockaddr_in address;
+        address.sin_family = AF_INET;
+        address.sin_port = htons(PORT);
+        address.sin_addr.s_addr = INADDR_ANY;
+
+        if (bind(sockfd,(struct sockaddr*)(&address),sizeof(address))) {
+                perror("Binding socket");
+                exit(1);
+        }
+
+        if (listen(sockfd,-1)) {
+                perror("Listening on socket");
+                exit(1);
+        }
+
+        /*
+         * Ignore SIGPIPE - we'll detect the remote end closing the connection
+         * by a failed write() .
+         */
+	struct sigaction action;
+        action.sa_handler = SIG_IGN;
+        sigaction(SIGPIPE,&action,NULL);
+
+    }
+
+    // Daemonize if we're supposed to
+    if (daemonize) {
+	daemon(0,0);
+    }
+
+    /*
+     * Main loop
+     */
+    unsigned int current_status, old_status;
+    // Bogus value so that we will detect a change the first time through
+    old_status = 31337;
+
+    // FD of the clients for our socket
+    int clientfds[MAX_CLIENTS];
+    for (int i = 0; i < MAX_CLIENTS; i++) { clientfds[i] = -1; }
+    bool newclient = false;
+    int current_clients = 0;
+    while(1) {
+	// If we have a socket, try to accept connections
+	if ((mode & MODE_SOCKET) && sockfd) {
+
+	    struct sockaddr client_addr;
+	    size_t client_addrlen;
+
+	    int newclientfd = accept(sockfd,&client_addr,&client_addrlen);
+	    if (newclientfd >= 0) {
+		if (current_clients == MAX_CLIENTS) {
+		    // Bummer, too many
+		    close(newclientfd);
+		}
+		newclient = true;
+		for (int i = 0; i < MAX_CLIENTS; i++) {
+		    if (clientfds[i] == -1) {
+			clientfds[i] = newclientfd;
+			current_clients++;
+			break;
+		    }
+		}
+	    }
+	}
+
+	// Read mote pin connectors
+	int yellow = sggpio.readPin(MOTELED_YELLOW_PIN);
+	int green = sggpio.readPin(MOTELED_GREEN_PIN);
+	int red = sggpio.readPin(MOTELED_RED_PIN);
+
+	// Mote LEDs use negative logic, reverse them
+	if (yellow) { yellow = 0; } else { yellow = 1; }
+	if (green) { green = 0; } else { green = 1; }
+	if (red) { red = 0; } else { red = 1; }
+
+	// In mirroring mode, set up a patter for the SG LEDs and ioctl() it
+	// into place
+	if (mode & MODE_MIRROR) {
+	    int ledpattern = 0;
+	    if (yellow) { ledpattern |= LED_RED; }
+	    if (green) { ledpattern |= LED_GREEN; }
+	    if (red) { ledpattern |= LED_YELLOW; }
+	    if (ioctl (ledfd, CLED_IOSET, ledpattern) < 0) {
+		fprintf (stderr, "ioctl set error: %s\n", LED_DEV);
+		exit(1);
+	    } 
+	}
+
+	// Check to see if what we got this time was different from last time
+	current_status = (red << 2) | (green << 1) | yellow;
+	if (old_status != current_status) {
+	    // In printing mode, do just that
+	    if (mode & MODE_PRINT) {
+		printf("%i %i %i\n",red,green,yellow);
+	    }
+	}
+
+	if ((old_status != current_status) || newclient) {
+	    // If we have a socket, print on that
+	    if ((mode & MODE_SOCKET) && (current_clients > 0)) {
+		char outbuf[1024];
+		snprintf(outbuf,1024,"%i %i %i\n",red,green,yellow);
+		for (int i = 0; i <= MAX_CLIENTS; i++) {
+		    int clientfd = clientfds[i];
+		    if (clientfd == -1) {
+			continue;
+		    }
+		    if (write(clientfd,outbuf,strlen(outbuf)) < 0) {
+			// Detect disconnected clients
+			if (errno != EPIPE) {
+			    perror("write");
+			}
+			close(clientfd);
+			clientfds[i] = -1;
+			current_clients--;
+		    }
+		}
+	    }
+	    newclient = false;
+	}
+	old_status = current_status;
+
+	// Get some, go again
+	usleep(naptime);
+    }
+}
diff --git a/mote/sgtools/motepower.C b/mote/sgtools/motepower.C
new file mode 100644
index 0000000000000000000000000000000000000000..5aa6ab9e607a7b4c3c76565053d01a5f525e80ad
--- /dev/null
+++ b/mote/sgtools/motepower.C
@@ -0,0 +1,73 @@
+
+/*
+ * EMULAB-COPYRIGHT
+ * Copyright (c) 2004 University of Utah and the Flux Group.
+ * All rights reserved.
+ */
+
+/*
+ * motepower.C - turn the power to a mote on a stargate "on" or "off" by
+ * toggling its RSTN pin
+ */
+
+#include "SGGPIO.h"
+
+// Pin used to reset the ATMega microcontroller
+#define RSTN_PIN 77
+
+// The RSTN pin is negative logic
+#define MOTE_ON 1
+#define MOTE_OFF 0
+
+void usage() {
+	fprintf(stderr,"Usage: motepower <on | off | cycle>\n");
+	exit(1);
+}
+
+int main(int argc, char **argv) {
+    /*
+     * Handle command-line argument
+     */
+    if (argc != 2) {
+	usage();
+    }
+
+    bool turnoff = false;
+    bool turnon = false;
+    if (!strcmp(argv[1],"on")) {
+	turnon = true;
+    } else if (!strcmp(argv[1],"off")) {
+	turnoff = true;
+    } else if (!strcmp(argv[1],"cycle")) {
+	turnon = turnoff = true;
+    } else {
+	usage();
+    }
+
+    /*
+     * Set the pin for output
+     */
+    SGGPIO_PORT sggpio;
+    sggpio.setDir(RSTN_PIN,1);
+
+    /*
+     * Turn off the mote, if we're supposed to
+     */
+    if (turnoff) {
+	sggpio.setPin(RSTN_PIN,MOTE_OFF);
+    }
+    
+    /*
+     * If cycling, give it a moment
+     */
+    if (turnon && turnoff) {
+	usleep(500 * 1000); // .5 seconds
+    }
+
+    /*
+     * Turn on the mote, if we're supposed to
+     */
+    if (turnon) {
+	sggpio.setPin(RSTN_PIN,MOTE_ON);
+    }
+}