surface-firmware-old
surface-firmware-old copied to clipboard
UEFI firmware updates for Microsoft Surface, flashable under linux using fwupd
Firmware updates for linux-surface
Usually if you want to install firmware updates on your surface, you have to reinstall Windows or dualboot it. There is no way to install firmware updates from within Linux.
However, there is a tool called fwupd
. It is a daemon that is used together
with the LVFS (Linux Vendor Firmware Server). Of course
Microsoft isn't part of the LVFS, but we can use the fwupd tool manually.
Microsoft has packaged their firmware updates as UEFI Capsules, which is a
technology that fwupd
already implements. The only thing that needs to be
done is convert them into a format that fwupd
can read. Again, it comes handy
that fwupd
already supports the format that is used by Windows Update (to make
it easier for vendors to support LVFS, I assume). The only thing that needs to
be added is a small file that contains fwupd
specific metadata.
This is not related to Microsoft or the LVFS in any way.
Receiving firmware updates through fwupd automatically
I have setup a remote for fwupd
, that you can add to your system to recieive
firmware updates automatically (either through the commandline or a fwupd
frontend like GNOME Software). To install it, run these commands:
You are flashing your UEFI firmware on an extremely locked down UEFI. I am not responsible for damages to your hardware. I don't know if a recovery mode exists. Please be careful!
# Add my gpg key to fwupd.
$ sudo wget -O /etc/pki/fwupd-metadata/GPG-KEY-Linux-Surface-Firmware https://tmsp.io/fs/repos/fwupd/linux-surface/key.asc
# Add the remote config to fwupd
$ sudo wget -O /etc/fwupd/remotes.d/linux-surface.conf https://tmsp.io/fs/repos/fwupd/linux-surface/linux-surface.conf
# List available updates
$ fwupdmgr get-updates
In case you don't trust the automatic update you can also download the .cab
files manually and
install them yourself.
How to get the firmware files
Ironically, an out of the box Windows installation has about as much support for surface as Linux: No battery stats, no touchscreen etc. Microsoft provides a gigantic driver package, that also contains the latest firmware. You can dowload it here: https://support.microsoft.com/en-us/help/4023482/surface-download-drivers-and-firmware-for-surface
I downloaded the one for Surface Book 2, because thats what I have. I will try to add the other ones gradually, but since I can't test them, contributions are welcome!
When you downloaded the MSI file, you need to extract it first. You need to
install the program msiextract
# For APT based systems
$ sudo apt install msitools
# For Arch based systems
$ git clone https://aur.archlinux.org/msitools.git
$ cd msitools
$ makepkg -si
# alternatively
$ yay -S msitools
# For Fedora
$ sudo dnf install msitools
Then extract the MSI you downloaded
$ msiextract SurfaceBook2_Win10_18362_1904009_0.msi
Inside the extracted folder, there will be a Firmware
folder. You have to
integrate the folder into the firmware
folder of this repository, like I did
for SB2 (i.e. make a folder for your model, and then copy the contents into that).
Writing metdata
First, you should read the official guide from LVFS about the metadata files: https://fwupd.org/lvfs/docs/metainfo
For the most part you can simply copy the examples, or the files that already exist.
The hardware GUID, the version number and the version timestamp can be scraped
from the .inf
file inside of the firmware directory.
DriverVer=04/18/2019,389.2706.768.0
First entry is the date when the driver was released, you have to convert that
date into an unix timestamp, and then enter it into the metadata file. The
second number might appear like a version number, and it is one, but it is not
the one that gets read by fwupd
for checking if the version is already
installed. That number is on another line, encoded as a hexadecimal number.
[Firmware_AddReg]
HKR,,FirmwareVersion,%REG_DWORD%,0x616A4B00
fwupd
has some logic to interpret that number as a triplet version number,
which I replicated in the getver.sh
script:
$ ./getver.sh 0x616A4B00
97.106.19200
This is the version number you have to enter in the metadata file, like this:
<release version="97.106.19200" timestamp="1555538400"></release>
For consistency, this is the only place where that number is used. The changelog contains Microsofts version number, so you can search for it on the official website.
Now, look for something that looks like this:
[Firmware_AddReg]
HKR,,FirmwareId,,{6726B589-D1DE-4F26-B2D7-7AC953210D39}
The text between the two curly brackets is the hardware GUID for the firmware. You need to convert it into lowercase (https://convertcase.net helps with that), and then put it here:
<firmware type="flashed">6726b589-d1de-4f26-b2d7-7ac953210d39</firmware>
This allows fwupd to tell you if a package can be installed on your hardware, or not.
Make sure to update the category in the metadata file, depending on what is being
installed: X-System
for UEFI updates, X-ManagementEngine
for Intel ME updates
and X-Device
for everything else.
Building
When you are done, invoke the bundle.sh
script with the path of the firmware
you want to bundle for fwupd
. For example, to bundle all files for SB2 at the
same time, you would do this:
$ ./bundle.sh firmware/SB2/*
The final bundles will be saved inside of the folder out
. For details on how
to build them manually, please look at the bundle script, or just ping me on
Gitter
Installing the firmware bundles manually
The bundle script will produce one .cab
file per firmware update. You can
install them with fwupdmgr
, the commandline interface for fwupd
. fwupd
should come preinstalled with Ubuntu and Fedora, if not please install it.
Arch users should consult the Arch Wiki entry about fwupd
.
You are flashing your UEFI firmware on an extremely locked down UEFI. I am not responsible for damages to your hardware. I don't know if a recovery mode exists. Please be careful!
$ fwupdmgr install <path/to/cab/file>
Driver Firmware
As part of my adventures I also took the opportunity to update the driver firmware
that jakedays setup script installs to the latest versions from the MS driver
package / the linux-firmware repository. You can find it in the driver
folder.