Changeset 12 for tt-loader/2nd/main.c


Ignore:
Timestamp:
May 23, 2008, 12:59:00 PM (16 years ago)
Author:
guillaume
Message:

Publication tt-loader v0.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tt-loader/2nd/main.c

    r11 r12  
    44 * Copyright (C) 2008 Guillaume Bougard <gbougard@pkg.fr>
    55 * 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
    610 *
    711 * This program is free software; you can redistribute it and/or
     
    2428#include "usb.h"
    2529
    26 #define _LSR_   ((volatile u8 *) 0xfffb0014)
    27 #define _THR_   ((volatile u8 *) 0xfffb0000)
    28 #define _RHR_   ((volatile u8 *) 0xfffb0000)
    29 
    30 #define MEM_READ_SIZE   32
     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
    3138
    3239static char *usb_hdr = "TIS" ;
    33 static char usb_outbuffer[64];
    34 
    35 // limited strcpy
     40static char usb_outbuffer[MEM_READ_SIZE+4];
     41
    3642static u32 strcpy ( char *dest, char *src )
    3743{
     
    3945        char *tmp = dest, *s = src;
    4046       
    41         while ( ++count < 256 && *s != '\0' )
     47        while ( ++count < MEM_READ_SIZE && *s != '\0' )
    4248                *tmp++ = *s++ ;
    4349       
     
    4551       
    4652        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 ;
    4765}
    4866
     
    5674       
    5775        return count ;
    58 }
    59 
    60 static void bsend (char ch)
    61 {
    62         while (!((*_LSR_) & 0x20));
    63         *_THR_= ch;
    64 }
    65 
    66 static inline int check_serial (void) { return (*_LSR_) & 0x01; }
    67 
    68 static char brecv (void)
    69 {
    70         while (!((*_LSR_) & 0x01));
    71         return *_RHR_;
    72 }
    73 
    74 char crecv (void)
    75 {
    76         return brecv ();
    77 }
    78 
    79 void csend (char ch)
    80 {
    81         if (ch == '\n')
    82                 bsend ('\r');
    83         bsend (ch);
    84 }
    85 
    86 void tsend (const char *text)
    87 {
    88         while (*text)
    89                 csend (*text++);
    90 }
    91 
    92 void xsend (unsigned value)
    93 {
    94         if (value < 10)
    95                 bsend (value + '0');
    96         else
    97                 bsend (value + ('A'-10));
    98 }
    99 
    100 void x8send (u8 value)
    101 {
    102         xsend (value >> 4);
    103         xsend (value & 0xf);
    104 }
    105 
    106 void x16send (u16 value)
    107 {
    108         int     i;
    109         for (i= 0; i < 4; ++i)
    110         {
    111                 xsend (value >> 12);
    112                 value<<= 4;
    113         }
    114 }
    115 
    116 void x32send (u32 value)
    117 {
    118         int     i;
    119         for (i= 0; i < 8; ++i)
    120         {
    121                 xsend (value >> 28);
    122                 value<<= 4;
    123         }
    12476}
    12577
     
    181133}
    182134
     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
    183216u32 _main (void)
    184217{       
     218        u32 params = CFG_PARAMADDR ;
    185219        u32 address = CFG_LOADADDR ;
     220        u32 crc = 0 ;
    186221        usb_msg ('m', "In omap plateform");
    187222       
     
    205240                u32 total, cmd, index = 0 ;
    206241               
    207                 u8 usb_inbuffer[64];
     242                u8 usb_inbuffer[CHUNK_SIZE];
    208243                usb_recv (usb_inbuffer, sizeof (usb_inbuffer));
    209244                while (!usb_rcvd ());
     
    239274                       
    240275                } 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
    241324                if ((char)cmd == 'f') // load file ACK
    242325                {
     
    256339                       
    257340                } 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
    258354                if ((char)cmd == 'c') // call command
    259355                {
    260                         index = ((u32_fnc_t *)address)();
     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                                                );
    261365                        usb_code ('i', index);
    262366                       
     
    265369                {
    266370                        usb_code ('b', address );
    267                         // Just return the address where is store the branch to do
    268                         u32 bootaddress = (u32) &address ; // Convert/cast address just to avoid gcc warning
    269                         return bootaddress ;
     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                       
    270409                }
    271410        }
Note: See TracChangeset for help on using the changeset viewer.