source: tt-loader/2nd/main.c @ 12

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

Publication tt-loader v0.2

File size: 9.2 KB
Line 
1/*
2 * 2nd - OMAP "second stage" tt-loader
3 *
4 * Copyright (C) 2008 Guillaume Bougard <gbougard@pkg.fr>
5 * Copyright (C) 2005 Luis Recuerda <lrec@helios.homeip.net>
6 *
7 * ARM kernel loader. Adapt from qemu-neo1973
8 * Copyright (c) 2006-2007 CodeSourcery.
9 * Written by Paul Brook
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24 *
25 */
26
27#include "config.h"
28#include "usb.h"
29
30extern u32 crc32( u32 crc, char* buf, u32 len, crc_cb_fnc_t* cb);
31
32/*
33 * Length of memory dump done by 2nd.bin, must be a multiple of DUMP_LINE_SIZE from host main.c
34 * Must also be sufficient to output lines of text, let's say 128 bytes
35 */
36#define MEM_READ_SIZE   128*32
37#define CHUNK_SIZE              8192
38
39static char *usb_hdr = "TIS" ;
40static char usb_outbuffer[MEM_READ_SIZE+4];
41
42static u32 strcpy ( char *dest, char *src )
43{
44        u32 count = 0 ;
45        char *tmp = dest, *s = src;
46       
47        while ( ++count < MEM_READ_SIZE && *s != '\0' )
48                *tmp++ = *s++ ;
49       
50        *tmp = '\0' ;
51       
52        return count ;
53}
54
55static u32 strlen ( char *src )
56{
57        u32 len = 0 ;
58       
59        while ( *src != '\0' ) {
60                src++ ;
61                len ++ ;
62        }
63       
64        return len ;
65}
66
67static u32 memcpy ( char *dest, char *src, u32 count )
68{
69        char *tmp = dest, *s = src;
70        u32 step = count ;
71
72        while (step--)
73                *tmp++ = *s++;
74       
75        return count ;
76}
77
78static void usb_msg (const char cmd, const char *msg)
79{
80        u32 len = strcpy(usb_outbuffer,usb_hdr);
81        usb_outbuffer[len-1] = cmd ;
82       
83        len += strcpy(&usb_outbuffer[len], msg ? (char *)msg : "" );
84
85        usb_send ( usb_outbuffer, len);
86        while (!usb_sent ());
87}
88
89static u32 usb_code (char cmd, u32 code)
90{
91        u32 len = strcpy(usb_outbuffer,usb_hdr);
92        usb_outbuffer[len-1] = cmd ;
93        (*(u32 *)(usb_outbuffer+len)) = code ;
94        len += sizeof(u32);
95
96        usb_send ( usb_outbuffer, len );
97        while (!usb_sent ());
98        return code ;
99}
100
101static void usb_blk (const char cmd, char *mem, u32 size)
102{
103        u32 len = strcpy(usb_outbuffer,usb_hdr);
104        usb_outbuffer[len-1] = cmd ;
105
106        len += memcpy(usb_outbuffer+len,mem,size);
107       
108        usb_send ( usb_outbuffer, len );
109        while (!usb_sent ());
110}
111
112// Code from linux-2.6.24.3/arch/arm/mach-omap1/id.c source
113static u16 omap_get_jtag_id(void)
114{
115        u32 prod_id, jtag_id;
116
117        prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
118        jtag_id = omap_readl(OMAP32_ID_1);
119       
120        /* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
121        if (((prod_id >> 20) == 0) || (prod_id == jtag_id))
122                prod_id = 0;
123        else
124                prod_id &= 0xffff;
125
126        if (prod_id)
127                return prod_id;
128
129        /* Use OMAP32_ID_1 as fallback */
130        prod_id = ((jtag_id >> 12) & 0xffff);
131
132        return prod_id;
133}
134
135// stl_raw is qemu related
136#define stl_raw(x,v) *(u32 *)(x) = v
137static void set_kernel_args(u32 ram_size, int initrd_size, const char *kernel_cmdline, u32 ram_start)
138{
139    u32 *p;
140       
141        // Set pointer to kernel params
142    p = (u32 *)(CFG_PARAMADDR);
143       
144    /* ATAG_CORE */
145    stl_raw(p++, 5);
146    stl_raw(p++, 0x54410001);
147    stl_raw(p++, 0); // 0 = ro ; 1= rw
148    stl_raw(p++, 0x1000); // Page size
149    stl_raw(p++, 0); // root device overrided by cmdline
150    /* ATAG_MEM */
151    stl_raw(p++, 4);
152    stl_raw(p++, 0x54410002);
153    stl_raw(p++, ram_size);
154    stl_raw(p++, ram_start);
155    if (initrd_size) {
156        /* ATAG_INITRD2 */
157        stl_raw(p++, 4);
158        stl_raw(p++, 0x54420005);
159        stl_raw(p++, ram_start + INITRD_LOAD_ADDR);
160        stl_raw(p++, initrd_size);
161    }
162    if (kernel_cmdline && *kernel_cmdline) {
163        /* ATAG_CMDLINE */
164        int cmdline_size;
165
166        cmdline_size = strlen((char *)kernel_cmdline);
167        memcpy ((char *)p + 2, (char *)kernel_cmdline, cmdline_size + 1);
168        cmdline_size = (cmdline_size >> 2) + 1;
169        stl_raw(p++, cmdline_size + 2);
170        stl_raw(p++, 0x54410009);
171        p += cmdline_size;
172    }
173    /* ATAG_END */
174    stl_raw(p++, 0);
175    stl_raw(p++, 0);
176}
177
178#define C1_DC           (1<<2)          /* dcache off/on */
179#define C1_IC           (1<<12)         /* icache off/on */
180
181void cleanup_before_linux (void)
182{
183        /*
184         * this function is called just before we call linux
185         * it prepares the processor for linux
186         *
187         * we turn off caches etc ...
188         */
189
190        unsigned long i;
191
192        /* turn off I/D-cache */
193        asm ("mrc p15, 0, %0, c1, c0, 0":"=r" (i));
194        i &= ~(C1_DC | C1_IC);
195        asm ("mcr p15, 0, %0, c1, c0, 0": :"r" (i));
196
197        /* flush I/D-cache */
198        i = 0;
199        asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
200}
201
202void usb_crc32_pos( u32 pos, u32 total, u32 crc )
203{
204        u32 len = strcpy(usb_outbuffer,usb_hdr);
205        usb_outbuffer[len-1] = 'x' ;
206        (*(u32 *)(usb_outbuffer+len)) = pos ;
207        len += sizeof(u32);
208        (*(u32 *)(usb_outbuffer+len)) = total ;
209        len += sizeof(u32);
210        (*(u32 *)(usb_outbuffer+len)) = crc ;
211        len += sizeof(u32);
212        usb_send ( usb_outbuffer, len );
213        while (!usb_sent ());
214}
215
216u32 _main (void)
217{       
218        u32 params = CFG_PARAMADDR ;
219        u32 address = CFG_LOADADDR ;
220        u32 crc = 0 ;
221        usb_msg ('m', "In omap plateform");
222       
223        u16 prod_id = omap_get_jtag_id();
224        switch (prod_id)
225        {
226                case 0xb55f:
227                        usb_msg ('m', "Found supported omap730");
228                        break;
229                default:
230                        usb_msg ('m', "Unsupported plateform found");
231                        usb_code ('v', (u32) prod_id);
232                        break;
233        }
234       
235        // Ready to manage requests
236        usb_msg ('r', "Waiting first request");
237       
238        for (;;)
239        {
240                u32 total, cmd, index = 0 ;
241               
242                u8 usb_inbuffer[CHUNK_SIZE];
243                usb_recv (usb_inbuffer, sizeof (usb_inbuffer));
244                while (!usb_rcvd ());
245               
246                // Check we are knowing the provided header
247                while ( usb_inbuffer[index] == (u8) usb_hdr[index] && usb_hdr[index] != '\0' )
248                        index++ ;
249               
250                if ( usb_hdr[index] != '\0' )
251                        continue ;
252               
253                cmd = usb_inbuffer[index++] ;
254               
255                if ((char)cmd == 's') // Ask size to upload
256                {
257                        total= *(u32 *) &usb_inbuffer[index];
258                        u32 size = 0;
259
260                        usb_code ('n', total);
261
262                        while (size < total)
263                        {
264                                u32     r;
265                               
266                                usb_recv ((u8 *)address, sizeof (usb_inbuffer));
267                                while ((r= usb_rcvd ()) == 0);
268                                                               
269                                address += r ;
270                                size += r ;
271                        }
272                       
273                        usb_code ('o', size);
274                       
275                } else
276                if ((char)cmd == 'C') // set crc32 value for next download
277                {
278                        crc = *(u32 *) &usb_inbuffer[index];
279                        usb_code ('i', crc);
280                       
281                } else
282                if ((char)cmd == 'm') // Download size from memory
283                {
284                        total= *(u32 *) &usb_inbuffer[index];
285                        u32 size = 0;
286                       
287                        usb_code ('I', total);
288                       
289                        // Check crc32 if it has been set
290                        if (total && crc)
291                        {
292                                crc_cb_fnc_t* cb = NULL ;
293                                if (total>1024*1024)
294                                        cb = &usb_crc32_pos ;
295                                u32 foundcrc = crc32(0, (char *)address,total,cb) ;
296                                usb_code ('C', foundcrc);
297                                // Skip download on crc match
298                                if (foundcrc == crc)
299                                        total = 0 ;
300                        }
301                       
302                        if (total == 0)
303                                usb_blk ('D', (char *)address, 0);
304                       
305                        while (size < total)
306                        {
307                                u32 bs = MEM_READ_SIZE ;
308                                if ( total - size < MEM_READ_SIZE)
309                                        bs = total - size ;
310                                usb_blk ('D', (char *)address, bs);
311                                address += bs ;
312                                size += bs ;
313                        }
314                       
315                        // reset crc for next download anyway
316                        crc = 0 ;
317                       
318                } else
319                if ((char)cmd == 'e') // End, just loop
320                {
321                        usb_reset();
322                       
323                } else
324                if ((char)cmd == 'f') // load file ACK
325                {
326                        usb_msg ('f', (const char *)&usb_inbuffer[index]);
327                       
328                } else
329                if ((char)cmd == 'M') // dump memory command
330                {
331                        usb_blk ('M', (char *)address, MEM_READ_SIZE);
332                        address += MEM_READ_SIZE ;
333                       
334                } else
335                if ((char)cmd == 'a') // set address command
336                {
337                        address = *(u32 *) &usb_inbuffer[index];
338                        usb_code ('i', address);
339                       
340                } else
341                if ((char)cmd == 'p') // do a poke on address
342                {
343                        u32 size = memcpy( (char *) address, (char *) &usb_inbuffer[index], 4);
344                        address += size ;
345                        usb_code ('i', address );
346                       
347                } else
348                if ((char)cmd == 'P') // do a peek on address
349                {
350                        usb_code ('i', *(u32 *) address );
351                        address += 4 ;
352                       
353                } else
354                if ((char)cmd == 'c') // call command
355                {
356                        __asm__ __volatile__ (
357                                                "mov r0, #0     ;"
358                                                "mov r1, #0     ;"
359                                                "mov r2, #0     ;"
360                                                "ldr r3, %1     ;"
361                                                "blx r3         ;"
362                                                "mov %0, r0     ;"
363                                                : "=r"(index) : "m"(address) : "r0", "r1", "r2", "r3"
364                                                );
365                        usb_code ('i', index);
366                       
367                } else
368                if ((char)cmd == 'b') // boot command
369                {
370                        usb_code ('b', address );
371                        usb_reset();
372                        __asm__ __volatile__ (
373                                                "ldr r0, %0     ;"
374                                                "mov pc, r0     ;"
375                                                : : "m"(address)
376                                                );
377                       
378                } else
379                if ((char)cmd == 'k') // boot kernel command
380                {
381                        int machid =  * (int *) &usb_inbuffer[index];
382                        usb_code ('I', machid);
383                        set_kernel_args( RAM_SIZE, INITRD_SIZE, KERNEL_CMDLINE, CFG_BASESDRAM );
384                        usb_code ('b', address );
385                        usb_reset();
386                        cleanup_before_linux();
387                        __asm__ __volatile__ (
388                                                "mov r0, #0     ;"
389                                                "ldr r1, %0     ;"
390                                                "ldr r2, %1     ;"
391                                                "mov r3, #0     ;"
392                                                "mov r4, #0     ;"
393                                                "ldr r5, %2     ;"
394                                                "mov pc, r5     ;"
395                                                : : "m" (machid), "m"(params), "m"(address)
396                                                );
397                } else
398                if ((char)cmd == 'S') // Stack command
399                {
400                        __asm__ __volatile__ (
401                                                "ldr fp, %0     ;"
402                                                "sub fp, #4 ;"
403                                                "mov sp, fp     ;"
404                                                "sub sp, #256 ;"
405                                                : : "m"(address)
406                                                );
407                        usb_code ('i', address);
408                       
409                }
410        }
411}
Note: See TracBrowser for help on using the repository browser.