ZuluSCSI_log.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /**
  2. * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
  3. * Copyright (c) 2023 joshua stein <jcs@jcs.org>
  4. *
  5. * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
  6. *
  7. * https://www.gnu.org/licenses/gpl-3.0.html
  8. * ----
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version. 
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. * GNU General Public License for more details. 
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  21. **/
  22. #include "ZuluSCSI_log.h"
  23. #include "ZuluSCSI_config.h"
  24. #include "ZuluSCSI_platform.h"
  25. #include <stdio.h>
  26. #include <stdarg.h>
  27. const char *g_log_firmwareversion = ZULU_FW_VERSION " " __DATE__ " " __TIME__;
  28. bool g_log_debug = false;
  29. // This memory buffer can be read by debugger and is also saved to zululog.txt
  30. #define LOGBUFMASK (LOGBUFSIZE - 1)
  31. // The log buffer is in special uninitialized RAM section so that it is not reset
  32. // when soft rebooting or jumping from bootloader.
  33. uint32_t g_log_magic;
  34. char g_logbuffer[LOGBUFSIZE + 1];
  35. uint32_t g_logpos;
  36. void log_raw(const char *str)
  37. {
  38. // Keep log from reboot / bootloader if magic matches expected value
  39. if (g_log_magic != 0xAA55AA55)
  40. {
  41. g_log_magic = 0xAA55AA55;
  42. g_logpos = 0;
  43. }
  44. const char *p = str;
  45. while (*p)
  46. {
  47. g_logbuffer[g_logpos & LOGBUFMASK] = *p++;
  48. g_logpos++;
  49. }
  50. // Keep buffer null-terminated
  51. g_logbuffer[g_logpos & LOGBUFMASK] = '\0';
  52. platform_log(str);
  53. }
  54. // Log byte as hex
  55. void log_raw(uint8_t value)
  56. {
  57. const char *nibble = "0123456789ABCDEF";
  58. char hexbuf[5] = {
  59. '0', 'x',
  60. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  61. 0
  62. };
  63. log_raw(hexbuf);
  64. }
  65. // Log integer as hex
  66. void log_raw(uint32_t value)
  67. {
  68. const char *nibble = "0123456789ABCDEF";
  69. char hexbuf[11] = {
  70. '0', 'x',
  71. nibble[(value >> 28) & 0xF], nibble[(value >> 24) & 0xF],
  72. nibble[(value >> 20) & 0xF], nibble[(value >> 16) & 0xF],
  73. nibble[(value >> 12) & 0xF], nibble[(value >> 8) & 0xF],
  74. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  75. 0
  76. };
  77. log_raw(hexbuf);
  78. }
  79. // Log integer as hex
  80. void log_raw(uint64_t value)
  81. {
  82. const char *nibble = "0123456789ABCDEF";
  83. char hexbuf[19] = {
  84. '0', 'x',
  85. nibble[(value >> 60) & 0xF], nibble[(value >> 56) & 0xF],
  86. nibble[(value >> 52) & 0xF], nibble[(value >> 48) & 0xF],
  87. nibble[(value >> 44) & 0xF], nibble[(value >> 40) & 0xF],
  88. nibble[(value >> 36) & 0xF], nibble[(value >> 32) & 0xF],
  89. nibble[(value >> 28) & 0xF], nibble[(value >> 24) & 0xF],
  90. nibble[(value >> 20) & 0xF], nibble[(value >> 16) & 0xF],
  91. nibble[(value >> 12) & 0xF], nibble[(value >> 8) & 0xF],
  92. nibble[(value >> 4) & 0xF], nibble[(value >> 0) & 0xF],
  93. 0
  94. };
  95. log_raw(hexbuf);
  96. }
  97. // Log integer as decimal
  98. void log_raw(int value)
  99. {
  100. char decbuf[16] = {0};
  101. char *p = &decbuf[14];
  102. int remainder = (value < 0) ? -value : value;
  103. do
  104. {
  105. *--p = '0' + (remainder % 10);
  106. remainder /= 10;
  107. } while (remainder > 0);
  108. if (value < 0)
  109. {
  110. *--p = '-';
  111. }
  112. log_raw(p);
  113. }
  114. void log_raw(bytearray array)
  115. {
  116. for (size_t i = 0; i < array.len; i++)
  117. {
  118. log_raw(array.data[i]);
  119. log_raw(" ");
  120. if (i > 32)
  121. {
  122. log_raw("... (total ", (int)array.len, ")");
  123. break;
  124. }
  125. }
  126. }
  127. uint32_t log_get_buffer_len()
  128. {
  129. return g_logpos;
  130. }
  131. const char *log_get_buffer(uint32_t *startpos, uint32_t *available)
  132. {
  133. uint32_t default_pos = 0;
  134. if (startpos == NULL)
  135. {
  136. startpos = &default_pos;
  137. }
  138. // Check oldest data available in buffer
  139. uint32_t lag = (g_logpos - *startpos);
  140. if (lag >= LOGBUFSIZE)
  141. {
  142. // If we lose data, skip 512 bytes forward to give us time to transmit
  143. // pending data before new log messages arrive. Also skip to next line
  144. // break to keep formatting consistent.
  145. uint32_t oldest = g_logpos - LOGBUFSIZE + 512;
  146. while (oldest < g_logpos)
  147. {
  148. char c = g_logbuffer[oldest & LOGBUFMASK];
  149. if (c == '\r' || c == '\n') break;
  150. oldest++;
  151. }
  152. if (oldest > g_logpos)
  153. {
  154. oldest = g_logpos;
  155. }
  156. *startpos = oldest;
  157. }
  158. const char *result = &g_logbuffer[*startpos & LOGBUFMASK];
  159. // Calculate number of bytes available
  160. uint32_t len;
  161. if ((g_logpos & LOGBUFMASK) >= (*startpos & LOGBUFMASK))
  162. {
  163. // Can read directly to g_logpos
  164. len = g_logpos - *startpos;
  165. }
  166. else
  167. {
  168. // Buffer wraps, read to end of buffer now and start from beginning on next call.
  169. len = LOGBUFSIZE - (*startpos & LOGBUFMASK);
  170. }
  171. if (available) { *available = len; }
  172. *startpos += len;
  173. return result;
  174. }
  175. #ifdef NETWORK_DEBUG_LOGGING
  176. // TODO write directly global log buffer to save some memory
  177. static char shared_log_buf[1500 * 3];
  178. // core method for variadic printf like logging
  179. static void log_va(bool debug, const char *format, va_list ap)
  180. {
  181. vsnprintf(shared_log_buf, sizeof(shared_log_buf), format, ap);
  182. if (debug)
  183. {
  184. dbgmsg(shared_log_buf);
  185. }
  186. else
  187. {
  188. logmsg(shared_log_buf);
  189. }
  190. }
  191. void logmsg_f(const char *format, ...)
  192. {
  193. va_list ap;
  194. va_start(ap, format);
  195. log_va(false, format, ap);
  196. va_end(ap);
  197. }
  198. void dbgmsg_f(const char *format, ...)
  199. {
  200. if (!g_log_debug)
  201. return;
  202. va_list ap;
  203. va_start(ap, format);
  204. log_va(true, format, ap);
  205. va_end(ap);
  206. }
  207. // core method for logging a data buffer into a hex string
  208. void log_hex_buf(const unsigned char *buf, unsigned long size, bool debug)
  209. {
  210. static char hex[] = "0123456789abcdef";
  211. int o = 0;
  212. for (int j = 0; j < size; j++) {
  213. if (o + 3 >= sizeof(shared_log_buf))
  214. break;
  215. if (j != 0)
  216. shared_log_buf[o++] = ' ';
  217. shared_log_buf[o++] = hex[(buf[j] >> 4) & 0xf];
  218. shared_log_buf[o++] = hex[buf[j] & 0xf];
  219. shared_log_buf[o] = 0;
  220. }
  221. if (debug)
  222. dbgmsg(shared_log_buf);
  223. else
  224. logmsg(shared_log_buf);
  225. }
  226. void logmsg_buf(const unsigned char *buf, unsigned long size)
  227. {
  228. log_hex_buf(buf, size, false);
  229. }
  230. void dbgmsg_buf(const unsigned char *buf, unsigned long size)
  231. {
  232. if (!g_log_debug)
  233. return;
  234. log_hex_buf(buf, size, true);
  235. }
  236. #endif // NETWORK_DEBUG_LOGGING