深入浅出SSD 10:UFS介绍
2026/8/5 12:03:00 网站建设 项目流程

10. UFS介绍

10.1 UFS简介

电脑有三大件——CPU、内存和硬盘。CPU用于计算和控制,内存用于临时存储程序运行时所需的数据(掉电后数据丢失),而硬盘用于长久保存数据(掉电后不丢失)。

我们每天使用的手机,本质上就是一个移动的小型计算机,同样有三大件——CPU/GPU、内存和存储设备。其中存储设备相当于电脑的硬盘,用于长久保存手机上的数据,比如视频、照片、音乐、操作系统等。

UFS(Universal Flash Storage,通用闪存存储)有两层意思,一层是指一种移动存储接口协议,类似SATA、PCIe/NVMe;另一层是指使用该协议的移动存储设备。后文出现UFS,大家应该根据上下文理解具体为哪层含义。

为什么说UFS是手机存储的未来?无他,快!可以通过下表感受以下。

UFS版本2.0/2.1/2.23.0/3.14.0
单通道最大接口速率/(Mb/s)5836.811673.623347.2
单向最大通道数222
单向最大有效带宽(MB/s)108121634326

注:表中最大有效带宽不包括协议开销和8/10b编码开销,这是一种二进制速率。

UFS协议是JEDEC(www.jedec.org)组织指定的,三星、海力士、铠侠等公司力捧。我们可以看到,UFS协议一直在大踏步朝着更高更快的目标前进。

UFS为什么能那么快?

1)它在数据信号传输上使用的是差分串行传输。这是UFS快的基础。所有的高速传输总西安,如SATA、SAS、PCIe等,都是串行差分型号。串行,可以使用更快的时钟(时钟信息可以嵌在数据流中);差分信号,即用两根信号线上的电平差表示0或者1。与单端信号传输相比,差分信号抗干扰能力强,能提供更宽的带宽(跑得更快)。打个比方,假设用两根信号线上电平差表示0和1,差值大于0表示1,差值小于0表示0。如果传输过程中存在干扰,两根线上加了近乎同样大小的干扰电平,两者相减,差值几乎不变。但对单端信号传输来说,就很容易受干扰,比如0 ~ 1V表示0,1 ~ 3V表示1,一个本来是0.8V的电压,加入干扰,变成1.5V,相当于0变成1,数据就出错了。因为具有抗干扰能力强的特性,所以差分串行信号线可以用更快的速度进行数据传输,从而提供更宽的带宽。

UFS的前辈是eMMC。eMMC使用的是并行数据传输方式。并行最大的问题是速度上不去,因为一旦时钟上去,干扰就变大,信号完整性无法保证。另外并口需要更多的数据传输线。

2)UFS和PCIe一样,支持多通道数据传输,目前,一个方向上最多支持两个通道。多通道选项可以让UFS在成本、功耗和性能之间做取舍。

3)UFS采用全双工工作模式,就是读写可以并行。它的前辈eMMC是半双工,读写不能同时进行,两个的对比如下图所示。

UFS和eMMC工作模式对比

要让UFS速度快,底层硬件基础设施要跟上层数据传输协议的配合。就好比我们想要速度快,除了需要一条又宽敞又平坦的高速公路,还需要一辆可高速行驶的汽车。你如果仅有一辆拖拉机,那么即使上了高速公路也跑不快。

UFS上层协议怎样来充分发挥底层硬件速度快的优势呢?

UFS支持命令队列,也就是主机可以同时发很多个命令,然后UFS设备支持并行和乱序执行,谁先完成谁先返回状态。这种命令处理方式称为异步命令处理。而它的前辈eMMC,早期版本是不支持命令队列的,命令一个一个执行或者一包一包(每个包里面含有若干个命令)执行,前面命令没有执行完成,后面的命令是不能发下去的。这种命令处理方式称为同步命令队列

我们来比较一下“全双工+异步命令处理”和“半双工+同步命令处理”两者命令处理方式的执行效率。

1. 半双工+同步

如下图所示,主机发了一个写命令W1给设备,主机把数据写到设备。同步命令处理方式下,命令是被串行处理的,所以在发读命令R2之前,必须等前一个写m命令W1处理完成。同样,在发送写命令W3之前,必须等命令R2处理完成。

同步命令处理流程示例

2. 全双工+异步

由于支持命令队列,主机以下可以发若干个命令给设备,如下图所示,主机同发一个写命令W1和一个读命令R2给设备。设备可以并行处理这两个命令。由于协议支持全双工操作,主机传输写命令W1的数据给设备的同时,设备也可以把读命令R2的数据返回给主机。后面命令R3、R4、R5的处理方式与此类似。

异步命令处理流程示例

再形象一点,我们以搬运货物为例来比较以下eMMC和UFS命令执行方式,如下图所示。

eMMC和UFS命令处理方式对比

现在的手机,应用非常丰富,用户可能要一边看新闻,一边听歌,一边聊微信,多线程操作。由于全双工和命令队列的存在,UFS处理命令的效率大大提高,给用户极好的体验。

