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