Project import
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5e0a6be
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,102 @@
+#
+#    Copyright (c) 2010-2014 Nest, Inc.
+#    All rights reserved.
+#
+#    This document is the property of Nest. It is considered
+#    confidential and proprietary information.
+#
+#    This document may not be reproduced or transmitted in any form,
+#    in whole or in part, without the express written permission of
+#    Nest.
+#
+#    Description:
+#      This file is the make file for the Freescale UTP over USB MSC
+#      tool, uuc.
+#
+
+BuildConfigSpecialized	:= No
+BuildProductSpecialized	:= No
+
+include pre.mak
+
+PackageName		:= uuc
+
+PackageExtension	:= tar.gz
+PackageSeparator	:= -
+
+PackagePatchArgs	:= -p1
+
+PackageArchive		:= $(PackageName)-$(PackageVersion).$(PackageExtension)
+PackageSourceDir	:= $(PackageName)$(PackageSeparator)$(PackageVersion)
+
+PackageBuildMakefile	= $(call GenerateBuildPaths,Makefile)
+
+LicenseSourceFile	:= $(PackageSourceDir)/COPYING
+
+CleanPaths		+= $(PackageLicenseFile)
+
+UUIDDir         	:= sw/tps/e2fsprogs
+UUIDIncDir      	= $(call GenerateResultPaths,$(UUIDDir),usr/include)
+UUIDLibDir      	= $(call GenerateResultPaths,$(UUIDDir),usr/lib)
+
+all: $(PackageDefaultGoal)
+
+# Generate the package license contents.
+
+$(LicenseSourceFile): source
+
+$(PackageLicenseFile): $(LicenseSourceFile)
+	$(copy-result)
+
+# Extract the source from the archive and apply patches, if any.
+
+$(PackageSourceDir): $(PackageArchive) $(PackagePatchPaths)
+	$(expand-and-patch-package)
+
+# Prepare the sources.
+
+.PHONY: source
+source: | $(PackageSourceDir)
+
+# Patch the sources, if necessary.
+
+.PHONY: patch
+patch: source
+
+# Generate the package build makefile.
+
+$(PackageBuildMakefile): | $(PackageSourceDir) $(BuildDirectory)
+	$(call create-links,$(CURDIR)/$(PackageSourceDir),$(BuildDirectory))
+
+# Configure the source for building.
+
+.PHONY: configure
+configure: source $(PackageBuildMakefile)
+
+# Build the source.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: build
+build: configure | $(BuildDirectory)
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) -C $(BuildDirectory) \
+	CC="$(CC)" CXX="$(CXX)" AR=$(AR) NM=$(NM) RANLIB=$(RANLIB) STRIP=$(STRIP) \
+	CFLAGS="-I$(LinuxHeaderDir)" \
+	all
+
+# Stage the build to a temporary installation area.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: stage
+stage: build | $(ResultDirectory)
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) -C $(BuildDirectory) DEST_DIR=$(ResultDirectory) install
+
+clean:
+	$(Verbose)$(RM) $(RMFLAGS) -r $(PackageSourceDir)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(BuildDirectory)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(ResultDirectory)
+
+include post.mak
diff --git a/uuc-3.0.35-4.1.0.tar.gz b/uuc-3.0.35-4.1.0.tar.gz
new file mode 100755
index 0000000..cebbbfc
--- /dev/null
+++ b/uuc-3.0.35-4.1.0.tar.gz
Binary files differ
diff --git a/uuc-3.0.35-4.1.0/Makefile b/uuc-3.0.35-4.1.0/Makefile
new file mode 100644
index 0000000..29ce91a
--- /dev/null
+++ b/uuc-3.0.35-4.1.0/Makefile
@@ -0,0 +1,20 @@
+CC=$(CROSS_COMPILE)gcc
+AR=$(CROSS_COMPILE)AR
+
+all: uuc sdimage
+
+uuc: uu.c
+	$(CC)  uu.c -o uuc -lpthread
+
+sdimage: sdimage.c
+	$(CC) sdimage.c -o sdimage
+
+install:
+	mkdir -p   $(DEST_DIR)
+	cp linuxrc $(DEST_DIR)
+	mkdir -p   $(DEST_DIR)/usr/bin
+	cp uuc	   $(DEST_DIR)/usr/bin
+	cp sdimage $(DEST_DIR)/usr/bin
+clean:
+	rm -f uuc
+	rm -f sdimage
diff --git a/uuc-3.0.35-4.1.0/linuxrc b/uuc-3.0.35-4.1.0/linuxrc
new file mode 100755
index 0000000..7f1fdcc
--- /dev/null
+++ b/uuc-3.0.35-4.1.0/linuxrc
@@ -0,0 +1,15 @@
+#!/bin/sh
+#mkdir /sys /proc
+mount -t sysfs none /sys
+mount -t proc none /proc
+export PATH=/sbin:/bin:/usr/sbin:/usr/bin
+echo "Starting UTP"
+cd /home
+#disable turn off display
+mknod /dev/tty0 c 4 0
+#get up-to-date mount information
+ln -s /proc/mounts /etc/mtab
+echo "disable turn off display"
+echo -e "\033[9;0]" > /dev/tty0
+/etc/rc.d/init.d/udev start
+/usr/bin/uuc
diff --git a/uuc-3.0.35-4.1.0/sdimage.c b/uuc-3.0.35-4.1.0/sdimage.c
new file mode 100644
index 0000000..d41f2cc
--- /dev/null
+++ b/uuc-3.0.35-4.1.0/sdimage.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+char *g_filedev;
+char *g_firmware;
+
+struct PART {
+	unsigned char boot;
+	unsigned char starthead;
+	unsigned char startsector;
+	unsigned char startcylinder;
+	unsigned char filesystem;
+	unsigned char endhead;
+	unsigned char endsector;
+	unsigned char endcylinder;
+	unsigned int start;
+	unsigned int count;
+} __attribute__ ((packed));
+struct MBR {
+	unsigned char resevered[446];
+	struct PART part[4];
+	unsigned short sign;
+} __attribute__ ((packed));
+
+struct DeviceInfo {
+	unsigned int u32ChipNum;
+	unsigned int u32DriverType;
+	unsigned int u32Tag;
+	unsigned int u32FirstSectorNumber;
+	unsigned int u32SectorCount;
+} __attribute__ ((packed));
+
+struct ConfigBlock {
+	unsigned int u32Sigature;
+	unsigned int u32PrimaryBootTag;
+	unsigned int u32SecondaryBootTags;
+	unsigned int u32NumCopies;
+	struct DeviceInfo aDriverInfo[10];
+} __attribute__ ((packed));
+
+int main(int argc, char **argv)
+{
+	int i = 0;
+	int devhandle;
+	int firmwarehandle;
+	struct MBR mbr;
+	struct ConfigBlock bcb;
+	char *buff;
+	struct stat filestat;
+
+	if (argc < 2) {
+		printf("sdimage -f <firmware.sb> -d </dev/mmcblk>\n");
+		return -1;
+	}
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "-f") == 0) {
+			g_firmware = argv[i + 1];
+			i++;
+		}
+		if (strcmp(argv[i], "-d") == 0) {
+			g_filedev = argv[i + 1];
+			i++;
+		}
+	}
+	if (g_firmware == NULL) {
+		printf("you need give -f <firmware file>\n");
+		return -1;
+	}
+	if (g_filedev == NULL) {
+		printf("you need give -d <dev file> \n");
+		return -1;
+	}
+
+	devhandle = open(g_filedev, O_RDWR);
+	if (devhandle < 0) {
+		printf("can't open file %s\n", g_filedev);
+		return -1;
+	}
+
+	firmwarehandle = open(g_firmware, O_RDWR);
+	if (firmwarehandle < 0) {
+		printf("can't open file %s\n", g_firmware);
+		return -1;
+	}
+	if (stat(g_firmware, &filestat)) {
+		printf("stat %s error\n", g_firmware);
+		return -1;
+	}
+	if (read(devhandle, &mbr, sizeof(mbr)) < sizeof(mbr)) {
+		printf("read block 0 fail");
+		return -1;
+	}
+
+	if (mbr.sign != 0xAA55) {
+		printf("Check MBR signature fail 0x%x\n", mbr.sign);
+		return -1;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (mbr.part[i].filesystem == 'S')
+			break;
+	}
+
+	if (i == 4) {
+		printf("Can't found boot stream partition\n");
+		return -1;
+	}
+
+	if ((mbr.part[i].count * 512) < (2 * filestat.st_size + 1)) {
+		printf("firmare partition is too small\n");
+		return -1;
+	}
+
+	memset(&bcb, 0, sizeof(bcb));
+	bcb.u32Sigature = 0x00112233;
+	bcb.u32PrimaryBootTag = 1;
+	bcb.u32SecondaryBootTags = 2;
+	bcb.u32NumCopies = 2;
+
+	bcb.aDriverInfo[0].u32ChipNum = 0;
+	bcb.aDriverInfo[0].u32DriverType = 0;
+	bcb.aDriverInfo[0].u32Tag = bcb.u32PrimaryBootTag;
+	bcb.aDriverInfo[0].u32FirstSectorNumber = mbr.part[i].start + 1;
+
+	bcb.aDriverInfo[1].u32ChipNum = 0;
+	bcb.aDriverInfo[1].u32DriverType = 0;
+	bcb.aDriverInfo[1].u32Tag = bcb.u32SecondaryBootTags;
+	bcb.aDriverInfo[1].u32FirstSectorNumber =
+	    bcb.aDriverInfo[0].u32FirstSectorNumber
+	    + ((filestat.st_size + 511) / 512);
+
+	lseek(devhandle, mbr.part[i].start * 512, SEEK_SET);
+	if (write(devhandle, &bcb, sizeof(bcb)) != sizeof(bcb)) {
+		printf("write bcb error\n");
+		return -1;
+	}
+
+	buff = malloc(filestat.st_size);
+	if (buff == NULL) {
+		printf("malloc fail\n");
+		return -1;
+	}
+
+	if (read(firmwarehandle, buff, filestat.st_size) != filestat.st_size) {
+		printf("read firmware fail\n");
+		return -1;
+	}
+
+	printf("write first firmware\n");
+
+	lseek(devhandle, (mbr.part[i].start + 1) * 512, SEEK_SET);
+	if (write(devhandle, buff, filestat.st_size) != filestat.st_size) {
+		printf("first firmware write fail\n");
+		return -1;
+	}
+
+	printf("write second firmware\n");
+
+	lseek(devhandle, bcb.aDriverInfo[1].u32FirstSectorNumber * 512,
+	      SEEK_SET);
+	if (write(devhandle, buff, filestat.st_size) != filestat.st_size) {
+		printf("second firmware write fail\n");
+		return -1;
+	}
+	free(buff);
+	close(devhandle);
+	close(firmwarehandle);
+	printf("done\r\n");
+	return 0;
+}
diff --git a/uuc-3.0.35-4.1.0/uu.c b/uuc-3.0.35-4.1.0/uu.c
new file mode 100644
index 0000000..0dbbe94
--- /dev/null
+++ b/uuc-3.0.35-4.1.0/uu.c
@@ -0,0 +1,763 @@
+/*
+ * iMX utp decode program
+ *
+ * Copyright 2010-2013 Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syscall.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <pthread.h>
+#include <linux/reboot.h>
+#include <sys/reboot.h>
+/* mxc SoC will enable watchdog at USB recovery mode
+ * so, the user must service watchdog
+ */
+#include <linux/watchdog.h>
+
+#define UTP_DEVNODE 	"/dev/utp"
+#define UTP_TARGET_FILE	"/tmp/file.utp"
+
+#define UTP_FLAG_COMMAND	0x00000001
+#define UTP_FLAG_DATA		0x00000002
+#define UTP_FLAG_STATUS		0x00000004    //indicate an error happens
+#define UTP_FLAG_REPORT_BUSY	0x10000000
+
+
+#pragma pack(1)
+
+#define PACKAGE "uuc"
+#define VERSION "0.4"
+
+char *utp_firmware_version = "2.6.31";
+char *utp_sn = "000000000000";
+char *utp_chipid = "370000A5";
+/* for utp ioctl */
+#define UTP_IOCTL_BASE  'U'
+#define UTP_GET_CPU_ID  _IOR(UTP_IOCTL_BASE, 0, int)
+
+#define NEED_TO_GET_CHILD_PID 1
+/*
+ * this structure should be in sync with the same in
+ * $KERNEL/drivers/usb/gadget/fsl_updater.c
+ */
+struct utp_message {
+	uint32_t flags;
+	size_t 	 size;
+	union {
+		struct {
+			uint64_t payload;
+			char command[1];
+		};
+		struct {
+			size_t bufsize;
+			uint8_t data[1];
+		};
+		uint32_t status;
+	};
+};
+#pragma pack()
+
+static int utp_file = -1;
+static FILE *utp_file_f = NULL;
+
+static inline char *utp_answer_type(struct utp_message *u)
+{
+	if (!u)
+		return "UNKNOWN";
+	if (u->flags & UTP_FLAG_STATUS)
+		return "Non-success";
+	if (u->flags & UTP_FLAG_DATA)
+		return "Data";
+	if (u->flags & UTP_FLAG_REPORT_BUSY)
+		return "Busy";
+	if (u->flags & UTP_FLAG_COMMAND)
+		return "Command ?!";
+	return "Success";
+}
+
+/*
+ * utp_mk_devnode
+ *
+ * Parse the /sys entry to find major and minor for device
+ * If/when found, create device node with type 'type'
+ *
+ * Example: utp_mk_devnode("block", "sda", "/dev/scsi-disk-0", S_IFBLK)
+ */
+static int utp_mk_devnode(char *class, char *name, char *node, int type)
+{
+	char sys[256];
+	char devnode[20]; /* major:minor */
+	int major, minor;
+	char *colon;
+	int len, f, rc = -EINVAL;
+
+	if (access(node, F_OK) == 0) {
+		printf("UTP: file/device node %s already exists\n", node);
+		return 0;
+	}
+
+	snprintf(sys, sizeof(sys), "/sys/%s/%s/dev", class, name);
+	f = open(sys, O_RDONLY);
+	if (f >= 0) {
+		memset(devnode, 0, sizeof(devnode));
+		len = read(f, devnode, sizeof(devnode));
+		if (len >= 0) {
+			sscanf(devnode, "%d:%d", &major, &minor);
+		printf("%s: creating node '%s' with %d+%d\n", __func__, node, major, minor);
+			unlink(node);
+			rc = mknod(node, type | 0666, makedev(major, minor));
+		}
+		close(f);
+	}
+	return rc;
+}
+
+/*
+ * utp_run
+ *
+ * Start the subshell and execute the command passed
+ */
+static utp_run(char *command, ... )
+{
+	int r;
+	char cmd[1024];
+	va_list vptr;
+
+	va_start(vptr, command);
+	vsnprintf(cmd, sizeof(cmd), command, vptr);
+	va_end(vptr);
+
+	printf("UTP: executing \"%s\"\n", cmd);
+	return system(cmd);
+}
+
+/*
+ * utp_send_busy
+ *
+ * report the busy state to the kernel state machine
+ */
+static void utp_send_busy(int u)
+{
+	struct utp_message w;
+
+	w.flags = UTP_FLAG_REPORT_BUSY;
+	w.size = sizeof(w);
+	write(u, &w, w.size);
+}
+
+/*
+ * utp_partition_mmc
+ *
+ * chat with fdisk to create bootable partition of type 0x53 and extended one
+ */
+static int utp_partition_mmc(char *disk)
+{
+	char fc[50];
+	int i;
+	char shell_cmd[256];
+	int fdisk;
+	FILE *fdisk_f;
+
+	sprintf(shell_cmd, "fdisk %s", disk);
+	fdisk_f = popen(shell_cmd, "w");
+	if (fdisk_f < 0)
+		return errno;
+
+	fdisk = fileno(fdisk_f);
+	for (i = 4; i >= 1 ; i--) {
+		sprintf(fc, "d\n%d\n", i);
+		write(fdisk, fc, strlen(fc));
+	}
+
+	sprintf(fc, "n\np\n1\n1\n+16M\n");
+	write(fdisk, fc, strlen(fc));
+
+	sprintf(fc, "n\np\n2\n\n\n");
+	write(fdisk, fc, strlen(fc));
+
+	sprintf(fc, "t\n1\n0x%X\n\n", 0x53);
+	write(fdisk, fc, strlen(fc));
+
+	write(fdisk, "w\nq\n", 2);
+
+	pclose(fdisk_f);
+
+	return 0;
+}
+
+/*
+ * utp_do_selftest
+ *
+ * perform some diagnostics
+ *
+ * TBW
+ */
+static int utp_do_selftest(void)
+{
+	return 0;
+}
+/*
+ * Put the command which needs to send busy first
+ * And the host will send poll for getting its return value
+ * later, we call these kinds of commands as Asynchronous Commands.
+ */
+static int utp_can_busy(char *command)
+{
+	char *async[] ={
+		"$ ", "frf", "pollpipe", NULL,
+	};
+	char **ptr;
+
+	ptr = async;
+	while (*ptr) {
+		if (strncmp(command, *ptr, strlen(*ptr)) == 0)
+			return 1;
+		ptr++;
+	}
+	return 0;
+}
+#ifdef NEED_TO_GET_CHILD_PID
+/* for pipe */
+#define READ 0
+#define WRITE 1
+static pid_t child_pid = -1;
+static int utp_flush(void)
+{
+	int pstat;
+	int ret = 0;
+	pid_t pid;
+	if (utp_file >= 0) {
+		fflush(NULL);
+		ret = close(utp_file);
+		do{
+			pid = waitpid(child_pid, &pstat, 0); /* wait for child finished */
+		}while (pid == -1 && errno == EINTR);
+		printf("UTP: closing the file\n");
+	}
+	utp_file = -1;
+	return ret;
+}
+pid_t popen2(const char *command, int *infp, int *outfp)
+{
+	int p_stdin[2], p_stdout[2];
+	pid_t pid;
+
+	if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
+		return -1;
+
+	pid = fork();
+
+	if (pid < 0)
+		return pid;
+	else if (pid == 0){
+		close(p_stdin[WRITE]);
+		if (infp == NULL)
+			close(p_stdin[READ]);
+		else
+			dup2(p_stdin[READ], READ);
+		close(p_stdout[READ]);
+		if (outfp == NULL)
+			close(p_stdout[WRITE]);
+		else
+			dup2(p_stdout[WRITE], WRITE);
+
+		execl("/bin/sh", "sh", "-c", command, NULL);
+		perror("execl");
+		exit(1);
+	}
+
+	if (infp == NULL)
+		close(p_stdin[WRITE]);
+	else
+		*infp = p_stdin[WRITE];
+
+	if (outfp == NULL)
+		close(p_stdout[READ]);
+	else
+		*outfp = p_stdout[READ];
+
+	close(p_stdin[READ]);
+	close(p_stdout[WRITE]);
+	return pid;
+}
+int utp_pipe(char *command, ... )
+{
+	int r, infp;
+	char shell_cmd[1024];
+	va_list vptr;
+	va_start(vptr, command);
+	vsnprintf(shell_cmd, sizeof(shell_cmd), command, vptr);
+	va_end(vptr);
+
+	child_pid = popen2(shell_cmd, &infp, NULL);
+	if (child_pid < 0){
+		printf("the fork is failed \n");
+		return -1;
+	}
+	utp_file = infp;
+	printf("pid is %d, UTP: executing \"%s\"\n",child_pid, shell_cmd);
+	return 0;
+}
+int utp_poll_pipe()
+{
+	int ret = 0, cnt = 0xFFFF;
+	while(ret == 0 && cnt > 0){
+		ret = is_child_dead();
+		usleep(10000);
+		cnt--;
+	}
+
+	if(ret == 0)
+		return 1;//failure
+	else
+		return 0;//Success
+}
+
+
+#else
+static int utp_flush(void)
+{
+	int ret;
+	if (utp_file_f) {
+		printf("UTP: waiting for pipe to close\n");
+		ret = pclose(utp_file_f);
+	}
+	else if (utp_file >= 0) {
+		printf("UTP: closing the file\n");
+		ret = close(utp_file);
+	}
+	utp_file_f = NULL;
+	utp_file = -1;
+	printf("UTP: files were flushed.\n");
+	return ret;
+}
+static int utp_pipe(char *command, ... )
+{
+	int r;
+	char shell_cmd[1024];
+	va_list vptr;
+
+	va_start(vptr, command);
+	vsnprintf(shell_cmd, sizeof(shell_cmd), command, vptr);
+	va_end(vptr);
+
+	utp_file_f = popen(shell_cmd, "w");
+	utp_file = fileno(utp_file_f);
+
+	return utp_file_f ? 0 : errno;
+}
+#endif
+/*
+ * utp_handle_command
+ *
+ * handle the command from MSC driver
+ * command can be:
+ * 	?
+ *	!<type>
+ *	$ <shell_command>
+ *	wfs/wff <X>		write firmware to SD/flash
+ *	wrs/wrf <X>		write rootfs to SD/flash
+ *	frs/frf <X>		format partition for root on SD/flash
+ *	erase <X>		erase partition on flash
+ *	read			not implemented yet
+ *	write			not implemented yet
+ */
+static struct utp_message *utp_handle_command(int u, char *cmd, unsigned long long payload)
+{
+	struct utp_message *w = NULL;
+	char devnode[50];	/* enough to fit /dev/mmcblk0p99    */
+	char sysnode[50];	/*   -"-    -"-  mmcblk0/mmcblk0p99 */
+	uint32_t flags, status;
+	char *data = NULL;
+	int f;
+	size_t size;
+
+	printf("UTP: received command '%s'\n", cmd);
+
+	/* defaults */
+	status = 0;
+	flags = 0;
+	size = 0;
+
+	/* these are asynchronous commands and need to send busy */
+	if (utp_can_busy(cmd)){
+		utp_send_busy(u);
+	}
+
+	if (strcmp(cmd, "?") == 0) {
+		/* query */
+		flags = UTP_FLAG_DATA;
+		data = malloc(256);
+		sprintf(data,
+			"<DEVICE>\n"
+			" <FW>%s</FW>\n"
+			" <DCE>%s</DCE>\n"
+			" <SN>%s</SN>"
+			" <CID>%s</CID>"
+			" <VID>%04X</VID>"
+			" <PID>%04X</PID>"
+			"</DEVICE>\n", utp_firmware_version, VERSION, utp_sn, utp_chipid, 0x66F, 0x37FF);
+		size = (strlen(data) + 1 ) * sizeof(data[0]);
+	}
+
+	else if (cmd[0] == '!') {
+		/* reboot the system, and the ACK has already sent out */
+		if (cmd[1] == '3') {
+			sync();
+			kill(-1, SIGTERM);
+			sleep(1);
+			kill(-1, SIGKILL);
+
+			reboot(LINUX_REBOOT_CMD_RESTART);
+			return NULL;
+		}
+	}
+
+	else if (strncmp(cmd, "$ ", 2) == 0) {
+		status = utp_run(cmd + 2);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+	else if ((strcmp(cmd,"wff") == 0) || (strcmp(cmd, "wfs") == 0)) {
+		/* Write firmware - to flash or to SD, no matter */
+		utp_file = open(UTP_TARGET_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+	}
+
+	else if (strcmp(cmd, "fff") == 0) {
+		/* perform actual flashing of the firmware to the NAND */
+		utp_flush();
+		if (utp_mk_devnode("class/mtd", "mtd1", "/dev/mtd1", S_IFCHR) >= 0 &&
+  		    utp_mk_devnode("class/mtd", "mtd0", "/dev/mtd0", S_IFCHR) >= 0) {
+			utp_run("kobs-ng -v -d %s", UTP_TARGET_FILE);
+		}
+	}
+	else if (strcmp(cmd, "ffs") == 0) {
+		/* perform actual flashing of the firmware to the SD */
+		utp_flush();
+
+		/* partition the card */
+		if (!status  && utp_mk_devnode("block", "mmcblk0", "/dev/mmc", S_IFBLK) >= 0) {
+			status = utp_partition_mmc("/dev/mmc");
+			/* waiting for partition table to settle */
+			sleep(5);
+		}
+
+		/* write data to the first partition */
+		if (!status && utp_mk_devnode("block", "mmcblk0/mmcblk0p1", "/dev/mmc0p1", S_IFBLK) >= 0) {
+			utp_run("dd if=/dev/zero of=/dev/mmc0p1 bs=512 count=4");
+			utp_run("dd if=%s of=/dev/mmc0p1 ibs=512 seek=4 conv=sync,notrunc", UTP_TARGET_FILE);
+		}
+
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "mknod", 5) == 0) {
+		int devtype = S_IFCHR;
+		char *class, *item, *type, *node;
+
+		class = strtok(cmd + 6, " \t,;");
+		printf("class = '%s'\n", class);
+		item = strtok(NULL, " \t,;");
+		printf("item = '%s'\n", item);
+		node = strtok(NULL, " \t,;");
+		printf("node = %s\n", node);
+		type = strtok(NULL, " \t,;");
+		printf("type = %s\n", type);
+		if (!node && item)
+			sprintf(devnode, "/dev/%s", item);
+		else
+			strcpy(devnode, node);
+		if (type && (strcmp(type, "block") == 0 || strcmp(type, "blk") == 0))
+			devtype = S_IFBLK;
+		printf("UTP: running utp_mk_devnode(%s,%s,%s,0x%x)\n",
+				class, item, devnode, devtype);
+		status = utp_mk_devnode(class, item, devnode, devtype);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "wrf", 3) == 0) {
+		/* Write rootfs to flash */
+		printf("UTP: writing rootfs to flash, mtd #%c, size %lld\n",
+				cmd[3], payload);
+
+		/* ensure that device node is here  */
+		snprintf(devnode, sizeof(devnode), "/dev/mtd%c", cmd[3]);
+		utp_mk_devnode("class/mtd", devnode + 5, devnode, S_IFCHR);
+
+		/* then start ubiformat and redirect its input */
+		status = utp_pipe("ubiformat %s -f - -S %lld", devnode, payload);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "pipe", 4) == 0) {
+		status = utp_pipe(cmd + 5);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "pollpipe", 8) == 0) {
+		printf("UTP: poll pipe.\n");
+		status = utp_poll_pipe();
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "wrs", 3) == 0) {
+		/* Write rootfs to the SD */
+		printf("UTP: writing rootfs to SD card, mmc partition #%c, size %lld\n",
+				cmd[3], payload);
+
+		/* ensure that device node is here  */
+		snprintf(devnode, sizeof(devnode), "/dev/mmcblk0p%c", cmd[3]);
+		snprintf(sysnode, sizeof(sysnode), "mmcblk0/mmcblk0p%d", cmd[3]);
+		utp_mk_devnode("block", sysnode, devnode, S_IFBLK);
+
+		if (payload % 1024)
+			printf("UTP: WARNING! payload %% 1024 != 0, the rest will be skipped");
+
+		status = utp_pipe("dd of=%s bs=1K", devnode);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+
+	else if (strcmp(cmd, "frf") == 0 || strcmp(cmd, "frs") == 0) {
+		/* perform actual flashing of the rootfs to the NAND/SD */
+		status = utp_flush();
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "untar.", 6) == 0) {
+		status = utp_pipe("tar %cxv -C %s", cmd[6], cmd + 8);
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else if (strncmp(cmd, "read", 4) == 0) {
+		f = open(cmd + 5, O_RDONLY);
+		if (f < 0) {
+			flags = UTP_FLAG_STATUS;
+			status = errno;
+		} else {
+			size = lseek(f, 0, SEEK_END);	/* get the file size */
+			lseek(f, 0, SEEK_SET);
+
+			data = malloc(size);
+			if (!data) {
+				flags = UTP_FLAG_STATUS;
+				status = -ENOMEM;
+			} else {
+				read(f, data, size);
+				flags = UTP_FLAG_DATA;
+			}
+		}
+	}
+
+	else if (strcmp(cmd, "send") == 0) {
+		utp_file = open(UTP_TARGET_FILE, O_TRUNC | O_CREAT | O_WRONLY, 0666);
+	}
+
+	else if (strncmp(cmd, "save", 4) == 0) {
+		close(utp_file);
+		rename(UTP_TARGET_FILE, cmd + 5);
+	}
+
+
+	else if (strcmp(cmd, "selftest") == 0) {
+		status = utp_do_selftest();
+		if (status)
+			flags = UTP_FLAG_STATUS;
+	}
+
+	else {
+		printf("UTP: Unknown command received, ignored\n");
+		flags = UTP_FLAG_STATUS;
+		status = -EINVAL;
+	}
+
+	w = malloc(size + sizeof(*w));
+	if (!w) {
+		printf("UTP: Could not allocate %d+%d bytes!\n", size, sizeof(*w));
+		return NULL;
+	}
+
+	memset(w, 0, sizeof(*w) + size);
+	w->flags = flags;
+	w->size = size + sizeof(*w);
+	if (flags & UTP_FLAG_DATA) {
+		w->bufsize = size;
+		memcpy(w->data, data, size);
+	}
+	if (flags & UTP_FLAG_STATUS)
+		w->status = status;
+	if (data)
+		free(data);
+	return w;
+}
+
+/*
+ * Check the process is dead
+ */
+#define NAME_MAX 30
+int is_child_dead(void)
+{
+	FILE *fh;
+	char path[NAME_MAX + 1];
+	sprintf(path, "/proc/%u/status", (unsigned int)child_pid);
+	if ((fh = fopen(path, "r"))){
+		char buf[1024];
+		while (fgets(buf, sizeof(buf) -1, fh)){
+			if (!strncmp(buf, "State:", 6))
+			{
+				char *p = buf + 6;
+				while (*p == '\t'){
+					p++;
+					continue;
+				}
+				if (*p == 'Z'){
+					printf("Process status polling: %s is in zombie.\n",path);
+					fclose(fh);
+					return 1;
+				}
+				break;
+			}
+		}
+	}
+	else{
+		printf("Process polling: can't open %s, maybe the process %u has been killed already\n",path,child_pid);
+		return 1;
+	}
+
+	fclose(fh);
+	return 0;
+}
+
+
+void feed_watchdog(void *arg)
+{
+	int res;
+	int *fd = arg;
+	while(1) {
+		res = ioctl(*fd, WDIOC_KEEPALIVE);
+		if (res)
+			printf("ioctl WDIOC_KEEPALIVE error L%d, %s\n", __LINE__, strerror(errno));
+		printf("%s\n", __func__);
+		sleep(60);
+	}
+}
+
+int main(void)
+{
+	int u = -1, wdt_fd = -1, r, need_watchdog = 0;
+	int watchdog_timeout = 127;  /* sec */
+	int cpu_id = 50;
+	struct utp_message *uc, *answer;
+	char env[256];
+	pthread_t a_thread;
+	void *thread_result;
+
+	printf("%s %s [built %s %s]\n", PACKAGE, VERSION, __DATE__, __TIME__);
+	/* set stdout unbuffered, what is the usage??? */
+//	setvbuf(stdout, NULL, _IONBF, 0);
+	uc = malloc(sizeof(*uc) + 0x10000);
+
+	mkdir("/tmp", 0777);
+
+	setenv("FILE", UTP_TARGET_FILE, !0);
+
+	printf("UTP: Waiting for device to appear\n");
+	while (utp_mk_devnode("class/misc", "utp", UTP_DEVNODE, S_IFCHR) < 0) {
+		putchar('.');
+		sleep(1);
+	}
+	u = open(UTP_DEVNODE, O_RDWR);
+	r = ioctl(u, UTP_GET_CPU_ID, &cpu_id);
+	if (r)
+		printf("cpu id get error:L%d, %s\n", __LINE__, strerror(errno));
+	else{
+		switch (cpu_id) {
+			case 23:
+			case 25:
+			case 28:
+			case 50:
+				need_watchdog = 0;
+				break;
+			case 35:
+			case 51:
+			case 53:
+				need_watchdog = 1;
+				break;
+			default:
+				need_watchdog = 0;
+		}
+		printf("cpu_id is %d\n", cpu_id);
+		if (need_watchdog){
+			if (utp_mk_devnode("class/misc", "watchdog", "/dev/watchdog", S_IFCHR)){
+				printf("The watchdog is not configured, needed by mx35/mx51/mx53 \n");
+				printf("%d, %s\n", __LINE__, strerror(errno));
+			} else{
+				wdt_fd = open("/dev/watchdog", O_RDWR);
+				/* set the MAX timeout */
+				r = ioctl(wdt_fd, WDIOC_SETTIMEOUT, &watchdog_timeout);
+				if (r)
+					printf("%d, %s\n", __LINE__, strerror(errno));
+				r = pthread_create(&a_thread, NULL, (void *)feed_watchdog, (void *)(&wdt_fd));
+				if (r != 0) {
+					perror("Thread creation failed");
+					exit(EXIT_FAILURE);
+				}
+			}
+		}
+	}
+
+	for(;;) {
+		r = read(u, uc, sizeof(*uc) + 0x10000);
+		if (uc->flags & UTP_FLAG_COMMAND) {
+			answer = utp_handle_command(u, uc->command, uc->payload);
+			if (answer) {
+				printf("UTP: sending %s to kernel for command %s.\n", utp_answer_type(answer), uc->command);
+				write(u, answer, answer->size);
+				free(answer);
+			}
+		}else if (uc->flags & UTP_FLAG_DATA) {
+			write(utp_file, uc->data, uc->bufsize);
+		}else {
+			printf("UTP: Unknown flag %x\n", uc->flags);
+		}
+	}
+
+	/* should never be here */
+	return 0;
+}
+
diff --git a/uuc.patches/uuc-0001-fix-includes.patch b/uuc.patches/uuc-0001-fix-includes.patch
new file mode 100644
index 0000000..3c52ab1
--- /dev/null
+++ b/uuc.patches/uuc-0001-fix-includes.patch
@@ -0,0 +1,12 @@
+diff -Naur a/sdimage.c b/sdimage.c
+--- a/sdimage.c	2014-07-28 10:44:24.900046829 -0700
++++ b/sdimage.c	2014-07-28 10:45:34.108632190 -0700
+@@ -21,6 +21,8 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
++#include <string.h>
++#include <stdlib.h>
+ char *g_filedev;
+ char *g_firmware;
+ 
diff --git a/uuc.url b/uuc.url
new file mode 100644
index 0000000..fd00a19
--- /dev/null
+++ b/uuc.url
@@ -0,0 +1 @@
+https://www.freescale.com/webapp/sps/download/license.jsp?colCode=L3.0.35_4.1.0_ER_SOURCE_BSP&appType=file2&location=null&DOWNLOAD_ID=null
diff --git a/uuc.version b/uuc.version
new file mode 100644
index 0000000..8fc2e4f
--- /dev/null
+++ b/uuc.version
@@ -0,0 +1 @@
+3.0.35-4.1.0