前面我们拿UFS和eMMC做了对比,但什么是eMMC?eMMC(Embedded MultiMedia Card)和UFS一样,也是JEDEC制定的一种移动存储协议。eMMC最新标准是2015年发布的eMMC5.1,支持的最高速度是400MB/s。JEDEC已经有了UFS,应该不会再发布新的eMMC标准。毕竟,并行传输的eMMC受限于物理信号,速度想要有质的飞跃是不现实的。

UFS正在慢慢取代eMMC成为主流移动存储协议,UFS最终取代eMMC也是必然。下图所示是eMMC和UFS的应用趋势变化。

eMMC和UFS的应用趋势变化(来源:CFM闪存市场)

不过,UFS一统天下的道路上还有一个拦路虎,那就是NVMe。有人说,NVMe不是SSD的协议标准吗?没错,不过,现在苹果手机中的存储协议是PCIe+NVMe而不是UFS。在短期内,UFS和NVMe会分别在安卓和苹果手机中存在。长期来说,UFS和NVMe是二分天下,还是合二为一,暂未可知。最终可能会两者并存,UFS会借鉴NVMe的优点,毕竟NVMe走在前面。

给大家看看嵌入式UFS的实物图,如下图所示。

UFS设备实物图

嵌入式UFS为BGA形态,一般尺寸为11.5mm × 13mm × 1mm(或0.8mm),如大拇指的指甲盖大小。但麻雀虽小,五脏俱全。UFS存储芯片内部,如下图封装了UFS控制器和闪存阵列,和SSD结构很相似。不过和SSD相比,由于它的容量更小,因此闪存Die比较少,闪存的通道数也少。另外,出于功耗和成本考虑,UFS芯片一般是不带DRAM。

UFS设备框架图

10.2 UFS协议栈

任何一种接口或者协议,都是由一个完整的协议栈组成的,UFS也不例外。UFS的协议栈如下图所示。

UFS协议栈

UFS定义了一个完整的协议栈,从上到下依次为应用层、传输层、数据链路层和物理层。UFS所使用MIPI(Mobile Industry Proceor Interface,移动产业处理器接口)联盟的Unipro作为数据链路层,使用MIPI的M-PHY作为物理层,两者合起来称为UFS互连层(UFS INterConnect Layer, UIC)。UFS主机(比如手机、平板电脑等设备)和UFS存储设备两侧都需要实现UFS协议栈。

目前,UFS主要使用的命令是简化的SCSI命令(基于SBC和SPC),这是由INCITS T10组织定义的。关于SCSI相关协议,可以参看相应的协议规范。

UFS协议栈的四层中有三层是别人的:命令层是T10的,数据链路层和物理层是MIPI的,只有传输层是JEDEC自己的。

UFS至今已经有多个版本(本章都是基于UFS4.0之前的版本撰写的),每个版本使用的Unipro和M-PHY版本也不尽相同,如下表所示。

UFS版本和对应的各层版本

10.2.1 应用层

应用层包括UFS命令集、设备管理器(Device Manager)和任务管理器(Task Manager)。应用层是整个协议栈的最高层,所有的命令或者请求都来源于该层。它是最高统帅,所有的战术和策略都是它制定的,真正去冲锋陷阵的是将军和士兵(应用层下面的各层)。

1. 命令集

如前所述,UFS主要使用简化的SCSI命令,具体如下表所示。

UFS使用的SCSI命令集

2. 设备管理器

顾名思义,设备管理器用于管理UFS设备。设备管理器有两个功能:一是处理设备级操作,二是管理设备级配置。前者包括管理设备功耗、设置数据传输相关参数、使能/禁止设备后台操作(Background Operation)以及其他设备相关操作。后者通过维护和存储一系列描述符,通过Query请求修改或获取设备的配置信息。

如下图所示,设备管理器既可以通过下层的传输层为自己服务(通过UDM_SAP接口),通过Query命令去处理设备级操作和修改获取设备配置信息,也可以绕过传输层,直接通过UIC提供的服务接口UIO_SAP去管理与控制互连层。

设备管理器可以通过互连层提供的接口(UIO_SAP),使用一系列的原语(Primitive)直接控制并操作互连层。这些原语包括重启设备、重启互连层、让物理层进入和退出休眠模式(Hibernate)等。

设备管理器通过UIO_SAP和UDM_SAP接口与互连层、传输层交互

总之,设备管理器既可以走常规渠道(通过传输层,以数据包UPIU的形式传输数据),也可以走快速通道(发送互连层能理解的命令,以原语的形式)管理和操作设备。

3. 任务管理器

任务管理器用于管理命令队列中的命令。比如任务管理可以发Abort命令,中止之前发下去的命令。它也可以清空命令队列中的所有命令。任务管理器的具体功能如下表所示。

任务管理器功能表

当某个命令超时时,系统可能发Abort命令把这个命令中止。

10.2.2 传输层

