more tracelog rework

This commit is contained in:
Philippe Teuwen 2020-05-19 02:14:43 +02:00
commit 2ba350903a
2 changed files with 51 additions and 78 deletions

View file

@ -18,6 +18,7 @@
#include "comms.h" // for sending cmds to device. GetFromBigBuf #include "comms.h" // for sending cmds to device. GetFromBigBuf
#include "fileutils.h" // for saveFile #include "fileutils.h" // for saveFile
#include "cmdlfhitag.h" // annotate hitag #include "cmdlfhitag.h" // annotate hitag
#include "pm3_cmd.h" // tracelog_hdr_t
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -25,17 +26,6 @@ static int CmdHelp(const char *Cmd);
static uint8_t *g_trace; static uint8_t *g_trace;
long g_traceLen = 0; long g_traceLen = 0;
typedef struct {
uint32_t timestamp;
uint16_t duration;
uint16_t data_len;
uint8_t frame[];
} PACKED tracelog_hdr_t;
// 4 + 2 + 2
#define TRACELOG_HDR_LEN sizeof(tracelog_hdr_t)
#define TRACELOG_NEXT_PARITY_LEN(x) (((x)hdr->data_len - 1) / 8 + 1)
static int usage_trace_list(void) { static int usage_trace_list(void) {
PrintAndLogEx(NORMAL, "List protocol data in trace buffer."); PrintAndLogEx(NORMAL, "List protocol data in trace buffer.");
PrintAndLogEx(NORMAL, "Usage: trace list <protocol> [f][c| <0|1>"); PrintAndLogEx(NORMAL, "Usage: trace list <protocol> [f][c| <0|1>");
@ -88,7 +78,7 @@ static bool is_last_record(uint16_t tracepos, uint16_t traceLen) {
static bool next_record_is_response(uint16_t tracepos, uint8_t *trace) { static bool next_record_is_response(uint16_t tracepos, uint8_t *trace) {
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos); tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos);
return ((hdr->data_len & 0x8000) == 0x8000); return (hdr->isResponse);
} }
static bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, static bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen,
@ -106,24 +96,18 @@ static bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, ui
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + *tracepos); tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + *tracepos);
uint32_t next_timestamp = hdr->timestamp; *tracepos += TRACELOG_HDR_LEN + hdr->data_len;
uint16_t next_duration = hdr->duration;
uint16_t next_data_len = hdr->data_len & 0x7FFF;
uint8_t *next_frame = hdr->frame;
*tracepos += TRACELOG_HDR_LEN + next_data_len; if ((hdr->data_len == 1) && (*data_len + hdr->data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
memcpy(topaz_reader_command + *data_len, hdr->frame, hdr->data_len);
if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) { *data_len += hdr->data_len;
memcpy(topaz_reader_command + *data_len, next_frame, next_data_len); last_timestamp = hdr->timestamp + hdr->duration;
*data_len += next_data_len;
last_timestamp = next_timestamp + next_duration;
} else { } else {
// rewind and exit // rewind and exit
*tracepos = *tracepos - next_data_len - TRACELOG_HDR_LEN; *tracepos = *tracepos - hdr->data_len - TRACELOG_HDR_LEN;
break; break;
} }
uint16_t next_parity_len = (next_data_len - 1) / 8 + 1; *tracepos += TRACELOG_PARITY_LEN(hdr);
*tracepos += next_parity_len;
} }
*duration = last_timestamp - timestamp; *duration = last_timestamp - timestamp;
@ -137,24 +121,12 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos); tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos);
bool isResponse; if (TRACELOG_HDR_LEN + hdr->data_len + TRACELOG_PARITY_LEN(hdr) > traceLen) {
uint16_t parity_len;
if ((hdr->data_len & 0x8000) == 0x8000) {
hdr->data_len &= 0x7fff;
isResponse = true;
} else {
isResponse = false;
}
parity_len = (hdr->data_len - 1) / 8 + 1;
if (TRACELOG_HDR_LEN + hdr->data_len + parity_len > traceLen) {
return traceLen; return traceLen;
} }
//set trace position //set trace position
tracepos += TRACELOG_HDR_LEN + hdr->data_len + parity_len; tracepos += TRACELOG_HDR_LEN + hdr->data_len + TRACELOG_PARITY_LEN(hdr);
if (hdr->data_len == 0) { if (hdr->data_len == 0) {
PrintAndLogEx(NORMAL, "<empty trace - possible error>"); PrintAndLogEx(NORMAL, "<empty trace - possible error>");
@ -190,7 +162,7 @@ static uint16_t printHexLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trac
PrintAndLogEx(NORMAL, "0.%010u", hdr->timestamp); PrintAndLogEx(NORMAL, "0.%010u", hdr->timestamp);
PrintAndLogEx(NORMAL, "000000 00 %s %s %s %s", PrintAndLogEx(NORMAL, "000000 00 %s %s %s %s",
(isResponse ? "ff" : "fe"), (hdr->isResponse ? "ff" : "fe"),
temp_str1, temp_str1,
temp_str2, temp_str2,
line); line);
@ -210,44 +182,32 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
// sanity check // sanity check
if (is_last_record(tracepos, traceLen)) return traceLen; if (is_last_record(tracepos, traceLen)) return traceLen;
bool isResponse; uint32_t duration;
uint16_t data_len, parity_len; uint16_t data_len;
uint32_t duration, timestamp, first_timestamp, EndOfTransmissionTimestamp; uint32_t EndOfTransmissionTimestamp;
uint8_t topaz_reader_command[9]; uint8_t topaz_reader_command[9];
char explanation[40] = {0}; char explanation[40] = {0};
uint8_t mfData[32] = {0}; uint8_t mfData[32] = {0};
size_t mfDataLen = 0; size_t mfDataLen = 0;
tracelog_hdr_t *first_hdr = (tracelog_hdr_t *)(trace); tracelog_hdr_t *first_hdr = (tracelog_hdr_t *)(trace);
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos); tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos);
first_timestamp = first_hdr->timestamp;
timestamp = hdr->timestamp;
duration = hdr->duration; duration = hdr->duration;
data_len = hdr->data_len; data_len = hdr->data_len;
if (data_len & 0x8000) { if (tracepos + TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr) > traceLen) {
data_len &= 0x7fff;
isResponse = true;
} else {
isResponse = false;
}
parity_len = (data_len - 1) / 8 + 1;
if (tracepos + TRACELOG_HDR_LEN + data_len + parity_len > traceLen) {
return traceLen; return traceLen;
} }
uint8_t *frame = hdr->frame; uint8_t *frame = hdr->frame;
uint8_t *parityBytes = hdr->frame + data_len; uint8_t *parityBytes = hdr->frame + data_len;
tracepos += TRACELOG_HDR_LEN + data_len + parity_len; tracepos += TRACELOG_HDR_LEN + data_len + TRACELOG_PARITY_LEN(hdr);
if (protocol == TOPAZ && !isResponse) { if (protocol == TOPAZ && !hdr->isResponse) {
// topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each. // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
// merge them: // merge them:
if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) { if (merge_topaz_reader_frames(hdr->timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
frame = topaz_reader_command; frame = topaz_reader_command;
} }
} }
@ -258,7 +218,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
if (data_len > 2) { if (data_len > 2) {
switch (protocol) { switch (protocol) {
case ICLASS: case ICLASS:
crcStatus = iclass_CRC_check(isResponse, frame, data_len); crcStatus = iclass_CRC_check(hdr->isResponse, frame, data_len);
break; break;
case ISO_14443B: case ISO_14443B:
case TOPAZ: case TOPAZ:
@ -266,12 +226,12 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
crcStatus = !felica_CRC_check(frame + 2, data_len - 4); crcStatus = !felica_CRC_check(frame + 2, data_len - 4);
break; break;
case PROTO_MIFARE: case PROTO_MIFARE:
crcStatus = mifare_CRC_check(isResponse, frame, data_len); crcStatus = mifare_CRC_check(hdr->isResponse, frame, data_len);
break; break;
case ISO_14443A: case ISO_14443A:
case MFDES: case MFDES:
case LTO: case LTO:
crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); crcStatus = iso14443A_CRC_check(hdr->isResponse, frame, data_len);
break; break;
case THINFILM: case THINFILM:
frame[data_len - 1] ^= frame[data_len - 2]; frame[data_len - 1] ^= frame[data_len - 2];
@ -319,11 +279,11 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
&& protocol != THINFILM && protocol != THINFILM
&& protocol != FELICA && protocol != FELICA
&& protocol != LTO && protocol != LTO
&& (isResponse || protocol == ISO_14443A) && (hdr->isResponse || protocol == ISO_14443A)
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]); snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]);
} else if (protocol == ICLASS && isResponse == false) { } else if (protocol == ICLASS && hdr->isResponse == false) {
uint8_t parity = 0; uint8_t parity = 0;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
parity ^= ((frame[0] >> i) & 1); parity ^= ((frame[0] >> i) & 1);
@ -353,19 +313,19 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
// Draw the CRC column // Draw the CRC column
const char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " ")); const char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
EndOfTransmissionTimestamp = timestamp + duration; EndOfTransmissionTimestamp = hdr->timestamp + duration;
// Always annotate LEGIC read/tag // Always annotate LEGIC read/tag
if (protocol == LEGIC) if (protocol == LEGIC)
annotateLegic(explanation, sizeof(explanation), frame, data_len); annotateLegic(explanation, sizeof(explanation), frame, data_len);
if (protocol == PROTO_MIFARE) if (protocol == PROTO_MIFARE)
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse); annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, TRACELOG_PARITY_LEN(hdr), hdr->isResponse);
if (protocol == FELICA) if (protocol == FELICA)
annotateFelica(explanation, sizeof(explanation), frame, data_len); annotateFelica(explanation, sizeof(explanation), frame, data_len);
if (!isResponse) { if (!hdr->isResponse) {
switch (protocol) { switch (protocol) {
case ICLASS: case ICLASS:
annotateIclass(explanation, sizeof(explanation), frame, data_len); annotateIclass(explanation, sizeof(explanation), frame, data_len);
@ -412,9 +372,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
for (int j = 0; j < num_lines ; j++) { for (int j = 0; j < num_lines ; j++) {
if (j == 0) { if (j == 0) {
PrintAndLogEx(NORMAL, " %10u | %10u | %s |%-72s | %s| %s", PrintAndLogEx(NORMAL, " %10u | %10u | %s |%-72s | %s| %s",
(timestamp - first_timestamp), (hdr->timestamp - first_hdr->timestamp),
(EndOfTransmissionTimestamp - first_timestamp), (EndOfTransmissionTimestamp - first_hdr->timestamp),
(isResponse ? "Tag" : "Rdr"), (hdr->isResponse ? "Tag" : "Rdr"),
line[j], line[j],
(j == num_lines - 1) ? crc : " ", (j == num_lines - 1) ? crc : " ",
(j == num_lines - 1) ? explanation : ""); (j == num_lines - 1) ? explanation : "");
@ -426,12 +386,12 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
} }
} }
if (DecodeMifareData(frame, data_len, parityBytes, isResponse, mfData, &mfDataLen)) { if (DecodeMifareData(frame, data_len, parityBytes, hdr->isResponse, mfData, &mfDataLen)) {
memset(explanation, 0x00, sizeof(explanation)); memset(explanation, 0x00, sizeof(explanation));
if (!isResponse) { if (!hdr->isResponse) {
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen);
} }
uint8_t crcc = iso14443A_CRC_check(isResponse, mfData, mfDataLen); uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen);
PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s", PrintAndLogEx(NORMAL, " | | * |%-72s | %-4s| %s",
sprint_hex_inrow_spaces(mfData, mfDataLen, 2), sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
(crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")), (crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
@ -440,16 +400,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
if (is_last_record(tracepos, traceLen)) return traceLen; if (is_last_record(tracepos, traceLen)) return traceLen;
if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) { if (showWaitCycles && !hdr->isResponse && next_record_is_response(tracepos, trace)) {
tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos); tracelog_hdr_t *next_hdr = (tracelog_hdr_t *)(trace + tracepos);
uint32_t next_timestamp = next_hdr->timestamp;
PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): %d", PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp), (EndOfTransmissionTimestamp - first_hdr->timestamp),
(next_timestamp - first_timestamp), (next_hdr->timestamp - first_hdr->timestamp),
" ", " ",
(next_timestamp - EndOfTransmissionTimestamp)); (next_hdr->timestamp - EndOfTransmissionTimestamp));
} }
return tracepos; return tracepos;

View file

@ -121,6 +121,20 @@ typedef struct {
int32_t samples_to_skip; int32_t samples_to_skip;
bool verbose; bool verbose;
} PACKED sample_config; } PACKED sample_config;
typedef struct {
uint32_t timestamp;
uint16_t duration;
uint16_t data_len : 15;
bool isResponse : 1;
uint8_t frame[];
// data_len bytes of data
// ceil(data_len/8) bytes of parity
} PACKED tracelog_hdr_t;
#define TRACELOG_HDR_LEN sizeof(tracelog_hdr_t)
#define TRACELOG_PARITY_LEN(x) (((x)->data_len - 1) / 8 + 1)
/* /*
typedef struct { typedef struct {
uint16_t start_gap; uint16_t start_gap;