binloader.c 5.2 KB

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