From c10868f345027142b0bcea3c76b8ebd8c27d45c0 Mon Sep 17 00:00:00 2001 From: Baldanos Date: Fri, 28 Aug 2020 20:47:41 +0200 Subject: [PATCH] Add serprog protocol Serprog is fully supported by flashrom. This fixes #76 (...) --- src/hydrabus/hydrabus.mk | 3 +- src/hydrabus/hydrabus_serprog.c | 173 ++++++++++++++++++++++++++++++++ src/hydrabus/hydrabus_serprog.h | 46 +++++++++ src/main.c | 8 ++ 4 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 src/hydrabus/hydrabus_serprog.c create mode 100644 src/hydrabus/hydrabus_serprog.h diff --git a/src/hydrabus/hydrabus.mk b/src/hydrabus/hydrabus.mk index dac6ad6b..8e9f2cd4 100644 --- a/src/hydrabus/hydrabus.mk +++ b/src/hydrabus/hydrabus.mk @@ -36,7 +36,8 @@ HYDRABUSSRC = hydrabus/hydrabus.c \ hydrabus/hydrabus_mode_wiegand.c \ hydrabus/hydrabus_mode_lin.c \ hydrabus/hydrabus_bbio_aux.c \ - hydrabus/hydrabus_aux.c + hydrabus/hydrabus_aux.c \ + hydrabus/hydrabus_serprog.c # Required include directories HYDRABUSINC = ./hydrabus diff --git a/src/hydrabus/hydrabus_serprog.c b/src/hydrabus/hydrabus_serprog.c new file mode 100644 index 00000000..c6b4d604 --- /dev/null +++ b/src/hydrabus/hydrabus_serprog.c @@ -0,0 +1,173 @@ +/* + * HydraBus/HydraNFC + * + * Copyright (C) 2014-2020 Benjamin VERNOUX + * Copyright (C) 2020 Nicolas OBERLI + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "tokenline.h" + +#include "hydrabus_bbio.h" +#include "hydrabus_serprog.h" +#include "bsp_spi.h" + +void bbio_serprog_init_proto_default(t_hydra_console *con) +{ + mode_config_proto_t* proto = &con->mode->proto; + + /* Defaults */ + proto->dev_num = BSP_DEV_SPI2; + proto->config.spi.dev_gpio_pull = MODE_CONFIG_DEV_GPIO_NOPULL; + proto->config.spi.dev_mode = DEV_MASTER; + proto->config.spi.dev_speed = 7; + proto->config.spi.dev_polarity = 0; + proto->config.spi.dev_phase = 0; + proto->config.spi.dev_bit_lsb_msb = DEV_FIRSTBIT_MSB; +} + +void bbio_mode_serprog(t_hydra_console *con) +{ + uint8_t serprog_command; + uint32_t to_rx, to_tx, i; + uint8_t *tx_data = (uint8_t *)g_sbuf; + uint8_t *rx_data = (uint8_t *)g_sbuf+4096; + mode_config_proto_t* proto = &con->mode->proto; + + bbio_serprog_init_proto_default(con); + + // We no not initialize here, since flashrom takes care of starting the + // SPI interface. this allows to avoid potential electrical issues. + //bsp_spi_init(proto->dev_num, proto); + + while (!hydrabus_ubtn()) { + if(chnRead(con->sdu, &serprog_command, 1) == 1) { + switch(serprog_command) { + case S_CMD_NOP: + break; + case S_CMD_Q_IFACE: + //TODO + cprint(con, S_ACK, 1); + cprint(con, "\x01\x00", 2); + break; + case S_CMD_Q_CMDMAP: + cprint(con, S_ACK, 1); + //TODO + cprint(con, "\x3f\x01\x3f\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + cprint(con, "\x00\x00\x00\x00", 4); + break; + case S_CMD_Q_PGMNAME: + cprint(con, S_ACK, 1); + cprint(con, "Hydrabus\x00\x00\x00\x00\x00\x00\x00\x00", 16); + break; + case S_CMD_Q_SERBUF: + cprint(con, S_ACK, 1); + //16 bytes UART buffer + cprint(con, "\x10\x00", 2); + break; + case S_CMD_Q_BUSTYPE: + cprint(con, S_ACK, 1); + cprint(con, "\x08", 1); + break; + case S_CMD_SYNCNOP: + cprint(con, S_NAK, 1); + cprint(con, S_ACK, 1); + break; + case S_CMD_S_BUSTYPE: + // Dummy read + chnRead(con->sdu, &serprog_command, 1); + cprint(con, S_ACK, 1); + break; + case S_CMD_Q_WRNMAXLEN: + cprint(con, S_ACK, 1); + //4096 bytes write buffer + cprint(con, "\x00\x10\x00", 3); + break; + case S_CMD_Q_RDNMAXLEN: + cprint(con, S_ACK, 1); + //4096 bytes write buffer + cprint(con, "\x00\x10\x00", 3); + break; + case S_CMD_O_SPIOP: + chnRead(con->sdu, rx_data, 6); + to_tx = (rx_data[2] << 16) + (rx_data[1] << 8) + rx_data[0]; + to_rx = (rx_data[5] << 16) + (rx_data[4] << 8) + rx_data[3]; + if ((to_tx > 4096) || (to_rx > 4096)) { + cprint(con, S_NAK, 1); + break; + } + bsp_spi_select(proto->dev_num); + if(to_tx > 0) { + chnRead(con->sdu, tx_data, to_tx); + i=0; + while(i= 255) { + bsp_spi_write_u8(proto->dev_num, + tx_data+i, + 255); + } else { + bsp_spi_write_u8(proto->dev_num, + tx_data+i, + to_tx-i); + } + i+=255; + } + } + i=0; + while(i= 255) { + bsp_spi_read_u8(proto->dev_num, + rx_data+i, + 255); + } else { + bsp_spi_read_u8(proto->dev_num, + rx_data+i, + to_rx-i); + } + i+=255; + } + bsp_spi_unselect(proto->dev_num); + cprint(con, S_ACK, 1); + cprint(con, (char *)rx_data, to_rx); + break; + case S_CMD_S_SPI_FREQ: + chnRead(con->sdu, rx_data, 4); + //TODO: define variable speed. + cprint(con, S_ACK, 1); + break; + case S_CMD_S_PIN_STATE: + chnRead(con->sdu, rx_data, 1); + + if(rx_data[0] == 0) { + bsp_spi_deinit(proto->dev_num); + } else { + bsp_spi_init(proto->dev_num, proto); + } + cprint(con, S_ACK, 1); + break; + default: + break; + } + } + } + bsp_spi_deinit(proto->dev_num); + return; +} diff --git a/src/hydrabus/hydrabus_serprog.h b/src/hydrabus/hydrabus_serprog.h new file mode 100644 index 00000000..bd771809 --- /dev/null +++ b/src/hydrabus/hydrabus_serprog.h @@ -0,0 +1,46 @@ +/* + * HydraBus/HydraNFC + * + * Copyright (C) 2020 Nicolas OBERLI + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* According to Serial Flasher Protocol Specification - version 1 */ +#define S_ACK "\x06" +#define S_NAK "\x15" +#define S_CMD_NOP 0x00 /* No operation */ +#define S_CMD_Q_IFACE 0x01 /* Query interface version */ +#define S_CMD_Q_CMDMAP 0x02 /* Query supported commands bitmap */ +#define S_CMD_Q_PGMNAME 0x03 /* Query programmer name */ +#define S_CMD_Q_SERBUF 0x04 /* Query Serial Buffer Size */ +#define S_CMD_Q_BUSTYPE 0x05 /* Query supported bustypes */ +#define S_CMD_Q_CHIPSIZE 0x06 /* Query supported chipsize (2^n format) */ +#define S_CMD_Q_OPBUF 0x07 /* Query operation buffer size */ +#define S_CMD_Q_WRNMAXLEN 0x08 /* Query Write to opbuf: Write-N maximum length */ +#define S_CMD_R_BYTE 0x09 /* Read a single byte */ +#define S_CMD_R_NBYTES 0x0A /* Read n bytes */ +#define S_CMD_O_INIT 0x0B /* Initialize operation buffer */ +#define S_CMD_O_WRITEB 0x0C /* Write opbuf: Write byte with address */ +#define S_CMD_O_WRITEN 0x0D /* Write to opbuf: Write-N */ +#define S_CMD_O_DELAY 0x0E /* Write opbuf: udelay */ +#define S_CMD_O_EXEC 0x0F /* Execute operation buffer */ +#define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */ +#define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */ +#define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */ +#define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */ +#define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */ +#define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */ + +void bbio_serprog_init_proto_default(t_hydra_console *con); +void bbio_mode_serprog(t_hydra_console *con); diff --git a/src/main.c b/src/main.c index 7c913610..fee5e789 100644 --- a/src/main.c +++ b/src/main.c @@ -38,6 +38,7 @@ #endif #include "hydrabus/hydrabus_bbio.h" #include "hydrabus/hydrabus_sump.h" +#include "hydrabus/hydrabus_serprog.h" #include "bsp.h" @@ -100,6 +101,13 @@ THD_FUNCTION(console, arg) sump(con); } break; + /* SERPROG identification is 8*\x00, then \x10 */ + /* Enter SERPROG mode automatically */ + case 0x10: + if(i == 8) { + bbio_mode_serprog(con); + } + break; default: i=0; tl_input(con->tl, input);