Updating the BIOS on an HP laptop without Windows
I've been using an HP laptop for a while, and it works pretty well with Linux (and Qubes), though one thing that bothered me was the only way to update the BIOS seems to be booting to Windows and using the .exe from there.
TLDR: How to update the BIOS
- Create a FAT32-formatted USB drive (e.g. using gparted) [1]
- Create the folder
HP/DEVFWon the USB drive [2] - Download the .exe file containing the BIOS update for the device from https://support.hp.com
- Extract it with
7z e file.exe - Save the .bin file from the extracted .exe as
HP/DEVFW/firmware.binon the USB drive - Reboot the laptop and open BIOS settings by pressing the escape key during boot
- Navigate to
Update System BIOS > Update System and Supported Device Firmware Using Local Media
[1] I don't know if other filesystems than FAT32 will work since it's all that I tested, but it's the most common filesystem for flash drives.
[2] The recovery USB installer creates other directories, but the update works fine without them
Reverse engineering the installer, or how I came up with these steps
When looking through the BIOS options, I saw "Update System and Supported Device Firmware Using Local Media", which looked promising. There are instructions on HP's support site for creating a recovery USB drive from a Windows computer using the installer.
To see what this does, I ran the installer in a virtual machine and ran through the installer steps, which were pretty straightforward.




Notably, the installer appears to be a self-extracting zip, which can be confirmed by listing the contents with 7zip:
$ 7z l sp160239.exe
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) Ultra 5 135U (A06A4),ASM,AES-NI)
Scanning the drive for archives:
1 file, 27689472 bytes (27 MiB)
Listing archive: sp160239.exe
--
Path = sp160239.exe
Type = PE
Physical Size = 27689472
CPU = x86
Characteristics = Executable 32-bit
Created = 2020-11-19 07:38:27
Headers Size = 1024
Checksum = 27731312
Name = hpsoftpaqwrapper.exe
Image Size = 327680
Section Alignment = 4096
File Alignment = 512
Code Size = 186880
Initialized Data Size = 126464
Uninitialized Data Size = 0
Linker Version = 14.16
OS Version = 6.0
Image Version = 0.0
Subsystem Version = 6.0
Subsystem = Windows GUI
DLL Characteristics = Relocated NX-Compatible TerminalServerAware
Stack Reserve = 1048576
Stack Commit = 4096
Heap Reserve = 1048576
Heap Commit = 4096
Image Base = 4194304
Comment = FileVersion: 0.2.56.9141
ProductVersion: 0.2.0.0
ProductVersion: 01.06.10
CompanyName: HP Inc.
FileDescription: HP BIOS and System Firmware (W70)
InternalName: hpsoftpaqwrapper
OriginalFilename: hpsoftpaqwrapper.exe
ProductName: HP BIOS and System Firmware (W70)
LegalCopyright: Copyright (c) 2024 HP Development Company, L.P.
----
Path = [0]
Size = 27363320
Packed Size = 27363320
Virtual Size = 27363320
Offset = 314368
--
Path = [0]
Type = Cab
Offset = 16882
Physical Size = 27346438
Method = LZX:15
Blocks = 1
Volumes = 1
Volume Index = 0
ID = 27033
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2025-04-22 03:19:52 ....A 17928 BCUsignature32.dll
2025-04-22 03:19:52 ....A 17928 BCUsignature64.dll
2025-03-07 19:52:54 ....A 18758 Bios Flash.htm
2025-04-22 02:43:38 ....A 1410 contents.txt
2025-07-10 07:47:46 ....A 4737 History.txt
2025-04-22 03:19:52 ....A 3968008 HpFirmwareUpdRec.exe
2025-04-22 02:43:38 ....A 3457 HpFirmwareUpdRec.txt
2025-04-22 03:19:52 ....A 5554696 HpFirmwareUpdRec64.exe
2025-04-22 03:19:52 ....A 2244616 HpqPswd.exe
2023-02-01 21:46:30 ....A 1011 HpqPswd.txt
2025-04-22 03:19:52 ....A 2843144 HpqPswd64.exe
2025-04-22 03:19:52 ....A 398344 HPToastNotificationActivator.exe
2025-04-22 03:19:52 ....A 474120 HPToastNotificationActivator64.exe
2023-02-01 21:46:36 ....A 14513 license.txt
2020-08-11 10:04:48 ....A 14894 logo.bmp
2025-05-31 02:01:24 ....A 40758302 W70_01061000.bin
2025-05-31 02:01:24 ....A 1498 W70_01061000.inf
------------------- ----- ------------ ------------ ------------------------
2025-07-10 07:47:46 56337364 27689472 17 files
After completing the install, a few folders have been added to the USB drive, most of them empty:

