tools/build-R2_19_3/fsboot/cbl/common.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *!
00003 *! FILE NAME  : common.c
00004 *!
00005 *! DESCRIPTION: Level 2 loader common for serial and network boot.
00006 *!
00007 *! ---------------------------------------------------------------------------
00008 *! (C) Copyright 1998-2006, Axis Communications AB, LUND, SWEDEN
00009 *!***************************************************************************/
00010 
00011 #include <e100boot.h>   
00012 #include <ser_defs.h>
00013 #include <config_defs.h>
00014 #include <timer_defs.h>
00015 #include <stdio.h>
00016 #include <cbl.h>
00017 #include <nand/rflflash.h>
00018 #include <nandwr.h>
00019 
00020 extern byte __Stext[];
00021 extern byte __Edata[];
00022 
00023 FILE *stdin;
00024 FILE *stdout;
00025 FILE *stderr;
00026 
00027 extern udword seq;
00028 extern char svinto_boot_version[];
00029 
00030 byte change_baudrate;
00031 udword new_baudrate;
00032 reg_config_r_bootsel r_bootsel;
00033 
00034 /************************************************************************/
00035 /* function prototypes */
00036 
00037 void (*send_ack)(void)              = send_net_ack;
00038 void (*send_hex)(udword h, byte nl) = send_net_hex;
00039 void (*send_string)(char *str)      = send_net_string;
00040 static void read_file(byte* addr, udword size);
00041 static int  memory_test(udword from, udword to, udword *failed_address);
00042 static void memory_dump(udword *from, udword *to);
00043 static void read_file(byte* addr, udword size);
00044 static void read_file(byte* addr, udword size);
00045 static void read_load_info(void);
00046 static void decode_load_info(void);
00047 static void toggle_led(void);
00048 
00049 /************************************************************************/
00050 
00051 void 
00052 next_level_boot(void)
00053 {
00054   init_libc();
00055 
00056   {
00057     r_bootsel = REG_RD(config, regi_config, r_bootsel);
00058     
00059     if (r_bootsel.boot_mode == regk_config_ser) {
00060       send_string = send_ser_string;
00061       send_ack    = send_ser_ack;
00062       send_hex    = send_ser_hex;
00063     }
00064     else {
00065       net_init(2);
00066     }
00067   }
00068 
00069   stdout = stderr = freopen("/dev/eth0", "w", stdout);
00070 
00071   printf("\r\n\r\nDevice ID = %8.8x\r\n", NTOHL(tx_header.id));
00072   printf(svinto_boot_version);
00073 
00074   {
00075     udword sum = 0;
00076     byte *b;
00077       
00078     for (b=(byte*)__Stext; b != (byte*)__Edata; b++) {
00079       sum+=*b;
00080     }
00081     send_string("Checksum of bootloader is ");
00082     send_hex(sum, NL);
00083   }
00084 
00085   read_load_info();
00086   
00087   while(1) {
00088     ;
00089   }
00090 }
00091 
00092 static void 
00093 toggle_led(void)
00094 {
00095 
00096 #if 0
00097   REG_SET(R_PORT_PA_DATA, data_out, 0x55);
00098   
00099   while(1) {
00100     REG_SET(R_PORT_PA_DATA, data_out, ~REG_GET(R_PORT_PA_READ, data_in));
00101     {
00102       volatile udword i;
00103       
00104       for(i=0; i!=2000000; i++);
00105     }
00106   }
00107 #endif
00108 }
00109 
00110 static void
00111 read_load_info(void)
00112 {
00113   change_baudrate = 0;
00114   
00115   send_string("Waiting for load info.\r\n");
00116 
00117   send_ack();
00118   read_file((byte*)IO_BUF_START, IO_BUF_END - IO_BUF_START - CRC_LEN);
00119   send_string("Got load info.\r\n");
00120 
00121   decode_load_info();
00122 
00123 #if 0  
00124   if (change_baudrate) {
00125     reg_ser_rw_rec_baud_div rw_rec_baud_div = {0,};
00126     reg_ser_rw_tr_baud_div  rw_tr_baud_div  = {0,};
00127 
00128     rw_tr_baud_div.divisor  = new_baudrate;
00129     rw_rec_baud_div.divisor = new_baudrate;
00130 
00131     REG_WR(ser, regi_ser0, rw_rec_baud_div, rw_rec_baud_div);
00132     REG_WR(ser, regi_ser0, rw_tr_baud_div,  rw_tr_baud_div);
00133     {
00134       udword i = 0;
00135       
00136       while (i++ < 1000000);
00137     }
00138     send_ack();
00139     
00140   }
00141 #endif
00142   toggle_led();
00143 }
00144 
00145 static void
00146 packet_info(packet_info_T *packet_info)
00147 {
00148   
00149   send_string("PACKET_INFO\r\n");
00150   send_hex(packet_info->addr, NL);
00151   send_hex(packet_info->size, NL);
00152   
00153   send_ack();
00154   
00155   read_file((byte*)packet_info->addr, packet_info->size);
00156 }
00157 
00158 static void 
00159 set_register(set_register_T *set_register)
00160 {
00161 
00162   send_string("SET_REGISTER\r\n");
00163   send_hex(set_register->addr, NL);
00164   send_hex(set_register->val, NL);
00165   *(udword*)set_register->addr = set_register->val;
00166 
00167 }
00168 
00169 static void 
00170 pause_loop(pause_loop_T *pause_loop)
00171 {
00172 
00173   send_string("PAUSE_LOOP\r\n");
00174   send_hex(pause_loop->pause, NL);
00175   pause_loop = (pause_loop_T*)pause_loop->pause; /* reuse pointer as counter */
00176   for (;(udword)pause_loop;((udword)pause_loop)--);
00177 }
00178 
00179 static void 
00180 get_register(get_register_T *get_register)
00181 {
00182 
00183   send_string("GET_REGISTER\r\n");
00184   send_hex(get_register->addr, NL);
00185   send_hex(*(udword*)get_register->addr, NL);
00186 
00187 }
00188 
00189 static void 
00190 mem_verify(mem_verify_T *mem_verify)
00191 {
00192 
00193   send_string("MEM_VERIFY\r\n");
00194   send_hex(mem_verify->addr, NL);
00195   send_hex(mem_verify->val, NL);
00196   if (*(udword*)mem_verify->addr != mem_verify->val) {
00197     send_string("verify failed\r\n");
00198     read_load_info();
00199   }
00200 }
00201 
00202 static void 
00203 mem_test(mem_test_T *mem_test)
00204 {
00205   send_string("MEM_TEST\r\n");
00206   udword failed_address;
00207   send_hex(mem_test->from, NL);
00208   send_hex(mem_test->to, NL);
00209   
00210   if (!memory_test(mem_test->from, mem_test->to, &failed_address)) {
00211     send_string("### Memory test failed at ");
00212     send_hex(failed_address, NL);
00213     memory_dump((udword*)DWORD_ALIGN(failed_address - 64), (udword*)DWORD_ALIGN(failed_address + 64));
00214     read_load_info();
00215   }
00216   send_string("Passed memory test.\r\n");
00217   
00218 }
00219 
00220 static void 
00221 mem_dump(mem_dump_T *mem_dump)
00222 {
00223   send_string("MEM_DUMP\r\n");
00224   send_hex(mem_dump->from_addr, NL);
00225   send_hex(mem_dump->to_addr, NL);
00226   memory_dump((udword*)mem_dump->from_addr, (udword*)mem_dump->to_addr);
00227 }
00228 
00229 static void
00230 mem_clear(mem_clear_T *mem_clear)
00231 {
00232   send_string("MEM_CLEAR\r\n");
00233   send_hex(mem_clear->from_addr, NL);
00234   send_hex(mem_clear->to_addr, NL);
00235   {
00236     udword i;
00237     
00238     for (i=mem_clear->from_addr; i <= mem_clear->to_addr; i++) {
00239       *(byte*)i = 0x00;
00240     }
00241   }
00242 }
00243 
00244 static void 
00245 jump(jump_T *jump)
00246 {
00247   
00248   /* for the printf function in our libc */
00249 #if 0
00250   REG_WR(R_DMA_CH8_FIRST, *(udword*)&tx_header.dest[0]);
00251   REG_WR(R_DMA_CH9_FIRST, *(uword*)&tx_header.dest[4]);
00252   
00253   send_hex(REG_RD(R_DMA_CH8_FIRST), NL);
00254   send_hex(REG_RD(R_DMA_CH9_FIRST), NL);
00255 #endif
00256   send_string("JUMP\r\n");
00257   send_hex(jump->addr, NL);
00258   __asm__ volatile ("\n\
00259 jump %0\n\
00260 nop\n\
00261 " :: "r" (jump->addr));    
00262 }
00263 
00264 static void 
00265 decode_load_info(void)
00266 {
00267   udword *type_p = (udword*)IO_BUF_START;
00268   udword i;
00269   /* dword counter last in buffer */
00270   udword dword_cnt = NTOHL(*(udword*)(IO_BUF_END-CRC_LEN-sizeof(udword))); 
00271   
00272   /* ntohl the commands in command buffer */
00273   for(i=0; i<=dword_cnt; i++) {
00274     type_p[i] = NTOHL(type_p[i]);
00275   }
00276 
00277   /* loop through and execute all commands */
00278   while (*type_p != END_OF_CMDS) {
00279 
00280     switch (*type_p) {
00281 
00282     case PACKET_INFO: {
00283       packet_info((packet_info_T*)type_p);
00284       (byte*)type_p += sizeof(packet_info_T);
00285       break;
00286     }
00287 
00288     case SET_REGISTER: {
00289       set_register((set_register_T*)type_p);
00290       (byte*)type_p += sizeof(set_register_T);
00291       break;
00292     }    
00293       
00294     case GET_REGISTER: {
00295       get_register((get_register_T*)type_p);
00296       (byte*)type_p += sizeof(get_register_T);
00297       break;
00298     }
00299 
00300     case PAUSE_LOOP: {
00301       pause_loop((pause_loop_T*)type_p); 
00302       (byte*)type_p += sizeof(pause_loop_T);
00303       break;
00304     }
00305 
00306     case MEM_VERIFY: {
00307       mem_verify((mem_verify_T*)type_p);
00308       (byte*)type_p += sizeof(mem_verify_T);
00309       break;
00310     }
00311 
00312     case MEM_TEST: {
00313       mem_test((mem_test_T*)type_p);
00314       (byte*)type_p += sizeof(mem_test_T);
00315       break;
00316     }
00317 
00318     case MEM_DUMP: {
00319       mem_dump((mem_dump_T*)type_p);
00320       (byte*)type_p += sizeof(mem_dump_T);
00321       break;
00322     }
00323 
00324     case MEM_CLEAR: {
00325       mem_clear((mem_clear_T*)type_p);
00326       (byte*)type_p += sizeof(mem_clear_T);
00327       break;
00328     }
00329 
00330     case FLASH: {
00331       send_string("FLASH\r\n");
00332       send_hex((udword)((flash_T*)(type_p))->source, NL);
00333       send_hex((udword)((flash_T*)(type_p))->dest, NL);
00334       send_hex((udword)((flash_T*)(type_p))->size, NL);
00335       if (flash_write((unsigned)((flash_T*)(type_p))->source,
00336                       (unsigned)((flash_T*)(type_p))->dest,
00337                       ((flash_T*)(type_p))->size) != ERR_FLASH_OK) {
00338         read_load_info();
00339       }
00340       (byte*)type_p += sizeof(flash_T);
00341       break;
00342     }
00343 
00344       
00345     case NAND_FLASH: {
00346       send_string("NAND_FLASH\r\n");
00347       send_hex((udword)((nand_flash_T*)(type_p))->source, NL);
00348       send_hex((udword)((nand_flash_T*)(type_p))->dest, NL);
00349       send_hex((udword)((nand_flash_T*)(type_p))->maxdest, NL);
00350       send_hex((udword)((nand_flash_T*)(type_p))->size, NL);
00351       rflflash_init();
00352       rflflash_write(((nand_flash_T*)(type_p))->source, 
00353                      ((nand_flash_T*)(type_p))->dest,
00354                      ((nand_flash_T*)(type_p))->maxdest, 
00355                      ((nand_flash_T*)(type_p))->size);
00356       
00357       (byte*)type_p += sizeof(nand_flash_T);
00358       break;
00359     }
00360 
00361     case NAND_FLASH_DUMP: {
00362       send_string("NAND_FLASH_DUMP\r\n");
00363       send_hex((udword)((mem_dump_T*)(type_p))->from_addr, NL);
00364       send_hex((udword)((mem_dump_T*)(type_p))->to_addr, NL);
00365       rflflash_dump((udword)((mem_dump_T*)(type_p))->from_addr,
00366                     (udword)((mem_dump_T*)(type_p))->to_addr);
00367       (byte*)type_p += sizeof(mem_dump_T);
00368       break;
00369     }
00370 
00371     case NAND_FLASH_IGNORE_BAD: {
00372       send_string("NAND_FLASH_IGNORE_BAD\r\n");
00373       rflflash_ignore_bad();
00374       (byte*)type_p++;
00375       break;
00376     }
00377 
00378     case NAND_FLASH_MARK_BAD: {
00379       send_string("NAND_FLASH_MARK_BAD\r\n");
00380       send_hex((udword)((mem_dump_T*)(type_p))->from_addr, NL);
00381       send_hex((udword)((mem_dump_T*)(type_p))->to_addr, NL);
00382       rflflash_mark_bad((udword)((mem_dump_T*)(type_p))->from_addr,
00383                        (udword)((mem_dump_T*)(type_p))->to_addr);
00384       (byte*)type_p += sizeof(mem_dump_T);
00385       break;
00386     }
00387 
00388     case NAND_FLASH_ERASE: {
00389       send_string("NAND_FLASH_ERASE\r\n");
00390       send_hex((udword)((mem_dump_T*)(type_p))->from_addr, NL);
00391       send_hex((udword)((mem_dump_T*)(type_p))->to_addr, NL);
00392       rflflash_nand_do_erase((udword)((mem_dump_T*)(type_p))->from_addr,
00393                           (udword)((mem_dump_T*)(type_p))->to_addr);
00394       (byte*)type_p += sizeof(mem_dump_T);
00395       break;
00396     }
00397 
00398     case NAND_FLASH_OOB_DUMP: {
00399       send_string("NAND_FLASH_OOB_DUMP\r\n");
00400       send_hex((udword)((mem_dump_T*)(type_p))->from_addr, NL);
00401       send_hex((udword)((mem_dump_T*)(type_p))->to_addr, NL);
00402       rflflash_dump_oob((udword)((mem_dump_T*)(type_p))->from_addr,
00403                         (udword)((mem_dump_T*)(type_p))->to_addr,
00404                         0);
00405       (byte*)type_p += sizeof(mem_dump_T);
00406       break;
00407     }
00408 
00409     case NAND_FLASH_OOB_DUMP_BAD: {
00410       send_string("NAND_FLASH_OOB_DUMP_BAD\r\n");
00411       send_hex((udword)((mem_dump_T*)(type_p))->from_addr, NL);
00412       send_hex((udword)((mem_dump_T*)(type_p))->to_addr, NL);
00413       rflflash_dump_oob((udword)((mem_dump_T*)(type_p))->from_addr,
00414                         (udword)((mem_dump_T*)(type_p))->to_addr,
00415                         1);
00416       (byte*)type_p += sizeof(mem_dump_T);
00417       break;
00418     }
00419 
00420 #if 0
00421       /* for testing */
00422     case STUPID_NAND_FLASH: {
00423       send_string("STUPID_NAND_FLASH\r\n");
00424       nandwr();
00425       (byte*)type_p += sizeof(flash_T);
00426       break;
00427     }
00428 #endif
00429       
00430     case RESTART_FS: {
00431       send_string("RESTART_FS\r\n");
00432       {
00433         reg_timer_rw_wd_ctrl rw_wd_ctrl = {
00434           .cmd = regk_timer_yes,
00435           .cnt = 0
00436         };
00437         REG_WR(timer, regi_timer, rw_wd_ctrl, rw_wd_ctrl);
00438       }
00439       (byte*)type_p++;
00440       break;
00441     }
00442 
00443     case JUMP: {
00444       jump((jump_T*)type_p);
00445       (byte*)type_p += sizeof(jump_T);
00446       break;
00447     }
00448 
00449     case LOOP: {
00450       send_string("LOOP\r\n");
00451       bne_T *bne = (bne_T*)type_p;
00452       send_hex(bne->addr, NL);
00453       send_hex(bne->target, NL);
00454       if (*(udword*)bne->addr) {
00455         (*(udword*)bne->addr)--;
00456         (byte*)type_p = bne->target;
00457       }
00458       else {
00459         (byte*)type_p += sizeof(bne_T);
00460       }
00461       break;
00462     }
00463 
00464     case BAUDRATE: {
00465       send_string("BAUDRATE\r\n");
00466       send_hex(((br_T*)type_p)->baudrate, NL);
00467       new_baudrate = ((br_T*)type_p)->baudrate;
00468       break;
00469     }
00470 
00471     default: {
00472       send_string("### Unknown type : ");
00473       send_hex(*type_p, NL);
00474       read_load_info();
00475       break;
00476     }
00477     }
00478   }
00479   
00480   send_string("END\r\n");
00481 }
00482 
00483 static void 
00484 read_file(byte* addr, udword size)
00485 {
00486   udword nbr_read_last;
00487   byte *b;
00488   byte *from;
00489   
00490   //  send_string(">read_file\r\n");
00491   
00492   nbr_read = 0;
00493   nbr_read_last = 0;
00494   
00495   if (r_bootsel.boot_mode != regk_config_ser) {
00496     //    net_init();    
00497     rx_descr2.buf    = (char*)addr;
00498     bytes_to_read    = size;
00499     rx_descr2.after  = rx_descr2.buf+(size + CRC_LEN > 1500 ? 1500 : size + CRC_LEN);
00500     
00501     init_dma1();
00502     
00503     while (nbr_read < size) {
00504 
00505       if (rx_descr2.in_eop == regk_dma_yes) { /* got a packet? */
00506 
00507         /* was it to us? */
00508         volatile unsigned bip = handle_network_read() - sizeof(struct packet_header_T);
00509         nbr_read_last = nbr_read;
00510 
00511 #if 0
00512         {
00513           send_string("Read ");
00514           send_hex(bip, NO_NL);
00515           send_string(" bytes. ");
00516           send_hex((udword)from, NO_NL);
00517           send_string(" - ");
00518           send_hex(rx_descr2.buf-1, NO_NL);
00519           send_string(" (");
00520           send_hex(nbr_read, NO_NL);
00521           send_string("/");
00522           send_hex(size, NO_NL);
00523           send_string(")\r\n");
00524           from +=bip;
00525         }
00526 #endif
00527       }
00528 
00529       if (timeout()) {
00530         send_net_ack();
00531       }
00532 
00533     }
00534   }
00535   else  {  /* interface != NETWORK */
00536     bytes_to_read    = size;
00537 
00538     while (nbr_read < size) {  
00539       reg_ser_rs_stat_din rs_stat_din = REG_RD(ser, regi_ser0, rs_stat_din);
00540       
00541       if (rs_stat_din.dav == regk_ser_yes) {
00542         *(char*)(addr + nbr_read++)  = rs_stat_din.data; 
00543         last_timeout = REG_RD(timer, regi_timer, r_time);
00544       }
00545       
00546 #if 0
00547       if (timeout()) {
00548         send_ser_ack();
00549       }
00550 #endif
00551     }
00552   }
00553 
00554   if(0)
00555   {
00556     udword sum;
00557     
00558     sum = 0;
00559     for (b=addr; b != (byte*)(addr+size); b++) {
00560       sum^=(*b);
00561       sum = sum<<1 | sum>>31;   /* rotl */
00562     }
00563     send_string("Checksum of file is ");
00564     send_hex(sum, NL);
00565   }
00566 
00567   /*  send_string("<read_file\r\n");*/
00568   
00569 }
00570 
00571 #if 0
00572 static void 
00573 print_descr(dma_descr_data *d)
00574 {
00575   
00576   send_string("Descriptor at ");
00577   send_hex((udword)d, NL);
00578   
00579   send_string("ctrl   : ");
00580   send_hex(d->ctrl, NL);
00581   
00582   send_string("sw_len : ");
00583   send_hex(d->sw_len, NL);
00584   
00585   send_string("next   : ");
00586   send_hex(d->next, NL);
00587   
00588   send_string("buf    : ");
00589   send_hex(d->buf, NL);
00590   
00591   send_string("status : ");
00592   send_hex(d->status, NL);
00593   
00594   send_string("hw_len : ");
00595   send_hex(d->hw_len, NL);
00596   
00597 }
00598 #endif
00599 
00600 static int
00601 memory_test(udword from, udword to, udword *failed_address)
00602 {
00603   udword i;
00604   udword j;
00605   byte b;
00606   
00607   /* 
00608      At each dword (but bytewise) write the inverse of the adress,
00609      check that it worked, then write the inverse of the last byte
00610      written. Exit on fail. The memory after a successfull test will
00611      be: 
00612 
00613      0xC0000000 : 0xC0000000 0xC0000004 0xC0000008 0xC000000C
00614      0xC0000010 : 0xC0000010 0xC0000014 0xC0000018 0xC000001C
00615      */
00616 
00617 send_string("\nMemory test 1:");
00618   for (i=from; i<to; i+=4) {
00619 if((i & 0xfffff) == 0) send_string(".");
00620     for (j=0; (j != sizeof(udword)) && (i+j < to); j++) {
00621       b = ((~i)>>(j*8)) & 0xff;
00622       *(volatile byte*)(i+j) = b;
00623       if (*(volatile byte*)(i+j) == b) {
00624         *(volatile byte*)(i+j) = ~b;
00625       }
00626       else {
00627         *failed_address = i+j;
00628                 send_string("### Memory test 1 failed at ");
00629                 send_hex(*failed_address, NL);
00630         return(FALSE);
00631       }
00632     }
00633   }
00634 
00635   /* Now check for mirrored memory. Run through entire region, check
00636      bytewise that the dwords contain the address to the dword. Exit
00637      on fail. */
00638   
00639 send_string("\nMemory test 2:");
00640   for (i=from; i<to; i+=4) {
00641 if((i & 0xfffff) == 0) send_string(".");
00642     for (j=0; (j != sizeof(udword)) && (i+j < to); j++) {
00643       b = ((i)>>(j*8)) & 0xff;
00644       if (*(volatile byte*)(i+j) != b) {
00645         *failed_address = i+j;
00646         send_string("### Memory test 2 failed at ");
00647         send_hex(*failed_address, NL);
00648         return(FALSE);
00649       }
00650     }
00651   }
00652 
00653   return(TRUE);
00654 }
00655 
00656 static void
00657 memory_dump(udword *from, udword *to)
00658 {
00659   udword *i = from;
00660   int j;
00661   
00662   for (; i <= to; i+=4) {
00663     printf("%8.8x :", i);
00664     for(j=0; j != 4 && (i+j <= to); j++) {
00665       printf(" %8.8x", *(udword*)(i+j));
00666     }
00667     printf("\r\n");
00668   }
00669 }
00670 
00671 

Generated on Fri Nov 28 00:06:25 2008 for elphel by  doxygen 1.5.1