【UEFI基础】BIOS下的NVMe

news2024/10/1 13:58:18

什么是NVMe

NVMe全称NonVolatile Memory Express(非易失性内存主机控制器接口规范),其官方(NVMe官网NVM Express)定义将其描述为“一个开放的标准和信息集合,以充分释放非易失性存储在从移动端到数据中心的所有类型的计算环境中能够提供的优势。NVMe从底层开始设计,为当前和未来的NVM技术提供高带宽和低延迟存储访问。”

NVMe的历史

机械硬盘(HDD,Hard Disk Drive的缩写形式)其内部主要由马达(控制电机)、磁盘片、磁头、转轴、磁头控制器、数据转换器、接口和缓存等几个部分组成,它存在体积大、使用过程容易受震动和碰撞等影响导致损坏、速度慢等问题。固态硬盘(SSD,Solid State Drives的缩写形式)由主控和固态存储芯片(通常是NAND Flash)阵列构成,如下图所示:

在这里插入图片描述

相比与机械硬盘,其存在的优点包括:读写速度快、防震抗摔性、低功耗、无噪音、工作温度范围大、轻便等等。

SSD开始作为存储使用时,一般使用如SATA、SAS或光纤通道等接口与计算机的总线连接。随着固态硬盘在大众市场上的流行,SATA已成为个人计算机中连接SSD的最典型方式。但是,SATA的设计主要是作为机械硬盘的接口,并随着时间的推移越来越难满足速度日益提高的SSD。随着在大众市场的流行,许多固态硬盘的数据速率提升已经放缓。不同于机械硬盘,部分SSD已受到SATA最大吞吐量的限制。

在NVMe出现之前,高端SSD只得以采用PCI Express总线制造,但需使用非标准规范的接口。若使用标准化的SSD接口,操作系统只需要一个驱动程序就能使用匹配规范的所有SSD。这也意味着每个SSD制造商不必用额外的资源来设计特定接口的驱动程序。

2009年Intel开始着手寻找SATA的替代方案。SATA作为串行接口,采用AHCI规范,其已经成为制约SSD速度的瓶颈。AHCI只有1个命令队列,队列深度32;而NVMe可以有65535个命令队列,每个队列都可以深达65536个命令。NVMe也充分使用了MSI的2048个中断向量优势,延迟大大减小。

后续的版本:

在这里插入图片描述

NVMe基础

NVMe是一种用于高速并行数据传输的协议,在存储架构中的位置:

在这里插入图片描述

使用NVMe可减少固态硬中使用的每个输入/输出(I/O)的系统开销。由于设备驱动器的更改允许并行和轮询,因此NVMe SSD能够提供比传统硬盘驱动器(HDD)更快的响应时间。这些改进有助于减少延迟,使其成为企业工作负载以及众多消费者和专业应用程序的理想选择。

NVMe基于PCIe,所以它不像SATA这样需要额外的控制器,而是可以直接与CPU或者芯片组连接:

在这里插入图片描述

以下是使用 NVMe 存储相对于 SAS 或 SATA 驱动器的一些优势:

  • 提升性能:NVMe技术可以使用PCIe将SSD存储直接连接到服务器或中央处理单元(CPU)。凭借性能的显著提高,对于游戏玩家、视频编辑器和其他需要比SAS或SATA HDD更高性能的用户来说,NVMe技术成为了首选数据存储/传输选项。
  • 速度更快:NVMe驱动器可以提供比 SAS或 SATA 驱动器更高的速度,因为它们可以更快地发送和接收NVMe命令并提供更好的吞吐量。
  • 提高兼容性:NVMe被广泛视为比SAS/SATA更具兼容性的选项,并且随着AI、ML和云计算等快速发展的关键技术的发展而经常更新。NVMe技术可以与所有现代操作系统无缝协作,包括手机、笔记本电脑和游戏机。
  • 改进的带宽:PCIe连接比SAS或SATA端口更宽并且具有更多的带宽。它还随着每一代的改进而改进,带宽是上一代的两倍。SAS和SATA的带宽连接要低得多并且是固定的,因此它们不会随着时间的推移而改进。PCIe连接脱颖而出的另一个特点是它们在“通道”中可扩展,因此即使在同一代产品中,用户也可以通过两倍的通道数量将带宽加倍。

