FreeCalypso > hg > freecalypso-sw
view loadtools/ltdump.c @ 463:aad742029813
doc/Compiling: everything except gsm-fw
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Tue, 24 Jun 2014 00:16:04 +0000 |
parents | b3ed63722eb5 |
children |
line wrap: on
line source
/* * This module implements the dump2bin and dump2srec functionality * of fc-loadtool. */ #include <sys/types.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <strings.h> #include <stdlib.h> #include <time.h> extern uint32_t crc32_table[]; extern char target_response_line[]; crc32_on_target(area_base, area_len, retptr) u_long area_base, area_len, *retptr; { char arg1[10], arg2[10], *argv[4]; int stat; char *strtoul_endp; sprintf(arg1, "%lx", area_base); sprintf(arg2, "%lx", area_len); argv[0] = "crc32"; argv[1] = arg1; argv[2] = arg2; argv[3] = 0; tpinterf_make_cmd(argv); if (tpinterf_send_cmd() < 0) return(-1); stat = tpinterf_capture_output_oneline(10); /* 10 s timeout */ if (stat != 1) { errout: fprintf(stderr, "error: malformed response to crc32 command\n"); return(-1); } if (strlen(target_response_line) != 8) goto errout; *retptr = strtoul(target_response_line, &strtoul_endp, 16); if (strtoul_endp != target_response_line + 8) goto errout; return(0); } cmd_crc32(argc, argv) char **argv; { u_long area_base, area_len; char *strtoul_endp; u_long crc_result; int stat; area_base = strtoul(argv[1], &strtoul_endp, 16); if (*strtoul_endp) { inv: fprintf(stderr, "usage: crc32 hex-start hex-len\n"); return(-1); } area_len = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; stat = crc32_on_target(area_base, area_len, &crc_result); if (stat == 0) printf("%08lX\n", crc_result); return(stat); } /* the actual dump facility */ static FILE *dump_outfile; static int dump_save_srec; static uint32_t dump_nextaddr, dump_crcaccum; static uint32_t dump_total_len, dump_progress_len; static u_char dump_binrec[0x86]; static time_t dump_last_time; static char dumpsrec_s0_line[] = "S007000044554D50C2\n"; static char dumpsrec_s7_line[] = "S70500000000FA\n"; static dump_receiver(line) char *line; { int i, b; u_char sr_cksum; uint32_t addr_from_srec; time_t curtime; if (strncmp(line, "S385", 4)) { fprintf(stderr, "error: target response is not the expected S385...\n"); return(-1); } for (i = 0; i < 0x86; i++) { b = decode_hex_byte(line + i*2 + 2); if (b < 0) { fprintf(stderr, "data from target: S-record hex decode error\n"); return(-1); } dump_binrec[i] = b; } sr_cksum = 0; for (i = 0; i < 0x86; i++) sr_cksum += dump_binrec[i]; if (sr_cksum != 0xFF) { fprintf(stderr, "data from target: bad S-record checksum\n"); return(-1); } /* basic S-record format OK; now verify the address */ addr_from_srec = ((uint32_t) dump_binrec[1] << 24) | ((uint32_t) dump_binrec[2] << 16) | ((uint32_t) dump_binrec[3] << 8) | (uint32_t) dump_binrec[4]; if (addr_from_srec != dump_nextaddr) { fprintf(stderr, "error: S3 record from target has the wrong address\n"); return(-1); } /* all checks passed - save it */ if (dump_save_srec) { if (!dump_progress_len) fputs(dumpsrec_s0_line, dump_outfile); fprintf(dump_outfile, "%s\n", line); } else fwrite(dump_binrec + 5, 1, 0x80, dump_outfile); /* update running CRC */ for (i = 0; i < 0x80; i++) dump_crcaccum = crc32_table[dump_crcaccum & 0xFF ^ dump_binrec[i+5]] ^ (dump_crcaccum >> 8); /* progress indication */ dump_progress_len += 0x80; i = dump_progress_len * 100 / dump_total_len; time(&curtime); if (curtime != dump_last_time || i == 100) { printf("\rRx %lu out of %lu bytes (%i%%)", (u_long) dump_progress_len, (u_long) dump_total_len, i); fflush(stdout); } dump_nextaddr += 0x80; dump_last_time = curtime; return(1); } loadtool_memdump(start_addr, area_len, filename, fmt_srec) u_long start_addr, area_len; char *filename; { u_long target_crc_init, target_crc_fin; char *target_argv[4], target_arg1[10], target_arg2[10]; int stat; if (start_addr & 0x7F || area_len & 0x7F) { fprintf(stderr, "error: implementation limit: 128-byte alignment required\n"); return(-1); } printf("Requesting initial CRC-32 of the area from target...\n"); stat = crc32_on_target(start_addr, area_len, &target_crc_init); if (stat) return(stat); printf("got %08lX\n", target_crc_init); dump_outfile = fopen(filename, "w"); if (!dump_outfile) { perror(filename); return(-1); } dump_save_srec = fmt_srec; dump_nextaddr = start_addr; dump_crcaccum = 0xFFFFFFFF; dump_total_len = area_len; dump_progress_len = 0; printf("Requesting memory dump...\n"); sprintf(target_arg1, "%lx", start_addr); sprintf(target_arg2, "%lx", area_len); target_argv[0] = "DUMP"; target_argv[1] = target_arg1; target_argv[2] = target_arg2; target_argv[3] = 0; tpinterf_make_cmd(target_argv); stat = tpinterf_send_cmd(); if (stat < 0) { fclose(dump_outfile); return(stat); } stat = tpinterf_capture_output(2, dump_receiver); if (stat < 0) { fclose(dump_outfile); return(stat); } putchar('\n'); /* after last progress line */ /* sanity checks */ if (dump_nextaddr != start_addr + area_len) { fclose(dump_outfile); fprintf(stderr, "error: received dump length does not match expected\n"); return(-1); } if (dump_crcaccum != (uint32_t) target_crc_init) { fclose(dump_outfile); fprintf(stderr, "error: CRC mismatch (computed %lX)\n", (u_long) dump_crcaccum); return(-1); } if (fmt_srec) fputs(dumpsrec_s7_line, dump_outfile); fclose(dump_outfile); printf("Requesting another CRC-32 of the area from target...\n"); stat = crc32_on_target(start_addr, area_len, &target_crc_fin); if (stat) return(stat); if (target_crc_fin == target_crc_init) { printf("match, dump successful\n"); return(0); } else { fprintf(stderr, "mismatch: got %lX this time\n", target_crc_fin); return(-1); } } cmd_dump2bin(argc, argv) char **argv; { u_long area_base, area_len; char *strtoul_endp; area_base = strtoul(argv[1], &strtoul_endp, 16); if (*strtoul_endp) { inv: fprintf(stderr, "usage: dump2bin hex-start hex-len outfile\n"); return(-1); } area_len = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; return loadtool_memdump(area_base, area_len, argv[3], 0); } cmd_dump2srec(argc, argv) char **argv; { u_long area_base, area_len; char *strtoul_endp; area_base = strtoul(argv[1], &strtoul_endp, 16); if (*strtoul_endp) { inv: fprintf(stderr, "usage: dump2srec hex-start hex-len outfile\n"); return(-1); } area_len = strtoul(argv[2], &strtoul_endp, 16); if (*strtoul_endp) goto inv; return loadtool_memdump(area_base, area_len, argv[3], 1); }