NVMe-eMMC Bridge 芯片固件开发(九):Windows平台NVMe设备固件升级工具

概述

本文档以 BayHub BH799 NVMe-eMMC Bridge 芯片 的 Windows 固件升级工具为实例,系统讲解:

  1. MFC GUI 架构设计:对话框分层、控件通信机制、日志系统
  2. 固件升级流程:基于 Microsoft 官方文档的 IOCTL 接口实现
  3. 多平台适配:Microsoft Inbox Driver 与 Intel RST/VMD Driver 的差异与特殊处理
  4. 关键技术实现:固件头校验、防错机制、进度更新

1. MFC GUI 架构设计

1.1 整体架构

本工具采用 MFC 对话框分层架构,主对话框承载三个功能子页面(Tab Control),每个子页面独立处理特定功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
+------------------------------------------------------------------+
| BayHub Firmware Update Tool |
+------------------------------------------------------------------+
| +------------------------------------------------------------+ |
| | [Tab1: NVMe固件升级] [Tab2:eMMC升级] [Tab3:读取Flash头] | |
| +------------------------------------------------------------+ |
| | | |
| | +------------------------------------------------------+ | |
| | | 子对话框内容区域 | | |
| | | | | |
| | | - 设备选择 ComboBox | | |
| | | - 固件文件路径 Edit + Browse按钮 | | |
| | | - 固件槽位选择 ComboBox | | |
| | | - 进度条 Progress Control | | |
| | | - 升级按钮 / 检测按钮 | | |
| | | | | |
| | +------------------------------------------------------+ | |
| | | |
| +------------------------------------------------------------+ |
| |
| +------------------------------------------------------------+ |
| | 日志输出区域 (ListBox) | |
| | [2026-03-16 10:23:45] Device detected: BH799 NVMe | |
| | [2026-03-16 10:23:46] Firmware version: 10100070 | |
| | [2026-03-16 10:23:47] Downloading firmware... 10% | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+

1.2 对话框类层次结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// BBFirmwareupdatetoolDlg.h

// 主对话框 - 管理所有子对话框和公共资源
class CBBFirmwareupdatetoolDlg : public CDialogEx
{
public:
// Tab控件和列表框
CTabCtrl m_tabctrl; // Tab选择控件
CListBox m_listboxctrl; // 日志显示区域
CComboBox m_comboBox; // 设备列表

// 子对话框实例(作为成员变量)
eMMCFFUDlg emmcffudlg; // eMMC升级对话框
FirmwareUpdateDlg fwupdatedlg; // NVMe固件升级对话框
ReadFlashHeaderDlg readflashheaderdlg; // Flash头读取对话框

// 设备列表
NVME_DEVICE_LIST hNVMeDevices[MAX_DISK_NUMBER];
BB_DEVICE_LIST hBBDevices[MAX_DISK_NUMBER];

// 平台选择
int m_radio1; // 0 = Microsoft NVMe, 1 = Intel RST

// 日志文件
CFile m_File;
CString m_LogfileName;

// 消息处理 - 后台线程向前台更新日志
afx_msg LRESULT OnUpdatelistBox(WPARAM wParam, LPARAM lParam);
};

关键设计点

  1. 子对话框作为成员变量:避免频繁创建销毁,提高响应速度
  2. 公共资源集中在主对话框:设备列表、日志文件、平台选择由主对话框统一管理
  3. 消息机制实现线程安全:后台线程通过 PostMessage / SendMessage 更新 UI

1.3 图标与后台操作的通信机制

1.3.1 工作线程创建

固件升级是耗时操作(可能需要数分钟),必须在 后台线程 中执行,避免阻塞 UI 主线程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// FirmwareUpdateDlg.cpp

void FirmwareUpdateDlg::OnBnClickedButton2() // 升级按钮
{
// 启动后台工作线程
m_hThread = CreateThread(
NULL, // 安全属性
0, // 栈大小
FirmwareUpgradeThread, // 线程函数
this, // 传入参数
0, // 创建标志
NULL // 线程ID
);

// 禁用按钮,防止重复点击
GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
}