传输层为它上面的应用层服务。当传输层接收到应用层的命令或者请求后,会生成UPIU(UFS Protocol Information Unit,UFS协议信息单元),把命令块或者请求封装成固定格式的数据结构,然后交由下层传到接收端的传输层。和命令相关的数据、状态、也有相应的UPIU。UPIU是主机和设备进行信息交换的基本数据单元,上层命令或者数据都是通过此类数据包封装起来,然后传输到接收端的。

10.2.3 互连层

互连层包括MIPI Unipro和M-PHY,它们分别充当UF数据链路层和物理层的角色。数据链路层负责主机和设备的连接,物理层负责传输实实在在的物理信号。

Unipro其实不仅定义了数据链路层,还是一个比较完整的协议栈,如下图所示。

Unipro协议栈

传输层(L4)支持多设备之间的双向连接,但UFS只支持CPort0;网络层(L3)支持通过设备ID寻址多达128个设备,但由于UFS是点到点传输,所以不需要网络层;数据链路层(L2)支持流控、CRC生成和校验、重传机制等,UFS利用UniPro的数据链路层作为主机和设备之间的通信提供可靠的连接;物理适配层(L1.5)对物理层做了抽象,使UniPro适配不同的具体物理接口。

物理层(M-PHY)使用8/10b编码、差分信号以串行的方式进行数据传输。数据传输分高速(Hgh Speed)和低速(Low Speed)两种模式,每种模式下又有几种不同的速度档(Gear)。当线上没有数据传输时,M-PHY会进入省电模式,其中高速模式下对应的省电模式是STALL,低速模式下对应的省电模式为SLEEP,而最为省电的状态为HIBERNATE。

这里以下图所示为例来解释一下M-PHY连接的一些术语。

M-PHY通道示例

LINE(线路):发送模块和相应接收模块之间点对点的互联信号线,包括两根差分信号线。

Lane(通道):单向、单信号、物理传输通道,用于点A到点B的信息传输。由上图可以看到,通道包括发送模块和其对应的接收模块,以及它们之间的连接信号线(Line)。UFS在每个方向可以有2条Lane,由于相反方向必须具有跟它同样多的Lane,所以UFS事实上可以有4条Lane(每个方向各2条)。我们平时说UFS有2条Lane,其实是指单方向的。

SUB-LINK(子链接):由统一方向的所有Lane组成的连接。两个具有不同方向的子连接给UFS提供了双向数据传输功能。

LINK(连接):由所有子连接组成的点A(比如主机)和点B(比如设备)之间的连接。

下图所示是2通道的UFS主机和设备连接的示意图,具体信号线如下表所示。

主机和设备互连示意图

UFS信号线

应用层和传输层之间是CPort接口,PA层(物理适配层)和PHY层使用的RMMI接口。

10.3 UPIU

UFS协议中数据包称为UPIU,它是固定格式的数据结构,用于传输应用层发来的命令或者请求,以及跟它们关联的数据或者状态信息。UFS中的UPIU类似于SATA中的FIS和PCIe的TLP。

UFS采用“客户-服务器”结构(或者说从主从的命令结构),UFS主机(客户)发送命令或者请求给UFS设备(服务器),UFS设备执行命令并返回命令状态(Response)。注意:UFS所有的数据传输都是主机发起的,设备不能主动发起数据的传输,但跟PCIe是不同的(PCIe设备可以主动向主机传输数据)。

一个命令或者请求的执行包含下面几个阶段,如下图所示

UFS命令执行过程包含的几个阶段

图中所示几个阶段说明如下。

命令阶段:主机发起命令或请求给设备,这是“因”。

数据阶段:传输跟数据关联的命令(比如读写命令),这个过程肯定会涉及数据的传输;有些命令不涉及数据的传输,就没有这个阶段。所以这个阶段并不是总存在,跟具体命令和请求相关。

响应阶段:设备执行完命令,必须给主机返回命令执行状态信息。这个是“果”,是必不可少的。在PCIe中,有Posted和Non-posted的TLP,对于前者,命令执行者无须返回命令执行状态给命令发起者;对于后者,命令执行者必须返回状态给命令发起者。对UFS来说,它的命令总是Non-posted,即设备必须返回命令状态给主机。

无论是命令执行过程中的哪个阶段,UFS主机和设备间都是通过UPIU进行信息交互的。

  • UFS主机通过命令或者请求UPIU发命令请求给设备。
  • UFS主机或者设备通过UPIU传输数据。
  • UFS设备通过UPIU返回命令状态信息给主机。

10.3.1 UPIU事务

下面我们看看UFS中都有哪些UPIU事务。

1. 命令或者请求UPIU

应用层包括UFS命令、设备管理器和任务管理器3个模块,传输层根据不同模块发来的命令或者请求分别产生不同类型的UPIU。

UFS命令模块发送简化版本的SCSI命令,当传输层收到命令请求后,它会生成COMMAND UPIU,把命令封装起来。

