A developer named Hofstede published a post recently about replacing Lenovo’s proprietary WWAN unlock binary with a 100-line bash script. It’s the kind of thing that reads as a minor curiosity at first, but once you understand the infrastructure involved, the exercise reveals exactly how much ceremony gets embedded in hardware initialization that nobody asked for.
What FCC Unlock Actually Is
The term “FCC unlock” shows up in Linux WWAN documentation without much explanation. Here is what it means: the FCC (Federal Communications Commission) requires that radio transmitters in devices sold in the United States be controllable, and one enforcement mechanism is that modem vendors ship hardware with the transmitter disabled by default. Before the modem can transmit on cellular frequencies, a software step must enable it. This is the FCC unlock step.
This is distinct from the older Lenovo WWAN whitelist problem, which ThinkPad users from the early 2010s will remember. Back then, Lenovo maintained a BIOS-level list of approved WWAN card PCI IDs. Insert a card that wasn’t on that list, and the machine refused to boot with an error message. That restriction was eventually reverse-engineered and patched out, but the FCC unlock mechanism is different: it’s a protocol-level requirement baked into the modem firmware itself, not a BIOS gate.
The modem used in modern ThinkPads, commonly the Fibocom L850-GL (based on Intel’s XMM 7360 LTE chipset), ships with its RF frontend disabled. Until an unlock command is sent via the host software stack, the modem connects to the system but cannot transmit. ModemManager, the Linux daemon that manages mobile broadband connections, is aware of this and has a hook mechanism specifically for it.
ModemManager’s FCC Unlock Hook
ModemManager has a well-documented (if lightly used) FCC unlock facility. When it detects a modem that requires an unlock step, it looks for an executable file in /usr/share/ModemManager/fcc-unlock.d/ or /etc/ModemManager/fcc-unlock.d/ with a name matching the modem’s USB vendor and product ID. For example, a file named 2cb7:0210 would be invoked for the modem with that USB ID.
The file can be anything executable: a compiled binary, a Python script, or a bash script. ModemManager passes the modem’s primary port path as an argument, runs the helper, and if it exits cleanly, considers the modem unlocked. The design deliberately makes the unlock mechanism pluggable.
Lenovo’s solution was to ship a compiled binary for this hook. The binary ships as part of their software support packages or is available via third-party packaging. It works, but it is opaque. You can’t read it, you can’t audit it, and you have to trust that it does only what it claims.
The Protocol Underneath
Understanding why 100 lines of bash is sufficient requires knowing what the modem actually speaks. Modern LTE modems typically expose two interface types over USB.
The first is MBIM (Mobile Broadband Interface Model), an open USB-IF standard for mobile broadband communication. On Linux, libmbim provides the userspace library and the mbimcli command-line tool. You can query device capabilities, manage connections, and send vendor-specific messages all through this interface.
The second is a set of AT command serial ports. The AT command set dates to Hayes modems in the 1980s, and while it has been extended enormously for GSM/LTE, the basic mechanism is the same: you open a character device like /dev/ttyUSB2, write an AT command as a string, and read the response. Vendor-specific extensions follow a consistent prefix convention; Intel/Fibocom modems use AT+X prefixed commands for proprietary operations.
A typical mbimcli invocation looks like this:
mbimcli --device=/dev/wwan0mbim0 --device-open-proxy --query-device-caps
And an AT command exchange via a character device can be scripted straightforwardly:
exec 3<>/dev/ttyUSB2
echo -e 'AT+COMMAND\r' >&3
read -t 2 response <&3
exec 3>&-
This is not exotic. The MBIM spec is public, the AT extensions for common modems are documented or reverse-engineered and widely known, and the Linux tooling for both interfaces is mature. The only thing preventing someone from writing the unlock script themselves was knowing which commands to send.
What the Blob Was Doing
When you replace a binary with 100 lines of bash that does the same thing, you learn something: the binary wasn’t complex. The FCC unlock for modems like the L850-GL typically involves sending one or a small number of vendor-specific commands to enable the radio, then verifying the response. The modem firmware enforces the lock; the host software just needs to send the right credential or command sequence.
This is the pattern across a lot of hardware initialization blobs. The “blob” label implies opacity, but opacity often obscures simplicity rather than sophistication. Firmware blobs for GPU initialization, WiFi calibration data, embedded controller code: each exists on a spectrum from genuinely complex (GPU microcontrollers running millions of lines of vendor code) to trivially simple (a handful of register writes that nobody documented). WWAN unlock sits closer to the simple end.
The bash replacement benefits are real and compounding. The script can be read, modified, packaged by any distribution, audited for what it actually sends to the modem, and maintained by anyone who understands shell scripting and the MBIM/AT command interfaces. The binary requires trusting Lenovo to ship a correct, non-malicious unlock helper. Given that the helper runs with sufficient privilege to open raw modem interfaces, that trust has some weight.
The Broader Blob Ecosystem
Linux’s relationship with binary blobs is long and uncomfortable. The kernel itself links against firmware blobs for WiFi adapters, Bluetooth controllers, GPU microcontrollers, and network cards. The linux-firmware repository collects hundreds of these, redistributed with varying license terms and essentially zero transparency into what they contain or do.
The FCC unlock blob occupies a slightly different category. It’s not firmware loaded into hardware; it runs as a userspace process on the host CPU and sends commands over a documented protocol to a modem. The modem’s own firmware remains proprietary regardless, but the host-side orchestration doesn’t need to be. This is the same distinction that separates coreboot from proprietary UEFI implementations: the hardware still has closed components, but the software that initializes and talks to those components can be open.
Projects like coreboot and Libreboot have spent years pushing this distinction in the context of BIOS/UEFI. The WWAN FCC unlock is a much smaller battleground, but the principle is identical. When the host-side initialization code is open, users can verify behavior, distributions can ship it without legal ambiguity, and the community can maintain it when the vendor stops caring.
Distribution Packaging and the Practical Gap
One practical consequence of the binary blob approach is distribution packaging. Most Linux distributions will not ship proprietary binaries without specific license agreements. A Lenovo-provided binary FCC unlock helper may or may not be redistributable; the bash script replacement is unambiguously distributable under whatever license the author chooses.
This matters for users who install ThinkPads with Linux. If the FCC unlock helper isn’t in your distribution’s repositories, your WWAN modem may appear to connect but never transmit. The typical workaround involves finding the binary from a third-party source, which creates its own supply chain questions. A shell script published on a git forge with a clear license is a better artifact for this part of the toolchain.
The ModemManager project has been moving in this direction, accumulating open-source FCC unlock helpers for various modems in its own tree. Hofstede’s script fits naturally into that ecosystem and represents exactly the kind of contribution that makes the Linux hardware support story incrementally more coherent.
What This Means for ThinkPad Users
If you run Linux on a ThinkPad with a WWAN card and have ever fought with the modem not transmitting despite appearing connected, the FCC unlock is the likely explanation. The fix has historically required installing Lenovo’s binary, finding a community-maintained package, or using a workaround. A readable, auditable bash script that does the same thing is strictly better for everyone in that position.
The larger lesson is modest but worth stating plainly: when the interface is documented and the protocol is open, there is rarely a technical reason for initialization code to be a binary blob. The blob exists because the vendor wrote it that way, not because the task requires it. One hundred lines of bash is not a performance. It’s evidence.