BIOS下的NVMe驱动

BIOS下的NVMe驱动对应模块时edk2\MdeModulePkg\Bus\Pci\NvmExpressDxe\NvmExpressDxe.inf。它时一个UEFI Model Driver,所以有以下的接口:

//
// NVM Express Driver Binding Protocol Instance
//
EFI_DRIVER_BINDING_PROTOCOL  gNvmExpressDriverBinding = {
  NvmExpressDriverBindingSupported,
  NvmExpressDriverBindingStart,
  NvmExpressDriverBindingStop,
  0x10,
  NULL,
  NULL
};

该模块依赖于gEfiDevicePathProtocolGuidgEfiPciIoProtocolGuid,最终提供的主要接口是gEfiNvmExpressPassThruProtocolGuidgEfiBlockIoProtocolGuidgEfiBlockIo2ProtocolGuidgEfiDiskInfoProtocolGuid

IN
IN
OUT
OUT
OUT
OUT
gEfiDevicePathProtocolGuid
NVMe
gEfiPciIoProtocolGuid
gEfiNvmExpressPassThruProtocolGuid
gEfiBlockIoProtocolGuid
gEfiBlockIo2ProtocolGuid
gEfiDiskInfoProtocolGuid

NvmExpressDriverBindingSupported

Supported主要就是判断Device Path和PCI IO的情况。

前者需要判断Device Path的类型,主要需要关注的是RemainingDevicePath部分:

  //
  // Check whether device path is valid
  //
  if (RemainingDevicePath != NULL) {
    //
    // Check if RemainingDevicePath is the End of Device Path Node,
    // if yes, go on checking other conditions
    //
    if (!IsDevicePathEnd (RemainingDevicePath)) {
      //
      // If RemainingDevicePath isn't the End of Device Path Node,
      // check its validation
      //
      DevicePathNode.DevPath = RemainingDevicePath;

      if ((DevicePathNode.DevPath->Type    != MESSAGING_DEVICE_PATH) ||
          (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||
          (DevicePathNodeLength (DevicePathNode.DevPath) != sizeof (NVME_NAMESPACE_DEVICE_PATH)))
      {
        return EFI_UNSUPPORTED;
      }
    }
  }

这是因为NVMe存在逻辑上的分区,称为Namespace。

后者主要是通过PCI IO获取Class Code:

  //
  // Examine Nvm Express controller PCI Configuration table fields
  //
  if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) {
    Status = EFI_UNSUPPORTED;
  }

两者判断都成功之后才会执行Start函数。

NvmExpressDriverBindingStart

该函数中的操作包括:

  • 初始化NVME_CONTROLLER_PRIVATE_DATA
//
// Nvme private data structure.
//
struct _NVME_CONTROLLER_PRIVATE_DATA {
  UINT32                                Signature;

  EFI_HANDLE                            ControllerHandle;
  EFI_HANDLE                            ImageHandle;
  EFI_HANDLE                            DriverBindingHandle;

  EFI_PCI_IO_PROTOCOL                   *PciIo;
  UINT64                                PciAttributes;

  EFI_DEVICE_PATH_PROTOCOL              *ParentDevicePath;

  EFI_NVM_EXPRESS_PASS_THRU_MODE        PassThruMode;
  EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL    Passthru;

  //
  // pointer to identify controller data
  //
  NVME_ADMIN_CONTROLLER_DATA            *ControllerData;

