I have a Raspberry Pi 5 with a Samsung 990 EVO. Samsung released new firmware. Their official utility is x86-64 only. What now?
When You Need This
Samsung’s official method is booting from an ISO and running their utility. That’s not always possible:
- ARM systems — Raspberry Pi, Ampere, Apple Silicon, AWS Graviton. Samsung’s utility simply won’t run.
- Fleet updates — you have 50 servers and want to update firmware via Ansible, not run around with a USB stick.
- Headless servers — no physical access, SSH only. Rebooting into recovery isn’t an option.
- CI/CD automation — hardware provisioning before deployment, firmware as part of the pipeline.
- Remote management — server in a datacenter, iLO/IPMI available, but mounting an ISO and waiting is slow and inconvenient.
In all these cases, you need a way to flash firmware from a running system via nvme-cli.
TL;DR
Samsung encrypts firmware with AES-256-ECB, but the key is right there in the binary. Extract the key, decrypt, flash via standard
nvme-cli. Works on any architecture.
The Problem
Samsung distributes firmware updates as bootable ISOs. Inside is fumagician, a utility that only runs on x86-64. Can’t run it on ARM.
You’d think nvme-cli — the standard tool for NVMe operations — would work. But Samsung encrypts the firmware files, so direct flashing fails.
The Solution
The encryption is AES-256-ECB. The key? Sitting right inside the fumagician binary. Samsung apparently bet on security through obscurity.
Step 1: Extract Firmware from ISO
# Mount the ISO
sudo mount -o loop Samsung_SSD_990_EVO_1B2QKXJ7.iso /mnt
# Extract initrd
cd /tmp
zcat /mnt/boot/x86_64/loader/initrd | cpio -idmv
# Firmware files are in root/fumagician/
ls root/fumagician/*.enc
Step 2: Extract the Key
strings root/fumagician/fumagician | grep -E '^[A-Za-z0-9+/]{43}=$'
This finds a base64 string — the 32-byte AES key.
Step 3: Decrypt
#!/usr/bin/env python3
from Crypto.Cipher import AES
import base64
import zipfile
import io
import sys
KEY_B64 = "YOUR_KEY_HERE" # from step 2
key = base64.b64decode(KEY_B64)
def decrypt_aes_ecb(data: bytes) -> bytes:
cipher = AES.new(key, AES.MODE_ECB)
return cipher.decrypt(data)
# First layer — decrypt .enc file
with open(sys.argv[1], "rb") as f:
encrypted = f.read()
decrypted = decrypt_aes_ecb(encrypted)
# Inside is a ZIP archive
with zipfile.ZipFile(io.BytesIO(decrypted)) as z:
inner_enc = z.read(z.namelist()[0])
# Second layer — decrypt again
firmware = decrypt_aes_ecb(inner_enc)
# Remove PKCS7 padding
padding_len = firmware[-1]
firmware = firmware[:-padding_len]
with open("firmware_payload.bin", "wb") as f:
f.write(firmware)
print("Done: firmware_payload.bin")
Step 4: Flash the Firmware
# Upload firmware to SSD
sudo nvme fw-download /dev/nvme0 --fw=firmware_payload.bin --xfer=32768
# Activate in slot 2
sudo nvme fw-commit /dev/nvme0 --slot=2 --action=1
# Reboot
sudo reboot
After reboot, verify:
sudo nvme id-ctrl /dev/nvme0 | grep fr
# fr: 1B2QKXJ7
Why This Is Safe
Samsung uses two-layer protection:
- Transport layer — AES encryption for distribution. This is what we’re bypassing.
- Hardware layer — The SSD itself verifies firmware signatures. Can’t flash unofficial firmware.
So this isn’t a vulnerability — just a way to deliver official firmware to an unsupported architecture.
Tested On
- Raspberry Pi 5, Ubuntu 25.10
- Samsung 990 EVO 1TB
- Update: 0B2QKXJ7 → 1B2QKXJ7