应用层通过任务管理器来管理任务队列,比如中止或查询命令队列中的命令。当传输层收到来自任务管理器的请求后,它会生成TASK MANAGEMENT REQUEST UPIU,把请求封装起来。

UFS通过设备管理器来管理UFS设备,比如设置、查询配置UFS设备。当传输层收到来自设备管理器发来的请求后,它会生成QUERY REQUEST UPIU,把请求封装起来。

把命令请求类UPIU归总到下表中。

命令请求类UPIU

应用层模块对应的UPIU传输方向作用
SCSI命令COMMAND UPIU主机到设备主机发送SCSI命令给设备
任务管理器TASK MANAGEMENT REQUEST UPIU主机到设备主机管理命令队列中的命令,比如中止或者查询设备命令队列中的命令
设备管理器QUERY REQUEST UPIU主机到设备主机通过设备管理器查询、配置、管理设备

2.数据传输相关UPIU

当主机发送了类似读命令这样的与数据相关的命令给设备之后,设备需要通过DATA IN UPIU向主机传输数据。

当主机发送了类似写命令这样的与数据相关的命令给设备之后,主机需要通过DATA OUT UPIU向设备传输数据。

UFS主机在向设备写数据的时候,会考虑设备这个时候能不能接收数据(因为此时设备可能没有足够的内存空间接收主机数据),它在向设备发了写命令之后,不会立刻把数据传输给设备,而是在那里等设备的反馈。当设备准备好接收数据并确定能接收多少数据时,设备通过READY TO TRANSFER UPIU(RTT)告知主机。当主机收到该RTT后,才开始根据RTT的信息传输数据。RTT中包含该次传输多少数据的信息,主机根据RTT提供的信息进行传输。所以,主机只有在收到设备的RTT后才能发DATA OUT UPIU

注意,读命令不需要这种机制。因为设备从闪存中获得数据后,是设备控制数据的传输。对主机来说,它在发读命令之前,已经准备好足够的空间来接收数据,所以不存在主机没有空间接收数据的情况。

我们把数据传输类UPIU归总在下表中。

数据传输类UPIU

数据传呼相关的UPIU传输方向作用
DATA IN UPIU

设备到主机

设备传输数据给主机
DATA OUT UPIU主机到设备主机写数据到设备,主机只有收到RTT后才能往设备写数据
READY TO TRANSFER UPIU主机到设备同步,处理写命令时,设备告诉主机可以传输数据已经传多少数据

3. 响应UPIU

前面看到,主机有3中请求——SCSI命令、任务管理器发出的任务管理请求(Task Management Request),以及设备管理器发出的查询请求(Query Request)。针对不同的命令或者请求,设备在执行完相应的任务后,分别返回对应的状态UPIU给主机。

我们把命令响应类UPIU归总在下表中。

命令响应类UPIU

设备响应UPIU传输方向作用
RESPONSE UPIU

设备到主机

设备返回命令执行状态
TASK MANAGEMENT RESPONSE UPIU设备到主机设备返回任务管理请求执行状态
QUERY RESPONSE UPIU设备到主机设备返回设备管理器的查询请求执行状态

4. 其它UPIU

除了以上常规的UPIU,还有其它UPIU,这里进行简单介绍。

设备上电后,主机检测是否与之连接,此时会发NOP OUT UPIU给设备。这如同我们平时想看与某台电脑能否连接上会发一个ping命令。

当设备收到NOP OUT UPIU后,会返回NOP IN UPIU。主机收到该UPIU后,确认与设备连接,然后就可以进行后续操作了。

最后一个UPIU就是REJECT UPIU。当设备收到一个无效的UPIU(或者无法识别的UPIU)时,它会发REJECT UPIU拒绝无效的UPIU。

我们把其它类UPIU归总到下表中

其它类UPIU

辅助UPIU传输方向作用
NOP OUT UPIU

主机到设备

主机ping命令,查询主机是否与设备相连
NOP IN UPIU设备到主机设备响应NOP OUT UPIU,主机收到该UPIU后,确认主机与设备相连

REJECT UPIU

设备到主机设备收到无效的UPIU,发送UPIU给主机

5. 读写命令中UPIU交互的例子

前面我们都是单独看每一个UPIU,现在我们以读写命令为例,看看它们是如何组合完成命令处理的。

首先是一个“主机往设备读取96KB数据”的例子,如下图所示。

读命令处理过程中UPIU交互的例子

首先,主机发送读96KB数据的命令给设备,然后设备执行命令,并分3批把数据返回给主机,最后返回命令执行状态给主机。

下面是一个“主机往设备写64KB数据”的例子,如下图所示。

写命令处理过程中UPIU交互的例子

主机发送写64KB数据的命令个设备,然后在那里等设备响应。很快,设备说,你可以传24KB数据下来了,于是主机写24KB数据给设备。接着,设备又来说可以继续传32KB数据,主机照做。最后,设备通知可以把最后8KB数据也传过来,主机于是写最后8KB数据。最后,主机收到设备命令执行完成的响应。我们看到,主机必须收到RTT后才能启动数据传输。