  //
  // 6 x 4kB aligned buffers will be carved out of this buffer.
  // 1st 4kB boundary is the start of the admin submission queue.
  // 2nd 4kB boundary is the start of the admin completion queue.
  // 3rd 4kB boundary is the start of I/O submission queue #1.
  // 4th 4kB boundary is the start of I/O completion queue #1.
  // 5th 4kB boundary is the start of I/O submission queue #2.
  // 6th 4kB boundary is the start of I/O completion queue #2.
  //
  UINT8          *Buffer;
  UINT8          *BufferPciAddr;

  //
  // Pointers to 4kB aligned submission & completion queues.
  //
  NVME_SQ        *SqBuffer[NVME_MAX_QUEUES];
  NVME_CQ        *CqBuffer[NVME_MAX_QUEUES];
  NVME_SQ        *SqBufferPciAddr[NVME_MAX_QUEUES];
  NVME_CQ        *CqBufferPciAddr[NVME_MAX_QUEUES];

  //
  // Submission and completion queue indices.
  //
  NVME_SQTDBL    SqTdbl[NVME_MAX_QUEUES];
  NVME_CQHDBL    CqHdbl[NVME_MAX_QUEUES];
  UINT16         AsyncSqHead;

  //
  // Flag to indicate internal IO queue creation.
  //
  BOOLEAN        CreateIoQueue;

  UINT8          Pt[NVME_MAX_QUEUES];
  UINT16         Cid[NVME_MAX_QUEUES];

  //
  // Nvme controller capabilities
  //
  NVME_CAP       Cap;

  VOID           *Mapping;

  //
  // For Non-blocking operations.
  //
  EFI_EVENT      TimerEvent;
  LIST_ENTRY     AsyncPassThruQueue;
  LIST_ENTRY     UnsubmittedSubtasks;
};
  • 创建与NVMe交互的Buffer。
    //
    // 6 x 4kB aligned buffers will be carved out of this buffer.
    // 1st 4kB boundary is the start of the admin submission queue.
    // 2nd 4kB boundary is the start of the admin completion queue.
    // 3rd 4kB boundary is the start of I/O submission queue #1.
    // 4th 4kB boundary is the start of I/O completion queue #1.
    // 5th 4kB boundary is the start of I/O submission queue #2.
    // 6th 4kB boundary is the start of I/O completion queue #2.
    //
    // Allocate 6 pages of memory, then map it for bus master read and write.
    //
    Status = PciIo->AllocateBuffer (
                      PciIo,
                      AllocateAnyPages,
                      EfiBootServicesData,
                      6,
                      (VOID **)&Private->Buffer,
                      0
                      );
    if (EFI_ERROR (Status)) {
      goto Exit;
    }

    Bytes  = EFI_PAGES_TO_SIZE (6);
    Status = PciIo->Map (
                      PciIo,
                      EfiPciIoOperationBusMasterCommonBuffer,
                      Private->Buffer,
                      &Bytes,
                      &MappedAddr,
                      &Private->Mapping
                      );

    if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (6))) {
      goto Exit;
    }
  • 构建EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL,它是与NVMe交互的接口。
//
// Protocol Interface Structure
//
struct _EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL {
  EFI_NVM_EXPRESS_PASS_THRU_MODE                  *Mode;
  EFI_NVM_EXPRESS_PASS_THRU_PASSTHRU              PassThru;
  EFI_NVM_EXPRESS_PASS_THRU_GET_NEXT_NAMESPACE    GetNextNamespace;
  EFI_NVM_EXPRESS_PASS_THRU_BUILD_DEVICE_PATH     BuildDevicePath;
  EFI_NVM_EXPRESS_PASS_THRU_GET_NAMESPACE         GetNamespace;
};
  • 创建定时器处理Asynchronous I/O。
    //
    // Start the asynchronous I/O completion monitor
    //
    Status = gBS->CreateEvent (
                    EVT_TIMER | EVT_NOTIFY_SIGNAL,
                    TPL_NOTIFY,
                    ProcessAsyncTaskList,
                    Private,
                    &Private->TimerEvent
                    );
    if (EFI_ERROR (Status)) {
      goto Exit;
    }

    Status = gBS->SetTimer (
                    Private->TimerEvent,
                    TimerPeriodic,
                    NVME_HC_ASYNC_TIMER
                    );
    if (EFI_ERROR (Status)) {
      goto Exit;
    }
  • 遍历NVMe所有的Namespace,并在其上安装Block IO等Protocol,重点函数是:
