/*----------------------------------------------------------------------------- * File omap3_sload.c * Talk with OMAP3 boot ROM via UART * * (c) 2008 Dirk Behme * * For protocol implemented by this tool see sprufd6.pdf * * http://focus.ti.com/dsp/docs/dspsupporttechdocsc.tsp?sectionId=3&tabId=409&familyId=1526&abstractName=sprufd6 * * Tool based on DaVinci dv_host.c from: * * Win32 console application * (c) 2005 G&W Instruments * Port to Linux * (c) 2007 Dirk Behme * * ---------------------------------------------------------------------------- * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include //#define SHOW_ASICID #define VERSION "0.1" #define INVALID_HANDLE_VALUE 0 #define TIMEOUT_3_SEC 3 #define OMAP3_SRAM_SIZE (64 * 1024) /* OMAP3 has 64kByte SRAM */ #define PERIPHERAL_BOOT_MSG 0xF0030002 /* Continue peripheral booting */ /* ASIC ID */ #define ITEMS_SIZE 1 #define IDSUBBLOCK_SIZE 7 #define SECUREMODESUBBLOCK_SIZE 4 #define PUBLICIDSUBBLOCK_SIZE 23 #define ROOTKEYHASHSUBBLOCK_SIZE 23 #define CHECKSUMSUBBLOCK_SIZE 11 #define GP_SIZE (ITEMS_SIZE + \ IDSUBBLOCK_SIZE + \ SECUREMODESUBBLOCK_SIZE + \ PUBLICIDSUBBLOCK_SIZE + \ ROOTKEYHASHSUBBLOCK_SIZE) #define HS_SIZE (GP_SIZE + CHECKSUMSUBBLOCK_SIZE) static struct { union { unsigned char data[HS_SIZE]; struct { unsigned char items[ITEMS_SIZE]; unsigned char id_sub_block[IDSUBBLOCK_SIZE]; unsigned char secure_mode_subblock[SECUREMODESUBBLOCK_SIZE]; unsigned char public_id_subblock[PUBLICIDSUBBLOCK_SIZE]; unsigned char root_key_hash_subblock[ROOTKEYHASHSUBBLOCK_SIZE]; unsigned char checksum_subblock[CHECKSUMSUBBLOCK_SIZE]; }; }; } asic_id; /*--------------------------------------------------------------------------*/ static int DevHandle = INVALID_HANDLE_VALUE; static void CloseCom(void); static int OpenCom(char * port) { struct termios my_termios; /* make sure port is closed */ CloseCom(); printf("Using port %s to connect to OMAP3", port); /* open Port */ DevHandle = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK); if (DevHandle == INVALID_HANDLE_VALUE) { printf("\nError: Open for %s failed with error: %d: %s\n", port, errno, strerror(errno)); return 0; } my_termios.c_cflag = B115200 | CS8 | CREAD | CLOCAL | PARENB; my_termios.c_iflag = IGNPAR; my_termios.c_oflag = 0; my_termios.c_lflag = 0; my_termios.c_cc[VMIN]=1; my_termios.c_cc[VTIME]=0; tcflush(DevHandle, TCIFLUSH); tcsetattr(DevHandle, TCSANOW, &my_termios); printf(" - okay\n"); return 1; } static void CloseCom(void) { if(DevHandle != INVALID_HANDLE_VALUE) { close(DevHandle); DevHandle = INVALID_HANDLE_VALUE; } } /*--------------------------------------------------------------------------- * Wait for ASIC ID with timeout (in seconds) *--------------------------------------------------------------------------*/ int WaitForASICID(int timeout) { unsigned char c; int cmplen = 0; int rcount = 0; int nread = 0; struct timeval time, stop; unsigned char txbuf[4]; gettimeofday(&time, NULL); stop.tv_sec = time.tv_sec + timeout; while(stop.tv_sec > time.tv_sec) { nread = read(DevHandle,&c,1); if(nread < 0) { nread = 0; } if(nread) { asic_id.data[rcount] = c; if(rcount == 0) { if (asic_id.items[0] == 4) { cmplen = GP_SIZE; } else { cmplen = HS_SIZE; } } rcount++; if(rcount == cmplen) { /* Have to send peripheral boot message within 300ms */ *(unsigned int *)txbuf = PERIPHERAL_BOOT_MSG; write(DevHandle, txbuf, 4); return 1; } } fflush(stdout); usleep(100); gettimeofday(&time, NULL); } return 0; } /*-------------------------------------------------------------------------*/ static void print_usage(char *bin) { printf("Error: Missing option(s)!\n\n"); printf("Usage:\n"); printf("======\n"); printf("%s [port] [target exe]\n", bin); printf("with: [port] : e.g. '/dev/ttyS0'\n"); printf("with: [target exe] : ARM executable to be downloaded to target SRAM\n"); printf("Exiting\n"); } /*-------------------------------------------------------------------------*/ int main(int argc, char ** argv) { unsigned char txbuf[4]; FILE * file; unsigned char *buf; int numread; struct termios newterm, oldterm; int fd = 0, ch = 0; int i; printf("\nTI OMAP3 UART boot ROM tool, version " VERSION "\n"); printf("(c) 2008 Dirk Behme \n\n"); /* Check given parameters */ if(argc != 3) { print_usage(argv[0]); exit(1); } if( !OpenCom(argv[1]) ){ printf("\nError: Failed to open port %s, exiting\n", argv[2]); exit(1); } buf = malloc(OMAP3_SRAM_SIZE); if(!buf) { printf("\nError: Failed to allocate buffer, exiting\n"); CloseCom(); exit(1); } file = fopen(argv[2],"rb"); numread = fread(buf, 1, OMAP3_SRAM_SIZE, file); printf("Read %d bytes from: %s", numread, argv[2]); fclose(file); if(!numread) { printf("\nError: Nothing read, exiting\n"); free(buf); CloseCom(); exit(1); } printf(" - okay\n"); printf("Waiting for ASIC ID from OMAP3 (press key to stop) "); /* Get stdin to handle user abort by keypress */ fd = fileno(stdin); tcgetattr(fd, &oldterm); memcpy(&newterm, &oldterm, sizeof(newterm)); newterm.c_lflag = newterm.c_lflag & (!ICANON); newterm.c_cc[VMIN] = 0; newterm.c_cc[VTIME] = 1; tcsetattr(fd, TCSANOW, &newterm); while(1) { printf("."); if(WaitForASICID(TIMEOUT_3_SEC)) break; if((ch = getchar()) != -1 ) { printf("\nProgram aborted by user, exiting\n"); CloseCom(); free(buf); tcsetattr(fd, TCSANOW, &oldterm); ungetc(ch, stdin); exit(0); } } tcsetattr(fd, TCSANOW, &oldterm); printf(" - okay\n"); #ifdef SHOW_ASICID printf("\nASIC ID found (hex):\nItems: "); for(i=0; i < ITEMS_SIZE; i++) printf("%02x ", asic_id.items[i]); printf("\nID sub block: "); for(i=0; i < IDSUBBLOCK_SIZE; i++) printf("%02x ", asic_id.id_sub_block[i]); printf("\nSecure mode subblock: "); for(i=0; i < SECUREMODESUBBLOCK_SIZE; i++) printf("%02x ", asic_id.secure_mode_subblock[i]); printf("\nPublic ID subblock: "); for(i=0; i < PUBLICIDSUBBLOCK_SIZE; i++) printf("%02x ", asic_id.public_id_subblock[i]); printf("\nRoot key hash subblock: "); for(i=0; i < ROOTKEYHASHSUBBLOCK_SIZE; i++) printf("%02x ", asic_id.root_key_hash_subblock[i]); if (asic_id.items[0] == 5) { printf("\nChecksum subblock: "); for(i=0; i < CHECKSUMSUBBLOCK_SIZE; i++) printf("%02x ", asic_id.checksum_subblock[i]); } printf("\n\n"); #endif /* SHOW_ASICID */ printf("Checking for OMAP3 ID "); if((asic_id.id_sub_block[3] != 0x34) || (asic_id.id_sub_block[4] != 0x30)) { printf("\nError: Unknown OMAP3 boot ROM ID! Found 0x%02x%02x -> " \ "Expecting 0x3430\n", asic_id.id_sub_block[3], asic_id.id_sub_block[4]); CloseCom(); free(buf); exit(1); } printf(" - okay\n"); printf("Sending image size "); *(unsigned int *)txbuf = numread; write(DevHandle, txbuf, 4); printf(" - okay\n"); usleep(1); /* Wait a moment, here we have 1 min time */ printf("Sending image "); for(i = 0; i < numread; i += 4) { *(unsigned int *)txbuf = *(unsigned int *)&buf[i]; write(DevHandle, txbuf, 4); fflush(stdout); usleep(1); } printf(" - okay\n"); printf("OMAP3 serial boot ROM download finished - Bye\n"); CloseCom(); return 0; }