$ ls -laR
.:
total 16K
drwxr-xr-x 4 user user 4.0K Jan 1 1970 .
drwxr-x---+ 3 root root 4.0K Sep 4 04:03 ..
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 HP
drwxr-xr-x 2 user user 4.0K Mar 6 18:12 'System Volume Information'
./HP:
total 20K
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 4 user user 4.0K Jan 1 1970 ..
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 BIOS
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 BiosUpdate
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 DEVFW
./HP/BIOS:
total 20K
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 Current
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 New
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 Previous
./HP/BIOS/Current:
total 8.0K
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
./HP/BIOS/New:
total 8.0K
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
./HP/BIOS/Previous:
total 8.0K
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
./HP/BiosUpdate:
total 8.0K
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
./HP/DEVFW:
total 39M
drwxr-xr-x 2 user user 4.0K Mar 6 18:15 .
drwxr-xr-x 5 user user 4.0K Mar 6 18:15 ..
-rw-r--r-- 1 user user 39M Mar 6 18:18 firmware.bin
'./System Volume Information':
total 16K
drwxr-xr-x 2 user user 4.0K Mar 6 18:12 .
drwxr-xr-x 4 user user 4.0K Jan 1 1970 ..
-rw-r--r-- 1 user user 76 Mar 6 18:12 IndexerVolumeGuid
-rw-r--r-- 1 user user 12 Mar 6 18:12 WPSettings.dat
The one file that looks interesting here is HP/DEVFW/firmware.bin, which both
has the same extension as the W70_01061000.bin from earlier and looks about
the same size. It's probably the same file, which would make creating similar
media from Linux pretty easy and not much reverse engineering needed after all.
This can be confirmed by comparing file hashes after extracting the zip:
$ md5sum W70_01061000.bin
e2944509ad68cb03b9c9e8f7e5ca78ed W70_01061000.bin
$ md5sum firmware.bin
5953b177524ffaa4e49c7d8353231590 firmware.bin
... or maybe not.
If you read Bios Flash.htm, there's an interesting paragraph:
These methods require that the firmware binary file is present on USB media or the hard drive in a specific folder - either "HP\DEVFW" or "EFI\HP\DEVFW" will support this feature. The file must be named 'firmware.bin'. The HP Firmware Update and Recovery utility has a feature that will copy the image file to the correct folder on a USB device for you. If no firmware file is found on USB media, the system will look for a firmware file on the hard drive. If a BIOS administrator password has been set, the password will be required before being able to access the "Update System BIOS" menu or BIOS Setup. The firmware update will not be complete until the system is restarted.
So you can actually stop here and just rename the .bin file to firmware.bin
and copy it to HP/DEVFW on a flash drive.
Just a bit more about what was changed in the file:
I opened both binaries in imhex and used the diffing tool to compare the two.


After looking at it for a moment, it's pretty obvious that a header was inserted before the bulk of the data.
I made a copy of the extracted binary and inserted 0x280 null bytes at address
0x200 to make the bulk of the data match, then diffed the binaries again, and
there were only a few minor differences left.




The largest non-null data string is the firmware GUID from the .inf file. Though I'm not sure what the rest of the changed bytes are yet.

I used UEFItool to look at the file, which indicated the first part of the binary is "just" padding, so it's likely used to implement logic that's non-standard for UEFI.

I poked around HpFirmwareUpdRec.exe using ghidra
for a bit, but decided to come back around to it later for a more thorough look.