binloader.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright 2012-2013 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <stdbool.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "deviceapi.h"
  17. #include "logging.h"
  18. #include "miner.h"
  19. #include "util.h"
  20. #define bailout(...) do { \
  21. applog(__VA_ARGS__); \
  22. return NULL; \
  23. } while(0)
  24. #define check_magic(L) do { \
  25. if (1 != fread(buf, 1, 1, f)) \
  26. bailout(LOG_ERR, "%s: Error reading bitstream ('%c')", \
  27. repr, L); \
  28. if (buf[0] != L) \
  29. bailout(LOG_ERR, "%s: Firmware has wrong magic ('%c')", \
  30. repr, L); \
  31. } while(0)
  32. #define read_str(eng) do { \
  33. if (1 != fread(buf, 2, 1, f)) \
  34. bailout(LOG_ERR, "%s: Error reading bitstream (" eng " len)", \
  35. repr); \
  36. len = (ubuf[0] << 8) | ubuf[1]; \
  37. if (len >= sizeof(buf)) \
  38. bailout(LOG_ERR, "%s: Firmware " eng " too long", \
  39. repr); \
  40. if (1 != fread(buf, len, 1, f)) \
  41. bailout(LOG_ERR, "%s: Error reading bitstream (" eng ")", \
  42. repr); \
  43. buf[len] = '\0'; \
  44. } while(0)
  45. void _bitstream_not_found(const char *repr, const char *fn)
  46. {
  47. applog(LOG_ERR, "ERROR: Unable to load '%s', required for %s to work!", fn, repr);
  48. applog(LOG_ERR, "ERROR: Please read README.FPGA for instructions");
  49. }
  50. FILE *open_xilinx_bitstream(const char *dname, const char *repr, const char *fwfile, unsigned long *out_len)
  51. {
  52. char buf[0x100];
  53. unsigned char *ubuf = (unsigned char*)buf;
  54. unsigned long len;
  55. char *p;
  56. FILE *f = open_bitstream(dname, fwfile);
  57. if (!f)
  58. {
  59. _bitstream_not_found(repr, fwfile);
  60. return NULL;
  61. }
  62. if (1 != fread(buf, 2, 1, f))
  63. bailout(LOG_ERR, "%s: Error reading bitstream (magic)",
  64. repr);
  65. if (buf[0] || buf[1] != 9)
  66. bailout(LOG_ERR, "%s: Firmware has wrong magic (9)",
  67. repr);
  68. if (-1 == fseek(f, 11, SEEK_CUR))
  69. bailout(LOG_ERR, "%s: Firmware seek failed",
  70. repr);
  71. check_magic('a');
  72. read_str("design name");
  73. applog(LOG_DEBUG, "%s: Firmware file %s info:",
  74. repr, fwfile);
  75. applog(LOG_DEBUG, " Design name: %s", buf);
  76. p = strrchr(buf, ';') ?: buf;
  77. p = strrchr(buf, '=') ?: p;
  78. if (p[0] == '=')
  79. ++p;
  80. unsigned long fwusercode = (unsigned long)strtoll(p, &p, 16);
  81. if (p[0] != '\0')
  82. bailout(LOG_ERR, "%s: Bad usercode in bitstream file",
  83. repr);
  84. if (fwusercode == 0xffffffff)
  85. bailout(LOG_ERR, "%s: Firmware doesn't support user code",
  86. repr);
  87. applog(LOG_DEBUG, " Version: %u, build %u", (unsigned)((fwusercode >> 8) & 0xff), (unsigned)(fwusercode & 0xff));
  88. check_magic('b');
  89. read_str("part number");
  90. applog(LOG_DEBUG, " Part number: %s", buf);
  91. check_magic('c');
  92. read_str("build date");
  93. applog(LOG_DEBUG, " Build date: %s", buf);
  94. check_magic('d');
  95. read_str("build time");
  96. applog(LOG_DEBUG, " Build time: %s", buf);
  97. check_magic('e');
  98. if (1 != fread(buf, 4, 1, f))
  99. bailout(LOG_ERR, "%s: Error reading bitstream (data len)",
  100. repr);
  101. len = ((unsigned long)ubuf[0] << 24) | ((unsigned long)ubuf[1] << 16) | (ubuf[2] << 8) | ubuf[3];
  102. applog(LOG_DEBUG, " Bitstream size: %lu", len);
  103. *out_len = len;
  104. return f;
  105. }
  106. bool load_bitstream_intelhex(bytes_t *rv, const char *dname, const char *repr, const char *fn)
  107. {
  108. char buf[0x100];
  109. size_t sz;
  110. uint8_t xsz, xrt;
  111. uint16_t xaddr;
  112. FILE *F = open_bitstream(dname, fn);
  113. if (!F)
  114. return false;
  115. while (!feof(F))
  116. {
  117. if (unlikely(ferror(F)))
  118. {
  119. applog(LOG_ERR, "Error reading '%s'", fn);
  120. goto ihxerr;
  121. }
  122. if (!fgets(buf, sizeof(buf), F))
  123. goto ihxerr;
  124. if (unlikely(buf[0] != ':'))
  125. goto ihxerr;
  126. if (unlikely(!(
  127. hex2bin(&xsz, &buf[1], 1)
  128. && hex2bin((unsigned char*)&xaddr, &buf[3], 2)
  129. && hex2bin(&xrt, &buf[7], 1)
  130. )))
  131. {
  132. applog(LOG_ERR, "Error parsing in '%s'", fn);
  133. goto ihxerr;
  134. }
  135. switch (xrt)
  136. {
  137. case 0: // data
  138. break;
  139. case 1: // EOF
  140. fclose(F);
  141. return true;
  142. default:
  143. applog(LOG_ERR, "Unsupported record type in '%s'", fn);
  144. goto ihxerr;
  145. }
  146. xaddr = be16toh(xaddr);
  147. sz = bytes_len(rv);
  148. bytes_resize(rv, xaddr + xsz);
  149. if (sz < xaddr)
  150. memset(&bytes_buf(rv)[sz], 0xff, xaddr - sz);
  151. if (unlikely(!(hex2bin(&bytes_buf(rv)[xaddr], &buf[9], xsz))))
  152. {
  153. applog(LOG_ERR, "Error parsing data in '%s'", fn);
  154. goto ihxerr;
  155. }
  156. // TODO: checksum
  157. }
  158. ihxerr:
  159. fclose(F);
  160. bytes_reset(rv);
  161. return false;
  162. }
  163. bool load_bitstream_bytes(bytes_t *rv, const char *dname, const char *repr, const char *fileprefix)
  164. {
  165. FILE *F;
  166. size_t fplen = strlen(fileprefix);
  167. char fnbuf[fplen + 4 + 1];
  168. int e;
  169. bytes_reset(rv);
  170. memcpy(fnbuf, fileprefix, fplen);
  171. strcpy(&fnbuf[fplen], ".bin");
  172. F = open_bitstream(dname, fnbuf);
  173. if (F)
  174. {
  175. char buf[0x100];
  176. size_t sz;
  177. while ( (sz = fread(buf, 1, sizeof(buf), F)) )
  178. bytes_append(rv, buf, sz);
  179. e = ferror(F);
  180. fclose(F);
  181. if (unlikely(e))
  182. {
  183. applog(LOG_ERR, "Error reading '%s'", fnbuf);
  184. bytes_reset(rv);
  185. }
  186. else
  187. return true;
  188. }
  189. strcpy(&fnbuf[fplen], ".ihx");
  190. if (load_bitstream_intelhex(rv, dname, repr, fnbuf))
  191. return true;
  192. // TODO: Xilinx
  193. _bitstream_not_found(repr, fnbuf);
  194. return false;
  195. }