s_record.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <s_record.h>
  9. static int hex1_bin (char c);
  10. static int hex2_bin (char *s);
  11. int srec_decode (char *input, int *count, ulong *addr, char *data)
  12. {
  13. int i;
  14. int v; /* conversion buffer */
  15. int srec_type; /* S-Record type */
  16. unsigned char chksum; /* buffer for checksum */
  17. chksum = 0;
  18. /* skip anything before 'S', and the 'S' itself.
  19. * Return error if not found
  20. */
  21. for (; *input; ++input) {
  22. if (*input == 'S') { /* skip 'S' */
  23. ++input;
  24. break;
  25. }
  26. }
  27. if (*input == '\0') { /* no more data? */
  28. return (SREC_EMPTY);
  29. }
  30. v = *input++; /* record type */
  31. if ((*count = hex2_bin(input)) < 0) {
  32. return (SREC_E_NOSREC);
  33. }
  34. chksum += *count;
  35. input += 2;
  36. switch (v) { /* record type */
  37. case '0': /* start record */
  38. srec_type = SREC_START; /* 2 byte addr field */
  39. *count -= 3; /* - checksum and addr */
  40. break;
  41. case '1':
  42. srec_type = SREC_DATA2; /* 2 byte addr field */
  43. *count -= 3; /* - checksum and addr */
  44. break;
  45. case '2':
  46. srec_type = SREC_DATA3; /* 3 byte addr field */
  47. *count -= 4; /* - checksum and addr */
  48. break;
  49. case '3': /* data record with a */
  50. srec_type = SREC_DATA4; /* 4 byte addr field */
  51. *count -= 5; /* - checksum and addr */
  52. break;
  53. /*** case '4' ***/
  54. case '5': /* count record, addr field contains */
  55. srec_type = SREC_COUNT; /* a 2 byte record counter */
  56. *count = 0; /* no data */
  57. break;
  58. /*** case '6' -- not used ***/
  59. case '7': /* end record with a */
  60. srec_type = SREC_END4; /* 4 byte addr field */
  61. *count -= 5; /* - checksum and addr */
  62. break;
  63. case '8': /* end record with a */
  64. srec_type = SREC_END3; /* 3 byte addr field */
  65. *count -= 4; /* - checksum and addr */
  66. break;
  67. case '9': /* end record with a */
  68. srec_type = SREC_END2; /* 2 byte addr field */
  69. *count -= 3; /* - checksum and addr */
  70. break;
  71. default:
  72. return (SREC_E_BADTYPE);
  73. }
  74. /* read address field */
  75. *addr = 0;
  76. switch (v) {
  77. case '3': /* 4 byte addr field */
  78. case '7':
  79. if ((v = hex2_bin(input)) < 0) {
  80. return (SREC_E_NOSREC);
  81. }
  82. *addr += v;
  83. chksum += v;
  84. input += 2;
  85. /* FALL THRU */
  86. case '2': /* 3 byte addr field */
  87. case '8':
  88. if ((v = hex2_bin(input)) < 0) {
  89. return (SREC_E_NOSREC);
  90. }
  91. *addr <<= 8;
  92. *addr += v;
  93. chksum += v;
  94. input += 2;
  95. /* FALL THRU */
  96. case '0': /* 2 byte addr field */
  97. case '1':
  98. case '5':
  99. case '9':
  100. if ((v = hex2_bin(input)) < 0) {
  101. return (SREC_E_NOSREC);
  102. }
  103. *addr <<= 8;
  104. *addr += v;
  105. chksum += v;
  106. input += 2;
  107. if ((v = hex2_bin(input)) < 0) {
  108. return (SREC_E_NOSREC);
  109. }
  110. *addr <<= 8;
  111. *addr += v;
  112. chksum += v;
  113. input += 2;
  114. break;
  115. default:
  116. return (SREC_E_BADTYPE);
  117. }
  118. /* convert data and calculate checksum */
  119. for (i=0; i < *count; ++i) {
  120. if ((v = hex2_bin(input)) < 0) {
  121. return (SREC_E_NOSREC);
  122. }
  123. data[i] = v;
  124. chksum += v;
  125. input += 2;
  126. }
  127. /* read anc check checksum */
  128. if ((v = hex2_bin(input)) < 0) {
  129. return (SREC_E_NOSREC);
  130. }
  131. if ((unsigned char)v != (unsigned char)~chksum) {
  132. return (SREC_E_BADCHKS);
  133. }
  134. return (srec_type);
  135. }
  136. static int hex1_bin (char c)
  137. {
  138. if (c >= '0' && c <= '9')
  139. return (c - '0');
  140. if (c >= 'a' && c <= 'f')
  141. return (c + 10 - 'a');
  142. if (c >= 'A' && c <= 'F')
  143. return (c + 10 - 'A');
  144. return (-1);
  145. }
  146. static int hex2_bin (char *s)
  147. {
  148. int i, j;
  149. if ((i = hex1_bin(*s++)) < 0) {
  150. return (-1);
  151. }
  152. if ((j = hex1_bin(*s)) < 0) {
  153. return (-1);
  154. }
  155. return ((i<<4) + j);
  156. }