srecLoad.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:4k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2.  * srecLoad
  3.  *
  4.  * by Curt McDowell, 09-05-99
  5.  */
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "srecLoad.h"
  9. /*
  10.  * nextByte:
  11.  *
  12.  * Utility routine for srecLoad()
  13.  */
  14. static int nextByte(char **p)
  15. {
  16.     int d1, d2;
  17.     d1 = **p;
  18.     if (d1 >= '0' && d1 <= '9')
  19. d1 = d1 - '0';
  20.     else if (d1 >= 'A' && d1 <= 'F')
  21. d1 = d1 - 'A' + 10;
  22.     else
  23. return -1;
  24.     d1 *= 16;
  25.     (*p)++;
  26.     d2 = **p;
  27.     if (d2 >= '0' && d2 <= '9')
  28. d1 += d2 - '0';
  29.     else if (d2 >= 'A' && d2 <= 'F')
  30. d1 += d2 - 'A' + 10;
  31.     else
  32. return -1;
  33.     (*p)++;
  34.     return d1;
  35. }
  36. /*
  37.  * srecLoad:
  38.  *
  39.  * Routine to read an S-record format file into a fixed-size buffer.
  40.  *
  41.  * On success, returns number of bytes loaded.
  42.  * On failure, returns negative error code.
  43.  */
  44. int srecLoad(FILE *fp, char *buf, int bufLen, int *entry)
  45. {
  46.     static unsigned char addrLens[] = { 2, 2, 3, 4, 0, 2, 0, 4, 3, 2 };
  47.     char line[1 + 1 + 2 + 255*2 + 1];
  48.     char dataBytes[255], *p;
  49.     int dataLen, dataRecs;
  50.     char *s;
  51.     int type, x, addrLen, byteCount, byteTotal;
  52.     int addr;
  53.     unsigned char chkSum;
  54.     memset(buf, 0, bufLen);
  55.     *entry = 0;
  56.     dataRecs = 0;
  57.     byteTotal = 0;
  58.     while (fgets(line, sizeof (line), fp) != 0) {
  59. s = line;
  60. chkSum = 0;
  61. if (*s++ != 'S')
  62.     continue;
  63. type = *s++;
  64. if (type < '0' || type > '9')
  65.     return SREC_ERROR_FORMAT;
  66. addrLen = addrLens[type - '0'];
  67. if ((byteCount = nextByte(&s)) < 0)
  68.     return SREC_ERROR_FORMAT;
  69. chkSum = (unsigned char) byteCount;
  70. byteCount -= addrLen;
  71. if (byteCount < 1)
  72.     return SREC_ERROR_FORMAT; /* Need at least addr and checksum */
  73. addr = 0;
  74. while (addrLen--) {
  75.     if ((x = nextByte(&s)) < 0)
  76. return SREC_ERROR_TRUNC;
  77.     addr = addr << 8 | x;
  78.     chkSum += (unsigned char) x;
  79. }
  80. p = dataBytes;
  81. dataLen = byteCount - 1;
  82. while (byteCount-- > 1) {
  83.     if ((x = nextByte(&s)) < 0)
  84. return SREC_ERROR_TRUNC;
  85.     *p++ = (char) x;
  86.     chkSum += (unsigned char) x;
  87. }
  88. if ((x = nextByte(&s)) < 0)
  89.     return SREC_ERROR_TRUNC;
  90. chkSum += (unsigned char) x;
  91. if (chkSum != (unsigned char) 0xff)
  92.     return SREC_ERROR_CHECKSUM;
  93. switch (type) {
  94. case '0': /* Header record */
  95.     dataRecs = 0;
  96.     break;
  97. case '5': /* Record count */
  98.     if (addr != dataRecs)
  99. return SREC_ERROR_NRECORDS;
  100.     break; /* Ignore */
  101. case '1': /* 2-byte address with data */
  102. case '2': /* 3-byte address with data */
  103. case '3': /* 4-byte address with data */
  104.     if (addr < 0 || addr + dataLen > bufLen){
  105. printf("addr=0x%x, addr+dataLen=0x%x, bufLen=%dn",
  106.        addr, addr + dataLen, bufLen);
  107. return SREC_ERROR_ADDR;
  108.     }
  109.     memcpy(buf + addr, dataBytes, dataLen);
  110.     byteTotal += dataLen;
  111.     dataRecs++;
  112.     break;
  113. case '7': /* Termination with 4-byte address */
  114. case '8': /* Termination with 3-byte address */
  115. case '9': /* Termination with 2-byte address */
  116.     *entry = addr;
  117.     dataRecs = 0;
  118.     break;
  119. default:
  120.     return SREC_ERROR_FORMAT;
  121. }
  122.     }
  123.     return byteTotal;
  124. }
  125. char *srecErrmsg(int errcode)
  126. {
  127.     switch (errcode) {
  128.     case SREC_ERROR_NONE:
  129. return "Success";
  130.     case SREC_ERROR_FORMAT:
  131. return "File format error";
  132.     case SREC_ERROR_CHECKSUM:
  133. return "Checksum mismatch";
  134.     case SREC_ERROR_NRECORDS:
  135. return "Incorrect number of records";
  136.     case SREC_ERROR_TRUNC:
  137. return "Truncated line";
  138.     case SREC_ERROR_ADDR:
  139. return "Address out of range";
  140.     }
  141.     return "Unknown error";
  142. }
  143. #ifdef TEST_MAIN
  144. /*
  145.  * Test main program
  146.  */
  147. #define PROM_SIZE (512 * 1024)
  148. main(int argc, char **argv)
  149. {
  150.     FILE *fp;
  151.     char buf[PROM_SIZE];
  152.     int entry, r;
  153.     if (argc != 2) {
  154. fprintf(stderr, "Usage: srecLoad file.hex > file.binn");
  155. exit(1);
  156.     }
  157.     if ((fp = fopen(argv[1], "r")) == 0) {
  158. fprintf(stderr, "srecLoad: could not open %sn", argv[1]);
  159. exit(1);
  160.     }
  161.     if ((r = srecLoad(fp, buf, sizeof (buf), &entry)) < 0) {
  162. fprintf(stderr, "srecLoad: load error %dn", r);
  163. exit(1);
  164.     }
  165.     fclose(fp);
  166.     write(1, buf, sizeof (buf));
  167.     fprintf(stderr, "Entry address: 0x%08xn", (unsigned int) entry);
  168.     exit(0);
  169. }
  170. #endif /* TEST_MAIN */