# HG changeset patch # User Mychaela Falconia # Date 1582942470 0 # Node ID 9c5b0629e3462b9dece57d8bba0f4469d57b837e # Parent d04502de49edfe26896049a266646772626e8096 fc-loadtool SREC programming revamp implemented, compiles diff -r d04502de49ed -r 9c5b0629e346 loadtools/flash.h --- a/loadtools/flash.h Fri Feb 28 06:07:19 2020 +0000 +++ b/loadtools/flash.h Sat Feb 29 02:14:30 2020 +0000 @@ -71,3 +71,11 @@ struct sector_info *sectors; int detect_done; }; + +/* support for flashing discontiguous S-record images */ + +struct discontig_prog { + uint32_t start; + uint32_t end; + uint32_t crc; +}; diff -r d04502de49ed -r 9c5b0629e346 loadtools/flprogsrec.c --- a/loadtools/flprogsrec.c Fri Feb 28 06:07:19 2020 +0000 +++ b/loadtools/flprogsrec.c Sat Feb 29 02:14:30 2020 +0000 @@ -12,74 +12,79 @@ #include "srecreader.h" extern struct flash_bank_info flash_bank_info[2]; +extern uint32_t crc32_table[]; -flashcmd_progsrec_gen(bank, imgfile, is_m0) - char *imgfile; -{ - struct flash_bank_info *bi; - struct srecreader srr; - char *targv[4], shortarg[10], longarg[513]; - int resp; - unsigned long rec_count; - time_t start_time, finish_time; - unsigned duration, mm, ss; +#define MAX_SREC_REGIONS 256 - if (flash_detect(bank, 0) < 0) - return(-1); - bi = flash_bank_info + bank; +read_srec_img_for_flash(imgfile, is_m0, bank_size, reglistp, regcountp, + totalp, tmpfilep) + char *imgfile; + uint32_t bank_size, *totalp; + struct discontig_prog *reglistp; + unsigned *regcountp; + FILE **tmpfilep; +{ + struct srecreader srr; + struct discontig_prog *regp; + unsigned regcount; + uint32_t total_len; + char tmpfilename[] = "/tmp/fc-loadtoolXXXXXX"; + int rc, tmpfd, i, c; + FILE *tmpfile; + + printf("Reading S-record image from %s\n", imgfile); srr.filename = imgfile; - resp = open_srec_file(&srr); - if (resp < 0) - return(resp); - sprintf(shortarg, "%lx", (u_long) bi->base_addr); - targv[0] = bi->ops->loadagent_setbase_cmd; - targv[1] = shortarg; - targv[2] = 0; - printf("Setting flash base address: %s %s\n", targv[0], targv[1]); - tpinterf_make_cmd(targv); - if (tpinterf_send_cmd() < 0) { + rc = open_srec_file(&srr); + if (rc < 0) + return(rc); + tmpfd = mkstemp(tmpfilename); + if (tmpfd < 0) { + fprintf(stderr, "unable to get temp file via mkstemp()\n"); fclose(srr.openfile); return(-1); } - resp = tpinterf_pass_output(1); - if (resp) { - fclose(srr.openfile); - return(resp); - } - if (bi->ops->prep_for_program(bi) < 0) { + unlink(tmpfilename); + tmpfile = fdopen(tmpfd, "w+"); + if (!tmpfile) { + perror("fdopen"); + close(tmpfd); fclose(srr.openfile); return(-1); } - targv[0] = bi->ops->loadagent_program_cmd; - targv[1] = shortarg; - targv[2] = longarg; - targv[3] = 0; - for (rec_count = 0; ; ) { + regp = reglistp; + regcount = 0; + total_len = 0; + for (;;) { if (read_s_record(&srr) < 0) { /* error msg already printed */ fclose(srr.openfile); + fclose(tmpfile); return(-1); } if (srr.record_type == '0') { if (srr.lineno == 1) continue; fprintf(stderr, - "Warning: S0 record found in line %d of %s (expected in line 1 only)\n", + "error: S0 record found in line %d of %s (expected in line 1 only)\n", srr.lineno, srr.filename); - continue; - } else if (srr.record_type == '7') { - time(&finish_time); + fclose(srr.openfile); + fclose(tmpfile); + return(-1); + } else if (srr.record_type == '7') break; - } else if (srr.record_type != '3') { + else if (srr.record_type != '3') { fprintf(stderr, - "Warning: unsupported S%c record type in line %d of %s\n", + "error: unsupported S%c record type in line %d of %s\n", srr.record_type, srr.lineno, srr.filename); - continue; + fclose(srr.openfile); + fclose(tmpfile); + return(-1); } /* must be S3 */ if (s3s7_get_addr_data(&srr) < 0) { /* error msg already printed */ fclose(srr.openfile); + fclose(tmpfile); return(-1); } if (srr.datalen < 1) { @@ -93,51 +98,208 @@ "%s line %d: violates word alignment requirement\n", srr.filename, srr.lineno); fclose(srr.openfile); + fclose(tmpfile); return(-1); } - srr.addr &= bi->geom->total_size - 1; - if (srr.addr + srr.datalen > bi->geom->total_size) { + srr.addr &= bank_size - 1; + if (srr.addr + srr.datalen > bank_size) { fprintf(stderr, "%s line %d: goes past the end of the flash bank\n", srr.filename, srr.lineno); fclose(srr.openfile); + fclose(tmpfile); + return(-1); + } + /* is this the first record of the first region? */ + if (!regcount) { + regp->start = srr.addr; + regp->end = srr.addr; + regp->crc = 0xFFFFFFFF; + regcount = 1; + } + if (srr.addr < regp->end) { + fprintf(stderr, "%s line %d: address going backwards\n", + srr.filename, srr.lineno); + fclose(srr.openfile); + fclose(tmpfile); return(-1); } - if (!rec_count) { - printf("Programming flash, each \'.\' is 100 S-records\n"); - time(&start_time); + if (srr.addr != regp->end) { + if (regcount >= MAX_SREC_REGIONS) { + fprintf(stderr, + "error: %s has too many discontiguous regions\n", + imgfile); + fclose(srr.openfile); + fclose(tmpfile); + return(-1); + } + regp++; + regcount++; + regp->start = srr.addr; + regp->end = srr.addr; + regp->crc = 0xFFFFFFFF; } - sprintf(shortarg, "%lx", (u_long) srr.addr); - build_flashw_hex_string(srr.record + 5, longarg, - srr.datalen >> 1, is_m0); - tpinterf_make_cmd(targv); - if (tpinterf_send_cmd() < 0) { - fclose(srr.openfile); - return(-1); + /* take in the payload */ + if (is_m0) { + for (i = 0; i < srr.datalen; i += 2) { + c = srr.record[i+6]; + regp->crc = crc32_table[regp->crc & 0xFF ^ c] + ^ (regp->crc >> 8); + putc(c, tmpfile); + c = srr.record[i+5]; + regp->crc = crc32_table[regp->crc & 0xFF ^ c] + ^ (regp->crc >> 8); + putc(c, tmpfile); + } + } else { + for (i = 0; i < srr.datalen; i++) { + c = srr.record[i+5]; + regp->crc = crc32_table[regp->crc & 0xFF ^ c] + ^ (regp->crc >> 8); + putc(c, tmpfile); + } } - resp = tpinterf_pass_output(8); /* 8 s timeout */ - if (resp) { - fclose(srr.openfile); - return(resp); - } - rec_count++; - if (rec_count % 100 == 0) { - putchar('.'); - fflush(stdout); - } + regp->end += srr.datalen; + total_len += srr.datalen; } /* got S7 */ fclose(srr.openfile); - if (!rec_count) { + if (!regcount) { fprintf(stderr, "%s line %d: S7 without any preceding S3 data records\n", srr.filename, srr.lineno); + fclose(tmpfile); + return(-1); + } + /* good read */ + if (regcount == 1) + printf("Got %lu (0x%lx) bytes in one contiguous region\n", + (u_long) total_len, (u_long) total_len); + else + printf("Got %lu (0x%lx) bytes in %u discontiguous regions\n", + (u_long) total_len, (u_long) total_len, regcount); + *regcountp = regcount; + *totalp = total_len; + *tmpfilep = tmpfile; + return(0); +} + +flashcmd_progsrec_gen(bank, imgfile, is_m0) + char *imgfile; +{ + struct flash_bank_info *bi; + struct discontig_prog regions[MAX_SREC_REGIONS], *regp; + unsigned nregions, reg; + uint32_t total_len, bytesdone, addr, len; + FILE *tmpfile; + char *targv[4], shortarg[10], longarg[513]; + u_char databuf[256]; + int reclen, cc, rc; + time_t initial_time, curtime, last_time; + unsigned duration, mm, ss; + u_long crc_from_target; + + if (flash_detect(bank, 0) < 0) + return(-1); + bi = flash_bank_info + bank; + rc = read_srec_img_for_flash(imgfile, is_m0, bi->geom->total_size, + regions, &nregions, &total_len, &tmpfile); + if (rc < 0) + return(rc); + sprintf(shortarg, "%lx", (u_long) bi->base_addr); + targv[0] = bi->ops->loadagent_setbase_cmd; + targv[1] = shortarg; + targv[2] = 0; + printf("Setting flash base address: %s %s\n", targv[0], targv[1]); + tpinterf_make_cmd(targv); + if (tpinterf_send_cmd() < 0) { + fclose(tmpfile); + return(-1); + } + rc = tpinterf_pass_output(1); + if (rc) { + fclose(tmpfile); + return(rc); + } + if (bi->ops->prep_for_program(bi) < 0) { + fclose(tmpfile); return(-1); } - duration = finish_time - start_time; + rewind(tmpfile); + targv[0] = bi->ops->loadagent_program_cmd; + targv[1] = shortarg; + targv[2] = longarg; + targv[3] = 0; + printf("Programming flash\n"); + bytesdone = 0; + last_time = 0; + time(&initial_time); + for (reg = 0, regp = regions; reg < nregions; reg++, regp++) { + addr = regp->start; + len = regp->end - addr; + while (len) { + if (len >= 256) + reclen = 256; + else + reclen = len; + cc = fread(databuf, 1, reclen, tmpfile); + if (cc != reclen) { + fclose(tmpfile); + fprintf(stderr, + "error reading from temp file!\n"); + return(-1); + } + sprintf(shortarg, "%lx", addr); + build_flashw_hex_string(databuf, longarg, reclen >> 1, + 0); + tpinterf_make_cmd(targv); + if (tpinterf_send_cmd() < 0) { + fclose(tmpfile); + return(-1); + } + rc = tpinterf_pass_output(8); /* 8 s timeout */ + if (rc) { + fclose(tmpfile); + return(rc); + } + addr += reclen; + len -= reclen; + bytesdone += reclen; + cc = bytesdone * 100 / total_len; + time(&curtime); + if (curtime != last_time || cc == 100) { + printf("\r0x%lx bytes programmed (%i%%)", + bytesdone, cc); + fflush(stdout); + } + last_time = curtime; + } + } + putchar('\n'); + fclose(tmpfile); + duration = last_time - initial_time; mm = duration / 60; ss = duration - mm * 60; - printf("\nOperation completed in %um%us\n", mm, ss); + printf("Operation completed in %um%us\n", mm, ss); + + /* reset flash to read mode */ + if (bi->ops->reset_cmd(bi) < 0) + return(-1); + printf("Verifying CRC-32 of %u programmed region(s)\n", nregions); + for (reg = 0, regp = regions; reg < nregions; reg++, regp++) { + rc = crc32_on_target((u_long) regp->start, + (u_long) (regp->end - regp->start), + &crc_from_target); + if (rc < 0) + return(rc); + if (crc_from_target != regp->crc) { + fprintf(stderr, "error: CRC mismatch!\n"); + return(-1); + } + putchar('.'); + fflush(stdout); + } + putchar('\n'); return(0); }