A while ago I bought a ThinkPad X220 that came with a Realtek Wi-Fi card, a RTK-RTL8188CE that requires some extra work on Debian, and in turn Linux, to get running. Wi-Fi has always been hit-and-miss for me due to the proprietary nature of most vendor-supplied wireless drivers. Therefore, I went on a journey to install another Wi-Fi card and tell you the tale of these epic travels below.
Here be danger (and dragons): The following report describes my own experiences swapping out a Wi-Fi card. I recommend that you consult the maintenance manual of your X220 and take great care flashing the BIOS. Furthermore, there is always the risk of outputting unwanted radio waves or keep your neighbor from streaming Space Force or Chasing Cameron on Netflix.
The Wi-Fi card
The German ThinkPad wiki lists the Intel Centrino Ultimate-N 6300 WLAN as one of the Lenovo first-party distributed cards for the X220. Upon ordering this card online and receiving it, I discovered that this third-party card won’t work with this Lenovo ThinkPad for profit/we-care reasons.
When booting up the X220, I received a very nasty BIOS error along the lines of
Unauthorized network card plugged in
And I thought for a second that my laptop is joking. But it wasn’t. Lenovo does not joke. So, I went on trying to make it work.
Getting the files
First, I needed to get the tools necessary to modify the BIOS. The BIOS holds the whitelisted PCI card IDs and we need to change them or completely disable the whitelist check. I had to do the following:
- Download modified BIOS from Bios Mods
- Download Windows 7 PE https://archive.org/details/win-7-pe because Flash tools don’t care about Linux, and I don’t care about paying for Windows.
- Create a bootable USB stick in Windows VM using Rufus (I wasn’t sure whether just dd-ing into the USB drive from Debian would work) and copy the BIOS files on there as well
Rufus on Windows is pleasant to use. My attempt of using unetbootin on macOS
was not pleasant. And again, I wasn’t sure whether dd
or tail
ing to
/dev/diskN
would have worked. Previous attempts of flashing Windows XP PE did
not go well and the ThinkPad X220 refused to boot, regardless of UEFI/Legacy
boot settings.
Flashing to the original Lenovo BIOS
My BIOS was reasonably old and never updated by me (I am trying to remember the exact version it was shipped with), but the linked patches BIOS will first have you update to the Lenovo distributed version v1.45 of the BIOS. To install the original BIOS, I performed the following steps:
- Boot into Windows 7 PE
- Unpack modified BIOS files
- Install the original Lenovo BIOS update as per the Readme.txt
The default flash step by Lenovo will fail because of a missing battery on my system, so I ran the following manually (remembering to adjust paths):
D:\DRIVERS\FLASH\8duj30us\WinFlash.exe /v /cs /sd /sv /ss ^
D:\DRIVERS\FLASH\8duj30us\8DET75WW\$01CB000.FL1
On a side note, this is how to retrieve information about your battery in the command line
WMIC Path Win32_Battery Get Availability
among others.
I received the integer 2
as a response, meaning that despite my having an
original X220 battery installed, Windows 7 PE, in this combination with my
ThinkPad cannot recognize the battery correctly. This is despite DeviceID
and
EstimatedChargeRemaining
giving me back numbers that make sense. The official
flash tool repeatedly instructed me to restart and install a battery.
Using rare hardware and software combinations sometimes feels like slow erosion chipping off your patience bit by bit. Too bad for slow erosion, as I have laser focus and a coffee machine.
Flashing the patched BIOS
Now it was time to flash the modded BIOS on top of Lenovo’s original BIOS. I
restarted and booted into Windows 7 PE again and ran Flash.bat
from
Lenovo X220 v1.45 Modified Bios (no whitelist only)
folder, and restarted one
more time after the flashing concluded successfully.
Install the PCI card
Following the instructions from the maintenance manual, I installed the new Mini PCIe card, taking care to connect the labeled antenna jacks on the card correctly to their corresponding cables as per the manual:
- Jack TR1: Gray cable
- Jack TR2: Black cable
- Jack TR3: White cable
In my case, the jacks on the Wi-Fi card were labeled 1, 2, and 3 without the TR in front. I hope this still means that the correct antennas are connected to the interface in the right order.
The steps to open the case are as follows:
- Disconnect the battery and power
- Remove the keyboard
- Remove the palm rest with trackpad
Then to replace the Wi-Fi card, I performed the following:
- Remove the antenna connectors carefully with your fingers
- Remove the screw holding down the Wi-Fi card
- Replace the Wi-Fi card
- Mount the Wi-Fi card into places using the screw you just removed
- Install the antenna cables correctly as described above
Then, I reinstalled the palm rest and keyboard, install the battery, and connect the power again.
Trying out the new Wi-Fi card in Debian
I boot into Debian bullseye and run lspci
and see
03:00.0 Network controller: Intel Corporation Centrino Ultimate-N 6300 (rev 35)
...
Kernel moduels: iwlwifi
So far, good. This Wi-Fi adapter has an open driver (iwlwifi) but still
requires installing non-free firmware. Running dmesg
reveals that this is the
issue:
iwlwifi 0000:03:00.0: firmware: failed to load iwlwifi-6000-4.ucode (-2)
firmware_class: See https://wiki.debian.org/Firmware for information about
missing firmware
iwlwifi 0000:03:00.0: Direct firmware load for iwlwifi-6000-4.ucode failed with
error -2
iwlwifi 0000:03:00.0: iwlwifi-6000-4 is required
To install the firmware, I needed to add a non-free package to Debian. First, I
edited the apt sources in /etc/apt/source.list
:
-deb http://deb.debian.org/debian/ bullseye main
+deb http://deb.debian.org/debian/ bullseye main non-free
Then, I ran
apt update
apt install firmware-iwlwifi
The firmware is now installed. I reloaded the driver and was able to verify that the interface is being detected:
sudo modprobe -r iwlwifi
sudo modprobe iwlwifi
ip a
The last command output something like the following:
1: lo: ...
2: enp0s25: ...
3: wlp3s0: ...
The last device is the interface that I have just added. The 3 in wlp3s0
is
derived from the PCI path.
I double check that the hardware switch on the left side of the X220 is in its
On position. Running sudo rfkill list
(a tool that can be installed with apt)
gives me the following:
0: tpacpi_bluetooth_sw: Bluetooth
Soft blocked: no
Hard blocked: no
1: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
2: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
Testing the connection speed
Now it’s just a matter of using the Gnome network manager to connect to my home network.
On my Gigabit Fiber connection (BIGLOBE Japan) served with a Ubiquiti Dream Router, I get 590 Mbps on fast.com wired and 150 Mbps wireless on the X220. That is okay for a 10-year-old computer, but also not shockingly fast and in line with what to expect of 802.11n. Now that I know how to install and configure a new wireless card, I wish to add one that supports Wi-Fi 5 / 802.11ac. Even here, the support for wireless drivers could be flaky.
For reference, my M2 MacBook Air placed equidistantly from the access point gets 310 Mbps on fast.com. But then again, I don’t use open drivers there. And it helps that the M2 supports Wi-Fi 6.
What went well
Hardware maintenance on Lenovo ThinkPad X220 is straightforward. I appreciate that the Wi-Fi card is replaceable in the first place. The device comes apart with minimum effort, and the manual is easy to read. The chapters cross-reference each other a lot, so you immediately know where to jump when told to perform prerequisite steps. You can tell that Lenovo thought about busy people when creating the manual.
What I would improve
Why does the BIOS have a hardware whitelist in the first place? The official reasoning is FCC approval, but I should be able to install another FCC-compliant Wi-Fi card from a third-party provider with no trouble, right? It’s too bad I need to mod the BIOS, which could go drastically wrong and brick my machine.
The other workarounds could also be more reliable, like plugging the card into
the second Mini PCIe slot, meant for WAN, or taping over pins on the PCIe card.
Having the card in the second slot did not work for me, and the card was not
recognized or enumerated by lspci
. Taping over pins is difficult and
unreliable.
And finally, I still have to add proprietary firmware to my system to run the Intel Wi-Fi card. In a perfectly open world, everything can be covered by the kernel and open firmware, and in turn, be bundled with the standard Debian distributed kernel. That way, I can install my favorite flavor of Linux and start with wireless networking immediately.