// 线程函数
DWORD WINAPI FirmwareUpdateDlg::FirmwareUpgradeThread(LPVOID lpParameter)
{
FirmwareUpdateDlg* pDlg = (FirmwareUpdateDlg*)lpParameter;
CBBFirmwareupdatetoolDlg* pMain = pDlg->m_pMainDlg;

// 执行固件升级
int ret = DeviceFirmwareUpgrade(
pMain->hNVMeDevices[pMain->m_iBBDevice].hDevice,
pDlg->m_slotNum,
(TCHAR*)(LPCTSTR)pDlg->m_str_bin_file,
pDlg
);

// 通知主线程升级完成
::PostMessage(pMain->m_UIMainThreadId, WM_UPDATE_LISTBOX, 0, 0);

return ret;
}

1.3.2 消息映射机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// BBFirmwareupdatetoolDlg.h - 消息声明
class CBBFirmwareupdatetoolDlg : public CDialogEx
{
afx_msg LRESULT OnUpdatelistBox(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};

// BBFirmwareupdatetoolDlg.cpp - 消息映射
BEGIN_MESSAGE_MAP(CBBFirmwareupdatetoolDlg, CDialogEx)
ON_MESSAGE(WM_UPDATE_LISTBOX, &CBBFirmwareupdatetoolDlg::OnUpdatelistBox)
END_MESSAGE_MAP()

// 消息处理实现
LRESULT CBBFirmwareupdatetoolDlg::OnUpdatelistBox(WPARAM wParam, LPARAM lParam)
{
// 恢复按钮状态
fwupdatedlg.GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE);

// 滚动日志到底部
int count = m_listboxctrl.GetCount();
if (count > 0) {
m_listboxctrl.SetCurSel(count - 1);
}

return 0;
}

1.3.3 日志输出机制

日志同时输出到 UI ListBox磁盘文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// BBFirmwareupdatetoolDlg.cpp

void CBBFirmwareupdatetoolDlg::WriteLogFile(CString str)
{
// 1. 添加到UI列表框
m_listboxctrl.AddString(str);
int count = m_listboxctrl.GetCount();
if (count > 0) {
m_listboxctrl.SetCurSel(count - 1);
}

// 2. 写入日志文件
if (m_logCreated) {
SYSTEMTIME st;
GetLocalTime(&st);
CString timeStr;
timeStr.Format(_T("[%04d-%02d-%02d %02d:%02d:%02d] "),
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond);

m_File.Write(timeStr, timeStr.GetLength());
m_File.Write(str, str.GetLength());
m_File.Write(_T("\r\n"), 2);
m_File.Flush(); // 确保写入磁盘
}
}

// 日志文件创建
BOOL CBBFirmwareupdatetoolDlg::CreateLogFile()
{
CTime time = CTime::GetCurrentTime();
m_LogfileName = time.Format(_T("FWUpdate_%Y%m%d_%H%M%S.log"));

BOOL ret = m_File.Open(m_LogfileName,
CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive);

if (ret) {
m_logCreated = TRUE;
}
return ret;
}

1.4 UI 控件与后台数据绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// FirmwareUpdateDlg.cpp - 进度更新

// 设置进度条
void FirmwareUpdateDlg::SetProgressctrl(int offset)
{
// 通过消息更新进度条(线程安全)
::PostMessage(this->m_hWnd, WM_UPDATE_PROGRESS, offset, 0);
}

// 响应消息
LRESULT FirmwareUpdateDlg::OnUpdateProgressCtrl(WPARAM wParam, LPARAM lParam)
{
int offset = (int)wParam;
m_progressctrl.SetPos(offset);

// 更新进度文字
m_str_updating.Format(_T("升级中... %d%%"), offset);
SetDlgItemText(IDC_STATIC_UPDATING, m_str_updating);

return 0;
}

// 消息映射
BEGIN_MESSAGE_MAP(FirmwareUpdateDlg, CDialogEx)
ON_MESSAGE(WM_UPDATE_PROGRESS, &FirmwareUpdateDlg::OnUpdateProgressCtrl)
END_MESSAGE_MAP()

2. 固件升级流程实现

2.1 整体流程架构

参考 Microsoft 官方文档 Upgrading Firmware for an NVMe Device,固件升级分为三步:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+---------------------------------------------------------------------+
| NVMe 固件升级三步流程 |
+---------------------------------------------------------------------+
| |
| (1) 获取固件槽信息 (2) 下载固件镜像 (3) 激活固件 |
| +--------------------+ +--------------------+ +--------------------+ |
| | Get Firmware Info | | Firmware Download | | Firmware Commit | |
| | | | | | | |
| | - Slot Count | | - 分块传输 (4KB) | | - 指定目标槽位 | |
| | - Active Slot | | - Offset 递增 | | - 重启生效 | |
| | - Pending Slot | | - 每块等待完成 | | | |
| | - ReadOnly 属性 | | | | | |
| +--------------------+ +--------------------+ +--------------------+ |
| |
| IOCTL: IOCTL: IOCTL: |
| FIRMWARE_FUNCTION_ FIRMWARE_FUNCTION_ FIRMWARE_FUNCTION_ |
| GET_INFO DOWNLOAD ACTIVATE |
| |
+---------------------------------------------------------------------+

