mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-17 01:34:41 +00:00
Merge pull request #3613 from mfcarroll/t55xx-writetest-classify
lf t55xx writetest: read each block three times and name how it differs
This commit is contained in:
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `tests/lf_t55xx_writetest.lua` - reads each block three times and names how a bad read differs (`rol1`, `ror5`, `inverted`, `shr1`) instead of only pass/fail (@mfcarroll)
|
||||
- Fixed `lf t55xx detect` - PSK1 now detects at every bit rate and subcarrier. (@iceman1001)
|
||||
- Fixed `lf t55xx detect` - FSK was skipped entirely when the field-clock pair measured as neither legal pair, losing FSK1 at RF/32 and RF/40 and every variant at RF/16 (@iceman1001)
|
||||
- Fixed `lf t55xx dump/read` - blocks were extracted at a bit offset cached from the last `detect` The offset is now anchored in graph samples (@iceman1001)
|
||||
|
||||
@@ -16,7 +16,7 @@ A strict T55x7 test suite:
|
||||
|
||||
lf t55xx wipe
|
||||
lf t55xx write -b 1 -d 00000000
|
||||
lf t55xx write -b 2 -d ffffffff
|
||||
lf t55xx write -b 2 -d aa5500ff
|
||||
lf t55xx write -b 3 -d 80000000
|
||||
lf t55xx write -b 4 -d 00000001
|
||||
|
||||
@@ -24,6 +24,14 @@ Each row names the configuration word, what it means, what `lf t55xx detect`
|
||||
made of it and how many of the four data blocks read back intact. Markers are
|
||||
also written into the session log ( `rem [ERR:...]` and `rem [SUMMARY:...]` )
|
||||
|
||||
Every block is read three times. A block that reads back differently between
|
||||
those is marked `unstable`, which is the fault a single read cannot see: the
|
||||
value is silently wrong rather than missing. A block that is wrong the same way
|
||||
each time is named where it can be - `rol1`, `ror5`, `inverted`, `shr1` - because
|
||||
a rotation points at the word boundary and an inversion at psk phase, and the two
|
||||
want different fixes. Block 1 is `00000000`, which is equal to all of its own
|
||||
rotations, so a rotated read of it cannot be told from a correct one.
|
||||
|
||||
Note: that the card is wiped before each modulation.
|
||||
|
||||
Needs a T5577 in the field.
|
||||
@@ -161,30 +169,98 @@ local function prepare()
|
||||
return true
|
||||
end
|
||||
|
||||
-- a block is read this many times, so that a value which is silently wrong on
|
||||
-- only some reads is not mistaken for one that is right
|
||||
local READS = 3
|
||||
|
||||
local function rol32(v, n)
|
||||
n = n % 32
|
||||
if n == 0 then return v end
|
||||
return ((v << n) | (v >> (32 - n))) & 0xFFFFFFFF
|
||||
end
|
||||
|
||||
---
|
||||
-- Read blocks 1-4 back. Returns how many matched and a short note naming the
|
||||
-- ones that did not.
|
||||
-- Name how `got` differs from `want`, when it can be named. A rotation says the
|
||||
-- word boundary moved, an inversion says psk picked the opposite phase, and a
|
||||
-- shift says a demodulation opened a bit early and padded with zero - different
|
||||
-- faults wanting different fixes, so worth telling apart. A word equal to all of
|
||||
-- its own rotations carries no boundary information and only gets 'differs'.
|
||||
local function classify(want, got)
|
||||
|
||||
if got == want then return 'ok' end
|
||||
|
||||
if rol32(want, 1) == want then return 'differs' end
|
||||
|
||||
for n = 1, 31 do
|
||||
if rol32(want, n) == got then
|
||||
return (n <= 16) and ('rol' .. n) or ('ror' .. (32 - n))
|
||||
end
|
||||
end
|
||||
|
||||
if (want ~ 0xFFFFFFFF) == got then return 'inverted' end
|
||||
|
||||
for n = 1, 31 do
|
||||
if (rol32(want, n) ~ 0xFFFFFFFF) == got then
|
||||
return 'inv+' .. ((n <= 16) and ('rol' .. n) or ('ror' .. (32 - n)))
|
||||
end
|
||||
end
|
||||
|
||||
for n = 1, 8 do
|
||||
if ((want >> n) & 0xFFFFFFFF) == got then return 'shr' .. n end
|
||||
if ((want << n) & 0xFFFFFFFF) == got then return 'shl' .. n end
|
||||
end
|
||||
|
||||
return 'differs'
|
||||
end
|
||||
|
||||
---
|
||||
-- Read blocks 1-4 back, READS times each. Returns how many matched on every
|
||||
-- read and a short note naming what went wrong with the ones that did not.
|
||||
local function read_back(config)
|
||||
|
||||
local good, bad = 0, {}
|
||||
|
||||
for block, want in ipairs(DATA_BLOCKS) do
|
||||
|
||||
local data = core.t55xx_readblock(block, '0', '0', '')
|
||||
local got = data and ('%08X'):format(data) or ''
|
||||
local wantv = tonumber(want, 16)
|
||||
local seen, first, stable = {}, nil, true
|
||||
|
||||
if got:lower() == want:lower() then
|
||||
for _ = 1, READS do
|
||||
local data = core.t55xx_readblock(block, '0', '0', '')
|
||||
local v = data and (data & 0xFFFFFFFF) or nil
|
||||
table.insert(seen, v)
|
||||
if first == nil then
|
||||
first = v
|
||||
elseif v ~= first then
|
||||
stable = false
|
||||
end
|
||||
end
|
||||
|
||||
if stable and first == wantv then
|
||||
good = good + 1
|
||||
else
|
||||
table.insert(bad, tostring(block))
|
||||
core.console(format('rem [ERR:READ:%s:%d] block %d: read %s instead of %s',
|
||||
config, block, block, got, want), false, true)
|
||||
local what
|
||||
if stable == false then
|
||||
what = 'unstable'
|
||||
else
|
||||
what = classify(wantv, first)
|
||||
end
|
||||
|
||||
table.insert(bad, format('b%d %s', block, what))
|
||||
|
||||
local reads = {}
|
||||
for _, v in ipairs(seen) do
|
||||
table.insert(reads, v and ('%08X'):format(v) or '----')
|
||||
end
|
||||
core.console(format('rem [ERR:READ:%s:%d] block %d: %s, wanted %s, read %s',
|
||||
config, block, block, what, want,
|
||||
table.concat(reads, ' ')), false, true)
|
||||
end
|
||||
end
|
||||
|
||||
local note = ''
|
||||
if #bad > 0 then
|
||||
note = 'block ' .. table.concat(bad, ',') .. ' bad'
|
||||
note = table.concat(bad, ' ')
|
||||
end
|
||||
return good, note
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user