[NFC] Trim MIFARE Plus generator & admin-key mapping (in-place cleanup)#1035
Merged
Conversation
Replace the 18 near-identical MIFARE Plus generator thunks and their handler-table entries with a data-driven mf_plus_generator_configs[] table (uid_len / type / size / ATS per variant), dispatched via a small range predicate. The Ultralight/NTAG and Classic types keep their bespoke handlers, so the handler table now stops before the MF Plus range. Also drop mf_plus_ats_hist_ev, which was byte-identical to mf_plus_ats_hist_s (EV1/EV2 are identified by GetVersion, not the ATS). Pure refactor: the Add-Manually menu entries, the generated cards and the public SDK API are all unchanged. Trims firmware flash by removing the per-variant functions and the duplicate blob; a _Static_assert pins the config table to the enum range so a future type can't desync it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fold the three copies of the admin-key address<->type mapping (0x9000 CardMaster, 0x9001 CardConfig, 0x9003 L3Switch, 0x9004 SL1CardAuth) into one mf_plus_admin_key_addresses[] table with a forward helper (mf_plus_get_admin_key_address, replaces the poller's local id array) and a reverse helper (mf_plus_admin_key_type_from_address, replaces two identical switch statements in the listener's key-resolve and write-store paths). Behavior-preserving: both listener default fall-throughs are kept (resolve returns false; store falls through to data/config block handling), the poller authenticates the same addresses, and a _Static_assert pins the table to MfPlusAdminKeyNum. Internal helpers only; no SDK API change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🤖 Build & analyze —
|
| Metric | Size |
|---|---|
| Firmware (flash) | 855.18 KiB |
| DFU image | 855.48 KiB |
| Reserved — radio stack + FUS | 164.00 KiB |
| Free flash (usable) | 4.82 KiB |
| RAM (.data + .bss) | 7.94 KiB |
1 MiB flash = firmware + usable free + radio/FUS. The BLE coprocessor stack sits at the top of flash (load addr 0x080D7000); the linker's .free_flash (168.82 KiB) counts that region as free, so usable free = .free_flash − reserved (164.00 KiB).
📋 Public API changes
✅ No public API changes in this PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two behavior-preserving, in-place cleanups of the MIFARE Plus code. No functional change, no public SDK API change (
targets/f7/api_symbols.csvuntouched).Data-drive the MIFARE Plus manual-add generators (
lib/nfc/helpers/nfc_data_generator.c)mf_plus_generator_configs[]table, dispatched via a small range predicate. The Ultralight/NTAG and Classic types keep their bespoke handlers.mf_plus_ats_hist_ev, which was byte-identical tomf_plus_ats_hist_s(EV1/EV2 are identified by GetVersion, not the ATS)._Static_assertpins the config table to the enum range so a future type can't desync it.Single source of truth for the admin-key addresses (
lib/nfc/protocols/mf_plus/*)mf_plus_admin_key_id[]array and two identicalswitchstatements in the listener. Folded into onemf_plus_admin_key_addresses[]table with a forward helper (mf_plus_get_admin_key_address) and a reverse helper (mf_plus_admin_key_type_from_address). Internal helpers only.Why
Follow-up to #1033. The original plan there was to relocate the whole generator out of firmware into the NFC app to reclaim multiple KiB of internal flash. That turned out not to be feasible:
nfc_data_generatoris a public SDK API consumed by 5 external FAPs (nfc_magic, nfc_maker, flipcrypt, metroflip, seader), so moving it out oflib// the API would break their builds and force a major API bump. See the finding on #1033.What's left is the safe, non-breaking part: trimming redundancy in place. Also removes 3 copies of the admin-key mapping that had to be kept in sync by hand.
Flash
Measured
COMPACT=1 DEBUG=0, this branch vsdev:.text.rodata.free_flash~0.30 KiB reclaimed — modest, but free, plus the maintainability win of one source of truth.
Testing
fbt firmware_all COMPACT=1 DEBUG=0— links clean.fbt fap_nfc COMPACT=1 DEBUG=0— APPCHK passes (NFC FAP still resolves the unchanged generator API).clang-formatconformant.defaultfall-through semantics preserved exactly; poller authenticates the same addresses.Refs #1033