Written by ChatGPT. This post was generated entirely by ChatGPT. The investigation and commands are real; the prose was not human-written.
Diagnosing Intel RST NVMe remapping, finding HP’s hidden AHCI setting, changing the PchSetup UEFI variable, and verifying native NVMe operation in NixOS
Status: Resolved successfully
Confirmed platform: HP 348 G7, motherboard 86CB, Insyde BIOS F.47
1. Overview and confirmed scope
This HP 348 G7 had a normal SATA hard disk that Linux could use, plus an internal M.2 NVMe device that the firmware appeared to recognize. Linux showed the SATA disk as /dev/sda, but it did not expose /dev/nvme0n1.
The problem was not partitioning, formatting, a missing mount point, or a physically absent device. Intel Rapid Storage Technology had remapped the NVMe device behind the chipset’s RAID-mode storage controller. The Linux AHCI driver could detect that a remapped NVMe existed, but it could not present the device as a normal NVMe block device.
On many laptops the solution is simply to change the storage mode in the BIOS from RAID or Intel RST to AHCI. On this HP model, the firmware supported AHCI but HP did not expose the required setting in the normal BIOS interface.
The final solution was to inspect the exact firmware running on this laptop, extract its UEFI setup forms, identify the hidden PchSetup variable and its offsets, back up the live variable, change the controller mode from RAID to AHCI, reboot, and verify that Linux could see the NVMe natively.
The critical persistent change was:
PchSetup[0x42] = 0x00 # AHCI
After reboot, the Intel controller changed from RAID device 8086:282a to AHCI device 8086:9d03, and the Intel Optane module appeared independently as NVMe device 8086:2522 at PCI address 03:00.0.
This document preserves the complete investigation, including dead ends, exact commands, firmware identifiers, offsets, hashes, warnings, write verification, post-reboot checks, and later conclusions.
The variable offsets in this document were reverse-engineered and verified for this exact combination:
Laptop: HP 348 G7
Motherboard: HP 86CB
BIOS vendor: Insyde
BIOS version: F.47
BIOS release date: 03/24/2026
Platform firmware revision: 15.47
Embedded controller: 97.11
Do not assume that PchSetup offset 0x42, offset 0x61D, the variable size, or even the same GUID will be valid on another model or a later firmware version. Re-extract and inspect the IFR for any different board or BIOS release.
Writing a malformed UEFI variable can make a computer unable to complete POST. Recovery may require HP’s BIOS recovery procedure or an external SPI programmer. The procedure below succeeded on this machine, but it is not risk-free.
Before changing anything, keep the laptop on AC power. Preserve the original variable backup and the read-only SPI dump. Do not delete and recreate the EFI variable. If any write or verification command reports an error, stop.
If Windows is installed and configured for Intel RST, switching the controller to AHCI can stop that Windows installation from booting until its storage configuration is prepared for AHCI. This laptop’s active installation was NixOS on the SATA disk.
The relevant platform information was:
System manufacturer: HP
System product: HP 348 G7
Motherboard: HP 86CB
Motherboard/KBC version: 97.11
BIOS vendor: Insyde
BIOS version: F.47
BIOS release date: 03/24/2026
Platform firmware revision: 15.47
Embedded controller revision: 97.11
Linux distribution: NixOS
Kernel: Linux 6.18.36
The existing SATA disk was:
TOSHIBA MQ01ACF050
Approximately 465.8 GiB visible in Linux
The hidden M.2 device was later identified as:
INTEL MEMPEK1J016GA
Intel Optane Memory, nominally 16 GB
14.40 GB decimal / approximately 13.4 GiB in Linux
NVMe firmware: K4110400
The relevant PCI identities were:
Before the fix:
00:17.0 RAID bus controller [8086:282a]
Subsystem [103c:86cb]
After the fix:
00:17.0 SATA controller in AHCI mode [8086:9d03]
03:00.0 Intel NVMe Optane Memory [8086:2522]
Unique system serial numbers, UUIDs, and device serial numbers are intentionally omitted because they are not required to reproduce the diagnosis.
2. Original symptoms and diagnosis
Before the fix, lsblk showed only the SATA hard disk and zram. The layout was effectively:
NAME SIZE TYPE
sda 465.8G disk
sda1 512M part
sda2 8G part
sda3 457.3G part
zram0 3.8G disk
The SATA partitions contained:
/dev/sda1 512 MiB /boot
/dev/sda2 8 GiB swap
/dev/sda3 ~457 GiB / and /nix/store
There was no /dev/nvme0, /dev/ng0n1, or /dev/nvme0n1.
The absence of the NVMe from df -h was not decisive because df only lists mounted filesystems. A blank, unformatted, or unmounted disk would not appear there. The important evidence was that the device was absent from lsblk and nvme list.
That ruled out an ordinary filesystem or mount problem.
The necessary utilities did not need to be installed permanently. The newer Nix command was used with its experimental features enabled for each invocation:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#pciutils nixpkgs#nvme-cli nixpkgs#dmidecode
The classic equivalent is:
nix-shell -p pciutils nvme-cli dmidecode
For firmware extraction and analysis:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#uefitool nixpkgs#ifrextractor-rs \
nixpkgs#binutils nixpkgs#file
For SPI-flash probing and reading:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#flashrom
For chattr and the later read-only badblocks test:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#e2fsprogs
Entering a new temporary Nix shell can lose non-exported shell variables. This mattered later when $VAR was empty after starting a shell for chattr. Recreate or export important variables after entering a new shell.
The most useful initial command was:
sudo dmesg | grep -i nvme
The kernel reported:
ahci 0000:00:17.0: Found 1 remapped NVMe devices.
Expanding the context made the diagnosis explicit:
sudo dmesg | grep -i -A5 -B5 'remapped NVMe'
The important output was:
ahci 0000:00:17.0: Found 1 remapped NVMe devices.
ahci 0000:00:17.0: Switch your BIOS from RAID to AHCI mode to use them.
ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, RAID mode
This proved three things:
- An NVMe device physically existed.
- The Intel chipset had remapped it behind the RAID/RST storage controller.
- Linux wanted the firmware switched from RAID to AHCI.
The investigation therefore changed from finding a missing disk to finding a vendor-hidden controller-mode setting.
The initial PCI check was:
lspci -nn | grep -iE 'nvme|non-volatile|raid|vmd|sata'
It showed:
00:17.0 RAID bus controller [0104]: Intel Corporation 82801 Mobile SATA Controller [RAID mode] [8086:282a] (rev 21)
There was no independent Non-Volatile memory controller entry.
The controller-specific check was:
lspci -nnk -s 00:17.0
Its relevant output was:
00:17.0 RAID bus controller [0104]: Intel Corporation 82801 Mobile SATA Controller [RAID mode] [8086:282a] (rev 21)
Subsystem: Hewlett-Packard Company Device [103c:86cb]
Kernel driver in use: ahci
Kernel modules: ahci
The Linux driver was ahci, but the PCI device itself was still configured by the firmware as RAID mode. That distinction explained why the SATA disk worked while the remapped NVMe did not.
The native NVMe topology was absent:
sudo nvme list
The result was:
Failed to scan topology: No such file or directory
Linux also exposed the exact remap count through sysfs:
cat /sys/bus/pci/devices/0000:00:17.0/remapped_nvme
The result was:
1
Exactly one NVMe device was hidden behind Intel RST.
The normal solution would be to open the BIOS and change a setting named SATA Mode, SATA Operation, Storage Controller Mode, Intel RST, or similar from RAID/RST to AHCI.
The HP 348 G7 firmware did not show this option. Its normal BIOS interface had no usable advanced storage page and no exposed RAID/AHCI selector.
This did not mean that AHCI was absent from the firmware. It meant HP had suppressed the selector from the user-facing setup interface.
The platform was identified with:
sudo dmidecode -t system
sudo dmidecode -t baseboard
sudo dmidecode -t bios
The essential results were:
Manufacturer: HP
Product Name: HP 348 G7
Base Board Product Name: 86CB
BIOS Vendor: Insyde
BIOS Version: F.47
Release Date: 03/24/2026
Platform Firmware Revision: 15.47
Embedded Controller Firmware Revision: 97.11
The exact board and firmware version must be known before trusting a variable offset.
3. Approaches that did not solve the problem
Linux includes hp_bioscfg, which can expose HP firmware settings under sysfs. It was tested before attempting lower-level firmware analysis:
sudo modprobe hp_bioscfg
lsmod | grep hp_bioscfg
sudo dmesg | grep -i hp_bioscfg | tail -50
The module loaded, but the firmware rejected a command:
hp_bioscfg: Returned error 0x4, "Invalid command type"
The sysfs interface existed at:
/sys/class/firmware-attributes/hp-bioscfg/
It exposed Sure Start and authentication-related data, plus pending-reboot state, but no SATA, AHCI, RAID, RST, Optane, or storage-controller attribute.
The useful inspection commands were:
sudo find -L /sys/class/firmware-attributes/hp-bioscfg \
-maxdepth 5 -type f -print
grep -RHiE 'SATA|AHCI|RAID|RST|Optane|Storage|Controller' \
/sys/class/firmware-attributes/*/attributes/ 2>/dev/null
No supported HP/Linux setting could perform the required change.
The HP F.47 SoftPaq was:
sp172856.exe
It was downloaded and inspected without executing it:
mkdir -p ~/hp-bios-f47
cd ~/hp-bios-f47
curl -fLO \
https://ftp.hp.com/pub/softpaq/sp172501-173000/sp172856.exe
file sp172856.exe
ls -lh sp172856.exe
7z l sp172856.exe
The outer package was a 39,425,792-byte Windows executable containing a 39,148,048-byte Insydeflash.exe.
It was extracted with:
mkdir extracted
7z x sp172856.exe -oextracted
The inner package was an Insyde iFdPacker/7-Zip SFX image. BIOSUtilities was used to unpack its obfuscated payload:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#git nixpkgs#python313 \
nixpkgs#python313Packages.pip nixpkgs#p7zip
cd ~/hp-bios-f47
git clone --depth=1 https://github.com/platomav/BIOSUtilities.git
cd BIOSUtilities
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
mkdir -p ~/hp-bios-f47/bios-unpacked
python main.py \
~/hp-bios-f47/extracted/Insydeflash.exe \
-o ~/hp-bios-f47/bios-unpacked \
-u InsydeIfdExtract \
-e
The extracted payload contained several .fd images. Recorded sizes included:
086CB.fd 9,177,600 bytes
086CD.fd 18,354,944 bytes
086D7.fd 9,177,600 bytes
086D9.fd 18,354,944 bytes
The package also contained tools and configuration files including:
HPFlashWinx64.exe
HpBiosUpdate.efi
BiosMgmt.efi
HpBiosMgmt.efi
DevFwUpdate.efi
FWUpdLcl.exe
H2OFFT64.sys
platform.ini
The board mapping in platform.ini proved that 086CB.fd belonged to this laptop:
FD#11=PCI,0,0,0,2C,FFFFFFFF,86CB103C,086CB.fd
It also included:
PlatformName6=86CB
However, 086CB.fd did not contain directly usable UEFI firmware-volume signatures:
grep -abo '_FVH' 086CB.fd
There was no output. Direct IFR extraction returned:
No IFR data found
uefiextract also could not unpack it. The correct HP image was still encrypted, encoded, wrapped, or otherwise transformed for HP/Insyde’s update process. It was useful for identifying the right board payload, but not for direct firmware reverse engineering.
A Windows-based copy/export path through HP’s utilities was considered, but it was unnecessary once a Linux-only route succeeded.
4. Extracting the live firmware and finding the hidden settings
The firmware already installed in the laptop’s SPI flash had necessarily been transformed into the form used by the hardware. Instead of continuing to reverse HP’s update packaging, the installed BIOS region was read directly with flashrom.
Only a probe was attempted first:
mkdir -p ~/hp-bios-f47/live
cd ~/hp-bios-f47/live
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#flashrom nixpkgs#uefitool \
nixpkgs#ifrextractor-rs nixpkgs#binutils
sudo flashrom -p internal --flash-name
The first attempt identified the chipset but failed to map the PCI Express configuration region:
Found chipset "Intel Kaby Lake U w/ iHDCP2.2 Prem.".
pcilib: Cannot map ecam region: Operation not permitted.
Kernel lockdown was not active, and /proc/cmdline did not contain iomem=relaxed.
The following NixOS setting was temporarily added:
boot.kernelParams = [ "iomem=relaxed" ];
The next boot was built and started:
sudo nixos-rebuild boot
sudo reboot
For a flake-based configuration, the equivalent rebuild may be:
sudo nixos-rebuild boot --flake /etc/nixos#hp348
sudo reboot
After reboot, the parameter was verified:
cat /proc/cmdline
The output now included:
iomem=relaxed
This setting reduces /dev/mem protection. It was used only to permit the read and was removed after the investigation.
After iomem=relaxed was active, the probe found:
Chipset: Intel Kaby Lake U w/ iHDCP2.2 Prem.
Flash: Winbond W25Q64BV/W25Q64CV/W25Q64FV
Capacity: 8192 kB
The Intel flash descriptor reported:
FREG0: Flash Descriptor region (0x00000000-0x00000fff) is read-only.
FREG1: BIOS region (0x00200000-0x007fffff) is read-write.
FREG2: Management Engine region (0x00001000-0x001fffff) is locked.
PR0: 0x006d6000-0x007fffff is read-only.
PR1: 0x00200000-0x0021ffff is read-only.
flashrom warned that the laptop’s embedded controller was not positively identified and that even probing or reading can theoretically cause abnormal fan, backlight, or power behavior. The read was therefore performed once, on AC power, without suspend.
Only the BIOS region was read:
mkdir -p ~/hp-bios-f47/live
cd ~/hp-bios-f47/live
sudo flashrom -p internal --ifd -i bios -r live-bios.bin
The successful lines were:
Reading ich descriptor... done.
Using region: "bios".
Reading flash... done.
The dump was 8.0 MiB and had this SHA-256 hash:
6906154e4cf73cccc8b395c985c7c932aaace9923ac21657421f247dda43bfd5 live-bios.bin
The commands used to preserve its identity were:
ls -lh live-bios.bin
sha256sum live-bios.bin
file live-bios.bin
Unlike the encrypted HP .fd, the live dump contained real UEFI firmware-volume headers:
grep -abo '_FVH' live-bios.bin | head -20
The recorded offsets were:
2433064:_FVH
2768944:_FVH
3297320:_FVH
6570024:_FVH
7172136:_FVH
7190814:_FVH
7312208:_FVH
Important prohibitions during this stage were:
Do not use -w or --write.
Do not use -E or --erase.
Do not use --noverify-all.
Do not use laptop-force options.
Do not use ich_spi_force=yes.
The full live BIOS image can include NVRAM and machine-specific data. It should be kept private.
The firmware-analysis tools were entered again after the dump:
cd ~/hp-bios-f47/live
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#uefitool nixpkgs#ifrextractor-rs \
nixpkgs#binutils nixpkgs#file
command -v uefiextract
command -v uefifind
command -v ifrextractor
On this NixOS environment, the UEFITool commands were lowercase.
Direct IFR extraction from the complete SPI image returned no result because the useful forms were inside compressed firmware sections:
ifrextractor live-bios.bin list | tee live-ifr-list.txt
ifrextractor live-bios.bin
Both reported:
No IFR data found
The full firmware tree was therefore decompressed:
uefiextract live-bios.bin
echo "exit=$?"
ls -lah
Every decompressed file was checked for IFR:
mkdir -p ifr-results
find live-bios.bin.dump -type f -print0 |
while IFS= read -r -d '' f; do
if ifrextractor "$f" list 2>/dev/null | grep -qv 'No IFR data found'; then
echo "===== IFR FOUND: $f ====="
ifrextractor "$f" list
safe="$(echo "$f" | tr '/ ' '__')"
ifrextractor "$f" > "ifr-results/${safe}.txt" 2>/dev/null
fi
done
The extracted results were searched for the storage controls:
grep -RniE \
'AHCI|SATA|RAID|RST|Optane|VMD|Storage|Controller' \
ifr-results/
UTF-16LE firmware strings were also searched:
find live-bios.bin.dump -type f -print0 |
while IFS= read -r -d '' f; do
x="$(
strings -el "$f" 2>/dev/null |
grep -iE 'AHCI|SATA|RAID|RST|Optane|VMD|Storage Controller|Controller Mode' ||
true
)"
if [ -n "$x" ]; then
echo
echo "===== $f ====="
echo "$x"
fi
done | tee firmware-storage-strings.txt
This exposed the hidden setup forms and their exact variable definitions.
The extracted IFR identified this variable store:
Name: PchSetup
GUID: 4570B7F1-ADE8-4943-8DC3-406472842384
Variable-data size: 0x662 bytes
The hidden SATA selector was:
Setting: SATA Mode Selection
Offset: 0x42
AHCI: 0
RAID: 1
Default: RAID
Manufacturing default: RAID
The same variable contained PCIe storage remapping controls:
Port 1: 0x615
Port 3: 0x617
Port 5: 0x619
Port 7: 0x61B
Port 9: 0x61D
Port 11: 0x61F
Their values were:
Not RST Controlled: 0
RST Controlled: 1
This proved that HP had hidden the AHCI control from the visible BIOS rather than removing it from the firmware.
Linux exposed the exact variable at:
/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384
It was located and measured with:
sudo ls -l /sys/firmware/efi/efivars/ | grep -i pchsetup
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo stat -c '%n %s bytes' "$VAR"
The efivarfs file was exactly:
1638 bytes
That size is four bytes of efivarfs attributes followed by 0x662, or 1634, bytes of variable data. Every IFR data offset therefore had to be read at file position 4 + offset.
The SATA mode was checked with:
sudo od -An -tx1 -j $((4 + 0x42)) -N 1 "$VAR"
It returned:
01
All remapping offsets were checked with:
for off in 0x615 0x617 0x619 0x61B 0x61D 0x61F; do
printf 'PchSetup offset 0x%X = ' "$off"
sudo od -An -tx1 -j $((4 + off)) -N 1 "$VAR"
done
The live values were:
PchSetup offset 0x615 = 00
PchSetup offset 0x617 = 00
PchSetup offset 0x619 = 00
PchSetup offset 0x61B = 00
PchSetup offset 0x61D = 01
PchSetup offset 0x61F = 00
This established the exact pre-change state:
PchSetup[0x42] = 0x01 # RAID
PchSetup[0x61D] = 0x01 # PCIe storage Port 9 RST-controlled
The target prepared during the investigation was:
PchSetup[0x42] = 0x00 # AHCI
PchSetup[0x61D] = 0x00 # Port 9 not RST-controlled
5. Applying the firmware-variable fix safely
An initial attempt to copy the efivarfs pseudo-file with cp failed:
cp: cannot lseek ...: Illegal seek
It created an empty destination whose SHA-256 was the standard empty-file hash:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
That empty file was not a valid backup.
The variable was instead streamed with cat:
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo cat "$VAR" > ~/hp-bios-f47/PchSetup.before.bin
It was verified with:
ls -lh ~/hp-bios-f47/PchSetup.before.bin
stat -c '%s bytes' ~/hp-bios-f47/PchSetup.before.bin
sha256sum ~/hp-bios-f47/PchSetup.before.bin
od -An -tx4 -N 4 ~/hp-bios-f47/PchSetup.before.bin
The valid backup identity was:
Size: 1638 bytes
SHA-256: 799039a89c17616eac626b2bf887fea6b261da569ddc523b02e24ed995a87cbb
Attributes: 0x00000007
The attributes 0x00000007 represent the normal non-volatile, boot-service-access, and runtime-access flags.
The two important bytes in the backup were confirmed:
od -An -tx1 -j $((4 + 0x42)) -N 1 \
~/hp-bios-f47/PchSetup.before.bin
od -An -tx1 -j $((4 + 0x61D)) -N 1 \
~/hp-bios-f47/PchSetup.before.bin
Both returned 01.
A human-readable hex dump was also saved:
od -Ax -tx1 ~/hp-bios-f47/PchSetup.before.bin \
> ~/hp-bios-f47/PchSetup.before.hex
The live efivarfs variable was not edited while preparing the new data. A normal file was copied from the verified backup:
cp ~/hp-bios-f47/PchSetup.before.bin \
~/hp-bios-f47/PchSetup.ahci.bin
Only the SATA-mode byte was changed:
printf '\x00' | dd \
of=~/hp-bios-f47/PchSetup.ahci.bin \
bs=1 seek=$((4 + 0x42)) count=1 \
conv=notrunc status=none
Only the Port-9 RST-remapping byte was changed:
printf '\x00' | dd \
of=~/hp-bios-f47/PchSetup.ahci.bin \
bs=1 seek=$((4 + 0x61D)) count=1 \
conv=notrunc status=none
The prepared file was checked before any firmware write:
stat -c '%s bytes' ~/hp-bios-f47/PchSetup.ahci.bin
od -An -tx4 -N 4 ~/hp-bios-f47/PchSetup.ahci.bin
od -An -tx1 -j $((4 + 0x42)) -N 1 \
~/hp-bios-f47/PchSetup.ahci.bin
od -An -tx1 -j $((4 + 0x61D)) -N 1 \
~/hp-bios-f47/PchSetup.ahci.bin
The results were:
1638 bytes
00000007
00
00
The most important check compared every byte:
cmp -l \
~/hp-bios-f47/PchSetup.before.bin \
~/hp-bios-f47/PchSetup.ahci.bin
It reported exactly two differences:
71 1 0
1570 1 0
cmp -l numbers byte positions starting from one. File position 71 corresponds to the four-byte header plus data offset 0x42. File position 1570 corresponds to the four-byte header plus data offset 0x61D. No other byte changed.
The live variable was protected with the immutable attribute:
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo lsattr "$VAR"
The output included:
----i-----------------
chattr was obtained through e2fsprogs:
nix --extra-experimental-features 'nix-command flakes' \
shell nixpkgs#e2fsprogs
Because the new shell lost the unexported value of $VAR, it was set again with export:
export VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
The immutable flag was then removed:
sudo chattr -i "$VAR"
sudo lsattr "$VAR"
The i was confirmed absent before proceeding.
The complete 1638-byte efivarfs file, including its original four-byte attribute header, was written in one operation:
sudo dd \
if="$HOME/hp-bios-f47/PchSetup.ahci.bin" \
of="$VAR" \
bs=1638 count=1 \
conv=notrunc
The successful result was:
1+0 records in
1+0 records out
1638 bytes copied
If this command produces any error, do not delete or recreate the variable. Stop and preserve the current state.
The live offsets were immediately checked:
sudo od -An -tx1 -j $((4 + 0x42)) -N 1 "$VAR"
sudo od -An -tx1 -j $((4 + 0x61D)) -N 1 "$VAR"
Both returned:
00
00
The complete live variable was streamed back to a normal file:
sudo cat "$VAR" > ~/hp-bios-f47/PchSetup.after-write.bin
It was compared byte-for-byte against the prepared image:
cmp \
~/hp-bios-f47/PchSetup.ahci.bin \
~/hp-bios-f47/PchSetup.after-write.bin \
&& echo "PchSetup write verified"
The confirmation was:
PchSetup write verified
The immutable protection was restored:
sudo chattr +i "$VAR"
sudo lsattr "$VAR"
The i flag was visible again.
Only after the full write verified was the machine rebooted:
sudo reboot
6. Verification, cleanup, and preserved recovery files
After NixOS returned, the PCI state was checked:
lspci -nn | grep -iE 'raid|sata|nvme|non-volatile'
The result was:
00:17.0 SATA controller [0106]: Intel Corporation Sunrise Point-LP SATA Controller [AHCI mode] [8086:9d03] (rev 21)
03:00.0 Non-Volatile memory controller [0108]: Intel Corporation NVMe Optane Memory Series [8086:2522]
This was the fundamental success condition. The controller was no longer 8086:282a RAID mode, and the Optane device now existed independently on the PCI bus.
Kernel initialization was checked with:
sudo dmesg | grep -iE 'ahci|nvme|rst'
The relevant result was:
nvme nvme0: pci function 0000:03:00.0
nvme nvme0: 4/0/0 default/read/poll queues
nvme0n1:
ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, SATA mode
ahci 0000:00:17.0: 2/2 ports implemented (port mask 0x3)
The old messages were gone:
Found 1 remapped NVMe devices.
Switch your BIOS from RAID to AHCI mode to use them.
The block-device view was checked with:
lsblk -o NAME,MODEL,SERIAL,SIZE,TYPE,FSTYPE,MOUNTPOINTS
The relevant result, with unique serials omitted here, was:
sda TOSHIBA MQ01ACF050 465.8G disk
sda1 512M part vfat /boot
sda2 8G part swap [SWAP]
sda3 457.3G part ext4 / /nix/store
zram0 3.8G disk swap [SWAP]
nvme0n1 INTEL MEMPEK1J016GA 13.4G disk
Native NVMe enumeration was checked with:
sudo nvme list
The device appeared as:
Node: /dev/nvme0n1
Generic: /dev/ng0n1
Model: INTEL MEMPEK1J016GA
Capacity: 14.40 GB
LBA format: 512 B
Firmware: K4110400
nvme0n1 did not appear in df -h because it was still a raw, unmounted block device. That was expected.
The live variable was checked again:
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo od -An -tx1 -j $((4 + 0x42)) -N 1 "$VAR"
sudo od -An -tx1 -j $((4 + 0x61D)) -N 1 "$VAR"
The post-reboot values were:
PchSetup[0x42] = 00
PchSetup[0x61D] = 01
HP firmware restored the Port-9 RST field at 0x61D to 01, but it did not restore the SATA-mode byte. The NVMe nevertheless remained exposed natively at 03:00.0 and the old remapping warning remained absent.
The conclusion is that PchSetup[0x42] = 00 is the critical persistent change. The Port-9 field is either ignored or disabled when the controller itself is operating in AHCI mode. It should now be left alone.
iomem=relaxed was needed only for the read-only SPI access. After the firmware analysis succeeded, it was removed from boot.kernelParams.
The boot configuration was rebuilt:
sudo nixos-rebuild boot
After the following reboot, /proc/cmdline should no longer contain iomem=relaxed.
There is no reason to leave the relaxed physical-memory policy enabled for normal use.
At minimum, preserve these files privately:
~/hp-bios-f47/live/live-bios.bin
~/hp-bios-f47/PchSetup.before.bin
~/hp-bios-f47/PchSetup.before.hex
~/hp-bios-f47/PchSetup.ahci.bin
~/hp-bios-f47/PchSetup.after-write.bin
The most important identities are:
live-bios.bin
SHA-256: 6906154e4cf73cccc8b395c985c7c932aaace9923ac21657421f247dda43bfd5
PchSetup.before.bin
Size: 1638 bytes
SHA-256: 799039a89c17616eac626b2bf887fea6b261da569ddc523b02e24ed995a87cbb
Do not publish the complete SPI dump casually. It can contain machine-specific NVRAM data.
7. Drive health, replacement, and Linux installation
Once the module was visible, its SMART log was inspected:
sudo nvme smart-log /dev/nvme0
The recorded values included:
critical_warning: 0
temperature: 31 °C
available_spare: 100%
percentage_used: 2%
Data Units Read: 35,085,334, approximately 17.96 TB
Data Units Written: 20,922,590, approximately 10.71 TB
power_cycles: 4780
power_on_hours: 6484
unsafe_shutdowns: 566
media_errors: 1544
num_err_log_entries: 146
The endurance, spare, temperature, and critical-warning values looked good, but the historical media-error count required investigation.
The NVMe error log contained genuine historical unrecovered read errors, including repeated entries around these LBAs:
0xbc8d
0xbc98
0xa105
This did not mean the AHCI change caused the errors. NVMe error logs persist across reboots, and the module had previously operated as an Optane/RST cache.
The counters were recorded:
sudo nvme smart-log /dev/nvme0 | \
grep -E 'media_errors|num_err_log_entries'
The known LBAs were read directly:
sudo dd if=/dev/nvme0n1 of=/dev/null \
bs=512 skip=$((0xbc8d)) count=1 \
iflag=direct status=progress
sudo dd if=/dev/nvme0n1 of=/dev/null \
bs=512 skip=$((0xbc98)) count=1 \
iflag=direct status=none
sudo dd if=/dev/nvme0n1 of=/dev/null \
bs=512 skip=$((0xa105)) count=1 \
iflag=direct status=none
All three reads succeeded.
Because the device was empty and only about 14 GB, a complete read-only scan was practical:
sudo badblocks -sv /dev/nvme0n1
The result was:
Pass completed, 0 bad blocks found. (0/0/0 errors)
The counters remained unchanged:
media_errors: 1544
num_err_log_entries: 146
dmesg showed no new NVMe I/O or medium errors.
The most reasonable interpretation is that the errors are historical rather than currently reproducible. The module is not obviously worn out, but its history makes it unsuitable for irreplaceable data. It is more appropriate for non-critical cache, temporary storage, scratch space, or possibly swap.
Never use badblocks -w on a device whose contents must be preserved. The -w mode is destructive. The scan above used the default read-only mode.
The controller-mode setting is stored in the laptop’s UEFI/NVRAM, not on the Optane module. Replacing the module should not undo PchSetup[0x42] = 00.
The current module is an M.2 2280 PCIe NVMe device. A sensible replacement is:
Form factor: M.2 2280
Interface: PCIe NVMe
Generation: Gen3 is the safest direct match
Capacity: 500 GB or 1 TB is a practical choice
HP sold the 348 G7 with conventional PCIe NVMe storage as well as the 16 GB Optane configuration, so the slot was designed to accept a normal NVMe SSD. A modern Gen4 SSD will usually negotiate down to the system’s supported PCIe generation, although there is little benefit in paying extra for very high Gen4 or Gen5 performance on this platform.
Capacity options originally sold by HP are not necessarily firmware capacity limits. A standard 1 TB M.2 2280 NVMe SSD is a reasonable choice, although any replacement should still be purchased from a seller with a usable return policy.
Linux can be installed directly on a replacement NVMe because the slot is now exposed as a normal native PCIe NVMe controller. The successful evidence is:
03:00.0 Non-Volatile memory controller
nvme nvme0: pci function 0000:03:00.0
A clean installation can place an EFI System Partition and the Linux root filesystem on the NVMe. The existing SATA hard disk can remain secondary storage for backups or bulk data.
During installation, identify disks by model or /dev/disk/by-id/... rather than assuming that a particular device will always be named /dev/nvme0n1 or /dev/sda.
It is sensible to leave the old SATA installation intact until the new NVMe installation boots reliably. Once verified, the SATA disk can be repurposed if desired.
8. Persistence, BIOS updates, and recovery
Ordinary reboot and shutdown have already been tested. PchSetup[0x42] remained 00, as expected for a non-volatile UEFI variable.
Replacing the NVMe, reinstalling Linux, replacing the SATA disk, or losing normal operating-system state should not normally reset this firmware setting.
The events most likely to restore RAID mode are loading BIOS defaults, choosing a factory-default or BIOS-reset function, performing a BIOS recovery, clearing firmware settings, replacing the motherboard, or installing a BIOS update that resets or migrates NVRAM.
The practical risk assessment is:
| Event | Reversion risk |
|---|---|
| Normal reboot | Very low; tested successfully |
| Normal shutdown and power-on | Very low |
| Replacing the NVMe SSD | Low |
| Reinstalling Linux | Essentially none |
| Removing or replacing the SATA disk | Very low |
| Loading BIOS defaults | High |
| Choosing Restore Factory Defaults | High |
| BIOS recovery procedure | Meaningful to high |
| BIOS firmware update | Possible; verify afterward |
| Motherboard replacement | Effectively certain |
No percentage can be assigned because HP does not document the persistence of this hidden variable.
After a BIOS update, first check the observable storage state. Do not immediately repeat the old write procedure.
Run:
lspci -nn | grep -iE 'raid|sata|nvme|non-volatile'
If the output still contains an AHCI SATA controller and an independent non-volatile memory controller, nothing needs to be changed.
Check the live byte if the same variable still exists:
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo od -An -tx1 \
-j $((4 + 0x42)) -N 1 "$VAR"
If it still returns 00, the machine remains in AHCI mode.
If a future BIOS resets it to 01, re-extract and inspect that new BIOS version’s IFR before writing anything. Do not assume that the F.47 offset remains valid in F.48, F.49, or any later release.
If the NVMe disappears again, start with:
lspci -nn | grep -iE 'raid|sata|nvme|non-volatile'
sudo dmesg | grep -iE 'ahci|nvme|rst|remapped'
lsblk -o NAME,MODEL,SIZE,TYPE,FSTYPE,MOUNTPOINTS
The known broken state is:
00:17.0 RAID bus controller [8086:282a]
Found 1 remapped NVMe devices.
Switch your BIOS from RAID to AHCI mode to use them.
The known working state is:
00:17.0 SATA controller [AHCI mode] [8086:9d03]
03:00.0 Non-Volatile memory controller [8086:2522]
/dev/nvme0n1 exists
On the confirmed F.47/86CB combination only, inspect the live value:
VAR="/sys/firmware/efi/efivars/PchSetup-4570b7f1-ade8-4943-8dc3-406472842384"
sudo stat -c '%n %s bytes' "$VAR"
sudo od -An -tx1 -j $((4 + 0x42)) -N 1 "$VAR"
Expected working result:
Size: 1638 bytes
Value at 0x42: 00
Before considering any rewrite, verify the board and BIOS again:
sudo dmidecode -t baseboard
sudo dmidecode -t bios
Also verify that the preserved original backup still matches:
stat -c '%s bytes' ~/hp-bios-f47/PchSetup.before.bin
sha256sum ~/hp-bios-f47/PchSetup.before.bin
The confirmed identity is:
1638 bytes
799039a89c17616eac626b2bf887fea6b261da569ddc523b02e24ed995a87cbb
If the BIOS version is no longer F.47, stop and re-derive the variable layout from the new firmware.
Do not guess a setup offset from another HP model or BIOS version.
Do not write to the complete SPI flash just to change this setting. The successful fix changed a UEFI setup variable; flashrom was used only for a read-only BIOS-region dump.
Do not use flashrom -w, --write, -E, --erase, --noverify-all, or laptop-force options for this procedure.
Do not delete and recreate the PchSetup efivarfs file if a write fails.
Do not write a single byte directly into the efivarfs pseudo-file. Preserve the complete four-byte attributes header and update the complete verified variable in one operation.
Do not proceed if the prepared image differs from the backup anywhere except the intended byte positions.
Do not leave iomem=relaxed enabled after the SPI read is finished.
Do not treat the absence of a raw disk from df -h as proof that the kernel cannot see it. Use lsblk, lspci, dmesg, and nvme list.
Do not assume the Optane module’s historical SMART counters were caused by the AHCI change. The counters did not increase, the logged LBAs read successfully, and a complete read-only scan found no current bad blocks.
9. Final conclusions
The NVMe device was physically present but hidden from Linux by Intel RST NVMe remapping while the PCH storage controller operated in RAID mode.
HP’s visible BIOS did not expose the necessary controller-mode selector, and the supported hp_bioscfg Linux interface did not expose it either.
HP’s distributed 086CB.fd image was the correct board image but remained unsuitable for direct UEFI parsing. Reading the installed BIOS region from SPI flash produced a valid UEFI image whose decompressed IFR exposed the hidden settings.
For HP 348 G7 board 86CB on Insyde F.47, the relevant variable was:
PchSetup-4570b7f1-ade8-4943-8dc3-406472842384
The decisive setting was:
Offset 0x42
RAID = 1
AHCI = 0
Changing the live value from 01 to 00, verifying the complete 1638-byte variable, and rebooting changed the machine to native AHCI/NVMe operation.
The final verified state was:
Intel SATA controller in AHCI mode: 8086:9d03
Intel Optane exposed as native NVMe: 8086:2522
Linux device: /dev/nvme0n1
The setting survived reboot. The Port-9 RST byte reverted to 01, but this did not matter once the controller’s SATA-mode byte remained 00.
The original problem is resolved: Intel RST NVMe remapping is no longer preventing Linux from accessing the internal M.2 device, and the slot can now be used with a normal NVMe SSD and as a Linux boot device.