10.3.2 UPIU格式

上面我们介绍了UFS的各个UPIU事务,下面我们具体看一下UPIU的内容。UPIU是有固定格式的数据包,分析数据包格式有助于我们深入理解UPIU以及整个UFS协议。

每个UPIU都有一个12Byte的Header,再加上跟每个UPIU相关的域,如下图所示。一个UPIU(包括Header)最小为32Byte,最大为65600Byte。

UPIU内容组成

我们看通用的Header,具体如下表所示。

UPIU Header格式

我们看看其中的一些域:

1)Tranaction Type(事务类型):用啦标识该UPIU是前面介绍的12个UPIU事务中的哪一个。

2)Flags(标识):只对命令和其响应的UPIU有用,指定命令的属性。

  • Flags.R:如果该位置起,说明该命令需要设备向主机传输数据(比如读命令)。
  • Flags.W:如果该位置起,说明该命令需要主机向设备传输数据(比如写命令)。
  • Flags.CP:表示命令的优先级。1为高优先级,0表示没有优先级。注意,该位只适用于简单命令(具有Simple属性的命令)。
  • Flags.ATTR:命令属性域。UFS命令有Simple、Ordered和Head of Queue属性,具体如下。
    • Flags.ATTR=00h表示命令为Simple command,就是一般的命令。设备收到这样的命令无效进行特别处理,一般谁先到谁先执行。这是系统中最常见的命令属性。
    • Flags.ATTR=01h表示命令为Ordered command。设备收到这样的命令,应该把该命令之前的命令都处理完,才处理该命令,后面的命令也必须等该命令处理完成后才能执行。
    • Flags.ATTR=10h表示是命令为Head of Queue Command。设备收到该命令后,将其放到命令队列的头部,立即执行。

3)LUN(Logical Unit Number,逻辑单元编号):指定该UPIU的目标LU。UFS上层协议来自SCSI,它继承了LU的概念,即把物理存储空间划分成若干个逻辑空间,每个逻辑空间都从LBA 0开始,用LUN标识。主机在发命令中指定该命令发给哪个LU。

4)Task Tag(任务标签):UFS支持命令队列,主机可以同时发送很多个命令给设备。为区分这些命令,主机需要为每个命令贴上标签。跟这个命令相关的数据UPIU和状态UPIU,都具有跟这个命令UPIU一样的标签。比如对读命令来说,COMMAND UPIU、所有的DATA IN UPIU和RESPONSE UPIU都具有同一个标签。

5)Command Set Type(命令集类型):UFS预期有三类命令,即简化的SCSI命令、UFS原生命令和用户自定义命令。目前,UFS的命令都是从别人家(SCSI)借来的,自己一个命令也没有制定。如果用户无自定义命令,该域就是0(SCSI命令)。

6)Initiator ID(身份编号):UPIU发起者身份编号。手机系统中一般一个主机连接一个UFS设备,所以主机ID一般为0.

7)Response(响应):设备告知主机命令是否执行成功。

8)Status(状态):设备返回的命令执行的状态。UFS有下表所示状态。

状态码响应说明
00hGOOD表明命令成功执行
02hCHECK CONDITION此状态表示设备以完成命令,但有错误,或者需要其它操作来处理结果。出现此状态时,将在响应UPIU中返回最后处理的命令的有效sense数据
08hBUSY此状态表示逻辑单元忙。当逻辑单元无法接收命令时,将返回此状态。主机稍后发送命令是标准的恢复操作。
28hTASK SET FULL此状态表示由于缺少资源(如任务队列已满或命令执行所需的内存暂时不可用),逻辑单元无法处理命令

9)Query Function,Task Manag Function(查询和任务管理功能):任务管理器包括中止任务、中止任务集、清除任务集、重置LU、查询任务、查询任务集等功能。设备管理器包括标准的查询读、用户自定义查询读、标准的查询写、用户自定义查询写等功能。

10)Device Information(设备信息):该域往往跟该命令无关,属于设备夹带的私活。因为UFS主机和设备是主从关系,如果UFS主机没有向设备发命令,UFS设备是不能主动向主机报告设备状况的。如果UFS设备上有特殊事件发生,它可以趁返回RESPONSE UPIU的时候把事件告诉主机。所以该域只对REPONSE UPIU有效。

11)Total EHS Length(EHS总长)和Data Segment Length(数据段总长):这两部分见名知义,很好理解。

10.4 逻辑单元

NVMe里面有命名空间的概念,就是把SSD物理空间划分成若干个逻辑地址空间。UFS中也有这个特性。用户可以把UFS设备的物理存储空间分配成若干个独立的逻辑地址空间(这就是“分区”的概念),我们把这些独立的逻辑地址空间称为LU(Logical Unit)。由前文可知,在每个UPIU的Header中都有一个LUN域,这就是标识与该UPIU关联的命令的目标逻辑单元。每个LUN的地址空间是独立的,主机在发命令给设备的时候,需通过UPIU Header的LUN域指定目标逻辑单元。

