Installing Lenovo Firmware Packaged as a .exe on a Linux Machine
My new Lenovo Carbon X1 Gen 7 has one irritating problem: the trackpad sometimes disappears, flooding dmesg with messages like "i2c_designware i2c_designware.1: controller timed out". Once this happens, the only fix is to reboot.
Lenovo has a fix -- new trackpad firmware -- but unlike their BIOS updates, which are installable from Linux, device firmware updates are distributed as Windows EXE files that require running Windows on the bare metal, leaving Linux users out in the cold. Ironic, since Lenovo is so popular among Linux users and is a member of the Linux Firmware Service, and the CX1 is supposedly Ubuntu certified.
Those Linux users on the forums who managed to install the firmware update raved about it, saying that indeed it solved their problem. But finding a way to to install it led me on a not-so-merry four-day quest.
Here's how I installed the firmware, in the end:
Make a Windows to Go using Rufus on a Real Windows Box
Back up anything you don't want to lose, because you never know.
- Borrow a real Windows box. I tried many times using Windows inside VirtualBox and QEmu on top of Linux, but it never worked.
On Windows, install Rufus.
Download the Windows 10 Installer ISO (5 gigabytes, give or take)
Find a USB stick or SD card, 16G or larger. Actually, find a bunch of them: this process is incredibly finicky about the stick you use and the only way you find out is that it doesn't work and you have to try again (see below).
Use Rufus to create a Windows to Go image. The alternative is to make a Windows installer; that won't work, because you can't run anything useful from the installer, and you don't want to actually install Windows, or you wouldn't be in this fix in the first place.
Be patient: creating a W2G image takes several hours. Click on Rufus' log file button (it's the rightmost of four obscure icons down near the lower left of the Rufus window; it has a mouseover tooltip) at any time to see what's happening; if things don't go right you might at least get some idea why.
When the W2G stick is finished (whew!), move it to your Linux machine and mount its second partition (/dev/sdb2 or whatever). This will tell you it wasn't properly unmounted and it's fixing it, giving you a heart attack about whether Linux is going to change the filesystem in some way that makes it fail after you waited all that time creating it.
Copy the firmware .exe to it. Wherever you want; I just put it at the root of the filesystem. Sync and unmount it.
Boot your computer from the USB stick. This will take forever and may fail if the phase of the moon is wrong.
If you're lucky and the planets are in alignment, eventually a Windows installer will come up and ask you a bunch of annoying questions about language, keyboard, whether you consent to having Microsoft spy on you in a skillion different ways, name, password, three security questions, etc. Meanwhile, you're having another heart attack because does this mean it's going to install Windows to your real disk on top of Linux? Hopefully not -- at least it didn't in my case -- but here's where you really want to have that recent backup.
If you make it all the way through the questions and get a Windows screen, rejoice! Navigate to wherever you put your exe and run it. Cross your fingers -- maybe you're done!
If it hangs or bluescreens during boot, or Rufus fails to create the W2G stick in the first place, try running Rufus again with a different USB stick. I think I tried five before finally finding one that worked, and the successful one (a Transcend SD card in an old Patriot USB adapter) wasn't the newest, or the fastest, or the largest. It's a mystery.
Some Approaches that Didn't Work
Before I finally got this working, I wasted four days trying many other approaches. Many of them sound very clever and reasonable and ought to work, but they didn't work for me. These include:
Install Windows PE or the full Windows 10 installer directly onto a USB stick using qemu using a command like this:
sudo qemu-system-x86_64 -drive file=/dev/sdX,format=raw -cdrom Win10_1903_V2_English_x64.iso -cpu host -enable-kvm -m 2048 -display gtk -nic none
That brought up a window in which the Windows installer booted and proceeded to install using the USB stick mounted at /dev/sdX as the disk. At least in theory.
I tried this several times first without the
-nic none
, and every time, the installer eventually hit an infinite loop of "Why did my PC restart?" bluescreens. Adding the-nic none
cured that problem, but I ended up with a USB stick that wasn't bootable.This was my favorite method in theory because it's clever and I understand at least a little what it was supposedly doing. I wish it had actually worked. Possibly if I knew enough about Windows and UEFI boot architecture, it might have been possible to patch the stick to make it bootable.
Various other attempts to make a bootable WinPE -- I liked the minimal WinPE idea so I kept trying it in different ways, but I've lost track of all the different methods.
Use vboxmanage to clone the Win10 I already had in Virtualbox to a USB stick, as suggested here.
Use FreeDOS. "This program must be run under Win32."
Use Windows 10 inside Virtualbox to run the initial exe to extract the installer inside, another exe, then run that in FreeDOS. "This program cannot be run in DOS mode."
Boot from a Win10 installer, use Shift-F10 to get a command prompt window, and run the exe from that. "The image file is valid, but is for a machine type other than the current machine."
Use Windows 10 running inside Virtualbox to run Rufus to make a Windows to Go stick. I had no trouble making a regular USB installer using Rufus in virtual Windows, but when I tried Win to Go, it failed every time. Sometimes it failed because it couldn't read the USB stick properly (even though I had configured Virtualbox to pass it through); other times it failed because it was confused by the Win10 installer ISO, which was on a Virtualbox shared drive (because I didn't have that much spare space in the virtual Windows instance). Apparently there's something not entirely reliable about Virtualbox's USB handling and its shared folders, at least for very data transfers.
Use WinToUSB or some such program. There seem to be lots of different programs with names similar to this, they're all closed source (Rufus is open source), it's hard to tell which ones are real and which are malware, and when I did think I'd finally found one from a reliable source, it just hung when I tried to run it.
Use a backup made with Macrium Reflect on a real Windows box, and boot from that. "The version of [exename] is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher."
So, lots of different ways. Some of them have worked at some time for someone. Also, I never did try Wine. I don't think Wine would be able to run the actual exe and update the trackpad firmware (I was afraid to try it), but it's possible that Rufus in Wine might have been able to make a Windows To Go stick.
If anyone manages that -- or any other way of getting this to work -- I'd love to hear about it.
[ 20:16 Nov 30, 2019 More linux | permalink to this entry | ]