v3hil: handle new protocol versions

This commit is contained in:
Triss 2022-05-19 01:07:18 +02:00
parent c375f74c51
commit 43f9d7bc54
2 changed files with 200 additions and 52 deletions

View File

@ -170,12 +170,30 @@ typedef enum {
HAL_PROTO_CONFIG_JTAG_LOCK_5XX = 0x17, HAL_PROTO_CONFIG_JTAG_LOCK_5XX = 0x17,
} hal_proto_config_t; } hal_proto_config_t;
static hal_proto_fid_t map_ver(const struct v3hil *h, hal_proto_fid_t src)
{
hal_proto_fid_t dst;
if (h->proto_ver < 0x0300 && src > HAL_PROTO_FID_GET_DEVICE_ID_PTR) {
dst = src - 1;
} else {
dst = src;
}
dbg_printc("map ver: %02x -> %02x\n", src, dst);
return dst;
}
static hal_proto_fid_t map_fid(const struct v3hil *h, hal_proto_fid_t src) static hal_proto_fid_t map_fid(const struct v3hil *h, hal_proto_fid_t src)
{ {
hal_proto_fid_t dst = h->chip->v3_functions[src]; hal_proto_fid_t dst = h->chip->v3_functions[src];
if (dst == 0) {
dst = src;
}
dbg_printc("map fid: %02x -> %02x\n", src, dst); dbg_printc("map fid: %02x -> %02x\n", src, dst);
return dst; return map_ver(h, dst);
} }
void v3hil_init(struct v3hil *h, transport_t trans, void v3hil_init(struct v3hil *h, transport_t trans,
@ -191,7 +209,7 @@ int v3hil_set_vcc(struct v3hil *h, int vcc_mv)
w16le(data, vcc_mv); w16le(data, vcc_mv);
dbg_printc("Setting VCC...\n"); dbg_printc("Setting VCC...\n");
return hal_proto_execute(&h->hal, HAL_PROTO_FID_SET_VCC, data, 2); return hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_SET_VCC), data, 2);
} }
int v3hil_comm_init(struct v3hil *h) int v3hil_comm_init(struct v3hil *h)
@ -206,6 +224,43 @@ int v3hil_comm_init(struct v3hil *h)
return -1; return -1;
if (h->hal.length < 8) { if (h->hal.length < 8) {
printc_err("warning: v3hil: short reply to version request\n"); printc_err("warning: v3hil: short reply to version request\n");
} else if (h->hal.length == 40) {
#ifdef DEBUG_V3HIL
printc_dbg("v3hil: Version:");
for (int i = 0; i < h->hal.length; i++)
printc_dbg(" %02x", h->hal.payload[i]);
printc_dbg("\n");
#endif
const uint16_t sw_version = r32le(h->hal.payload + 0);
const uint16_t sw_build = r32le(h->hal.payload + 2);
const uint32_t hw_thing = r32le(h->hal.payload + 4);
const uint32_t tool_id = r16le(h->hal.payload + 8);
const uint16_t core_version = r16le(h->hal.payload + 10);
const uint16_t hil_version = r16le(h->hal.payload + 12);
const uint16_t dcdc_layer_version = r16le(h->hal.payload + 14);
const uint16_t dcdc_mcu_version = r16le(h->hal.payload + 16);
const uint16_t com_version = r16le(h->hal.payload + 18);
const uint16_t hil_crc = r16le(h->hal.payload + 20);
const uint16_t hal_crc = r16le(h->hal.payload + 22);
const uint16_t dcdc_crc = r16le(h->hal.payload + 24);
const uint16_t core_crc = r16le(h->hal.payload + 26);
const uint16_t com_crc = r16le(h->hal.payload + 28);
const uint16_t fpga_version = r16le(h->hal.payload + 30);
const uint16_t n_rx_queues = r16le(h->hal.payload + 32);
const uint16_t rx_queue_size = r16le(h->hal.payload + 34);
const uint8_t major = (sw_version >> 14) + 1;
const uint8_t minor = (sw_version >> 8) & 0x3f;
const uint8_t patch = sw_version & 0xff;
const uint8_t build = sw_build;
printc_dbg("Version: %d.%d.%d.%d Core version: 0x%02x, HIL version: 0x%02x, HW: 0x%04x\n",
major, minor, patch, build,
core_version, hil_version, hw_thing);
h->proto_ver = (major << 8) | minor;
} else { } else {
const uint8_t major = h->hal.payload[1] >> 6; const uint8_t major = h->hal.payload[1] >> 6;
const uint8_t minor = h->hal.payload[1] & 0x3f; const uint8_t minor = h->hal.payload[1] & 0x3f;
@ -215,11 +270,13 @@ int v3hil_comm_init(struct v3hil *h)
printc_dbg("Version: %d.%d.%d.%d, HW: 0x%04x\n", printc_dbg("Version: %d.%d.%d.%d, HW: 0x%04x\n",
major, minor, patch, flavour, major, minor, patch, flavour,
r32le(h->hal.payload + 4)); r32le(h->hal.payload + 4));
h->proto_ver = (major << 8) | minor;
} }
printc_dbg("Reset firmware...\n"); printc_dbg("Reset firmware...\n");
if (hal_proto_execute(&h->hal, if (hal_proto_execute(&h->hal,
HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS, NULL, 0) < 0) map_ver(h, HAL_PROTO_FID_RESET_STATIC_GLOBAL_VARS), NULL, 0) < 0)
return -1; return -1;
return 0; return 0;
@ -231,7 +288,7 @@ int v3hil_start_jtag(struct v3hil *h, v3hil_jtag_type_t type)
uint8_t chain_id[2] = {0, 0}; uint8_t chain_id[2] = {0, 0};
dbg_printc("Start JTAG...\n"); dbg_printc("Start JTAG...\n");
if (hal_proto_execute(&h->hal, HAL_PROTO_FID_START_JTAG, if (hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_START_JTAG),
&data, 1) < 0) &data, 1) < 0)
return -1; return -1;
@ -246,19 +303,30 @@ int v3hil_start_jtag(struct v3hil *h, v3hil_jtag_type_t type)
} }
printc_dbg("Device count: %d\n", h->hal.payload[0]); printc_dbg("Device count: %d\n", h->hal.payload[0]);
return hal_proto_execute(&h->hal, HAL_PROTO_FID_SET_DEVICE_CHAIN_INFO, return hal_proto_execute(&h->hal,
chain_id, 2); map_ver(h, HAL_PROTO_FID_SET_DEVICE_CHAIN_INFO), chain_id, 2);
} }
int v3hil_stop_jtag(struct v3hil *h) int v3hil_stop_jtag(struct v3hil *h)
{ {
dbg_printc("Stop JTAG...\n"); dbg_printc("Stop JTAG...\n");
return hal_proto_execute(&h->hal, HAL_PROTO_FID_STOP_JTAG, NULL, 0); if (hal_proto_execute(&h->hal, map_ver(h, HAL_PROTO_FID_STOP_JTAG), NULL, 0) < 0)
return -1;
dbg_printc("Reset communications...\n");
h->hal.ref_id = 0;
if (hal_proto_send(&h->hal, HAL_PROTO_TYPE_EXCEPTION, NULL, 0) < 0) {
h->hal.ref_id = 0;
return -1;
}
h->hal.ref_id = 0;
return 0;
} }
int v3hil_sync(struct v3hil *h) int v3hil_sync(struct v3hil *h)
{ {
uint8_t data[32]; uint8_t data[32], datalen = 21;
h->cal.is_cal = 0; h->cal.is_cal = 0;
@ -273,8 +341,21 @@ int v3hil_sync(struct v3hil *h)
if (h->chip) { if (h->chip) {
int i; int i;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++) {
data[i + 20 - i] = h->chip->clock_map[i].value; dbg_printc("clock map %d = %02x -> %d\n",
i, h->chip->clock_map[i].value, 20-i);
data[16 + 4 - i] = h->chip->clock_map[i].value;
}
if (h->proto_ver >= 0x0308) {
datalen = 21+16;
for (i = 16; i < 32; i++) {
dbg_printc("clock map2 %d = %02x -> %d\n",
i, h->chip->clock_map[i].value, 16+4+16*2 - i);
data[16+4+16*2 - i] = h->chip->clock_map[i].value;
}
}
} else { } else {
data[5] = 1; data[5] = 1;
data[15] = 40; data[15] = 40;
@ -283,13 +364,36 @@ int v3hil_sync(struct v3hil *h)
/* We can't use map_fid() because h->chip might be NULL -- this /* We can't use map_fid() because h->chip might be NULL -- this
* function will be called before identification is complete. * function will be called before identification is complete.
*/ */
hal_proto_fid_t cmdid = (h->jtag_id == 0x89/*0x90*/)
? HAL_PROTO_FID_SJ_ASSERT_POR_SC
: HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2;
dbg_printc("Sync: assert POR\n"); dbg_printc("Sync: assert POR\n");
if (hal_proto_execute(&h->hal, if (h->chip) {
(h->jtag_id == 0x89) if (hal_proto_execute(&h->hal, map_fid(h, cmdid), data, datalen) < 0) {
? HAL_PROTO_FID_SJ_ASSERT_POR_SC return -1;
: HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2, }
data, 21) < 0) } else {
return -1; /* Need to do something for X/Xv2 devices, so try each in turn... */
cmdid = map_ver(h, cmdid);
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
cmdid = map_ver(h, HAL_PROTO_FID_SJ_ASSERT_POR_SC_X);
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
cmdid = map_ver(h, HAL_PROTO_FID_SJ_ASSERT_POR_SC_XV2);
if (hal_proto_execute(&h->hal, cmdid, data, datalen) < 0) {
return -1;
}
}
}
}
#ifdef DEBUG_V3HIL
printc_dbg("v3hil: POR result: (len %d) ", h->hal.length);
for (int i = 0; i < h->hal.length; ++i) {
printc_dbg("%02x%s", h->hal.payload[i],
(i == h->hal.length - 1) ? "\n" : " ");
}
#endif
if (h->hal.length < 8) { if (h->hal.length < 8) {
printc_err("v3hil: short reply: %d\n", h->hal.length); printc_err("v3hil: short reply: %d\n", h->hal.length);
@ -599,17 +703,24 @@ static int write_ram(struct v3hil *h, const struct chipinfo_memory *m,
address_t addr, const uint8_t *mem, address_t size) address_t addr, const uint8_t *mem, address_t size)
{ {
uint8_t data[256]; uint8_t data[256];
bool fram = false;
if (h->chip->features & CHIPINFO_FEATURE_FRAM) {
if (!strcmp(m->name, "Main") || !strcmp(m->name, "Info")) {
dbg_printc("write ram: to FRAM!\n");
fram = true;
}
}
w32le(data, addr); w32le(data, addr);
w32le(data + 4, (m->bits == 8) ? size : (size >> 1)); w32le(data + 4, (m->bits == 8 || fram) ? size : (size >> 1));
memcpy(data + 8, mem, size); memcpy(data + 8, mem, size);
dbg_printc("write ram\n"); dbg_printc("write ram\n");
if (hal_proto_execute(&h->hal, hal_proto_fid_t fid = (m->bits == 8) ? HAL_PROTO_FID_WRITE_MEM_BYTES
map_fid(h, (m->bits == 8) ? HAL_PROTO_FID_WRITE_MEM_BYTES : HAL_PROTO_FID_WRITE_MEM_WORDS;
: HAL_PROTO_FID_WRITE_MEM_WORDS), if (fram) fid = HAL_PROTO_FID_WRITE_FRAM_QUICK_XV2;
data, size + 8) < 0) { if (hal_proto_execute(&h->hal, map_fid(h, fid), data, size + 8) < 0) {
printc_err("v3hil: failed writing %d bytes to 0x%05x\n", printc_err("v3hil: failed writing %d bytes to 0x%05x\n",
size, addr); size, addr);
return -1; return -1;
@ -632,11 +743,12 @@ int v3hil_write(struct v3hil *h, address_t addr,
if (size > 128) if (size > 128)
size = 128; size = 128;
dbg_printc("write: call write flash\n"); if (m->type == CHIPINFO_MEMTYPE_FLASH) {
if (m->type == CHIPINFO_MEMTYPE_FLASH) dbg_printc("write: call write flash\n");
return write_flash(h, addr, mem, size); return write_flash(h, addr, mem, size);
}
dbg_printc("call write ram\n"); dbg_printc("write: call write ram\n");
return write_ram(h, m, addr, mem, size); return write_ram(h, m, addr, mem, size);
} }
@ -729,9 +841,11 @@ int v3hil_erase(struct v3hil *h, address_t segment)
int v3hil_update_regs(struct v3hil *h) int v3hil_update_regs(struct v3hil *h)
{ {
const hal_proto_fid_t fid = const hal_proto_fid_t fid = map_fid(h, HAL_PROTO_FID_READ_ALL_CPU_REGS);
map_fid(h, HAL_PROTO_FID_READ_ALL_CPU_REGS); const int reg_size = (fid == HAL_PROTO_FID_READ_ALL_CPU_REGS
const int reg_size = (fid == HAL_PROTO_FID_READ_ALL_CPU_REGS) ? 2 : 3; || fid == HAL_PROTO_FID_READ_ALL_CPU_REGS - 1)
? 2 : 3;
int i; int i;
int sptr = 0; int sptr = 0;
@ -767,9 +881,10 @@ int v3hil_update_regs(struct v3hil *h)
int v3hil_flush_regs(struct v3hil *h) int v3hil_flush_regs(struct v3hil *h)
{ {
const hal_proto_fid_t fid = const hal_proto_fid_t fid = map_fid(h, HAL_PROTO_FID_WRITE_ALL_CPU_REGS);
map_fid(h, HAL_PROTO_FID_WRITE_ALL_CPU_REGS); const int reg_size = (fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS
const int reg_size = (fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS) ? 2 : 3; || fid == HAL_PROTO_FID_WRITE_ALL_CPU_REGS - 1)
? 2 : 3;
int i; int i;
int dptr = 0; int dptr = 0;
uint8_t data[64]; uint8_t data[64];
@ -905,7 +1020,7 @@ static int set_param(struct v3hil *fet, hal_proto_config_t cfg,
data[0] = cfg; data[0] = cfg;
dbg_printc("Set param 0x%02x to 0x%08x\n", cfg, value); dbg_printc("Set param 0x%02x to 0x%08x\n", cfg, value);
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_CONFIGURE, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_CONFIGURE),
data, 8) < 0) { data, 8) < 0) {
printc_err("v3hil: can't set param 0x%02x to 0x%08x\n", printc_err("v3hil: can't set param 0x%02x to 0x%08x\n",
cfg, value); cfg, value);
@ -925,7 +1040,7 @@ static int idproc_89(struct v3hil *fet, uint32_t id_data_addr,
memset(data, 0, 8); memset(data, 0, 8);
w32le(data, id_data_addr); w32le(data, id_data_addr);
data[4] = 8; data[4] = 8;
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_WORDS, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_WORDS),
data, 8) < 0) data, 8) < 0)
return -1; return -1;
if (fet->hal.length < 16) { if (fet->hal.length < 16) {
@ -941,7 +1056,7 @@ static int idproc_89(struct v3hil *fet, uint32_t id_data_addr,
id->config = fet->hal.payload[13] & 0x7f; id->config = fet->hal.payload[13] & 0x7f;
printc_dbg("Read fuses...\n"); printc_dbg("Read fuses...\n");
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_GET_FUSES, NULL, 0) < 0) if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_FUSES), NULL, 0) < 0)
return -1; return -1;
if (!fet->hal.length) { if (!fet->hal.length) {
printc_err("v3hil: short reply: %d\n", fet->hal.length); printc_err("v3hil: short reply: %d\n", fet->hal.length);
@ -965,7 +1080,7 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
memset(data, 0, 8); memset(data, 0, 8);
w32le(data, dev_id_ptr); w32le(data, dev_id_ptr);
data[4] = 4; data[4] = 4;
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_QUICK_XV2, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_QUICK_XV2),
data, 8) < 0) data, 8) < 0)
return -1; return -1;
if (fet->hal.length < 8) { if (fet->hal.length < 8) {
@ -989,7 +1104,7 @@ static int idproc_9x(struct v3hil *fet, uint32_t dev_id_ptr,
w32le(data, dev_id_ptr); w32le(data, dev_id_ptr);
w32le(data + 4, tlv_size >> 1); w32le(data + 4, tlv_size >> 1);
w32le(data + 8, fet->regs[MSP430_REG_PC]); w32le(data + 8, fet->regs[MSP430_REG_PC]);
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_READ_MEM_QUICK_XV2, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_READ_MEM_QUICK_XV2),
data, 8) < 0) data, 8) < 0)
return -1; return -1;
if (fet->hal.length < tlv_size) { if (fet->hal.length < tlv_size) {
@ -1023,26 +1138,56 @@ int v3hil_identify(struct v3hil *fet)
int i; int i;
printc_dbg("Fetching JTAG ID...\n"); printc_dbg("Fetching JTAG ID...\n");
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_GET_JTAG_ID, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_JTAG_ID),
NULL, 0) < 0) NULL, 0) < 0)
return -1; return -1;
if (fet->hal.length < 12) {
printc_err("v3hil: short reply: %d\n", fet->hal.length);
return -1;
}
printc_dbg("ID:"); printc_dbg("ID:");
for (i = 0; i < fet->hal.length; i++) for (i = 0; i < fet->hal.length; i++)
printc_dbg(" %02x", fet->hal.payload[i]); printc_dbg(" %02x", fet->hal.payload[i]);
printc_dbg("\n"); printc_dbg("\n");
/* Byte at 0 is JTAG ID. 0x91, 0x95, 0x99 means CPUxV2. 0x89 if (fet->hal.length < 12) {
* means old CPU. if (fet->hal.length == 2) {
*/ fet->jtag_id = fet->hal.payload[0];
fet->jtag_id = fet->hal.payload[0];
dev_id_ptr = r32le(fet->hal.payload + 4); if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_GET_DEVICE_ID_PTR),
id_data_addr = r32le(fet->hal.payload + 8); NULL, 0) < 0)
return -1;
#ifdef DEBUG_V3HIL
dbg_printc("len: %d\n", fet->hal.length);
printc_dbg("v3hil: IDPtr:");
for (i = 0; i < fet->hal.length; i++)
printc_dbg(" %02x", fet->hal.payload[i]);
printc_dbg("\n");
#endif
if (fet->hal.length < 10) {
printc_err("v3hil: short reply: %d\n", fet->hal.length);
return -1;
} else {
dev_id_ptr = r32le(fet->hal.payload + 0);
if (dev_id_ptr == 0) {
/* welp sometimes it's this instead (JTAG ID == 0x89?) */
dev_id_ptr = r32le(fet->hal.payload + 4);
}
id_data_addr = dev_id_ptr; /* idk */
}
} else {
printc_err("v3hil: short reply: %d\n", fet->hal.length);
return -1;
}
} else {
/* Byte at 0 is JTAG ID. 0x91, 0x95, 0x99 means CPUxV2. 0x89
* means old CPU.
*/
fet->jtag_id = fet->hal.payload[0];
dev_id_ptr = r32le(fet->hal.payload + 4);
id_data_addr = r32le(fet->hal.payload + 8);
}
/* Pick fail-safe configuration */ /* Pick fail-safe configuration */
printc_dbg("Reset parameters...\n"); printc_dbg("Reset parameters...\n");
@ -1053,12 +1198,12 @@ int v3hil_identify(struct v3hil *fet)
set_param(fet, HAL_PROTO_CONFIG_PSA_TCKL_HIGH, 0) < 0 || set_param(fet, HAL_PROTO_CONFIG_PSA_TCKL_HIGH, 0) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG_MASK, 0) < 0 || set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG_MASK, 0) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG3V_MASK, 0) < 0 || set_param(fet, HAL_PROTO_CONFIG_POWER_TESTREG3V_MASK, 0) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL, 0) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ, 0) < 0) set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ, 0) < 0)
return -1; return -1;
set_param(fet, HAL_PROTO_CONFIG_NO_BSL, 0); /* is allowed to fail */
printc_dbg("Check JTAG fuse...\n"); printc_dbg("Check JTAG fuse...\n");
if (hal_proto_execute(&fet->hal, HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN, if (hal_proto_execute(&fet->hal, map_ver(fet, HAL_PROTO_FID_IS_JTAG_FUSE_BLOWN),
NULL, 0) < 0) NULL, 0) < 0)
return -1; return -1;
if ((fet->hal.length >= 2) && if ((fet->hal.length >= 2) &&
@ -1127,13 +1272,13 @@ int v3hil_configure(struct v3hil *fet)
fet->chip->power.enable_lpm5_3v) < 0 || fet->chip->power.enable_lpm5_3v) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_TESTREG3V_DISABLE_LPMX5, set_param(fet, HAL_PROTO_CONFIG_TESTREG3V_DISABLE_LPMX5,
fet->chip->power.disable_lpm5_3v) < 0 || fet->chip->power.disable_lpm5_3v) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_NO_BSL,
(fet->chip->features &
CHIPINFO_FEATURE_NO_BSL) ? 1 : 0) < 0 ||
set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ, set_param(fet, HAL_PROTO_CONFIG_ALT_ROM_ADDR_FOR_CPU_READ,
(fet->chip->features & (fet->chip->features &
CHIPINFO_FEATURE_1337) ? 1 : 0) < 0) CHIPINFO_FEATURE_1337) ? 1 : 0) < 0)
return -1; return -1;
/* is allowed to fail */
set_param(fet, HAL_PROTO_CONFIG_NO_BSL,
(fet->chip->features & CHIPINFO_FEATURE_NO_BSL) ? 1 : 0);
return 0; return 0;
} }

View File

@ -44,6 +44,9 @@ struct v3hil {
/* Lower 8 bits of saved WDTCTL */ /* Lower 8 bits of saved WDTCTL */
uint8_t wdtctl; uint8_t wdtctl;
/* Is this a v2 or v3 firmware running on the eZ-FET? */
uint16_t proto_ver;
/* Register cache: this must be flushed before restoring context /* Register cache: this must be flushed before restoring context
* and updated after saving context. * and updated after saving context.
*/ */