每个LU都是独立的,“独立”表现在以下几个方面。

  • 逻辑地址空间是独立的,都是从LBA 0开始的。
  • 逻辑块大小可以不同,可以为4KB,8KB等。
  • 可以有不同的安全属性,比如可以设置不同的写保护属性。
  • 每个LU可以有自己的命令队列。
  • 不同的LU可以存储不同的数据,比如有的LU存储系统启动代码,有的LU存储普通的应用数据,有的LU存储用户特殊数据。

最新的UFS协议中可以有最多32个普通LU和4个核心LU(4个Well known LU,即众所周知的LU),如下图所示。

UFS中支持的LU

普通LU的逻辑块大小至少是4KB,但PRMB LU逻辑块大小为256Byte。至于什么是RPMB LU,下一节讲。

普通LU是用来存储用户数据的,这没必要展开。下面主要介绍4个核心LU。

1)Report LUNS LU:Report LUNS LU主要用来代表设备向主机汇报设备LU清单。主机想知道设备LU的支持情况,就需要发命令给该LU。UFS中有一个命令Report LUNS(和该LU名字一样)用来访问Report LUNS。

2)UFS Devcice LU:UFS设备的法人。当UFS主机不针对某个具体LU,而是对整个UFS发命令的时候,UFS Devcice LU就成为该命令接收的对象,比如格式化UFS设备(FORMAT UNIT命令)、切换UFS设备的功耗模式(START STOP UNIT命令)等时。

3)BOOT LU:顾名思义,就是用来存储启动代码的LU。不过,BOOT LU本身是不存储启动代码的,它只是一个虚拟的LU,启动代码在物理上是存储在普通LU上的。有两个BOOT LU——BOOT LU A和BOOT LU B,它们可以用来存储不同的启动代码(比如一个新,一个旧),但在启动过程中,只有一个是活跃的。32个普通LU中的任意一个都可以配成BOOT LU A或者BOOT LU B。

主机启动时,首先应该通过设备管理器发送查询请求给设备,获取一个名为bBootLunEn的属性,该属性标识当前活跃的BOOT LU,如下表所示。如果bBootLunEn=01,说明BOOT LU A是活跃的,因此主机会从与BOOT LU A对应的普通LU上读取启动代码完成系统的启动;如果bBootLunEn=02,则表明BOOT LU B是活跃的。

bBootLunEn属性表

bBootLunEn描述
00h

BOOT LU A = 禁止

BOOT LU B = 禁止

01h

BOOT LU A = 使能

BOOT LU B = 禁止

02h

BOOT LU A = 禁止

BOOT LU B = 使能

其它保留

值得一提的是,BOOT LU不是必须有的。如果系统的启动代码不是存储在UFS设备上,那么BOOT LU就不需要了,因此bBootLunEn=0.

4)RPMB LU:在UFS里有这样一个LU,主机往该LU写数据时,UFS设备会校验数据的合法性,只有特定的主机才能写入;同时。主机在读取数据时,也有对应校验机制,保证主机读取到的数据是从该LU上读的数据,而不是攻击者伪造的数据。这个LU就是RPMB LU。

下一节会专门讲解RPMB。

4个核心LU分工明确,分别执行不同的任务。下面对它们能接收的命令进行总结,如下表所示。

核心LU能接收命令列表

核心LUW-LUNUPIU头中的LUN域命令名称
Report LUNS01h81hINQUIRY、REQUET SENE、TEST UNIT READY、REPORT LUNS
UFS Device50hD0hINQUIRY、REQUET SENE、TEST UNIT READY、START STOP UNIT、FORMAT UNIT
BOOT30hB0hINQUIRY、REQUET SENE、TEST UNIT READY、READ(6)、READ(10)、READ(16)
RPMB44hC4hINQUIRY、REQUET SENE、TEST UNIT READY、SECURITY、PROTOCOL IN、SECURITY PROTOCOL OUT

需要注意的是,写BOOT LU和RPMB LU时,不支持缓存操作,也就是说,数据必须写到闪存以后这条写命令才算完成。而写一般LU,大多都是支持缓存操作的,即主机数据写到设备的内部缓存,设备就会将命令完成状态返给主机。

10.5 RPMB

UFS主机通过认证(authenticated)的方式访问RPMB LU。图10-19展示了RPMB数据写的过程。

主机和设备写RPMB数据流程

对上图所示流程说明如下。

1)UFS主机和UFS设备共享密钥,该密钥在UFS设备出厂时就保存在UFS设备。

2)UFS主机在发送主机数据给UFS设备前,会用该密钥和哈希算法生成消息认证码(Message Authentication Code,MAC)。

3)UFS主机把主机数据连同MAC一起发给UFS设备。

4)UFS设备把收到的主机数据和共享密钥在本地重新计算并生成MAC,然后把计算出的MAC和收到的MAC做对比,如果一致,则认证成功,写入到闪存;否则,拒绝该笔数据的写入。