2.2 Microsoft Inbox Driver 方案

2.2.1 设备发现

1
2
3
4
5
6
7
8
9
10
11
// BBFirmwareupdatetoolDlg.cpp

int CBBFirmwareupdatetoolDlg::searchBBDevicesOnMicrosoftNVMePlatform(void)
{
// 使用 WMI 查询 PCI 设备
CString inputCmd("wmic path win32_pnpentity where \"deviceid like '%PCI%'\" get deviceid");
wmicProcess(inputCmd);

// 遍历查找 BayHub 设备 (VID=0x1217, DID=0x8760/0x8761)
// ...
}

2.2.2 使用官方 Storage Firmware IOCTL

Microsoft 从 Windows 10 开始提供标准的存储固件升级接口:

IOCTL 功能
IOCTL_STORAGE_FIRMWARE_GET_INFO 获取固件槽信息
IOCTL_STORAGE_FIRMWARE_DOWNLOAD 下载固件镜像
IOCTL_STORAGE_FIRMWARE_ACTIVATE 激活固件槽
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// FirmwareUpgrade.cpp

int DeviceFirmwareUpgradeOnMicrosoftNVMePlatform(
HANDLE _hDevice,
BYTE bSlot,
TCHAR* FileName,
FirmwareUpdateDlg* pDlg)
{
// 1. 获取固件信息
STORAGE_FIRMWARE_INFO firmwareInfo;
DeviceIoControl(hDevice, IOCTL_STORAGE_FIRMWARE_GET_INFO,
..., &firmwareInfo, ...);

// 2. 下载固件(分块)
STORAGE_FIRMWARE_DOWNLOAD firmwareDownload;
firmwareDownload.Version = 1;
firmwareDownload.Size = sizeof(firmwareDownload);
firmwareDownload.Offset = imageOffset;
firmwareDownload.BufferSize = readLength;
memcpy(firmwareDownload.ImageBuffer, buffer, readLength);

DeviceIoControl(hDevice, IOCTL_STORAGE_FIRMWARE_DOWNLOAD,
..., &firmwareDownload, ...);

// 3. 激活固件
STORAGE_FIRMWARE_ACTIVATE firmwareActivate;
firmwareActivate.SlotToActivate = slotNumber;

DeviceIoControl(hDevice, IOCTL_STORAGE_FIRMWARE_ACTIVATE,
..., &firmwareActivate, ...);
}

2.3 Intel RST/VMD 方案

2.3.1 为什么需要特殊处理?

Intel RST (Rapid Storage Technology) 和 VMD (Volume Management Device) 使用 scsi miniport 架构,设备访问方式与 Microsoft inbox driver 不同:

特性 Microsoft Inbox Driver Intel RST/VMD
设备句柄 \\.\PhysicalDriveN \\.\ScsiN
IOCTL 接口 IOCTL_STORAGE_FIRMARE_* IOCTL_SCSI_MINIPORT + IOCTL_NVME_PASS_THROUGH
NVMe 命令 内置封装 需要自行构造 NVMe Admin 命令
SCSI 地址 不需要 需要 Bus/Target/LUN

2.3.2 Intel RST 平台设备发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// BBFirmwareupdatetoolDlg.cpp

int CBBFirmwareupdatetoolDlg::searchBBDevicesOnIntelRSTPlatform(void)
{
// 使用 WMIC 获取 SCSI 地址信息
CString inputCmd(
"wmic diskdrive get firmwarerevision,model,scsibus,scsitargetid,scsilogicalunit"
);
wmicProcess(inputCmd);

// 解析输出获取:
// - SCSIBus (路径ID)
// - SCSITargetId (目标ID)
// - SCSILogicalUnit (LUN)

// 这些信息用于后续构造 NVMe Pass-Through 命令
hNVMeDevices[deviceIndex].SCSIBus = strtol(SCSIBus, NULL, 16);
hNVMeDevices[deviceIndex].SCSITargetId = strtol(SCSITargetId, NULL, 16);
hNVMeDevices[deviceIndex].SCSILogicalUnit = strtol(SCSILogicalUnit, NULL, 16);
}