/**
  Check if the specified Nvm Express device namespace is active, and create child handles
  for them with BlockIo and DiskInfo protocol instances.

  @param[in] Private         The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
  @param[in] NamespaceId     The NVM Express namespace ID  for which a device path node is to be
                             allocated and built. Caller must set the NamespaceId to zero if the
                             device path node will contain a valid UUID.

  @retval EFI_SUCCESS        All the namespaces in the device are successfully enumerated.
  @return Others             Some error occurs when enumerating the namespaces.

**/
EFI_STATUS
EnumerateNvmeDevNamespace (
  IN NVME_CONTROLLER_PRIVATE_DATA  *Private,
  UINT32                           NamespaceId
  )

有了Block IO等接口,就可以接入到了UEFI BIOS中,后续可以进行读写NVMe和创建启动项等操作。

参考资料

  1. 了解 SSD 技术:NVMe、SATA、M.2 - 金士顿科技 (kingston.com.cn)
  2. 什么是 NVMe?| IBM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2182479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【YOLO系列】YOLOv11正式发布!

Yolov11发布文档 代码链接 了解Ultralytics YOLO11的所有突破性功能,这是我们最新的人工智能模型,具有无与伦比的准确性和效率。 我们很高兴向大家介绍Ultralytics型号的下一次进化:YOLO11!YOLO11建立在以前YOLO模型版本令人印象…

【易上手快捷开发新框架技术】用Flet从零开始分步骤循序渐进编程实现购物清单助手手机应用app示例掰烂嚼碎深度讲解源代码IDE运行和调试通过截图为证

传奇开心果编程实例微博文 序言首先,明确任务,任务驱动:其次,开发工具选型考虑:第三,编程思路和应用结构设计: 第一步:从零开始搭建移动应用雏形框架第二步:设置窗口大小…

PCL 移除点云边缘不连续的点

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 法向量计算 2.1.2 边界检测和移除 2.1.3 边界检测和移除 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法与项目实战案例汇总&…

React学习笔记(4.0)

json-server实现数据Mock 1.项目中安装json-server npm i -D json-server 2.准备一个json文件 3.添加启动命令【package.json中配置】 "server":"json-server ./server/data.json --port 8888" 该命令中,路径就是自己创建的json文件路径&…

【C++】BitSet和Bloom_Filter

前言: 在计算机图形学中,位图(Bitmap)也称为光栅图,是由像素点组成的图像表示方式。在 C 编程中,位图可以通过特定的函数和数据结构来进行处理和操作。 BitMap 位图(BitMap)是一种数…

uniapp中uni.request的统一封装 (ts版)

文章目录 前言一、我们为什么要去封装?二、具体实现1.创建一个请求封装文件:2.封装 uni.request:3.如何去使用? 总结 前言 在uniapp中如何去更简洁高效的发送我们的请求,下面就介绍了uni.request()二次封装。 一、我们…

超强大的 Nginx 可视化管理工具

今天给大家介绍一款 Nginx 可视化管理界面,非常好用,小白也能立马上手。 nginx-proxy-manager 是一个反向代理管理系统,它基于 NGINX,具有漂亮干净的 Web UI。还可以获得受信任的 SSL 证书,并通过单独的配置、自定义和…

【计算机视觉】ch1-Introduction

相机模型与成像 1. 世界坐标系 (World Coordinate System) 世界坐标系是指物体在真实世界中的位置和方向的表示方式。在计算机视觉和图像处理领域,世界坐标系通常是一个全局坐标系统,描述了摄像机拍摄到的物体在实际三维空间中的位置。它是所有其他坐标…

【嵌入式开发】可编程4k蓝牙摄像头点击器

