How to update the firmware of a Dynabook (né Toshiba) X30 or X40 from Linux (without installing Windows)!
Firmware download location: https://emea.dynabook.com/support/businesslaptops/ (for models sold within Europe/Middle East/Africa). The model selector doesn't include all models; best to enter the serial number from the bottom of the device, or from /sys/class/dmi/id/product_serial).
The latest 'os-independent' BIOS download is currently version 3.80-WIN. The Zip files for the X30 and X40 have different names (bios-20200303145630.zip and bios-20200304090247.zip respectively), but both have the same content: a single file called P00ADv380_ECCDv290.exe.
The numbers in the filename correspond to the BIOS version (3.80) and the EC firmware version (2.90)
This file is a self-extracting archive, that (thanks to Process Monitor) we can see runs the following command after extracting its contents:
"C:\Windows\system32\WScript.exe" "C:\ProgramData\dynabook\BIOS_Package\autoExec.vbe" "/owner=C:\Users\sam\Downloads\bios-20200304090247\\P00ADv380_ECCDv290.exe"
Luckily, my guess that we can run the executable with /extract was right (you do need Windows for this, but perhaps it's possible with Wine), and we get the contents extracted for examination:
AtpTimerInfo.dll
- autoExec.0409
- autoExec.0411
- autoExec.vbe
- BIO00ADT.COM
- CHGBIOSA.EFI
- ECCDV290.BIN
- nchgbios2.exe
- nchgbios2.sys
- NCHGBIOS2x64.SYS
- nchgbios3.exe
- nchgbiosESP.exe
- TBiosSub.dll
TosPwChk.dll
TosPwChk.lng
TosWshHelper.exe
- version.ini
First we need to take a closer look at autoExec.vbe. Lucky it can be decoded with decode-vbe.py. We get autoExec.vbs.html, and... yikes! Rather than going through that detail...
Googling for some of the file names takes us to this page regarding updating the firmware of the Toshiba Satellite Z30-B-10W, in particular:
2018-05-03: bios upgrade - ok, I booted the FreeDOS stick, which has the 6.40 files on it, without any drivers (if I let it boot with jemm386, I got a message that chgbiosf is not available in V86 mode) and ran chgbiosf bio0096t.com,ecbfv140.bin and the bios got updated.
This sound promising. Unfortunately there's no chgbiosf.exe in the file list. Presumably the old DOS-based executable has been replaced by nchgbios2.exe, nchgbios3.exe and nchgbiosESP.exe.
Taking a closer look at autoExec.vbs, it looks liek nchgbiosESP.exe is used on UEFI systems, which the X30/X40 are. Let's try to run it:
>nchgbiosESP.exe -h ---------------------------------------------------------------- nchgbiosESP ---------------------------------------------------------------- [Help screen] Legend > [-s] [-p] [-b BIOxxxxT.COM] [-e ECxxVddd.BIN] [-h] s : Enable Silent Mode : Enable the [s]ilent mode. p : Enable Pegasus10P mode : Enable an E[x]tend mode. b : SBIOS File Path : Assign an S[b]IOS file path. e : EC/KBC File Path : Assign an [e]C/KBC file path. h : Show a help screen : Show a [h]elp screen. # Command line options are case sensitive. # Command line options can be connected like as "-xyz" if the 'x' and the 'y' do not require an argument. # Command line options with '[' and ']' are OPTIONAL. # If the Pegasus10P mode is enabled, this tool behaves as follows: # - SBIOS file name format is changed to BIOxxxxT.BIN. # - EC/KBC file name format is changed to ECPGVXXX.TXT. # - Copies following files implicitly. If any file is not available, the tool fails. # - TOSFIRMUP.EFI # - STARTUP.NSH # - H2OFFT-SX64.EFI # - CHGPGEC.EFI # [NCHGBIOS2 Compatibility] # A '/' also works as a command line option prefix. # You can set an SBIOS and EC/KBC file path directly. [ERROR] GetFirmwareEnvironmentVariable() for OsIndicationsSupported() failed. 1 [ERROR] Failed to check if the current SBIOS supports File Capsule Delivery, or it does not support it.
My assumption is that nchgbiosESP.exe acts a little bit like https://fwupd.org/: copy a UEFI executable (CHGBIOSA.EFI) to the EFI System Partition, along with the firmware file, and register a new Boot Manager entry that launches it with the appropriate arguments to perform the BIOS update. We can get a sneak preview of how this might work:
$ strings -e l CHGBIOSA.EFI ChgBiosA V %d.%02d Copyright (C) 2019 Dynabook Inc. All Rights Reserved. Usage: ChgBiosA [<option>] [<BIOS>][,[<EC>]] <Option> /f < %VForce update %N> /p < %VUpdating without AC connection %N> /d < %VDebug information %N> /h < %VHelp information %N> <BIOS> BIOS file ( %Bex. BIOxxxx.com%N ) <EC> EC file ( %Bex. ECxxxxx.bin%N ) [...]
Well look at that--it looks like the arguments are backward-compatible all the way back to the original DOS-based chgbiosf.exe command!
Now we need a convenient way to run the command. For that we'll use the UEFI Shell.
Download UEFI Shell
Extract UefiShell/X64/Shell.efi to /boot/efi
Create a boot entry with efibootmgr -c -L Shell -l '\Shell.efi' -d /dev/nvme0n1 -p 1
Copy the extracted firmware update files to /boot/efi
CHGBIOSA.EFI
BIOxxxxx.COM
ECCxxxxx.BIN
- Reboot and hold F2 to get into Firmware Setup
- Disable Secure Boot
- Reboot and hold F12 to get the boot entry menu
- Boot into the shell
Switch to the EFI System Partition with the command fs0:
Launch the firmware updater with the command CHGBIOSA BIOxxxx.COM,ECxxxxx.BIN
Toshiba is dead. Sic transit gloria mundi. Long live Dynabook!
(At this point the conscientious user will re-enable Secure Boot & remove the Shell boot entry with efibootmgr)
Various ways to check the firmware's version number
Via sysfs, using Linux's support for decoding DMI:
$ head /sys/class/dmi/id/{bios_version,ec_firmware_release} ==> /sys/class/dmi/id/bios_version <== Version 3.80 ==> /sys/class/dmi/id/ec_firmware_release <== 2.90
Via dmidecode -t bios:
Handle 0x0012, DMI type 0, 24 bytes BIOS Information Vendor: TOSHIBA Version: Version 3.80 Release Date: 01/06/2020 ROM Size: 8192 kB Characteristics: [...] BIOS Revision: 3.80 Firmware Revision: 2.90
The firmware's ESRT entry combines both version numbers:
$ cat /sys/firmware/efi/esrt/entries/entry0/vw_version 58720912 $ python -c 'print hex(58720912)' 0x3800290
Which fwupd get-devices can display correctly once it's told how to interpret it:
[...] ├─System Firmware: │ Device ID: 41c7c0481777610a3aa56cd85affca0935b6207b │ Current version: 3.80.2.90 │ Vendor: TOSHIBA (DMI:TOSHIBA) │ GUID: 28108d08-5027-42c2-a5b8-92d6ede9b97b │ Device Flags: • Internal device │ • Updatable │ • Requires AC power │ • Needs a reboot after installation │ • Cryptographic hash verification is available │ • Device is usable for the duration of the update │ [...]