add_tpdu_byte() accumulates bytes received from the reader, but passes
reader_to_card = 0, but ISO 7816-3 10.3.2 says P3 == 0 means 256 not 0
Only reachable with P3 == 0 in a receive data phase, but
simtrace2-cardem-pcsc only requests PB_AND_RX when there is command data.
Fix this anyway.
Change-Id: I0fa4741bc1293549816595e6b4e8af9e22bcfbc1
cardem:
- dispatch_usb_command_cardem() appends to uart_tx_queue from the main loop
- tx_byte_tpdu() dequeues from the USART IRQ handler @ NVIC prio 0
card_handle_reset() has the same issue, drains queue and
frees uart_tx_msg from main loop while the ISR may own them.
All of this needs protection against the irq.
Needs a fixed llist_add_tail_irqsafe(), which called __enable_irq() instead of
restoring the saved PRIMASK for some unknown reason?!?!?!?
Change-Id: I7d9cdcc56263b27dfd4649dfb1da1d67761ee923
ISO 7816-3 section 10.2 defines WT = WI x 960 x Fi/f seconds,
store as etu, etu = Fi / (D x f) seconds, so the Fi cancels,
but the D does not:
WT [etu] = WI x 960 x D
cemu dropped both (?!) -> WI x 960.
The old comment explains why Fi can be dropped, which is right, but
what about Di ?!
sniffer gets it right (wt_wi * 960UL * wt_d), so the two state machines
disagreed here again, by up to a factor of 64???!!?!!?
This was fixed in osmo-ccid-firmware in 066489d in 2020 but not ported
to st2.
Additionally the waiting time was only recalculated at the end of the ATR,
where D is still 1 by definition, so a PPS increasing D reprogrammed the
baud rate but left the waiting time untouched??!
etu duration shrinks with D by the same factor, wall clock WT is
independent of D, which is the whole point.
The old code decreased the waiting time by a factor of D:
after a PPS to D=8 the card emitted its NULL procedure byte at ~0.09s
instead of ~0.71s with a reader deadline of ~1.43s,
and the inactivity timeout fires 8x too early, which probably led to
unexplained wtime_exp errors.
Update wt when WI becomes known (end of ATR) and
where D changes (after the PPS response) + tests.
Change-Id: I4263176d6073029d01f9ff5b11a6311617956af6
US_FIDI_FI_DI_RATIO_Msk is 0x7ff,
cemu rejected >= 0x400 in emu_update_fidi() and masked with 0x3ff
in card_emu_uart_update_fidi(), but update_fidi() used by
the sniffer already used 0x7ff.
-> ratios 1024..2047 are unusable in cemu, which is the entire upper
half of ISO 7816-3 Table 7 at Di=1.
A reader trying one of those in a PPS gets the proposal echoed and
accepted, after which the card keeps transmitting at the old rate.
FI_DI_RATIO is clock periods per bit -> larger ratio is a SLOWER link.
The old check rejected slow values but accepted Fi=372/Di=64, ratio 5 !?
Unify and use the register mask (= shifed by 0 so usable as value) and
reject ratios that do not fit rather than truncating to garbage dividers.
Change-Id: I6211dd5be7c5c5d2150af2aa37a403b33e6d340d
iso7816_3_compute_fd_ratio() multiplied F by D for every d_index >= 8,
presumably because the upper half of ISO 7816-3 Table 8 encodes 1/D.
But 7816-3 2006 and 1997 differ!
That assumption is only true for the range 1010..1111, which in the
2006 version is RFU. Indices 1000 and 1001 are Di = 12 and Di = 20,
see iso7816_3_di_table[].
So right now Fi=372/Di=12 -> 372 * 12 = 4464 instead of 372 / 12 =
31.
In the cemu value is rejected in emu_update_fidi()
and the old baud rate is silently kept.
In the sniffer update_fidi() programs US_FIDI as
4464 & 0x7ff = 368, which is garbage.
Use F/D for indices 1..9 and keep the legacy 1/D reading only for the RFU
range, where we cant really do anything useful anyway.
Change-Id: I44d6451d8b04aea2b0db7291b06a812afe84e52f
libnewlib-arm-none-eabi has been removed in debian unstable, build the
firmware with picolibc instead.
Fixes: OS#7017
Change-Id: If136397b71435ea0850002ef6406067962e8d4d7
Add api call osmo_st2_cardem_request_config2(struct cardemu_usb_msg_config *)
which contains a full cardemu_usb_msg_config.
Related: SYS#6946
Change-Id: Iacde63e667472a85a5f18cb4ca99dcfa1a84dd59
The sim presence pin allows the simtrace2 to inform the modem
about the presence of the simcard. On a generic simcard slot a
button is pressed by the simcard which generate a high or low voltage level.
Even though there are specifications of minipcie or ngff defining this signal, certain
modems behave different.
Certain modems require different signals from the specification.
Extend the usb protocol to set the behaviour at runtime.
Related: SYS#6946
Change-Id: I77118114ba873fdf0778137402888b40f2442456
Set CFLAGS on top of the Makefile, to avoid using the distribution's
default CFLAGS. In debian testing and unstable, -fcf-protection was
recently added to the default CFLAGS, but it cannot be used with the
cross compiler:
[COMPILING libosmocore/source/backtrace.c]
cc1: error: '-fcf-protection=full' is not supported for this target
make[2]: *** [Makefile:270: obj/simtrace/flash_backtrace.o] Error 1
Change-Id: I5f7cd0402f9bb85dd600204fdf8855773ddbeb70
At the moment only APDUs are logged to GSMTAP. It is not uncommon that a
card is resetted by the UE multiple times during normal operation. When
the trace lacks the reset events (ATR) it becomes difficult to follow in
which state the card actually is. Let't mark reset events by sending the
ATR via GSMTAP (like simtrace2_sniff already does it)
Related: OS#6094
Change-Id: I6b4d82b6ee369c95eeca8f7d59478452395fbe54
Move the logic down to where make gets called, so we don't need the
variable. Print whether we use CLANG or GCC.
Don't put /opt/llvm-arm/bin infront of PATH unless building with CLANG.
Right now it doesn't seem to have e.g. an override for gcc, but the
files in that path may change when we update
LLVM-embedded-toolchain-for-Arm.
Related: OS#6026
Change-Id: Id768e0dbed9265f042b942e6699683723ca40a7c
Set --no-parallel, as in v10 debhelper defaults to parallel building.
This is apparently not supported by simtrace2's Makefile, it leads to
multiple non-trivial build errors. In contrib/jenkins.sh we also don't
build multiple firmwares in parallel.
Related: OS#5958
Related: https://manpages.debian.org/testing/debhelper/debhelper-compat-upgrade-checklist.7.en.html
Change-Id: I49fcc4fe9d3e795f8c3514d35ff3e2beca2917d1
The Makefile already runs autoreconf -fi in the "utils" target:
utils:
(cd host && \
autoreconf -fi && \
./configure --prefix=/usr --disable-werror && \
make)
The override is not useful, as it leads to debhelper running autoreconf
as well, but without running ./configure and make in the host directory
afterwards. So autoreconf just runs twice.
I've also considered to change debian/rules to only run the "fw"
target, and not the "utils" target of the Makefile. But that only makes
it more complex, as debhelper would then need to run make twice, once in
the root directory (as "make fw"), and once in the host directory. We
would need to add several lines to debian/rules to do effectively the
same thing.
Make this change now, as "cd host && dh_autoreconf" doesn't work with
debhelper compat level v10 anymore (--sourcedir could be used instead,
but as mentioned above, it's not useful).
Related: OS#5958
Change-Id: I12f379b4ec2de6adc86557d89319ab1d04ed5e73
* Fix UTF-8 encoding. This caused the endianness check to fail, which
reads all .c and .h files.
* Add .checkpatch.conf to skip linting for:
firmware/atmel_softpack_libraries
Change-Id: Ibb2e42e9b4307275a33e4000c201847a6bd60137
We so far didn't have interrupts enabled for those, and just caught
them "by accident" if a byte was received or if a timeout happened.
Let's explicitly enable those interrupts so we also catch those
conditions by themselves.
Change-Id: Ia27f537706b9a6252dd18175545c6f27a7d17d0e
Before this patch, all UART characters went through a fifo/ringbuffer
of depth 512, while events like timeout were delivered directly via
a global flags variable from ISR to main code. This means that one or
more correct/complete TPDUs could theoretically still be in the FIFO,
but the "Fast path" of the timeout handling is pre-empting that and
messing with the state machines.
All events from the UART should be delivered via the ring-buffer to make
sure they arrive in order at the main function.
The old "report timeout via change flags in separate USB message" code
is left in place. On the USB protocol we should keep it for
compatibility. Internally we should probably also migrate that over
to the new ring-buffer method in a second step.
Change-Id: I4434c6fcd59d1a425e9ded734bbc8b0411a0a0d8
those kind of errors should be passed to the main loop for further
processing, in-order together with the byte stream received from the
USART.
Change-Id: Iebd9bbc97c2a5a0c402e7a2711520299a1ade568
So far, we use a uint8_t ring buffer as "FIFO" between USART Rx
interrupt and main context. That's fine for expressing the bytes we
receive. However, if we also want to report USART errors synchronously
in that stream, we actually need more bits to express those.
Reporting USART errors via the ring buffer is the only way how the
sniffer code can know in which TPDU the error occurred. Reporting them
any other way (global variable, ...) would loose the timing relationship
where in the received stream the error occurred.
This change just changes the ringbuffer from 1024-entry 8bit to
512-entry 16bit and doesn't add any error reporting.
Change-Id: Ifde054fbfe7f753b61e7d3409c56eca6e0faeb4b
Not critical (we disable the USART interrupts in NVIC anyway), but
if Sniffer_init() enables this flag, it's good style for Sniffer_exit()
to disable it.
Change-Id: I92e16a160d60fcab33c81e0cf074088b9f20b9ae
It's a bad idea to have a two-character global variable which might
easily clash with local variable names.
Change-Id: Ic2fac64129d2772a1923f35e48582be3b130a0f2
This is a purely cosmetic change that groups PPS, TPDU and ATR related
global variables into structs. The structs get g_ prefixes to indicate
a global variable. This avoids confusion between very short/generic
variable names that might clash with local variables.
Change-Id: I3e02f6c6b063ebc860b7a2a54dfc6051f1ea584f
process_byte_pps() would never enter the error path in which the
first byte would be != 0xff. However, the caller already verified
this before calling process_byte_pps() so the error path should
never be hit anyway.
Change-Id: Ia74b6338219a6965e6bd35a6efcf369890e02d81
rbuf_write() will tell us in the return value if the buffer was full
(error) or not (success). Let's use that return value rather than a
theoretically race-y call to rbuf_is_full() before.
It's theoretical as the write happens from IRQ context and the read from
normal process context, so the fill-level cannot really change while
we're in the USART interrupt. So it doesn't fix a bug, just improves
coding style and also avoids an extra function call + irq-disable/re-enable.
Change-Id: Icf570d0aa48d67a19e63c6e2b6caa14438fe88e3