source: tt-loader/main.c @ 11

Last change on this file since 11 was 11, checked in by guillaume, 16 years ago

Publication tt-loader v0.1

File size: 14.5 KB
Line 
1/*
2 * tt-loader - A system loader through USB derived from OMAP Flash Loader
3 *
4 * Copyright (C) 2008 Guillaume Bougard <gbougard@pkg.fr>
5 * Copyright (C) 2005 Luis Recuerda <lrec@helios.homeip.net>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 */
22
23#include <stdio.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <sys/times.h>
29#include <fcntl.h>
30#include <usb.h>
31#include <endian.h>
32#include <byteswap.h>
33#include <errno.h>
34
35/*
36 * Here Vendor/Product detected for the target device
37 */
38#define OMAP_VENDOR             0x0451
39#define OMAP_PRODUCT    0x3f01
40
41#define IN_EP   0x81
42#define OUT_EP  0x02
43
44/*
45 * Length of memory dump done by 2nd.bin
46 */
47#define MEM_READ_SIZE           32
48
49struct mem_file {
50        void *content ;
51        int size ;
52};
53
54#define MAX_SIZE        65536
55static char     buffer[MAX_SIZE + 128];
56static int      buffsize = 0;
57static struct mem_file cmdfile = { NULL, 0 };
58static double btime ;
59static double ticks ;
60
61#define log1(X)         fprintf(stderr, "%9.3f: "X,((double)times(NULL)-btime)/ticks)
62#define log2(X,Y)       fprintf(stderr, "%9.3f: "X,((double)times(NULL)-btime)/ticks,Y)
63#define log3(X,Y,Z)     fprintf(stderr, "%9.3f: "X,((double)times(NULL)-btime)/ticks,Y,Z)
64
65#if __BYTE_ORDER == __LITTLE_ENDIAN
66# define cpu_to_le32(x) (x)
67# define le32_to_cpu(x) (x)
68#else
69# define cpu_to_le32(x) bswap_32 (x)
70# define le32_to_cpu(x) bswap_32 (x)
71#endif
72
73static inline unsigned do_div (unsigned v, unsigned d)
74{
75        v+= --d;
76        return v & ~d;
77}
78
79static int stringcopy( char * dest, const char *src, int max )
80{
81        char *tmp = dest, *s = (char *) src;
82        int count = 0 ;
83       
84        while (count++ < max)
85                if (!(*tmp++ = *s++ ))
86                        break ;
87       
88        return count;
89}
90
91static int send_cmd (usb_dev_handle *handle, const char req, const char *src)
92{
93        int     res, len = 5 ;
94        char buffer[64];
95       
96        buffer[0]= 'T';
97        buffer[1]= 'I';
98        buffer[2]= 'S';
99        buffer[3]= req ;
100        buffer[4]= '\0' ;
101        if (src!=NULL)
102                len += stringcopy (&buffer[4], src, 60);
103        buffer[63]= '\0' ; // truncate anyway
104       
105        res= usb_bulk_write (handle, OUT_EP, buffer, len, 1000);
106        if (res < len)
107        {
108                fprintf (stderr, "Error in usb_bulk_write during send_char: %d/4\n", res);
109                return 0;
110        }
111       
112        return 1;
113}
114
115static int send_binsize (usb_dev_handle *handle, int sz)
116{
117        int     res;
118        char    buffer[8];
119        buffer[0]= 'T';
120        buffer[1]= 'I';
121        buffer[2]= 'S';
122        buffer[3]= 's';
123        *(u_int32_t *) &buffer[4]= cpu_to_le32 ((sz>4096)?4096:sz);
124       
125        res= usb_bulk_write (handle, OUT_EP, buffer, 8, 1000);
126        if (res < 8)
127        {
128                fprintf (stderr, "Error in usb_bulk_write during send_binsize: %d/8\n", res);
129                return 0;
130        }
131       
132        return 1;
133}
134
135static int send_address (usb_dev_handle *handle, int addr)
136{
137        int     res;
138        char    buffer[8];
139        buffer[0]= 'T';
140        buffer[1]= 'I';
141        buffer[2]= 'S';
142        buffer[3]= 'a';
143        *(u_int32_t *) &buffer[4]= cpu_to_le32 (addr);
144       
145        res= usb_bulk_write (handle, OUT_EP, buffer, 8, 1000);
146        if (res < 8)
147        {
148                fprintf (stderr, "Error in usb_bulk_write: %d/8\n", res);
149                return 0;
150        }
151       
152        return 1;
153}
154
155static struct mem_file readfile( const char *filename )
156{
157        struct mem_file toread = { NULL, 0 };
158        int fd= open (filename, O_RDONLY);
159       
160        if (fd < 0)
161        {
162                fprintf (stderr, "Error opening %s file\n", filename);
163                return toread;
164        }
165       
166        toread.size = lseek (fd, 0, SEEK_END);
167        if (toread.size < 0  ||  lseek (fd, 0, SEEK_SET) < 0)
168        {
169                fprintf (stderr, "Error with lseek other %s file\n", filename);
170                close (fd);
171                return toread;
172        }
173       
174        toread.content= malloc (do_div (toread.size, 4));
175        if (toread.content == NULL)
176        {
177                fprintf (stderr, "Out of memory requesting %d bytes\n", toread.size);
178                close (fd);
179                return toread;
180        }
181       
182        if ((toread.size= read (fd, toread.content, toread.size)) < 0)
183        {
184                fprintf (stderr, "Error reading %s file\n", filename);
185                close (fd);
186                return toread;
187        }
188       
189        close (fd);
190       
191        return toread ;
192}
193
194static int process (usb_dev_handle *handle)
195{
196        int     err = -1 ;
197       
198        log1("OMAP found, trying to configure it\n");
199       
200        for (;;)
201        {
202                err= usb_set_configuration (handle, 1);
203                if (err == 0)
204                        break;
205               
206                if (err == -ENODEV)
207                {
208                        log1("OMAP error, retrying\n");
209                        return 1;
210                }
211               
212                sleep (1);
213        }
214       
215        err = usb_claim_interface (handle, 0);
216        if ( err < 0)
217                log2("Error in usb_claim_interface (%d)\n",err);
218        else
219        {
220                char    inbuff[256];
221                int     insize= usb_bulk_read (handle, IN_EP,
222                        inbuff, sizeof (inbuff), 5000);
223               
224                if (insize < 48)
225                        log2("Error in usb_bulk_read: %d\n", insize);
226                else
227                {
228                        log1("OMAP 1st boot contacted, sending 2nd boot\n");
229                       
230                        memcpy (&buffer[20], inbuff, 44);
231                        memcpy (&buffer[80], inbuff, 48);
232                       
233                        char *p = buffer;
234                        int     size= buffsize;
235                        while (size > 0)
236                        {
237                                int     outsize= usb_bulk_write (handle, OUT_EP, p, 64, 5000);
238                                if (outsize < 64)
239                                {
240                                        log2("Error in usb_bulk_write: %d/64\n", outsize);
241                                        break;
242                                }
243
244                                p+= 64;
245                                size-= 64;
246                        }
247                       
248                        if (size <= 0)
249                        {
250                                log2("Sent %d bytes to OMAP\n",buffsize);
251                                usb_bulk_write (handle, OUT_EP, buffer, 0, 1000);
252                               
253                                p= NULL;
254                                size= 0;
255                               
256                                int     res=1, sz= 0, loop= 1, cmd=0 ;
257                                int vendor, device, info ;
258                                char *cmdp = cmdfile.content ;
259                                struct mem_file current = { NULL, 0 };
260                               
261                                err = 1 ; // Set error by default
262                               
263                                while (loop != 0)
264                                {
265                                        if (loop<0) loop++ ; // Avoid infinite loop
266                                       
267                                        if (res>0)
268                                                res= usb_bulk_read (handle, IN_EP,
269                                                        inbuff, sizeof (inbuff), 5000);
270                                       
271                                        if (res < 0)
272                                        {
273                                                log2("Error in usb_bulk_read: %d\n",res);
274                                                break;
275                                        }
276                                       
277                                        if (res >= 4)
278                                        {
279                                                if (inbuff[0] == 'T'  &&  inbuff[1] == 'I'  &&
280                                                        inbuff[2] == 'S')
281                                                {
282                                                        switch (inbuff[3])
283                                                        {
284                                                        case 'f':
285                                                                // Target claims a file
286                                                                log3("OMAP File asked: %s (%d bytes)\n", &inbuff[4], size);
287                                                                if (!send_binsize (handle, size))
288                                                                        loop = 0 ; // Just quit on error
289                                                                break;
290                                                               
291                                                        case 'o':
292                                                                // Update upload file buffer offset
293                                                                sz= le32_to_cpu (*(u_int32_t *) &inbuff[4]);
294                                                                p+= sz;
295                                                                size-= sz;
296                                                                //log3("OMAP seek %d to 0x%08lX\n", sz, (long)p-(long)current.content);                                         // DEBUG
297                                                                if (size > 0  &&  !send_binsize (handle, size))
298                                                                        loop = 0 ; // Just quit on error
299                                                                if (size==0)
300                                                                        res = 0 ;
301                                                                break;
302                                                               
303                                                        case 'n':
304                                                                // Upload a requested size chunk from the file buffer
305                                                                sz= le32_to_cpu (*(u_int32_t *) &inbuff[4]);
306                                                                //log2("OMAP read %d\n", sz);                                   // DEBUG
307                                                                res= usb_bulk_write (handle, OUT_EP, p, sz, 5000);
308                                                                if (res < sz)
309                                                                {
310                                                                        log3("Error in usb_bulk_write: %d/%d\n", res, sz);
311                                                                        loop = 0 ; // Just quit on error
312                                                                }
313                                                                break;
314                                                               
315                                                        case 'I':
316                                                                info = le32_to_cpu (*(u_int32_t *) &inbuff[4]);
317                                                                log2("OMAP integer info: %d\n", info);
318                                                                break;
319                                                               
320                                                        case 'A':
321                                                                info = le32_to_cpu (*(u_int32_t *) &inbuff[4]);
322                                                                log2("OMAP address info: 0x%08X\n", info);
323                                                                break;
324                                                               
325                                                        case 'i':
326                                                                info = le32_to_cpu (*(u_int32_t *) &inbuff[4]);
327                                                                log2("OMAP Info returned: 0x%08X\n", info);
328                                                                res = 0 ; // Target is waiting a new command
329                                                                break;
330                                                               
331                                                        case 'v':
332                                                                vendor= le32_to_cpu (*(u_int32_t *) &inbuff[4]);
333                                                                log2("Flash Vendor found: 0x%02X\n", vendor);
334                                                                break;
335                                                               
336                                                        case 'd':
337                                                                device= le32_to_cpu (*(u_int32_t *) &inbuff[4]);
338                                                                log2("Flash Device found: 0x%02X\n", device);
339                                                                break;
340                                                               
341                                                        case 'm':
342                                                                log2("OMAP Message: %s\n", &inbuff[4]);
343                                                                break;
344                                                               
345                                                        case 'M':
346                                                                loop=3 ;
347                                                                log2("0x%08X | ",info);
348                                                                while (++loop<36)
349                                                                        fprintf (stderr,"%02hhX", inbuff[loop]);
350                                                                loop=3 ;
351                                                                fprintf (stderr, " |");
352                                                                while (++loop<36)
353                                                                        if ((int)inbuff[loop]>=0x20 && (int)inbuff[loop]<0x7f)
354                                                                                fprintf (stderr,"%c", inbuff[loop]);
355                                                                        else
356                                                                                fprintf (stderr,".");
357                                                                fprintf (stderr,"|\n");
358                                                                res = 0 ; // Target is waiting a new command
359                                                                info += 32 ;
360                                                                break;
361                                                               
362                                                        case 'r':
363                                                                log2("OMAP is ready: %s\n", &inbuff[4]);
364                                                                res = 0 ; // Target is waiting a new command
365                                                                break;
366
367                                                        case 'b':
368                                                                // Boot command has been received
369                                                                info = le32_to_cpu (*(u_int32_t *) &inbuff[4]);
370                                                                log2("OMAP is booting at address: 0x%08X\n", info);
371                                                                res = 0 ; // Target is waiting a new command
372                                                                break;
373
374                                                        default:
375                                                                log2("Unknown packet type '%c'\n", inbuff[3]);
376                                                                break;
377                                                        }
378                                                } else {
379                                                        // Fix the string just in case
380                                                        inbuff[res] = '\0' ;
381                                                        log2("Got: %s\n", inbuff);
382                                                }
383                                        }
384                                        else
385                                        {
386                                                // Manage commands
387                                                if (cmd + 1 >= cmdfile.size)
388                                                {
389                                                        if (loop>0) {
390                                                                log1("Command file read finished\n");
391                                                                loop = 0 ;
392                                                        }
393                                                       
394                                                } else {
395                                                        // res < 4
396                                                        //log2("Next command is '%c'\n", cmdp[cmd]);                    // DEBUG
397                                                        switch (cmdp[cmd])
398                                                        {
399                                                        case 'f': // Put a file to be uploaded in a memory buffer
400                                                                cmd += 2 ;
401                                                                if (cmd >= cmdfile.size || cmdp[cmd] == '\0')
402                                                                {
403                                                                        log1("Bad 'f' format in command file\n");
404                                                                        break ;
405                                                                }
406                                                                // Free previously used memory buffer
407                                                                if (current.content != NULL)
408                                                                        free((void *)current.content);
409                                                                current = readfile((const char *)&cmdp[cmd]);
410                                                                if (current.content == NULL)
411                                                                {
412                                                                        log2("Can't read file '%s'\n",&cmdp[cmd]);
413                                                                        loop = 0 ; // Just quit on error
414                                                                }
415                                                                p = current.content ;
416                                                                size = current.size ;
417                                                                // Say to OMAP target it can reclaim the file
418                                                                if (send_cmd (handle,'f',(const char *)&cmdp[cmd]))
419                                                                        log1("File loaded and ready for upload\n");
420                                                                else
421                                                                {
422                                                                        log1("Can't say we are ready for upload\n");
423                                                                        // Just quit on error
424                                                                        loop = 0 ;
425                                                                }
426                                                                break;
427                                                        case 'a': // Get an address and send it to target
428                                                                cmd += 2 ;
429                                                                if (sscanf((const char *)&cmdp[cmd], "%i", &info) != 1)
430                                                                {
431                                                                        log2("Can't read address '%s'\n",&cmdp[cmd]);
432                                                                        loop = 0 ; // Just quit on error
433                                                                }
434                                                                if (send_address (handle, info))
435                                                                        log2("Sending address 0x%02X\n", info);
436                                                                else
437                                                                {
438                                                                        log2("Can't send address 0x%02X\n", info);
439                                                                        loop = 0 ; // Just quit on error
440                                                                }
441                                                                break;
442                                                        case 'M': // Ask memory dump
443                                                                if (!(send_cmd (handle,'M',NULL)))
444                                                                {
445                                                                        log1("Can't ask to read memory\n");
446                                                                        loop = 0 ; // Just quit on error
447                                                                }
448                                                                break;
449                                                        case 'c': // Make a call to the last given address
450                                                                if (send_cmd (handle,'c',NULL))
451                                                                        log1("Asking function call\n");
452                                                                else
453                                                                {
454                                                                        log1("Can't ask to call a function\n");
455                                                                        loop = 0 ; // Just quit on error
456                                                                }
457                                                                break;
458                                                        case 'b': // Boot the target by just branching to the last given address
459                                                                if (send_cmd (handle,'b',NULL))
460                                                                        log1("Asking boot\n");
461                                                                else
462                                                                {
463                                                                        log1("Can't ask to boot\n");
464                                                                        loop = 0 ; // Just quit on error
465                                                                }
466                                                                break;
467                                                        case 'e': // End of commands
468                                                                log1("Commands read and sent\n");
469                                                                // Quit now witout error set
470                                                                loop = err = 0 ;
471                                                                cmd = cmdfile.size ;
472                                                                res = 1 ;
473                                                                break ;
474                                                        case '#':
475                                                        case '/':
476                                                                // skip comments
477                                                                res -- ;
478                                                                break ;
479                                                               
480                                                        default:
481                                                                log2("Unknown command type '%c'\n",cmdp[cmd]);
482                                                                break;
483                                                        }
484                                                        // kind of readline
485                                                        while (cmdp[++cmd] != '\0' && cmd < cmdfile.size);
486                                                        // point to next line
487                                                        while (cmdp[++cmd] == '\0' && cmd < cmdfile.size);
488                                                        res ++ ;
489                                                }
490                                        }
491                                }
492                        }
493                }
494        }
495       
496        if (err>=0) {
497                err = usb_release_interface (handle, 0);
498                if (err < 0)
499                        log2("Error in usb_release_interface (%d)\n",err);
500        }
501       
502        return err ;
503}
504
505enum {
506        ARG_PROGNAME,
507        ARG_2NDFILE,
508        ARG_CMDFILE,
509        NUM_ARGS
510};
511
512int main (int argc, char *argv[])
513{
514        int     size;
515        btime = (double) times(NULL);
516        ticks = (double) sysconf(_SC_CLK_TCK) / 1000 ;
517       
518        if (argc < NUM_ARGS)
519        {
520                log2("Usage: %s <2nd_boot_file> <command_file>\n", argv[ARG_PROGNAME]);
521                return 1;
522        }
523       
524        memset (buffer, 0, 128);
525       
526        u_int32_t       *p= (u_int32_t *) buffer;
527        p[0x00]= cpu_to_le32 (0xf0030002);
528       
529        int     fd= open (argv[ARG_2NDFILE], O_RDONLY);
530        if (fd < 0)
531        {
532                log1("open 2nd boot file\n");
533                return 1;
534        }
535        else
536        {
537                size= read (fd, &buffer[128], MAX_SIZE);
538                if (size < 0)
539                {
540                        log1("read 2nd boot file\n");
541                        close (fd);
542                        return 1;
543                }
544               
545                close (fd);
546                if (size < 1024)
547                {
548                        log2("2ndfile is too small! (%d bytes)\n", size);
549                        return 1;
550                }
551        }
552       
553        size= do_div (size, 4);
554       
555        p[0x21]= cpu_to_le32 (size - 0x40);
556       
557        p[0x01]= cpu_to_le32 (size);
558        p[0x02]= cpu_to_le32 (size);
559        p[0x03]= cpu_to_le32 (size);
560        p[0x10]= cpu_to_le32 (size);
561        p[0x11]= cpu_to_le32 (size);
562        p[0x12]= cpu_to_le32 (size);
563       
564        buffsize= 128 + do_div (size, 4);
565       
566        cmdfile = readfile(argv[ARG_CMDFILE]);
567        if (cmdfile.content == NULL)
568        {
569                log1("open cmdfile\n");
570                return 1;
571        } else {
572                int i = 0 ;
573                char *cmdbuffer = (char *)cmdfile.content ;
574                do {
575                        if (cmdbuffer[i] == '\n' || cmdbuffer[i] == '\r' || cmdbuffer[i] == ';')
576                                cmdbuffer[i] = '\0' ;
577                } while ( i++ < cmdfile.size );
578        }
579       
580        usb_init ();
581        usb_find_busses ();
582       
583        log1("Try to found OMAP730-USB connection\n");
584       
585        int     n= usb_find_devices ();
586        if (n)
587        {
588                log1("Searching OMAP730-USB connection...\n");
589                struct usb_bus  *bus;
590                for (bus= usb_get_busses (); bus; bus= bus->next)
591                {
592                        struct usb_device       *dev;
593                       
594                        for (dev= bus->devices; dev; dev= dev->next)
595                        {
596                                usb_dev_handle  *handle;
597                                if (dev->descriptor.idVendor == OMAP_VENDOR  &&
598                                        dev->descriptor.idProduct == OMAP_PRODUCT  &&
599                                        (handle= usb_open (dev)) != NULL)
600                                {
601                                        log1("Found OMAP730-USB connection\n");
602                                        int res= process (handle);
603                                        usb_close (handle);
604                                        if (res == 0) {
605                                                log1("OMAP730-USB connection processed\n");
606                                                return 0 ;
607                                        } else
608                                                log1("OMAP730-USB processing failed\n");
609                                }
610                        }
611                }
612               
613        } else {
614                log1("No USB bus found\n");
615        }
616       
617        // Free memory
618        if (cmdfile.content!=NULL)
619                free((void *)cmdfile.content);
620       
621        log1("No target connection found\n");
622        return 1 ;
623}
Note: See TracBrowser for help on using the repository browser.