2.3.3 Intel RST NVMe 命令传递

Intel RST 环境下,需要通过 IOCTL_SCSI_MINIPORT 传递原始 NVMe 命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// FirmwareUpgrade.cpp

BOOL DeviceGetFirmwareInfoOnIntelRSTPlatform(
HANDLE hDevice,
PUCHAR Buffer,
DWORD BufferLength,
BOOLEAN DisplayResult,
CBBFirmwareupdatetoolDlg* pMainDlg)
{
PSRB_IO_CONTROL srbControl;
PNVME_IOCTL_PASS_THROUGH firmwareRequest;

// 1. 构造 SRB 控制块
srbControl = (PSRB_IO_CONTROL)Buffer;
srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
srbControl->ControlCode = IOCTL_NVME_PASS_THROUGH;
RtlMoveMemory(srbControl->Signature, INTELNVM_SIGNATURE, 8); // "INTELNVM"
srbControl->Timeout = 10;

// 2. 构造 NVMe Admin 命令 - Get Log Page (LID=0x03)
firmwareRequest = (PNVME_IOCTL_PASS_THROUGH)(Buffer);
firmwareRequest->Version = NVME_PASS_THROUGH_VERSION;

// SCSI 地址(从 WMIC 获取)
firmwareRequest->PathID = pMainDlg->hNVMeDevices[...].SCSIBus;
firmwareRequest->TargetID = pMainDlg->hNVMeDevices[...].SCSITargetId;
firmwareRequest->Lun = pMainDlg->hNVMeDevices[...].SCSILogicalUnit;

// NVMe Admin 命令
firmwareRequest->Parameters.Command.CDW0.OPC = NVME_ADMIN_COMMAND_GET_LOG_PAGE;
firmwareRequest->Parameters.Command.u.GETLOGPAGE.CDW10_V13.LID = NVME_LOG_PAGE_FIRMWARE_SLOT_INFO;
firmwareRequest->Parameters.Command.u.GETLOGPAGE.CDW10_V13.NUMDL = 64/sizeof(DWORD) - 1;

// 3. 发送请求
return DeviceIoControl(hDevice,
IOCTL_SCSI_MINIPORT, // 注意:不是 IOCTL_STORAGE_*
Buffer,
BufferLength,
Buffer,
BufferLength,
&returnedLength,
NULL);
}

2.3.4 Intel RST 固件下载实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// FirmwareUpgrade.cpp - 分块下载

while (moreToDownload) {
// 构造 Firmware Download 命令 (Opcode=0x19)
firmwareRequest->Parameters.Command.CDW0.OPC = 0x19; // Firmware Image Download

// CDW10: Numd (传输数据长度-1, 以DWORD为单位)
firmwareRequest->Parameters.Command.CDW10 = (ChunkSize / 4) - 1;

// CDW11: Offset (以4KB为单位)
firmwareRequest->Parameters.Command.CDW11 = imageOffset / 4096;

// 复制固件数据
memcpy(buffer + firmwareRequest->Parameters.DataBufferOffset,
fileBuffer + imageOffset, ChunkSize);

result = DeviceIoControl(hDevice,
IOCTL_SCSI_MINIPORT,
buffer, bufferSize,
buffer, bufferSize,
&returnedLength, NULL);

imageOffset += ChunkSize;

// 更新进度
int progress = (imageOffset * 100) / FileSize;
pDlg->SetProgressctrl(progress);
}

// Firmware Commit (Opcode=0x10)
firmwareRequest->Parameters.Command.CDW0.OPC = 0x10; // Firmware Commit
// CDW10: FwAction=01 (Downloaded image replace), FwSlot=slotNumber
firmwareRequest->Parameters.Command.CDW10 = (slotNumber << 24) | 0x01;

DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT, ...);

3. 多平台适配架构设计

3.1 平台选择机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 平台选择通过单选按钮控制
// m_radio1 = 0: Microsoft Inbox Driver
// m_radio1 = 1: Intel RST/VMD

int DeviceFirmwareUpgrade(
HANDLE _hDevice,
BYTE bSlot,
TCHAR* FileName,
FirmwareUpdateDlg* pDlg)
{
if (pDlg->m_pMainDlg->m_radio1 == 0) {
// Microsoft 方案
return DeviceFirmwareUpgradeOnMicrosoftNVMePlatform(...);
}
else {
// Intel RST 方案
return DeviceFirmwareUpgradeOnIntelRSTPlatform(...);
}
}

