You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

srecord.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (c) 2005 Chris Kuethe <chris.kuethe@gmail.com>
  3. * This file is Copyright (c)2005-2019 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. *
  6. */
  7. #include "gpsd_config.h" /* must be before all includes */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "gpsd.h"
  11. /*
  12. * See srec(5) for a description of this format.
  13. * We read and write 4-byte addresses.
  14. * S0: Comments
  15. * S3: Memory Loadable Data, 4byte address
  16. * S5: Count of S1, S2 and S3 Records
  17. * S7: starting execution address interpreted as a 4-byte address
  18. */
  19. #define MAX_BYTES_PER_RECORD 16
  20. /*
  21. * bin2srec: turn a chunk of binary into an S-record
  22. * offset: used to specify load address
  23. * num: up to MAX_BYTES_PER_RECORD bytes can be encoded at one time
  24. * bytes are read from bbuf and a ready-to-go srecord is placed in sbuf
  25. */
  26. int
  27. bin2srec(unsigned int type, unsigned int offset, unsigned int num,
  28. unsigned char *bbuf, unsigned char *sbuf)
  29. {
  30. unsigned char abuf[MAX_BYTES_PER_RECORD * 2 + 2], sum;
  31. size_t len;
  32. if ((num < 1) || (num > MAX_BYTES_PER_RECORD))
  33. return -1;
  34. len = (size_t) (4 + num + 1);
  35. memset(abuf, 0, sizeof(abuf));
  36. hexdump((size_t) num, bbuf, abuf);
  37. sum = sr_sum((unsigned int)len, offset, bbuf);
  38. (void)snprintf((char *)sbuf, MAX_BYTES_PER_RECORD * 2 + 17,
  39. "S%u%02X%08X%s%02X\r\n",
  40. type, (unsigned)len, offset, (char *)abuf, (unsigned)sum);
  41. return 0;
  42. }
  43. // cppcheck-suppress unusedFunction
  44. int srec_hdr(unsigned int num, unsigned char *bbuf, unsigned char *sbuf)
  45. {
  46. return bin2srec(0, 0, num, bbuf, sbuf);
  47. }
  48. // cppcheck-suppress unusedFunction
  49. int srec_fin(unsigned int num, unsigned char *sbuf)
  50. {
  51. unsigned char bbuf[4], sum;
  52. memset(bbuf, 0, 4);
  53. bbuf[0] = (unsigned char)(num & 0xff);
  54. bbuf[1] = (unsigned char)((num >> 8) & 0xff);
  55. sum = sr_sum(3, 0, bbuf);
  56. (void)snprintf((char *)sbuf, 13, "S503%04X%02X\r\n", num, (unsigned)sum);
  57. return 0;
  58. }
  59. void hexdump(size_t len, unsigned char *bbuf, unsigned char *abuf)
  60. {
  61. size_t i;
  62. memset(abuf, 0, MAX_BYTES_PER_RECORD * 2 + 2);
  63. if (len > MAX_BYTES_PER_RECORD * 2)
  64. len = MAX_BYTES_PER_RECORD * 2;
  65. for (i = 0; i < len; i++) {
  66. abuf[i * 2] = hc((bbuf[i] & 0xf0) >> 4);
  67. abuf[i * 2 + 1] = hc(bbuf[i] & 0x0f);
  68. }
  69. }
  70. unsigned char hc(unsigned char x)
  71. {
  72. switch (x) {
  73. case 15:
  74. case 14:
  75. case 13:
  76. case 12:
  77. case 11:
  78. case 10:
  79. return ('A' + x - 10);
  80. case 9:
  81. case 8:
  82. case 7:
  83. case 6:
  84. case 5:
  85. case 4:
  86. case 3:
  87. case 2:
  88. case 1:
  89. case 0:
  90. return ('0' + x);
  91. default:
  92. return '0';
  93. }
  94. }
  95. unsigned char
  96. sr_sum(unsigned int count, unsigned int addr, unsigned char *bbuf)
  97. {
  98. int i, j;
  99. unsigned char sum = 0;
  100. sum = (count & 0xff);
  101. sum += ((addr & 0x000000ff));
  102. sum += ((addr & 0x0000ff00) >> 8);
  103. sum += ((addr & 0x00ff0000) >> 16);
  104. sum += ((addr & 0xff000000) >> 24);
  105. j = count - 5;
  106. for (i = 0; i < j; i++) {
  107. unsigned char k = bbuf[i];
  108. sum += k;
  109. }
  110. return ~sum;
  111. }