UFS使用HMAC(Hash-based Message Authentication Code,基于Hash的消息认证)SHA-256算法生成消息认证码。HMAC运算利用Hash算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。关于HMAC具体算法可参考https://en.wikipediia.org/wiki/HMAC。

消息认证码本质是Hash值。Hash的一个特点是,即使只改变原数据中的1位,两者的Hash值也是截然不同的。如果恶意攻击者在数据传输过程中篡改了用户数据,那么UFS设备根据收到的数据和接收到的MAC不一致,认证通不过,数据就不会写入UFS设备。

上述前提是共享密钥不能被恶意攻击者获取,否则,恶意攻击者完全可以模拟主机行为;用自己的恶意数据和共享密钥生成MAC,然后把恶意数据和与其对应的MAC发送给UFS设备。UFS设备胡认证成功,恶意数据被写入。所以,请保管好你的密码。

但是,恶意攻击者是狡猾的,即使他没有办法获得你的密钥,他还是有办法对你进行攻击的。比如,恶意攻击者可能监听到UFS主机和UFS设备之间某次数据传输,得到“用户数据+MAC”,然后他就可以重复发送该“用户数据+MAC”给UFS设备,由于“用户数据+MAC”是合法的,所以认证会通过,UFS设备就会接收该数据并写到闪存。这就是重放攻击——Replay Attack,示意图如下图。

重放攻击的概念

RPMB(Replay Protection Memory Block,重放保护存储块)的名字暗示了RPMB是能抵御重放攻击的。那么RPMB是怎么对付重放攻击的呢?

UFS维护了一个写计数(Write Counter),它的初始值为0。UFS设备每次成功处理完一个RPMB写命令,写计数加1.主机在往设备写入数据前,获得该计数。然后把用户数据和该计数一起做MAC计算。这样,即使恶意攻击者窃听到某次合法的“用户数据+MAC”,再往设备写入时,由于写计数发生变化,它无法生成写计数改变之后的MAC值,因此就无法一直重复往设备写入某次合法的“用户数据+MAC”。

下面回到UFS RPMB协议上来。

UFS中,RPMB LU最小逻辑空间为128KB,最大为16MB。它的逻辑块大小为256Byte(普通LU逻辑块大小一般为4KB)。应用层不是通过普通的读写命令去读/写RPMB上的数据,而是通过SERURITY PROTOCOL OUT/IN命令来访问RPMB的。下表给出了普通LU和RPMB LU的对比。

RPMB LU和普通LU对比表

对比项逻辑空间大小逻辑块大小访问命令安全性存储数据类型
RPMB LU128KB ~ 16MB256ByteSecurity Protocol OUT/IN数据认证防篡改的重要数据
普通 LU无限制一般为4KBRead/Write普通用户数据

UFS主机在访问设备RPMB时,可通过下表所示不同消息类型完成不同功能。

RPMB消息类型列表

请求(Request)响应(Response)说明
认证密钥写请求认证密钥写响应用于写认证密钥
写计数读请求写计数读响应用于读取写计数
认证数据写请求认证数据写响应用于写认证数据
认证数据读请求认证数据读响应用于读取认证数据
操作结果读请求读取操作结果
安全写保护配置块写请求安全写保护配置块写响应用于写安全写保护配置块
安全写保护配置块读请求安全写保护配置块读响应用于读安全写保护配置块

每条消息包含一条或者若干条消息数据帧。消息数据帧大小是512Byte,具体如下图所示。

从下图中我们可看到:

  • 认证密钥(key)是32B。
  • UFS使用SHA-256计算MAC,也就是说任意长度的数据产生的MAC值总是256位,即MAC大小为32Byte。
  • 逻辑块大小为256Byte。
  • 写计数(Write Counter)大小为4字节,当该值涨到0xFFFF FFFF时,它就会保持不动,不会继续增长了。
  • Addres:RPMB的逻辑地址,同LBA,大小为2字节,最多表示65536个逻辑块,每个逻辑块大小为256Byte,因此RPMB逻辑空间最大为16MB。
  • Block Count,逻辑块数,即指定读写多少个逻辑块。
  • Result,RPMB操作结果(状态)。

RPMB消息数据帧格式

下面以“主机写认证数据”为例来帮助大家理解上面的消息。

主机命令层通过SECURTY PROTOCOL OUT命令把用户数据和对应的MAC发送给设备,然后通过SECURTY PROTOCOL OUT请求获取前面数据的写结果,最后通过SECURTY PROTOCOL IN读取写结果。写结果中包含写的写计数,这样下次主机就可以利用新的写计数计算MAC了·。注意,只有本次写认证数据成功,设备擦灰递增该计数。下图所示为写RPMB的流程。

写RPMB数据的流程

