Firmware Image Download 命令
在 NVMe 规范中,Firmware Image Download 命令用于从主机向 NVMe 控制器下载固件镜像。该命令是 NVMe 管理命令集的一部分,通常用于更新或安装新的固件。
1. 目的:
从主机传输固件镜像到 NVMe 控制器。
2. 流程:
通常在该命令之后跟随一个 Firmware Commit 命令,指示控制器验证并激活新下载的固件。
3.命令结构:
操作码:0x11(Firmware Image Download 命令)。
CDW10:包含要传输的 dword(4 字节单位)的数量。
CDW11:包含在固件镜像中的偏移量(以 dword 为单位),从这个偏移量开始传输。
4.数据传输:
固件镜像分块传输,每个块的大小在命令中指定。
可能需要多个 Firmware Image Download 命令才能传输整个镜像。
5.Firmware Commit 命令:
操作码:0x10(Firmware Commit 命令)。
在完整的固件镜像下载后发出此命令。
指示控制器验证并可选地激活新的固件镜像。
流程示例
1. 准备工作:
- 确保固件镜像在主机上可用,并准备传输。
- 确定块大小和传输整个镜像所需的块数量。
2. 下载块:
- 发出多个 Firmware Image Download 命令,每个命令传输固件镜像的一块。
- 每个命令指定块大小和固件镜像中的偏移量。
3. 提交固件:
在所有块下载完成后,发出 Firmware Commit 命令以验证并激活新的固件。
示例代码
以下是一个简化的伪代码示例,用于说明这一过程:
#define FIRMWARE_IMAGE_DOWNLOAD_OPCODE 0x10
#define FIRMWARE_COMMIT_OPCODE 0x11
EFI_STATUS FirmwareImageDownload(EFI_PCI_IO_PROTOCOL *PciIo, UINT8 *FirmwareImage, UINTN FirmwareImageSize) {
EFI_STATUS Status;
UINTN ChunkSize = 4096; // 示例块大小
UINTN Offset = 0;
while (Offset < FirmwareImageSize) {
UINTN BytesToTransfer = MIN(ChunkSize, FirmwareImageSize - Offset);
// 准备命令
NVME_COMMAND Cmd;
ZeroMem(&Cmd, sizeof(Cmd));
Cmd.Opcode = FIRMWARE_IMAGE_DOWNLOAD_OPCODE;
Cmd.CDW10 = (UINT32)(BytesToTransfer / 4); // dword 数量
Cmd.CDW11 = (UINT32)(Offset / 4); // dword 偏移量
// 传输块
Status = PciIo->SubmitCommand(PciIo, &Cmd, FirmwareImage + Offset, BytesToTransfer);
if (EFI_ERROR(Status)) {
return Status;
}
Offset += BytesToTransfer;
}
// 提交固件
ZeroMem(&Cmd, sizeof(Cmd));
Cmd.Opcode = FIRMWARE_COMMIT_OPCODE;
Status = PciIo->SubmitCommand(PciIo, &Cmd, NULL, 0);
return Status;
}
总结
通过 Firmware Image Download 命令,可以从主机向 NVMe 控制器下载固件镜像,通常在下载完成后,需要发出 Firmware Commit 命令以验证并激活新固件。该过程包括准备工作、分块下载固件镜像、提交固件等步骤。