Rizin
unix-like reverse engineering framework and cli tools
io_gprobe.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2018 Dirk Eibach <dirk.eibach@gdsys.cc>
2 // SPDX-FileCopyrightText: 2018 Guntermann
3 // SPDX-FileCopyrightText: 2018 Drunck GmbH
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_io.h>
7 #include <rz_lib.h>
8 #include <rz_util.h>
9 #include <rz_util/rz_print.h>
10 
11 #if __UNIX__
12 #include <errno.h>
13 #include <fcntl.h>
14 #endif
15 
16 #define USE_OWNTIMER 1
17 #if USE_OWNTIMER
18 #include "io_gprobe.h"
19 #else
20 #define Timersub timersub
21 #define Timeradd timeradd
22 #define Timercmp timercmp
23 #endif
24 
25 #if __WINDOWS__
26 #include <rz_windows.h>
27 #include <tchar.h>
28 #else
29 
30 #if __linux__ || __APPLE__ || __OpenBSD__ || __FreeBSD__ || __NetBSD__ || __DragonFly__ || __HAIKU__
31 #include <sys/ioctl.h>
32 #include <termios.h>
33 #else
34 #include <stropts.h>
35 #endif
36 
37 #endif
38 
39 #define GPROBE_SIZE (1LL << 32)
40 #define GPROBE_I2C_ADDR 0x6e
41 
42 #define I2C_SLAVE 0x0703
43 
44 /* serial port code adapted from git://sigrok.org/libserialport */
45 struct gport {
46  const char *name;
47 #if __WINDOWS__
48  HANDLE hdl;
49  COMMTIMEOUTS timeouts;
50  OVERLAPPED write_ovl;
51  OVERLAPPED read_ovl;
52  OVERLAPPED wait_ovl;
53  DWORD events;
54  BYTE pending_byte;
55  BOOL writing;
56  BOOL wait_running;
57 #else
58  int fd;
59 #endif
60  int (*send_request)(struct gport *port, RzBuffer *request);
61  int (*get_reply)(struct gport *port, ut8 cmd, RzBuffer *reply);
62  void (*frame)(RzBuffer *frame);
63 
66 };
67 
68 typedef struct {
69  struct gport gport;
71 } RzIOGprobe;
72 
73 enum {
76  GPROBE_ACK = 0x0c,
77  GPROBE_RESET = 0x20,
83 };
84 
85 #if __UNIX__
86 static ut8 gprobe_checksum_i2c(const ut8 *p, unsigned int size, ut8 initial) {
87  ut8 res = initial;
88  unsigned int k;
89 
90  for (k = 0; k < size; k++) {
91  res ^= p[k];
92  }
93 
94  return res;
95 }
96 
97 static void gprobe_frame_i2c(RzBuffer *frame) {
98  ut8 size = rz_buf_size(frame) + 1;
99  ut8 header[] = { 0x51, 0x80 + size + 3, 0xc2, 0x00, 0x00 };
100 
103 
104  ut64 tmpsz;
105  const ut8 *tmp = rz_buf_data(frame, &tmpsz);
106  ut8 checksum = gprobe_checksum_i2c(tmp, tmpsz, GPROBE_I2C_ADDR);
107 
108  rz_buf_append_bytes(frame, &checksum, 1);
109 }
110 
111 static int gprobe_get_reply_i2c(struct gport *port, ut8 cmd, RzBuffer *reply) {
112  ut8 buf[131];
113  int count;
114  int ddc2bi3_len;
115  ut8 addr = 0x50;
116  ut8 checksum;
117 
118  rz_sys_usleep(40000);
119 
120  count = read(port->fd, buf, sizeof(buf));
121 
122  if (count != sizeof(buf)) {
123  return -1;
124  }
125 
126  ddc2bi3_len = buf[1] & ~0x80;
127 
128  if (((buf[0] & 0xfe) != GPROBE_I2C_ADDR) || !(buf[1] & 0x80) || (buf[2] != 0xc2) || (buf[3] != 0x00) || (buf[4] != 0x00) || (cmd != buf[6]) || !(buf[5] - 2) || (buf[5] != ddc2bi3_len - 2)) {
129  return -1;
130  }
131 
132  checksum = gprobe_checksum_i2c(&addr, 1, 0);
133 
134  if (gprobe_checksum_i2c(buf, ddc2bi3_len + 2, checksum) != buf[ddc2bi3_len + 2]) {
135  eprintf("gprobe rx checksum error\n");
136  }
137 
138  rz_buf_append_bytes(reply, buf + 7, buf[5] - 3);
139 
140  return 0;
141 }
142 
143 static int gprobe_send_request_i2c(struct gport *port, RzBuffer *request) {
144  ut64 tmpsz;
145  const ut8 *tmp = rz_buf_data(request, &tmpsz);
146  if (write(port->fd, tmp, tmpsz) != rz_buf_size(request)) {
147  return -1;
148  }
149  return 0;
150 }
151 
152 static int i2c_open(struct gport *port) {
153  char *end, filename[32];
154  int i2cbus = strtol(port->name + 4, &end, 0);
155 
156  if (*end) {
157  return -1;
158  }
159 
160  snprintf(filename, sizeof(filename), "/dev/i2c/%d", i2cbus);
161  filename[sizeof(filename) - 1] = '\0';
162  int file = rz_sys_open(filename, O_RDWR, 0);
163 
164  if (file < 0 && (errno == ENOENT || errno == ENOTDIR)) {
165  sprintf(filename, "/dev/i2c-%d", i2cbus);
167  }
168  if (file < 0) {
169  return -1;
170  }
171  if (ioctl(file, I2C_SLAVE, GPROBE_I2C_ADDR >> 1) < 0) {
172  close(file);
173  port->fd = -1;
174  return -1;
175  }
176  port->fd = file;
177  return 0;
178 }
179 #endif
180 
181 static int sp_close(struct gport *port) {
182 #if __WINDOWS__
183  /* Returns non-zero upon success, 0 upon failure. */
184  if (CloseHandle(port->hdl) == 0) {
185  return -1;
186  }
187  port->hdl = INVALID_HANDLE_VALUE;
188 
189  /* Close event handles for overlapped structures. */
190 #define CLOSE_OVERLAPPED(ovl) \
191  do { \
192  if (port->ovl.hEvent != INVALID_HANDLE_VALUE && \
193  CloseHandle(port->ovl.hEvent) == 0) \
194  return -1; \
195  } while (0)
196  CLOSE_OVERLAPPED(read_ovl);
197  CLOSE_OVERLAPPED(write_ovl);
198  CLOSE_OVERLAPPED(wait_ovl);
199 #else
200  if (close(port->fd) == -1) {
201  return -1;
202  }
203 
204  port->fd = -1;
205 #endif
206  return 0;
207 }
208 
209 #if __WINDOWS__
210 /* To be called after port receive buffer is emptied. */
211 static int restart_wait(struct gport *port) {
212  DWORD wait_result;
213 
214  if (port->wait_running) {
215  /* Check status of running wait operation. */
216  if (GetOverlappedResult(port->hdl, &port->wait_ovl,
217  &wait_result, FALSE)) {
218  port->wait_running = FALSE;
219  } else if (GetLastError() == ERROR_IO_INCOMPLETE) {
220  return 0;
221  }
222  return -1;
223  }
224  if (!port->wait_running) {
225  /* Start new wait operation. */
226  if (WaitCommEvent(port->hdl, &port->events,
227  &port->wait_ovl)) {
228  } else if (GetLastError() == ERROR_IO_PENDING) {
229  port->wait_running = TRUE;
230  }
231  return -1;
232  }
233  return 0;
234 }
235 #endif
236 
237 static int sp_open(struct gport *port) {
238 #if __WINDOWS__
239  int ret;
240  DWORD errors;
241  char *escaped_port_name;
242  COMSTAT status;
243  DCB dcb;
244  LPTSTR filename_;
245 
246  /* Prefix port name with '\\.\' to work with ports above COM9. */
247  if (!(escaped_port_name = malloc(strlen(port->name) + 5))) {
248  return -1;
249  }
250  sprintf(escaped_port_name, "\\\\.\\%s", port->name);
251 
252  filename_ = rz_sys_conv_utf8_to_win(escaped_port_name);
253 
254  port->hdl = CreateFile(filename_, GENERIC_READ | GENERIC_WRITE, 0, 0,
255  OPEN_EXISTING,
256  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0);
257 
258  free(escaped_port_name);
259 
260  if (port->hdl == INVALID_HANDLE_VALUE) {
261  return -1;
262  }
263 
264  /* All timeouts initially disabled. */
265  port->timeouts.ReadIntervalTimeout = 0;
266  port->timeouts.ReadTotalTimeoutMultiplier = 0;
267  port->timeouts.ReadTotalTimeoutConstant = 0;
268  port->timeouts.WriteTotalTimeoutMultiplier = 0;
269  port->timeouts.WriteTotalTimeoutConstant = 0;
270 
271  if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
272  sp_close(port);
273  return -1;
274  }
275 
276  /* Prepare OVERLAPPED structures. */
277 #define INIT_OVERLAPPED(ovl) \
278  do { \
279  memset(&port->ovl, 0, sizeof(port->ovl)); \
280  port->ovl.hEvent = INVALID_HANDLE_VALUE; \
281  if ((port->ovl.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL)) == INVALID_HANDLE_VALUE) { \
282  sp_close(port); \
283  return -1; \
284  } \
285  } while (0)
286 
287  INIT_OVERLAPPED(read_ovl);
288  INIT_OVERLAPPED(write_ovl);
289  INIT_OVERLAPPED(wait_ovl);
290 
291  /* Set event mask for RX and error events. */
292  if (SetCommMask(port->hdl, EV_RXCHAR | EV_ERR) == 0) {
293  sp_close(port);
294  return -1;
295  }
296 
297  port->writing = FALSE;
298  port->wait_running = FALSE;
299 
300  ret = restart_wait(port);
301 
302  if (ret < 0) {
303  sp_close(port);
304  return -1;
305  }
306 
307  dcb.fBinary = TRUE;
308  dcb.fDsrSensitivity = FALSE;
309  dcb.fErrorChar = FALSE;
310  dcb.fNull = FALSE;
311  dcb.fAbortOnError = FALSE;
312 
313  if (ClearCommError(port->hdl, &errors, &status) == 0) {
314  return -1;
315  }
316 
317  dcb.BaudRate = CBR_115200;
318 
319  dcb.ByteSize = 8;
320  dcb.Parity = NOPARITY;
321  dcb.StopBits = ONESTOPBIT;
322  dcb.fRtsControl = RTS_CONTROL_DISABLE;
323  dcb.fOutxCtsFlow = FALSE;
324  dcb.fDtrControl = DTR_CONTROL_DISABLE;
325  dcb.fOutxDsrFlow = FALSE;
326  dcb.fInX = FALSE;
327  dcb.fOutX = FALSE;
328 
329  if (!SetCommState(port->hdl, &dcb)) {
330  return -1;
331  }
332 
333  return 0;
334 #else
335  struct termios tty = { 0 };
336 
337  if ((port->fd = rz_sys_open(port->name, O_NONBLOCK | O_NOCTTY | O_RDWR, 0)) < 0) {
338  return -1;
339  }
340 
341  if (tcgetattr(port->fd, &tty) != 0) {
342  sp_close(port);
343  return -1;
344  }
345 
346  cfsetospeed(&tty, B115200);
347  cfsetispeed(&tty, B115200);
348 
349  tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
350  tty.c_iflag &= ~IGNBRK;
351  tty.c_lflag = 0;
352  tty.c_oflag = 0;
353  tty.c_cc[VMIN] = 0;
354  tty.c_cc[VTIME] = 0;
355  tty.c_iflag &= ~(IXON | IXOFF | IXANY);
356 
357  tty.c_cflag |= (CLOCAL | CREAD);
358  tty.c_cflag &= ~(PARENB | PARODD);
359  tty.c_cflag &= ~CSTOPB;
360 #ifdef CRTSCTS
361  tty.c_cflag &= ~CRTSCTS;
362 #else
363  tty.c_cflag &= ~020000000000;
364 #endif
365 
366  if (tcsetattr(port->fd, TCSANOW, &tty) != 0) {
367  return -1;
368  }
369 
370  return 0;
371 #endif
372 }
373 
374 #if __WINDOWS__
375 /* Restart wait operation if buffer was emptied. */
376 static int restart_wait_if_needed(struct gport *port, unsigned int bytes_read) {
377  DWORD errors;
378  COMSTAT comstat;
379 
380  if (bytes_read == 0) {
381  return 0;
382  }
383 
384  if (ClearCommError(port->hdl, &errors, &comstat) == 0) {
385  return -1;
386  }
387 
388  if (comstat.cbInQue == 0) {
389  if (restart_wait(port)) {
390  return -1;
391  }
392  }
393 
394  return 0;
395 }
396 #endif
397 
398 static int sp_blocking_read(struct gport *port, void *buf,
399  size_t count, unsigned int timeout_ms) {
400 #if __WINDOWS__
401  DWORD bytes_read = 0;
402 
403  /* Set timeout. */
404  if (port->timeouts.ReadIntervalTimeout != 0 ||
405  port->timeouts.ReadTotalTimeoutMultiplier != 0 ||
406  port->timeouts.ReadTotalTimeoutConstant != timeout_ms) {
407  port->timeouts.ReadIntervalTimeout = 0;
408  port->timeouts.ReadTotalTimeoutMultiplier = 0;
409  port->timeouts.ReadTotalTimeoutConstant = timeout_ms;
410  if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
411  return -1;
412  }
413  }
414 
415  /* Start read. */
416  if (ReadFile(port->hdl, buf, count, NULL, &port->read_ovl)) {
417  bytes_read = count;
418  } else if (GetLastError() == ERROR_IO_PENDING) {
419  if (GetOverlappedResult(port->hdl, &port->read_ovl, &bytes_read, TRUE) == 0)
420  return -1;
421  } else {
422  return -1;
423  }
424 
425  if (restart_wait_if_needed(port, bytes_read)) {
426  return -1;
427  }
428 
429  return bytes_read;
430 #else
431  size_t bytes_read = 0;
432  unsigned char *ptr = (unsigned char *)buf;
433  struct timeval start, delta, now, end = { 0, 0 };
434  int started = 0;
435  fd_set fds;
436  int result;
437 
438  if (timeout_ms) {
439  /* Get time at start of operation. */
441  /* Define duration of timeout. */
442  delta.tv_sec = timeout_ms / 1000;
443  delta.tv_usec = (timeout_ms % 1000) * 1000;
444  /* Calculate time at which we should give up. */
445  Timeradd(&start, &delta, &end);
446  }
447 
448  FD_ZERO(&fds);
449  FD_SET(port->fd, &fds);
450 
451  /* Loop until we have the requested number of bytes. */
452  while (bytes_read < count) {
453  /*
454  * Check timeout only if we have run select() at least once,
455  * to avoid any issues if a short timeout is reached before
456  * select() is even run.
457  */
458  if (timeout_ms && started) {
459  gettimeofday(&now, NULL);
460  if (Timercmp(&now, &end, >)) {
461  /* Timeout has expired. */
462  break;
463  }
464  Timersub(&end, &now, &delta);
465  }
466  result = select(port->fd + 1, &fds, NULL, NULL, timeout_ms ? &delta : NULL);
467  started = 1;
468  if (result < 0) {
469  if (errno == EINTR) {
470  continue;
471  } else {
472  return -1;
473  }
474  } else if (result == 0) {
475  /* Timeout has expired. */
476  break;
477  }
478 
479  /* Do read. */
480  result = read(port->fd, ptr, count - bytes_read);
481 
482  if (result < 0) {
483  if (errno == EAGAIN) {
484  /*
485  * This shouldn't happen because we did a
486  * select() first, but handle anyway.
487  */
488  continue;
489  } else {
490  /* This is an actual failure. */
491  return -1;
492  }
493  }
494 
495  bytes_read += result;
496  ptr += result;
497  }
498 
499  return bytes_read;
500 #endif
501 }
502 
503 static int sp_flush(struct gport *port) {
504 #if __WINDOWS__
505  /* Returns non-zero upon success, 0 upon failure. */
506  if (PurgeComm(port->hdl, PURGE_RXCLEAR) == 0) {
507  return -1;
508  }
509 
510  if (restart_wait(port)) {
511  return -1;
512  }
513 #else
514  if (tcflush(port->fd, TCIFLUSH) < 0) {
515  return -1;
516  }
517 #endif
518 
519  return 0;
520 }
521 
522 #if __WINDOWS__
523 static int await_write_completion(struct gport *port) {
524  DWORD bytes_written;
525  BOOL result;
526 
527  /* Wait for previous non-blocking write to complete, if any. */
528  if (port->writing) {
529  result = GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE);
530  port->writing = 0;
531  if (!result) {
532  return -1;
533  }
534  }
535 
536  return 0;
537 }
538 #endif
539 
540 static int sp_blocking_write(struct gport *port, const void *buf,
541  size_t count, unsigned int timeout_ms) {
542 #if __WINDOWS__
543  DWORD bytes_written = 0;
544 
545  if (await_write_completion(port)) {
546  return -1;
547  }
548 
549  /* Set timeout. */
550  if (port->timeouts.WriteTotalTimeoutConstant != timeout_ms) {
551  port->timeouts.WriteTotalTimeoutConstant = timeout_ms;
552  if (SetCommTimeouts(port->hdl, &port->timeouts) == 0) {
553  return -1;
554  }
555  }
556 
557  /* Start write. */
558  if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl)) {
559  return count;
560  } else if (GetLastError() == ERROR_IO_PENDING) {
561  if (GetOverlappedResult(port->hdl, &port->write_ovl, &bytes_written, TRUE) == 0) {
562  if (GetLastError() == ERROR_SEM_TIMEOUT)
563  return 0;
564  else
565  return -1;
566  }
567  return bytes_written;
568  } else {
569  return -1;
570  }
571 #else
572  size_t bytes_written = 0;
573  unsigned char *ptr = (unsigned char *)buf;
574  struct timeval start, delta, now, end = { 0, 0 };
575  int started = 0;
576  fd_set fds;
577  int result;
578 
579  if (timeout_ms) {
580  /* Get time at start of operation. */
582  /* Define duration of timeout. */
583  delta.tv_sec = timeout_ms / 1000;
584  delta.tv_usec = (timeout_ms % 1000) * 1000;
585  /* Calculate time at which we should give up. */
586  Timeradd(&start, &delta, &end);
587  }
588 
589  FD_ZERO(&fds);
590  FD_SET(port->fd, &fds);
591 
592  /* Loop until we have written the requested number of bytes. */
593  while (bytes_written < count) {
594  /*
595  * Check timeout only if we have run select() at least once,
596  * to avoid any issues if a short timeout is reached before
597  * select() is even run.
598  */
599  if (timeout_ms && started) {
600  gettimeofday(&now, NULL);
601  if (Timercmp(&now, &end, >)) {
602  /* Timeout has expired. */
603  break;
604  }
605  Timersub(&end, &now, &delta);
606  }
607  result = select(port->fd + 1, NULL, &fds, NULL, timeout_ms ? &delta : NULL);
608  started = 1;
609  if (result < 0) {
610  if (errno == EINTR) {
611  continue;
612  } else {
613  return -1;
614  }
615  } else if (result == 0) {
616  /* Timeout has expired. */
617  break;
618  }
619 
620  /* Do write. */
621  result = write(port->fd, ptr, count - bytes_written);
622 
623  if (result < 0) {
624  if (errno == EAGAIN) {
625  /* This shouldn't happen because we did a select() first, but handle anyway. */
626  continue;
627  } else {
628  /* This is an actual failure. */
629  return -1;
630  }
631  }
632 
633  bytes_written += result;
634  ptr += result;
635  }
636 
637  return bytes_written;
638 #endif
639 }
640 
641 static ut8 gprobe_checksum(const ut8 *p, unsigned int size) {
642  ut8 res = 0;
643  unsigned int k;
644 
645  for (k = 0; k < size; k++) {
646  res += p[k];
647  }
648 
649  res = ~res + 1;
650 
651  return res;
652 }
653 
654 static void gprobe_frame_sp(RzBuffer *frame) {
655  ut64 size;
656  const ut8 *tmp = rz_buf_data(frame, &size);
657  size += 2;
658  ut8 checksum;
659 
660  rz_buf_prepend_bytes(frame, (const ut8 *)&size, 1);
661  checksum = gprobe_checksum(tmp, size - 1);
662 
663  rz_buf_append_bytes(frame, &checksum, 1);
664 }
665 
666 static int gprobe_get_reply_sp(struct gport *port, ut8 cmd, RzBuffer *reply) {
667  ut8 buf[256];
668  int count = sp_blocking_read(port, buf, 2, 50);
669 
670  if (count < 2) {
671  return -1;
672  }
673 
674  if (cmd != buf[1]) {
675  return -1;
676  }
677 
678  if (!(buf[0] - 2)) {
679  return 0;
680  }
681 
682  count = sp_blocking_read(port, buf + 2, buf[0] - 2, 50) + 2;
683 
684  if (count != buf[0]) {
685  return -1;
686  }
687 
688 /* checksumming answers does not work reliably */
689 #if 0
690  if (gprobe_checksum(buf, count - 1) != buf[count - 1]) {
691  printf("### CHECKSUM FAILED\n");
692  }
693 #endif
694 
695  rz_buf_append_bytes(reply, buf + 2, count - 3);
696 
697  return 0;
698 }
699 
700 static int gprobe_send_request_sp(struct gport *port, RzBuffer *request) {
701  sp_flush(port);
702 
703  ut64 tmpsz;
704  const ut8 *tmp = rz_buf_data(request, &tmpsz);
705  if (sp_blocking_write(port, tmp, tmpsz, 100) != tmpsz) {
706  return -1;
707  }
708 
709  return 0;
710 }
711 
712 static int gprobe_read(struct gport *port, ut32 addr, ut8 *buf, ut32 count) {
714  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
715  const ut8 cmd = GPROBE_RAM_READ_2;
716  ut8 addr_be[4];
717  ut8 count_be[4];
718  int res;
719 
720  if (!request || !reply) {
722  rz_buf_free(reply);
723  return -1;
724  }
725 
726  count = RZ_MIN(port->max_rx_size, count);
727 
728  rz_write_be32(addr_be, addr);
729  rz_write_be32(count_be, count);
730 
732  rz_buf_append_bytes(request, addr_be, 4);
733  rz_buf_append_bytes(request, count_be, 4);
734 
735  port->frame(request);
736 
737  if (port->send_request(port, request)) {
738  goto fail;
739  }
740 
741  if (port->get_reply(port, cmd, reply)) {
742  goto fail;
743  }
744 
745  res = rz_buf_read_at(reply, 0, buf, rz_buf_size(reply));
746 
748  rz_buf_free(reply);
749 
750  return res;
751 
752 fail:
754  rz_buf_free(reply);
755  return -1;
756 }
757 
758 static int gprobe_write(struct gport *port, ut32 addr, const ut8 *buf, ut32 count) {
760  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
761  const ut8 cmd = GPROBE_RAM_WRITE_2;
762  ut8 addr_be[4];
763  ut8 count_be[4];
764 
765  if (!request || !reply) {
767  rz_buf_free(reply);
768  return -1;
769  }
770 
771  count = RZ_MIN(port->max_tx_size, count);
772 
773  rz_write_be32(addr_be, addr);
774  rz_write_be32(count_be, count);
775 
777  rz_buf_append_bytes(request, addr_be, 4);
779 
780  port->frame(request);
781 
782  if (port->send_request(port, request)) {
783  goto fail;
784  }
785 
786  if (port->get_reply(port, GPROBE_ACK, reply)) {
787  goto fail;
788  }
789 
791  rz_buf_free(reply);
792 
793  return count;
794 
795 fail:
797  rz_buf_free(reply);
798  return -1;
799 }
800 
801 static int gprobe_reset(struct gport *port, ut8 code) {
802  if (!port) {
803  return -1;
804  }
806  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
807  const ut8 cmd = GPROBE_RESET;
808 
809  if (!request || !reply) {
810  goto fail;
811  }
812 
815 
816  port->frame(request);
817 
818  sp_flush(port);
819 
820  if (port->send_request(port, request)) {
821  goto fail;
822  }
823 
824  if (port->get_reply(port, GPROBE_ACK, reply)) {
825  goto fail;
826  }
827 
829  rz_buf_free(reply);
830 
831  return 0;
832 
833 fail:
835  rz_buf_free(reply);
836  return -1;
837 }
838 
839 static int gprobe_debugon(struct gport *port) {
840  if (!port) {
841  return -1;
842  }
844  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
845  const ut8 cmd = GPROBE_DEBUGON;
846 
847  if (!request || !reply) {
848  goto fail;
849  }
851 
852  port->frame(request);
853 
854  if (port->send_request(port, request)) {
855  goto fail;
856  }
857 
858  if (port->get_reply(port, GPROBE_ACK, reply)) {
859  goto fail;
860  }
861 
863  rz_buf_free(reply);
864 
865  return 0;
866 
867 fail:
869  rz_buf_free(reply);
870  return -1;
871 }
872 
873 static int gprobe_debugoff(struct gport *port) {
875  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
876  const ut8 cmd = GPROBE_DEBUGOFF;
877 
878  if (!request || !reply) {
879  goto fail;
880  }
882  port->frame(request);
883  if (port->send_request(port, request)) {
884  goto fail;
885  }
886  if (port->get_reply(port, GPROBE_ACK, reply)) {
887  goto fail;
888  }
890  rz_buf_free(reply);
891  return 0;
892 fail:
894  rz_buf_free(reply);
895  return -1;
896 }
897 
898 static int gprobe_runcode(struct gport *port, ut32 addr) {
899  if (!port) {
900  return -1;
901  }
903  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
904  const ut8 cmd = GPROBE_RUN_CODE_2;
905  ut8 addr_be[4];
906 
907  if (!request || !reply) {
908  goto fail;
909  }
910 
911  rz_write_be32(addr_be, addr);
912 
914  rz_buf_append_bytes(request, addr_be, 4);
915 
916  port->frame(request);
917 
918  if (port->send_request(port, request)) {
919  goto fail;
920  }
921 
922  if (port->get_reply(port, GPROBE_ACK, reply)) {
923  goto fail;
924  }
925 
927  rz_buf_free(reply);
928 
929  return 0;
930 
931 fail:
933  rz_buf_free(reply);
934  return -1;
935 }
936 
937 static int gprobe_getdeviceid(struct gport *port, ut8 index) {
938  if (!port) {
939  return -1;
940  }
942  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
943  const ut8 cmd = GPROBE_GET_DEVICE_ID;
944 
945  if (!request || !reply) {
946  goto fail;
947  }
948 
950  rz_buf_append_bytes(request, &index, 1);
951 
952  port->frame(request);
953 
954  if (port->send_request(port, request)) {
955  goto fail;
956  }
957 
958  if (port->get_reply(port, cmd, reply)) {
959  goto fail;
960  }
961 
962  char *s = rz_buf_to_string(reply);
963  if (s) {
964  printf("%s\n", s);
965  free(s);
966  }
967 
969  rz_buf_free(reply);
970 
971  return 0;
972 
973 fail:
975  rz_buf_free(reply);
976  return -1;
977 }
978 
979 static int gprobe_getinformation(struct gport *port) {
980  if (!port) {
981  return -1;
982  }
984  RzBuffer *reply = rz_buf_new_with_bytes(NULL, 0);
986  const ut8 index = 0;
987 
988  if (!request || !reply) {
989  goto fail;
990  }
991 
993  rz_buf_append_bytes(request, &index, 1);
994 
995  port->frame(request);
996 
997  if (port->send_request(port, request)) {
998  goto fail;
999  }
1000 
1001  if (port->get_reply(port, cmd, reply)) {
1002  goto fail;
1003  }
1004 
1005  ut64 tmpsz;
1006  const ut8 *tmp = rz_buf_data(reply, &tmpsz);
1007  RzPrint *print = rz_print_new();
1008  char *dump = rz_print_hexdump_str(print, 0, tmp, tmpsz, 16, 1, 1);
1009  rz_cons_print(dump);
1010  free(dump);
1011  rz_print_free(print);
1012 
1014  rz_buf_free(reply);
1015 
1016  return 0;
1017 
1018 fail:
1020  rz_buf_free(reply);
1021  return -1;
1022 }
1023 
1024 static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count) {
1025  RzIOGprobe *gprobe;
1026  int res;
1027  int has_written = 0;
1028 
1029  if (!fd || !fd->data || !buf) {
1030  return -1;
1031  }
1032 
1033  gprobe = (RzIOGprobe *)fd->data;
1034 
1035  if ((gprobe->offset + count) > GPROBE_SIZE) {
1036  count = GPROBE_SIZE - gprobe->offset;
1037  }
1038 
1039  while (has_written < count) {
1040  res = gprobe_write(&gprobe->gport, gprobe->offset, buf + has_written, count - has_written);
1041  if (res <= 0) {
1042  return -1;
1043  }
1044  gprobe->offset += res;
1045  has_written += res;
1046  }
1047 
1048  return count;
1049 }
1050 
1051 static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count) {
1052  int res;
1053  RzIOGprobe *gprobe;
1054  int has_read = 0;
1055 
1056  if (!fd || !fd->data || !buf) {
1057  return -1;
1058  }
1059 
1060  gprobe = (RzIOGprobe *)fd->data;
1061 
1062  if ((gprobe->offset + count) > GPROBE_SIZE) {
1063  count = GPROBE_SIZE - gprobe->offset;
1064  }
1065 
1066  while (has_read < count) {
1067  res = gprobe_read(&gprobe->gport, gprobe->offset, buf + has_read, count - has_read);
1068  if (res <= 0) {
1069  return -1;
1070  }
1071  gprobe->offset += res;
1072  has_read += res;
1073  }
1074 
1075  return has_read;
1076 }
1077 
1078 static int __close(RzIODesc *fd) {
1079  RzIOGprobe *gprobe;
1080 
1081  if (!fd || !fd->data) {
1082  return -1;
1083  }
1084  gprobe = (RzIOGprobe *)fd->data;
1085 
1086  sp_close(&gprobe->gport);
1087  RZ_FREE(fd->data);
1088 
1089  return 0;
1090 }
1091 
1092 static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence) {
1093  RzIOGprobe *gprobe;
1094  if (!fd || !fd->data) {
1095  return offset;
1096  }
1097  gprobe = (RzIOGprobe *)fd->data;
1098  switch (whence) {
1099  case SEEK_SET:
1100  if (offset >= GPROBE_SIZE) {
1101  return gprobe->offset = GPROBE_SIZE - 1;
1102  }
1103  return gprobe->offset = offset;
1104  case SEEK_CUR:
1105  if ((gprobe->offset + offset) >= GPROBE_SIZE) {
1106  return gprobe->offset = GPROBE_SIZE - 1;
1107  }
1108  return gprobe->offset += offset;
1109  case SEEK_END:
1110  return gprobe->offset = GPROBE_SIZE - 1;
1111  }
1112  return offset;
1113 }
1114 
1115 static bool __plugin_open(RzIO *io, const char *pathname, bool many) {
1116  return pathname && rz_str_startswith(pathname, "gprobe://") && strlen(pathname + strlen("gprobe://"));
1117 }
1118 
1119 static RzIODesc *__open(RzIO *io, const char *pathname, int rw, int mode) {
1120  if (__plugin_open(io, pathname, 0)) {
1121  RzIOGprobe *gprobe = RZ_NEW0(RzIOGprobe);
1122 
1123  gprobe->offset = 0LL;
1124  gprobe->gport.name = pathname + strlen("gprobe://");
1125 
1126  if (rz_str_startswith(gprobe->gport.name, "i2c-")) {
1127 #if __UNIX__
1128  gprobe->gport.send_request = gprobe_send_request_i2c;
1129  gprobe->gport.get_reply = gprobe_get_reply_i2c;
1130  gprobe->gport.frame = gprobe_frame_i2c;
1131  gprobe->gport.max_tx_size = 117;
1132  gprobe->gport.max_rx_size = 121;
1133 
1134  if (i2c_open(&gprobe->gport)) {
1135  RZ_FREE(gprobe);
1136  return NULL;
1137  }
1138 #else
1139  RZ_FREE(gprobe);
1140  return NULL;
1141 #endif
1142  } else {
1145  gprobe->gport.frame = gprobe_frame_sp;
1146  gprobe->gport.max_tx_size = 248;
1147  gprobe->gport.max_rx_size = 252;
1148 
1149  if (sp_open(&gprobe->gport)) {
1150  RZ_FREE(gprobe);
1151  return NULL;
1152  }
1153  }
1154 
1155  return rz_io_desc_new(io, &rz_io_plugin_gprobe, pathname, rw, mode, gprobe);
1156  }
1157 
1158  return NULL;
1159 }
1160 
1161 static char *__system(RzIO *io, RzIODesc *fd, const char *cmd) {
1162  RzIOGprobe *gprobe;
1163 
1164  if (!fd || !fd->data) {
1165  return NULL;
1166  }
1167  gprobe = (RzIOGprobe *)fd->data;
1168 
1169  if (!cmd[0] || cmd[0] == '?' || !strcmp(cmd, "help")) {
1170  printf("Usage: R!cmd args\n"
1171  " R!reset code\n"
1172  " R!debugon\n"
1173  " R!debugoff\n"
1174  " R!runcode address\n"
1175  " R!getdeviceid\n"
1176  " R!getinformation\n");
1177  return NULL;
1178  }
1179 
1180  if (rz_str_startswith(cmd, "reset") && (strlen(cmd) > 6)) {
1181  ut32 code = (ut32)strtoul(cmd + 6, NULL, 10);
1182 
1183  gprobe_reset(&gprobe->gport, code);
1184 
1185  return NULL;
1186  }
1187 
1188  if (rz_str_startswith(cmd, "debugon")) {
1189  gprobe_debugon(&gprobe->gport);
1190 
1191  return NULL;
1192  }
1193 
1194  if (rz_str_startswith(cmd, "debugoff")) {
1195  gprobe_debugoff(&gprobe->gport);
1196 
1197  return NULL;
1198  }
1199 
1200  if (rz_str_startswith(cmd, "runcode") && (strlen(cmd) > 8)) {
1201  ut32 address = (ut32)strtoul(cmd + 8, NULL, 0);
1202 
1203  gprobe_runcode(&gprobe->gport, address);
1204 
1205  return NULL;
1206  }
1207 
1208  if (rz_str_startswith(cmd, "getdeviceid")) {
1209  ut8 index = 0;
1210 
1211  while (!gprobe_getdeviceid(&gprobe->gport, index++)) {
1212  };
1213 
1214  return NULL;
1215  }
1216 
1217  if (rz_str_startswith(cmd, "getinformation")) {
1218  gprobe_getinformation(&gprobe->gport);
1219 
1220  return NULL;
1221  }
1222 
1223  printf("Try: 'R!?'\n");
1224 
1225  return NULL;
1226 }
1227 
1229  .name = "gprobe",
1230  .desc = "Open gprobe connection",
1231  .license = "LGPL3",
1232  .uris = "gprobe://",
1233  .open = __open,
1234  .close = __close,
1235  .read = __read,
1236  .check = __plugin_open,
1237  .lseek = __lseek,
1238  .write = __write,
1239  .system = __system,
1240 };
1241 
1242 #ifndef RZ_PLUGIN_INCORE
1244  .type = RZ_LIB_TYPE_IO,
1245  .data = &rz_io_plugin_gprobe,
1246  .version = RZ_VERSION
1247 };
1248 #endif
#define RZ_API
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static fork write
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename request
Definition: sflib.h:62
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog gettimeofday
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename ioctl
Definition: sflib.h:62
uint32_t ut32
const char * k
Definition: dsignal.c:11
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static void gprobe_frame_sp(RzBuffer *frame)
Definition: io_gprobe.c:654
static int gprobe_debugoff(struct gport *port)
Definition: io_gprobe.c:873
static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count)
Definition: io_gprobe.c:1051
RzIOPlugin rz_io_plugin_gprobe
Definition: io_gprobe.c:1228
#define GPROBE_SIZE
Definition: io_gprobe.c:39
static int gprobe_getdeviceid(struct gport *port, ut8 index)
Definition: io_gprobe.c:937
static int gprobe_reset(struct gport *port, ut8 code)
Definition: io_gprobe.c:801
static int gprobe_send_request_sp(struct gport *port, RzBuffer *request)
Definition: io_gprobe.c:700
static int gprobe_getinformation(struct gport *port)
Definition: io_gprobe.c:979
static bool __plugin_open(RzIO *io, const char *pathname, bool many)
Definition: io_gprobe.c:1115
static int sp_flush(struct gport *port)
Definition: io_gprobe.c:503
static RzIODesc * __open(RzIO *io, const char *pathname, int rw, int mode)
Definition: io_gprobe.c:1119
@ GPROBE_DEBUGOFF
Definition: io_gprobe.c:75
@ GPROBE_DEBUGON
Definition: io_gprobe.c:74
@ GPROBE_GET_INFORMATION
Definition: io_gprobe.c:79
@ GPROBE_ACK
Definition: io_gprobe.c:76
@ GPROBE_RAM_READ_2
Definition: io_gprobe.c:80
@ GPROBE_RUN_CODE_2
Definition: io_gprobe.c:82
@ GPROBE_RAM_WRITE_2
Definition: io_gprobe.c:81
@ GPROBE_GET_DEVICE_ID
Definition: io_gprobe.c:78
@ GPROBE_RESET
Definition: io_gprobe.c:77
RZ_API RzLibStruct rizin_plugin
Definition: io_gprobe.c:1243
static int gprobe_get_reply_sp(struct gport *port, ut8 cmd, RzBuffer *reply)
Definition: io_gprobe.c:666
static int gprobe_debugon(struct gport *port)
Definition: io_gprobe.c:839
static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count)
Definition: io_gprobe.c:1024
static int gprobe_runcode(struct gport *port, ut32 addr)
Definition: io_gprobe.c:898
static int sp_blocking_read(struct gport *port, void *buf, size_t count, unsigned int timeout_ms)
Definition: io_gprobe.c:398
#define I2C_SLAVE
Definition: io_gprobe.c:42
static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence)
Definition: io_gprobe.c:1092
static int __close(RzIODesc *fd)
Definition: io_gprobe.c:1078
static ut8 gprobe_checksum(const ut8 *p, unsigned int size)
Definition: io_gprobe.c:641
#define GPROBE_I2C_ADDR
Definition: io_gprobe.c:40
static int sp_blocking_write(struct gport *port, const void *buf, size_t count, unsigned int timeout_ms)
Definition: io_gprobe.c:540
static char * __system(RzIO *io, RzIODesc *fd, const char *cmd)
Definition: io_gprobe.c:1161
static int sp_close(struct gport *port)
Definition: io_gprobe.c:181
static int sp_open(struct gport *port)
Definition: io_gprobe.c:237
static int gprobe_write(struct gport *port, ut32 addr, const ut8 *buf, ut32 count)
Definition: io_gprobe.c:758
static int gprobe_read(struct gport *port, ut32 addr, ut8 *buf, ut32 count)
Definition: io_gprobe.c:712
#define Timeradd(tvp, uvp, vvp)
Definition: io_gprobe.h:6
#define Timersub(tvp, uvp, vvp)
Definition: io_gprobe.h:15
#define Timercmp(tvp, uvp, cmp)
Definition: io_gprobe.h:4
voidpf void uLong size
Definition: ioapi.h:138
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char pathname
Definition: sflib.h:66
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz select
Definition: sflib.h:108
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
unsigned char BYTE
Definition: lz4.c:286
#define header(is_bt, len_min, ret_op)
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
RZ_API RzPrint * rz_print_new(void)
Definition: print.c:56
RZ_API RzPrint * rz_print_free(RzPrint *p)
Definition: print.c:101
RZ_API RZ_OWN char * rz_print_hexdump_str(RZ_NONNULL RzPrint *p, ut64 addr, RZ_NONNULL const ut8 *buf, int len, int base, int step, size_t zoomsz)
Prints a hexdump of buf at addr.
Definition: print.c:573
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
RZ_API bool rz_buf_prepend_bytes(RZ_NONNULL RzBuffer *b, RZ_NONNULL const ut8 *buf, ut64 len)
Prepend an array of bytes to the buffer.
Definition: buf.c:846
RZ_API bool rz_buf_append_bytes(RZ_NONNULL RzBuffer *b, RZ_NONNULL const ut8 *buf, ut64 len)
Append an array of bytes to the buffer.
Definition: buf.c:732
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API void rz_buf_free(RzBuffer *b)
Free all internal data hold by the buffer and the buffer.
Definition: buf.c:1253
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_bytes(RZ_NULLABLE RZ_BORROW const ut8 *bytes, ut64 len)
Creates a new buffer with a bytes array.
Definition: buf.c:465
RZ_DEPRECATE RZ_API RZ_BORROW ut8 * rz_buf_data(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut64 *size)
Return a borrowed array of bytes representing the buffer data.
Definition: buf.c:1287
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
RZ_API RZ_OWN char * rz_buf_to_string(RZ_NONNULL RzBuffer *b)
Stringify the buffer.
Definition: buf.c:642
static void rz_write_be32(void *dest, ut32 val)
Definition: rz_endian.h:98
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
Definition: io_desc.c:11
@ RZ_LIB_TYPE_IO
Definition: rz_lib.h:69
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API int rz_sys_open(const char *path, int perm, int mode)
Definition: sys.c:1740
RZ_API int rz_sys_usleep(int usecs)
Sleep for usecs microseconds.
Definition: sys.c:317
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
#define RZ_VERSION
Definition: rz_version.h:8
static int
Definition: sfsocketcall.h:114
#define ENOENT
Definition: sftypes.h:112
#define TCIFLUSH
Definition: sftypes.h:993
#define CS8
Definition: sftypes.h:942
#define FD_ZERO(set)
Definition: sftypes.h:204
#define CLOCAL
Definition: sftypes.h:948
#define O_NOCTTY
Definition: sftypes.h:491
#define IGNBRK
Definition: sftypes.h:870
#define PARODD
Definition: sftypes.h:946
#define O_NONBLOCK
Definition: sftypes.h:494
#define FD_SET(d, set)
Definition: sftypes.h:212
#define EINTR
Definition: sftypes.h:114
#define VMIN
Definition: sftypes.h:857
#define CSTOPB
Definition: sftypes.h:943
#define CRTSCTS
Definition: sftypes.h:967
#define VTIME
Definition: sftypes.h:856
#define IXON
Definition: sftypes.h:880
#define TCSANOW
Definition: sftypes.h:998
#define CREAD
Definition: sftypes.h:944
#define ENOTDIR
Definition: sftypes.h:130
#define O_RDWR
Definition: sftypes.h:488
#define PARENB
Definition: sftypes.h:945
#define IXANY
Definition: sftypes.h:881
#define CSIZE
Definition: sftypes.h:938
#define B115200
Definition: sftypes.h:951
#define EAGAIN
Definition: sftypes.h:121
#define IXOFF
Definition: sftypes.h:882
struct gport gport
Definition: io_gprobe.c:69
ut64 offset
Definition: io_gprobe.c:70
Definition: inftree9.h:24
Definition: gzappend.c:170
ut32 max_tx_size
Definition: io_gprobe.c:65
void(* frame)(RzBuffer *frame)
Definition: io_gprobe.c:62
int(* get_reply)(struct gport *port, ut8 cmd, RzBuffer *reply)
Definition: io_gprobe.c:61
int fd
Definition: io_gprobe.c:58
int(* send_request)(struct gport *port, RzBuffer *request)
Definition: io_gprobe.c:60
ut32 max_rx_size
Definition: io_gprobe.c:64
const char * name
Definition: io_gprobe.c:46
const char * name
Definition: rz_io.h:115
const char * version
Definition: rz_io.h:117
Definition: rz_io.h:59
uv_tty_t tty
Definition: main.c:7
#define fail(test)
Definition: tests.h:29
static st64 delta
Definition: vmenus.c:2425
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
DWORD
static const z80_opcode fd[]
Definition: z80_tab.h:997
static int file
Definition: z80asm.c:58
static int addr
Definition: z80asm.c:58
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
#define SEEK_END
Definition: zip.c:84
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115