3.2 设备列表管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// BBFirmwareupdatetoolDlg.h

typedef struct NVME_DEVICE_LIST {
HANDLE hDevice; // 设备句柄
char wide_FR[256]; // Firmware Revision
char wide_MN[256]; // Model Name

// Intel RST 专用 - SCSI 地址
ULONG SCSIBus;
ULONG SCSITargetId;
ULONG SCSILogicalUnit;
} NVME_DEVICE_LIST, *PNVME_DEVICE_LIST;

// 设备索引映射
int NVMeDevicesIndexMap[MAX_DISK_NUMBER]; // ComboBox索引 -> 设备列表索引

3.3 架构图:平台抽象层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
+------------------------------------------------------------------+
| Firmware Update GUI (MFC) |
+------------------------------------------------------------------+
| |
| +------------------+ +------------------+ +-----------------+ |
| | 设备检测 Tab | | NVMe升级 Tab | | eMMC升级 Tab | |
| +--------+---------+ +--------+---------+ +--------+--------+ |
| | | | |
| v v v |
| +------------------------------------------------------------+ |
| | CBBFirmwareupdatetoolDlg (主对话框) | |
| | - 平台选择 (m_radio1) | |
| | - 设备列表管理 | |
| | - 日志输出 | |
| +---------------------------+--------------------------------+ |
| | |
+------------------------------+----------------------------------+
|
v
+------------------------------------------------------------------+
| FirmwareUpgrade.cpp |
+------------------------------------------------------------------+
| |
| +----------------------------+ +---------------------------+ |
| | DeviceFirmwareUpgrade() | | 平台分发函数 | |
| | (统一入口) | | | |
| +----------------------------+ +---------------------------+ |
| | | |
| v v |
| +----------------------------+ +---------------------------+ |
| | Microsoft Inbox Driver | | Intel RST/VMD | |
| | | | | |
| | - IOCTL_STORAGE_FIRMWARE_*| | - IOCTL_SCSI_MINIPORT | |
| | - 标准 Windows 存储栈 | | - NVMe Pass-Through | |
| | - \\.\PhysicalDriveN | | - \\.\ScsiN | |
| +----------------------------+ +---------------------------+ |
| |
+------------------------------------------------------------------+

4. 关键技术实现

4.1 固件头防错机制(Fool Proof)

为防止用户误刷不兼容的固件,工具实现了 固件头校验 功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// FirmwareUpdateDlg.cpp - 固件头参数读取

// 读取设备当前固件头参数
if (pDlg->m_header_fool_proof_enable == TRUE) {
result = DeviceVendorSpecificCMDOnIntelRSTPlatform(
_hDevice, buffer, bufferSize, TRUE, pMainDlg);

// 解析固件头
PNVME_FLASH_HEADER_PARAMETER_INFO pheader =
(PNVME_FLASH_HEADER_PARAMETER_INFO)firmwareInfo;

// 校验参数兼容性
// - 检查 spi_page_program 设置
// - 检查 namespace 配置
// - 检查 L1.2 功耗配置
// ...
}

固件头结构定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// NVMeCommandReadHeaderParameter.h

typedef struct _NVME_FLASH_HEADER_PARAMETER_INFO {
// Bootloader 参数 (DWORD 0-31)
DWORD dwSpiPageProgram; // 0x08
DWORD dwSpiCtrlIoTiming; // 0x09
DWORD dwSpiEraseCfgReg1; // 0x0A
// ...

// Firmware 参数 (DWORD 32-79)
DWORD dwFwSlot; // 0x20 bit[3:0]
DWORD dwNamespaceClass; // 0x20 bit[7:4]
DWORD dwEmmcHideClass; // 0x20 bit[9:8]
DWORD dwNvmeNumberOfQueues; // 0x20 bit[11:10]
// ...

// 固件标识 (DWORD 248-255)
char cFwSignature[8]; // "BH799...." 魔数
char cFwRevision[8]; // "10100070" 版本号
char cFwMd5Hash[16]; // MD5 校验值
} NVME_FLASH_HEADER_PARAMETER_INFO;

4.2 MD5 完整性校验

固件镜像在下载前需要进行完整性校验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// FirmwareUpdateDlg.cpp