今天讲解的是一款可编程摄像头蓝牙点击器,支持离线文字识别 外观如下 B站有使用视频 链接: B站使用 下面是具体使用步骤(主要根据B站视频使用流程总结),文末附源码 全是干货 执行main代码 代码运行后,检查摄像头…

【电机-概述及分类】

文章目录 第1章1-1 电机的定义1-2 电机的构成要素1-3 电机的分类1-3-1 直流电机1-3-1-1 永磁励磁型直流电机1-3-1-2 电磁铁励磁型直流电机 第1章 重新认识电机的体系 电机包括许多种类。换个角度来看,并没有完美的电机,某种电机具有所谓A的优点&#xf…

docker 搭建minimalist-web-notepad

亲测可用 服务器 ubuntu sudo mkdir -p /root/docker/note# 切换到rootsu -chmod -R 755 /root/docker/notedocker pull carlosa/minimalist-web-notepad# 容器端口80 映射到 服务器7001端口,记得开防火墙 docker run -d --name notepad --restart always -p 7001…

u盘格式化后数据能恢复吗?2024年Top4恢复神器来帮忙

在这个电脑和手机满天飞的时代,U盘是我们用来存东西和传文件的得力助手,特别重要。但是,有时候U盘可能会不小心被格式化了,里面的重要文件就不见了。那么,U盘格式化后的数据还能恢复吗?当然可以。今天会告诉…

揭秘一下平时我们下载的python库跑到哪里了呢???

(阅读之前,祝福大家国庆假期快乐,以及真诚的祝福我们的祖国越来越强大)在那天的课上,老师问了我们这样一个问题:你们知道你们平时pip install下载库,下载好了,你们的库是下载到哪里了…

智邦国际ERP系统存在SQL注入漏洞

漏洞描述 智邦国际ERP系统是一款全面的企业资源规划工具,其主要目标是协助组织实现业务流程自动化和提升效率。此系统具备多种功能模块,包括但不限于财务管理、采办管理、销售操作、库存控制和生产过程管理,都能够满足企业多元化的业务需求。…

Ubuntu Server 20.04 64bit定时备份MySQL8.0.36数据库数据

一、编写sh脚本 常见备份命令介绍 我选用的是mysqldump命令,命令使用简介 [root]> mysqldump -helpUsage: mysqldump [OPTIONS] database_name [tables] OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] OR mysqldump [OPTIONS] --all…

朝天椒USB Server为赛力斯集团解决网银U盾难题

近期,赛力斯集团的财务部门引进了朝天椒USB Server,用几台USB服务器解决了集团困扰多年的银行U盾管理难题。 一、背景 赛力斯集团是一家以新能源汽车为核心业务的科技制造企业,A股上市公司,中国企业500强。赛力斯集团作为一家大型…

基于JAVA+SpringBoot+Vue的电商平台的设计与实现

基于JAVASpringBootVue的电商平台的设计与实现 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接&#x1f345…

如何利用 StarRocks 加速 Iceberg 数据湖的查询效率

数据湖作为一种存储各种类型数据的集中式存储系统,以其灵活性、可扩展性和低成本的优势受到越来越多企业的青睐。然而,数据湖虽然降低了数据存储成本,但在数据分析尤其是实时数据分析场景下,其性能仍存在一定瓶颈。 本文将探讨如何…

Linux shell编程学习笔记84:tee命令——显示保存两不误

0 引言 在前面的学习笔记中,我们经常使用echo命令和输出重定向来生成脚本文件或演示文件,其实Linux提供了一个可以从标准输入读取数据,并输出成文件的命令——tee。 1 tee命令 的帮助信息、功能、命令格式、选项和参数说明 1.1 tee命令 的…

攻防世界---->crazy

做题笔记: 草,不要怀疑自己。 下载 查壳。 64ida打开。 先运行一下程序: 先解决第一个问题 ——是不是输入的长度为32。 tips:这题加载了混淆函数等 ida 反正我跳不过去,pwndbg我用的不是很熟悉。 不过没关系 直接跑…