s_record.c 3.5 KB

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