dirtyjtag_spi: Add DJTAG version detection
Read the version with CMD_INFO and set our `spi_master.command`
accordingly.
Change-Id: Idbbeb149b1c3d92354817a2c8db570426d834452
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/73264
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jean THOMAS <virgule@jeanthomas.me>
diff --git a/dirtyjtag_spi.c b/dirtyjtag_spi.c
index 0abaacf..a7484f9 100644
--- a/dirtyjtag_spi.c
+++ b/dirtyjtag_spi.c
@@ -114,6 +114,31 @@
return transferred;
}
+static char *dirtyjtag_info(struct dirtyjtag_spi_data *djtag_data)
+{
+ uint8_t buffer[64] = {
+ CMD_INFO,
+ };
+
+ if (dirtyjtag_send(djtag_data, buffer, 1))
+ return NULL;
+
+ const int transferred = dirtyjtag_receive(djtag_data, buffer, sizeof(buffer), -1);
+ if (transferred < 1)
+ return NULL;
+
+ return strndup((char *)buffer, transferred);
+}
+
+static unsigned int dirtyjtag_version(const char *info)
+{
+ if (!strncmp(info, "DJTAG1\n", 7))
+ return 1;
+ if (!strncmp(info, "DJTAG2\n", 7))
+ return 2;
+ return 0;
+}
+
static int dirtyjtag_spi_shutdown(void *data)
{
struct dirtyjtag_spi_data *djtag_data = (struct dirtyjtag_spi_data*)data;
@@ -125,10 +150,11 @@
return 0;
}
-static int dirtyjtag_djtag1_spi_send_command(struct dirtyjtag_spi_data *context,
+static int dirtyjtag_djtag1_spi_send_command(const struct flashctx *flash,
unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
+ struct dirtyjtag_spi_data *context = flash->mst->spi.data;
const size_t max_xfer_size = 30; // max transfer size in DJTAG1
size_t len = writecnt + readcnt;
size_t num_xfer = (len + max_xfer_size - 1 ) / max_xfer_size; // ceil(len/max_xfer_size)
@@ -181,19 +207,10 @@
return -1;
}
-static int dirtyjtag_spi_spi_send_command(const struct flashctx *flash,
- unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- struct dirtyjtag_spi_data *djtag_data = flash->mst->spi.data;
- return dirtyjtag_djtag1_spi_send_command(djtag_data, writecnt, readcnt, writearr, readarr);
-}
-
static const struct spi_master spi_master_dirtyjtag_spi = {
.features = SPI_MASTER_4BA,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_WRITE_UNLIMITED,
- .command = dirtyjtag_spi_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
.write_256 = default_spi_write_256,
@@ -203,6 +220,7 @@
static int dirtyjtag_spi_init(void)
{
+ struct spi_master dirtyjtag_spi = spi_master_dirtyjtag_spi;
struct libusb_device_handle *handle = NULL;
struct dirtyjtag_spi_data *djtag_data = NULL;
@@ -281,6 +299,25 @@
}
free(tmp);
+ char *const info = dirtyjtag_info(djtag_data);
+ if (!info) {
+ msg_perr("Failed to read DirtyJTAG Info.\n");
+ goto cleanup_libusb_handle;
+ }
+
+ msg_pinfo("DirtyJTAG Info: %s\n", info);
+ const unsigned int djtag_version = dirtyjtag_version(info);
+ switch (djtag_version) {
+ default:
+ msg_pwarn("Warning: Unknown DJTAG version %u. Assuming DJTAG1 compatibility.\n",
+ djtag_version);
+ /* fall-through */
+ case 1:
+ dirtyjtag_spi.command = dirtyjtag_djtag1_spi_send_command;
+ break;
+ }
+ free(info);
+
uint8_t commands[] = {
CMD_SETSIG, /* Set TDI/TCK to low, SRST/TRST/TMS to high */
SIG_TDI | SIG_TMS | SIG_TCK | SIG_SRST | SIG_TRST,
@@ -298,7 +335,7 @@
goto cleanup_libusb_handle;
}
- return register_spi_master(&spi_master_dirtyjtag_spi, djtag_data);
+ return register_spi_master(&dirtyjtag_spi, djtag_data);
cleanup_libusb_handle:
libusb_attach_kernel_driver(handle, 0);