int Cfw_update_process::Md5Check()
{
// 读取固件文件
HANDLE hFile = CreateFile(m_inputFWbinFile, GENERIC_READ, ...);

// 读取文件末尾的 MD5 (偏移 0x3F0, 16字节)
SetFilePointer(hFile, FW_CUSTOMER_MD5_START_OFFSET, NULL, FILE_BEGIN);
DWORD bytesRead;
BYTE fileMd5[MD5LEN];
ReadFile(hFile, fileMd5, MD5LEN, &bytesRead, NULL);

// 计算文件实际 MD5
BYTE computedMd5[MD5LEN];
CalculateMd5(buffer, buffer_length, computedMd5);

// 比较
if (memcmp(fileMd5, computedMd5, MD5LEN) != 0) {
return -1; // 校验失败
}

return 0;
}

4.3 参数配置与跳过机制

工具支持 选择性跳过某些固件参数,便于产线调试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// FirmwareUpdateDlg.cpp - 参数解析

int Cfw_update_process::ParseParameterData(std::string& param_data)
{
// 配置文件格式: param_name:value
// 例如: spi_page_program:0xFF

// 解析并更新到固件二进制
for (auto& param : m_vParameters) {
if (param.m_customer_readable) {
// 写入到对应的偏移位置
WriteParameterToBin(param);
}
}
}

// 合并跳过参数到固件文件
int Cfw_update_process::MergeSkippedParametersToBinFile(void)
{
// 读取原始固件
ReadFirmwareBinFile(m_inputFWbinFile);

// 读取配置文件
ReadParameterData(m_str_skipped_cfg_file);

// 合并参数
ParseParameterData(param_data);

// 重新计算 MD5
Md5Check();

// 保存
SaveTheBinFile(m_outputFWbinFile, m_buffer_length);
}

5. 用户界面与使用流程

5.1 界面布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
+------------------------------------------------------------------+
| BayHub Firmware Update Tool v1.0.16 _ [] X |
+------------------------------------------------------------------+
| |
| +------------------------------------------------------------+ |
| | O Microsoft NVMe Driver O Intel RST/VMD Driver | |
| +------------------------------------------------------------+ |
| |
| +------------------------------------------------------------+ |
| | [Tab1: NVMe固件升级] [Tab2:eMMC升级] [Tab3:读取Flash头] | |
| +------------------------------------------------------------+ |
| | | |
| | 设备检测(D): [检测设备_______________▼] [关键词:___] | |
| | [x] 保存设置 | |
| | | |
| | 当前设备: NVMe BAYHUB BH799 固件版本: 10100070 | |
| | | |
| | 固件文件: [________________________] [浏览...] | |
| | | |
| | 固件槽位: [Slot 1 (当前活跃)___▼] | |
| | [x] 启用固件头防错检查 | |
| | | |
| | 参数配置: [________________________] [浏览...] | |
| | | |
| | [=========== ] | |
| | 升级 | |
| +------------------------------------------------------------+ |
| |
| +------------------------------------------------------------+ |
| | [INFO] 2026-03-16 10:23:45 Device detected... | |
| | [INFO] 2026-03-16 10:23:46 FW version: 10100070 | |
| | [INFO] 2026-03-16 10:23:47 Downloading: 10% | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+

5.2 典型使用流程

  1. 选择平台:根据目标机器的驱动类型选择 Microsoft NVMe 或 Intel RST
  2. 检测设备:点击”检测设备”按钮,列出系统中所有 BayHub 设备
  3. 选择固件:浏览并选择要升级的 .bin 文件
  4. 选择槽位:选择目标固件槽位(自动获取当前活跃槽位)
  5. (可选)启用防错:勾选固件头校验,防止参数不兼容
  6. 开始升级:点击”升级”按钮,等待完成
  7. 重启生效:升级完成后提示用户重启系统

6. 总结

本文档系统讲解了 Windows 平台 NVMe 固件升级工具的完整实现:

  1. MFC GUI 架构:对话框分层设计、工作线程与 UI 线程通信、日志系统
  2. 固件升级流程:三步走(获取信息→下载→激活),参考 Microsoft 官方文档
  3. 多平台适配:Microsoft Inbox Driver 与 Intel RST/VMD 的差异,平台抽象层设计
  4. 关键技术:固件头防错、MD5 校验、参数配置

该工具已支持 BH799 芯片,可作为其他存储设备固件升级工具的参考实现。