A Python script that patches the factory defaults in the MSI B760 TOMAHAWK DDR4 BIOS so that 4-DIMM configurations run stably at modest memory speeds.
Four-slot DDR4 boards need more voltage than two-slot boards, and the B760 TOMAHAWK ships with all voltages at auto. That works fine with two DIMMs. With four it causes random crashes, reboots, and display stalls at memory speeds that should be well within spec -- sometimes as low as 2133 MHz.
The root cause is two things hitting at once:
SA voltage (System Agent). The SA rail powers the memory controller and the DRAM PHY. When you populate all four slots the controller has to drive twice the load, and the auto voltage is not enough. The symptoms look like memory instability, but lowering DRAM clocks does not help because the memory controller itself is browning out.
Intel Vmin Shift on 13th and 14th gen CPUs. Pre-2024 microcode ran the CPU cores at elevated voltage continuously, which caused measurable and permanent degradation in some silicon lots. The CPU still passes benchmarks, but its minimum operating voltage has crept up. BIOS v1.C0 includes microcode 0x12B, which was Intel's fix for this. It is the last version that also has ME firmware 16.1.32.2473 -- newer BIOS versions switched to a later ME build that introduced its own instability on this board.
C-state depth. With marginal silicon, letting the CPU drop to C8 or C10 causes the SA and VDDQ rails to power-gate hard. On wake the voltage droop hits the memory controller before the rails stabilize, which crashes the training logic. Capping at C3 keeps the rails alive between active periods.
These values live in the firmware's default-settings store. They are what the BIOS loads on first boot, after a CMOS clear, or when you hit F6 (load optimized defaults). Your runtime NVRAM is not touched -- only the defaults the BIOS falls back to.
| Variable | Offset | Value | Meaning |
|---|---|---|---|
| Setup | 0x0CBF | 1350 mV | CPU SA voltage |
| Setup | 0x0F10 | 1250 mV | CPU VDDQ (CPU-side DDR4 I/O) |
| Setup | 0x0F98 | 1250 mV | DRAM VDDQ (DIMM-side DDR4 I/O) |
| Setup | 0x0F9A | 1250 mV | per-slot VDDQ override, slot A1 |
| Setup | 0x0F9C | 1250 mV | per-slot VDDQ override, slot A2 |
| Setup | 0x0F9E | 1250 mV | per-slot VDDQ override, slot B1 |
| Setup | 0x0FA0 | 1250 mV | per-slot VDDQ override, slot B2 |
| CpuSetup | 0x004B | 0x02 (C3) | Package C-state limit |
The patch is applied to all three copies of the defaults store in the image (the main NVAR store plus both external StdDefaults volumes), so the values are consistent regardless of which code path the BIOS uses.
- Python 3.9 or later (no external dependencies)
- The original unmodified BIOS file:
E7D96IMS.1C0, version 1.C0- Download from MSI's support page for the MAG B760 TOMAHAWK WIFI DDR4
- MD5:
9afdca8872da20eef74c308d28835f3c
python patch.py E7D96IMS.1C0
This writes E7D96IMS_patched.1C0 in the same directory. To specify the output path:
python patch.py E7D96IMS.1C0 output.1C0
Use M-Flash (the built-in MSI flash utility):
- Copy the patched file to a FAT32-formatted USB drive, root directory, named
E7D96IMS.1C0 - Boot into BIOS (Delete key)
- Go to M-Flash and select the file
- Let it flash and reboot
The board will reboot once or twice during training. That is normal.
After flashing, the new defaults load automatically. You do not need to manually enter the voltage values. If you want to verify, check the voltage settings in the BIOS -- they should show 1350 mV for SA and 1250 mV for VDDQ.
If you want to carry over your current BIOS configuration (boot order, memory speed, XMP profile, etc.) rather than starting from defaults, you need to read the live UEFI NVRAM and inject it into the patched image before flashing.
This requires SeSystemEnvironmentPrivilege, which means you need to run as Administrator on Windows. The script below reads your live NVRAM and produces a patched image that combines your current settings with the voltage fixes.
Save this as patch_with_live_nvram.ps1 and run it from an elevated PowerShell session:
# Reads live UEFI vars and injects them into the patched BIOS image.
# Run as Administrator.
$outDir = Split-Path $PSScriptRoot
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
public class EFIPriv {
[DllImport("advapi32.dll", SetLastError=true)]
static extern bool OpenProcessToken(IntPtr proc, uint access, out IntPtr token);
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool LookupPrivilegeValue(string sys, string name, out long luid);
[DllImport("advapi32.dll", SetLastError=true)]
static extern bool AdjustTokenPrivileges(IntPtr token, bool disable,
ref TOKEN_PRIVILEGES newState, uint bufLen, IntPtr prev, IntPtr retLen);
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct TOKEN_PRIVILEGES {
public uint PrivilegeCount;
public long Luid;
public uint Attributes;
}
const uint TOKEN_ADJUST_PRIVILEGES = 0x20;
const uint TOKEN_QUERY = 0x08;
const uint SE_PRIVILEGE_ENABLED = 2;
public static bool EnablePrivilege(string name) {
IntPtr token;
if (!OpenProcessToken(Process.GetCurrentProcess().Handle,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out token))
return false;
long luid;
if (!LookupPrivilegeValue(null, name, out luid)) return false;
var p = new TOKEN_PRIVILEGES {
PrivilegeCount=1, Luid=luid, Attributes=SE_PRIVILEGE_ENABLED };
bool ok = AdjustTokenPrivileges(token, false, ref p, 0,
IntPtr.Zero, IntPtr.Zero);
return ok && System.Runtime.InteropServices.Marshal.GetLastWin32Error() == 0;
}
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern uint GetFirmwareEnvironmentVariableExW(
string lpName, string lpGuid,
byte[] pBuffer, uint nSize, out uint pdwAttributes);
}
"@
[EFIPriv]::EnablePrivilege("SeSystemEnvironmentPrivilege") | Out-Null
$vars = @(
@{Name='Setup'; Guid='{ec87d643-eba4-4bb5-a1e5-3f3e36b20da9}'},
@{Name='CpuSetup'; Guid='{b08f97ff-e6e8-4193-a997-5e9e9b0adb32}'},
@{Name='SaSetup'; Guid='{72c5e28c-7783-43a1-8767-fad73fccafa4}'},
@{Name='PchSetup'; Guid='{4570b7f1-ade8-4943-8dc3-406472842384}'}
)
foreach ($v in $vars) {
$buf = New-Object byte[] 131072
$attr = [uint32]0
$sz = [EFIPriv]::GetFirmwareEnvironmentVariableExW(
$v.Name, $v.Guid, $buf, 131072, [ref]$attr)
if ($sz -gt 0) {
[System.IO.File]::WriteAllBytes("$outDir\nvram_$($v.Name).bin", $buf[0..($sz-1)])
Write-Host "OK $($v.Name): $sz bytes"
} else {
$err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Host "FAIL $($v.Name): win32 error $err"
}
}After running that script, pass the nvram directory to patch.py:
python patch.py E7D96IMS.1C0 --nvram-dir . output.1C0
(The --nvram-dir option looks for nvram_Setup.bin, nvram_CpuSetup.bin, etc. in
the specified directory and injects them into the main NVAR store before applying the
voltage patches on top.)
Flashing a modified BIOS can brick the board. The risk is real. This has been tested on one board running v1.C0. If your board is on a different BIOS version, do not use this.
MSI B760 TOMAHAWK DDR4 boards have no BIOS flashback feature, so a bad flash requires either a recovery flash via M-Flash from a working BIOS state or a programmer and a clip on the SPI chip.
BIOS v1.C0 is the most stable version available for this board because:
- It includes Intel microcode 0x12B, which limits core voltage to prevent further Vmin Shift
- It ships with ME firmware 16.1.32.2473
- ME firmware versions above 16.1.32.x, present in newer BIOS versions, introduced stability regressions on this board that are not voltage-related and not fixable through settings
The instability in newer versions is not well understood. Reverting to v1.C0 and patching the voltage defaults is currently the most reliable option for 4-DIMM setups.
The patch script is MIT licensed. The BIOS binary is MSI's property -- do not redistribute it.