FCC unlock for Lenovo ThinkPad WWAN modems on Linux. Lenovo cannot release software to unlock WWAN modules in the US for Linux because the FCC requires onerous red tape to recertify them, even though they are already certified to run on Windows. This is unacceptable, so we will do it ourselves.
When a WWAN radio is FCC locked the radio stays powered down until the host sends a vendor-specific unlock message after every modem power-on. Lenovo distributes closed binaries that do this, but they gate the unlock on the SIM's country and their license forbids modifying them.
This project removes only the country gate. Every FCC unlock here is
clean-room: each was derived by reading Lenovo's own code path for that modem
and reproducing the messages it sends with stock tooling, so no Lenovo code runs
during an unlock. Lenovo's bundled libraries and wwan-orch remain in the tree
for RF/SAR provisioning only. Full derivation, per modem, with the addresses it
came from: docs/CLEANROOM-UNLOCKS.md.
The installer picks ModemManager's own unlock when one exists (maintained upstream), and falls back to this implementation otherwise.
| Modem | ID(s) | Unlock | Derived from |
|---|---|---|---|
| Foxconn T99W696 (SDX61) | 17cb:0308 |
foxunlock |
setFccUnlock_fxn → libfiisdk |
| Rolling RW101R-GL | 33f8:0301/01a4/01a8/01a9/0302 |
at-gtfcclock |
fccunlock_rw101 → libmodemauthRW101 |
| Fibocom FM350-GL | 14c3:4d75 |
at-gtfcclock |
fccunlock_fm350_l860 → libmodemauth |
| Intel L860R+ | 8086:7560 |
at-gtfcclock on Lenovo, intel-fcc-mbim on Dell |
fccunlock_fm350_l860 → libmodemauth; Dell ModemAuthenticator.exe |
| Quectel EM160R-GL | 1eac:100d |
mbimcli |
setFccUnlock_cs24 → libmbimtools |
| Quectel RM520N-GL | 1eac:1007 |
mbimcli |
setFccUnlock_cs24 → libmbimtools |
| Quectel EM061K | 2c7c:6008 |
mbimcli |
setFccUnlock_cs24 → libmbimtools |
| Quectel EM05-G | 2c7c:030a |
mbimcli |
setFccUnlock_cs24 → libmbimtools |
| Quectel EM05-CN | 2c7c:0310 |
mbimcli |
setFccUnlock_cs24 → libmbimtools |
That is every id in Lenovo's own fcc-unlock.d list, plus the two EM05 variants.
Each row's unlock is the message that OEM's path composes, reproduced with stock
tooling. The derivation, down to the instruction, is in
docs/CLEANROOM-UNLOCKS.md, the per module traces in
docs/traces/, and what is covered against what is not in
docs/COVERAGE.md.
A PCI id is not an OEM id. Both the kernel and ModemManager match vendor and product only, so every OEM shipping the same module reaches the same script, and a script carrying one OEM's sequence is incomplete for the rest. The L860R+ is the worked example: Lenovo, Dell and HP all ship it, and the dispatcher picks the method from the DMI system vendor.
Where upstream ModemManager already ships an unlock for an id, the installer prefers it. These mechanisms are being upstreamed in libqmi!473 and ModemManager !1492, !1493, !1496, !1499, !1500 and !1501; the table in docs/CLEANROOM-UNLOCKS.md tracks their state.
- ModemManager 1.22+ and
libmbim(present on any modern desktop Linux); the Intel FCC lock commands needlibmbim1.30 or newer sha256sumfrom coreutils is the only external tool the dispatchers use.xxdis deliberately not used: it ships as part of vim, is installed by default nowhere, and when missing it would hash an empty input and look exactly like a wrong model idbuild-essential,pkgconf,libmbim-glib-dev,libqmi-glib-dev(for the helper)
sudo apt install build-essential pkgconf libmbim-glib-dev libqmi-glib-devgit clone https://github.com/<you>/wwan-unlock
cd wwan-unlock
./install.sh --detect # what do I have?
sudo ./install.sh # detect, build, installForce a specific module, or list what's bundled:
./install.sh --list
sudo ./install.sh --id 17cb:0308
sudo ./install.sh --uninstallThe installer builds the helper into /usr/local/lib/wwan-unlock/ and installs a
dispatcher at /etc/ModemManager/fcc-unlock.d/<id>. ModemManager then invokes it
automatically on every modem power-on — boot, resume, or modem reset. Any existing
entry is backed up to <id>.orig and restored on uninstall.
ModemManager logs nothing on a successful FCC unlock (it only warns on failure), so the dispatcher logs its own result:
journalctl -t fcc-unlock-foxconn -b
mmcli -m any | grep -iE 'state:|power state'A good run looks like:
invoked: modem=/org/freedesktop/ModemManager1/Modem/0 port=/dev/wwan0mbim0
FCC unlock: SUCCESS
result: rc=0 elapsed=0s
RF/SAR is applied the same way as the unlock: gate-free, via wwan-orch. For
the Foxconn module the installer runs wwan-orch --sar, which dlopen()s Lenovo's
libfiisdk and calls its own Set_RF_Files (chassis-matched from the bundled SAR
tables) with the US-SIM SAR gate omitted. Set_RF_Files does its own
compare-and-skip, so on an already-provisioned modem it is a no-op. A boot-time
oneshot (wwan-sar.service) re-checks on each boot.
SAR is implemented gate-free for every family — Foxconn (Set_RF_Files),
FM350/L860/RW101/RW350 (configservice_*), Quectel cs24 (EM160/EM061K/RM520, via
setSARConfig_common), and Quectel em05 (EM05-CN + EM05-G, via set_sar_value's
EM05 mbim_set_dprconfig branch). All reuse the bundled Lenovo libraries; the EM05-G
DPR band tables (DPRConfig.xml) are extracted at install from Lenovo's own
unmodified configservice_lenovo. Full mechanism map:
docs/configservice_lenovo-map.md. SAR data
persists in modem NV/EFS, so on a modem that was ever provisioned (e.g. ran Windows
once) this changes nothing.
Skip it with --no-sar (unlock only); re-apply it alone with --sar-only.
Every unlock is clean-room. For each modem, that OEM's own code path was read,
usually Lenovo's DPR_Fcc_unlock_service and the worker library it loads, and for
modules Dell or HP sell with a different sequence, their Windows tools as well.
The messages are then reproduced here with stock tooling, and no OEM code runs
during an unlock. Four mechanisms cover the modules here:
foxunlock— Foxconn T99W696. Computes the auth hash and sends the QMI-over-MBIM message itself (service0xE4, msg0x5571). Built and installed by the installer.at-gtfcclock— Rolling RW101R-GL, Fibocom FM350-GL, and the L860R+ on a Lenovo machine. Theat+gtfcclockgen/at+gtfcclockverchallenge/response, computed in the dispatcher with stocksha256sum.intel-fcc-mbim— the L860R+ on a Dell machine. CID 1 of the Intel Mutual Authentication service overmbimcli: query, a set that asks for the challenge, then a set carrying the response.mbimcli— every Quectel.mbimcli --quectel-set-radio-state=on, which is the Quectel-service MBIM command the vendor library sends.
Where each came from in the vendor binaries, down to the instruction: docs/CLEANROOM-UNLOCKS.md. The Foxconn derivation in particular: docs/T99W696-FCC-unlock-findings.md.
The RW101R-GL answers its FCC challenge on a ttyUSB port rather than the wwan
AT service. That needs the option driver bound to the device; Linux 6.18 added
33f8:01a8, 01a9, 0301 and 0302 to its id table (also in the stable
backports), and on an earlier kernel the installer adds a udev rule to bind it.
See docs/HARDWARE-STATUS.md.
wwan-orch — RF/SAR only. Lenovo's SAR logic lives in their libraries
(libfiisdk, configservice_*); only their orchestrator binaries hold the
US-SIM gate. wwan-orch reimplements just that orchestrator, dlopen()s
Lenovo's own unmodified libraries and calls the same functions without the gate.
It is not used by any unlock. The libraries are bundled unmodified under their
license (vendor/lenovo/, see its NOTICE.md).
- Every module records the vendor path it was derived from in
MODULE_VENDOR_SEQ, and the installer prints it before touching anything. - A failed FCC unlock leaves your radio disabled — recoverable with
--uninstall, but not something to try on a machine you can't afford offline. - Every unlock is clean-room and loads no Lenovo library at runtime. Our code
(
foxunlock, the dispatchers,wwan-orch, the installer) contains no Lenovo code and modifies none of Lenovo's binaries. Lenovo's own worker libraries and data are bundled unmodified invendor/lenovo/, used only for RF/SAR, under the terms of their license, which grants the right to use and distribute them unmodified — see vendor/lenovo/NOTICE.md.
MIT — see LICENSE.
Not affiliated with or endorsed by Lenovo, Foxconn, or Qualcomm.