从上图中我们可以看到,和普通数据读写相比,RPMB数据读写过程非常繁琐,比如读写一次需要发若干条命令,主机和设备交互太多。另外,数据传输效率也不高,512Byte的数据帧真正有效的数据只有256Byte,其它都是元数据。基于此,UFS4.0提出了Advanced RPMB,采用4KB的数据块,提升了RPMB访问效率,简化了读写访问流程。UFS4.0规范已发布,自行参考。

RPMB提供了认证访问方式和抵御重放攻击的机制,保证了存储在RPMB LU上的数据的安全。因此,用户可以把一些敏感和重要的信息写在RPMB上。在实际应用中,它通常用于存储一些有防止非法篡改需求的数据,例如手机上指纹支付相关的公钥、序列号等敏感信息。

10.6 UFS低功耗简介

UFS作为移动存储设备,对功耗要求很高,尤其是对低功耗的要求,因为移动存储设备大多数时候都处于空闲状态。本节将简单介绍一下UFS设备的低功耗管理。

前面提到,UFS协议采用MIPI的M-PHY作为物理层和UniPro作为数据链路层。M-PHY有高速模式(High Speed Mode,HS-MODE)和低速模式(Low Speed Mode, LS-MODE)。其中,高速模式下,M-PHY有2种状态——HS-BURST和STALL,其中HS-BURST表示高速数据传输状态,STALL表示没有数据传输时链路所处的一种省电状态。低速模式下,M-PHY有3种状态——LINE-CFG、SLEEP和PWM-BURST。其中PWM-BURST表示低速数据传输状态,SLEEP表示没有数据传输时链路所处的一种省电状态。

当链路上没有数据传输时,M-PHY会自动(无需主机或者设备上层干预)切换到STALL或者SLEEP状态,以达到省电的目的。HS-BURST和STALL、PWM-BURST和SLEEP之间的状态切换时间为纳秒级别。除此之外,M-PHY还有一种更加省电的状态——HIBERN8(Hbernate,休眠状态)。UFS主机和UFS设备不可能一直交互数据,总有闲下来的时候。和STALL和SLEEP状态不同的是,进入HIBERN8状态需要主机的干预;当UFS主机一段时间没有访问UFS设备时,它会发命令让彼此(主机和设备)的链路进入休眠状态,即HIBERN8状态。

那UFS主机如何通知M-PHY切换到休眠状态呢?

前面提到,设备管理器可以略过传输层,直接管理与控制互连层(UIC,即UniPro和M-PHY)。如

下图所示,主机设备管理器可以通过原语直接与UFS互连层通信。除了图中所示的重启互连层/设备的原语外,UFS还包括让UIC进入和退出休眠状态的原语——DME_HIBERNATE_EXIT(退出休眠状态)。

当设备收到主机发来的Hibernate进入命令时,它就明白在一段时间内主机不会访问设备,因此,在这段时间内,UFS设备可以进入低功耗模式;比如把当前UFS设备的软硬件上下文保存到闪存,然后切断设备绝大多数模块的电源以达到省电的目的;当UFS设备收到Hibernate退出命令时,UFS重新给这些模块上电,并把软硬件上下文加载回到控制器内存继续运行。

注意,UFS设备进入低功耗的时候,不是切换对所有模块的供电(否则,设备就没有办法接收到HIbernate退出命令),而是切断主要模块的供电,比如闪存模块的供电以及UFS控制器绝大多数模块的供电。为做到这一点,这就要求控制器采用Power Domain的设计,即控制器主要模块处于不同的Power Domain中,它们的供电是独立的,关闭某个模块的供电,不会影响到其它模块的供电。

以下图所示为例,某个控制器有3个Power Domain(不用纠结每个Power Domain里具体的模块是什么),当UFS设备进入低功耗的时候,它把耗电大户Power Domain3(比如CPU、RAM、LDPC模块等)的供电切断,是否切断Power Domain2的供电是可选的,保持Power Domain 1不断电(用于响应主机发来的Hibernate退出命令)。

Power Domain的概念

前面提到,UFS设备进入低功耗状态的时候,需要把设备软硬件上下文保存到闪存,退出的时候再把它们加载回来。相关数据表明,在典型手机应用中,一个UFS设备每天接收的Hibernate命令有几十万甚至上百万个,如果每次进入低功耗的时候都要写闪存,会加速闪存磨损,从而影响UFS设备寿命。另外,与访问内存相比,访问闪存是比较耗时的操作,如果把上下文保存到闪存,会影响Hibernate进入和退出的延时,这一方面会影响系统功耗(UFS设备如果能快点进入低功耗状态,南那么整个移动设备也可以尽快进入低功耗状态),另一方面会影响用户体验。UFS设备低功耗处理追求的是“快进快出”,小于1ms的低功耗退出延时也是业界追求的目标。为此,现在的控制器一般都提供比较大的保持内存(Retention RAM,如上图 Power Domain 2中所示),它可以在比较低的功耗保持数据。UFS设备进入低功耗的时候,上下文数据可以保存在保持内存,从而减少或者避免对闪存的访问,这对UFS设备寿命和用户体验来说都是一个好选择。

10.7 WriteBooster

10.8 HPB

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询