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