QCOM 平台 EFS 分区概述

1.EFS简介

在高通平台上,MPSS(Modem Processor)使用EFS(Embedded File System)来存储modem配置参数,且MPSS无法直接访问flash,而要通过APSS(App Processor)访问存储。即:当文件系统更新后,先由MPSS触发,然后由运行在APSS上的远程存储服务器模块控制,将整个文件系统分区写入flash。其关系流程大致如下图所示:

EFS包含FS1/FS2/FSG/FSG四个分区,其中:

(1)FS1(modemst1)和FS2(modemst2):

它们是EFS image的活动副本。EFS image会根据age字段来确定哪个分区最旧,通过覆盖旧的分区以乒乓方式写入FS1和FS2,由于APSS是不可信的,故而使用MPSS的设备专用加密引擎密钥来对其进行加密和散列处理。

(2)FSG(File system golden):

它的主要功能是在设备寿命期内存储工厂版本的EFS image。该分区具有写保护,不能被破坏。如果FS1和FS2分区都损坏,则EFS模块将回滚到存储在FSG分区中的工厂版本EFS image。执行EFS模块的EFS2_DIAG_MAKE_GOLDEN_COPY命令可以将FS1或FS2备份到FSG分区上。

(3)FSC(File system cookie):

FSC是cookie分区,用于标识是否将FS1或FS2备份到FSG上。

Modem SW需要使用密钥来解密存储在FSG分区中的EFS内容,除非设备无法识别EFS二进制文件,否则必须使用相同的密钥对其进行签名。 对于非efuse设备,使用dummy SW key,并使用dummy key对EFS进行相应签名。但是一旦熔丝,就会使用其他HW key进行EFS解密。如果存储在FSG分区中的原始EFS二进制文件用dummy key或任何其他key签名,则Modem SW将无法对其进行解密,即所有EFS内容都将丢失。因此Golden copy EFS 二进制文件必须与其他image使用相同的签名。

为防止EFS数据丢失,从非Fuse版本升级到Fuse版本时请参考以下步骤操作:

备份QCN -> 切换到EDL模式 -> 下载所有已签名的image文件和firehose的sec.dat -> 复位设备 -> 恢复QCN -> 触发EFS Golden Copy(可选的)

2.EFS开机初始化过程

设备启动时EFS初始化过程大致如下:

(1)EFS首先检查FS1和FS2分区中是否包含有效的EFS image,如果找到,则使用两者中最新的副本。

(2)如果FS1和FS2没有有效的EFS image,则会检查FSG以获取有效的签名并压缩过的.tar文件。如果找到,则创建一个新的文件系统。使用.tar文件的内容作为初始文件系统数据。

(3)如果FSG分区没有签名和压缩过的的.tar文件,则检查该分区中是否存在常规EFS image。如果找到,则使用该EFS image。

(4)如果任何FS1,FS2或FSG分区损坏了EFS数据或为空,则EFS在RAM中创建一个新的文件系统。一旦文件系统被更新,RAM分区则将其同步到FS1分区。

3.制作签名fsg image

(1)在vendor/qcom/proprietary-none-hlos/MPSS.TA.3.0/modem_proc/build/ms/cust8953.genw3k.prodq.h中定义FEATURE_EFS_ENABLE_FACTORY_IMAGE_SECURITY_HOLE:

1
#define FEATURE_EFS_ENABLE_FACTORY_IMAGE_SECURITY_HOLE

(2)通过使用QPST加载QCN文件并根据需要创建或修改EFS文件,为该golden设备提供所有EFS数据。将EFS中的所有数据加载到此特殊设备中,这些数据将用于预填充工厂中的其他设备。使用diag数据包以压缩的.tar格式提取此EFS数据。

(3)将vendor/qcom/proprietary-none-hlos/MPSS.TA.3.0/modem_proc/core/storage/tools/efsreadimage.pl脚本拷贝到本地来,再打开QPST确保设备连接成功,然后在终端运行命令。

(4)从代码中找到efsreadimage.pl脚本,打开QPST连接设备,在终端运行下面命令,执行成功后,Perl脚本将在当前文件夹中提取出一个压缩的.tar文件:

1
perl efsreadimage.pl -z

(5)修改MPSS.TH.2.0.1.C3.1/modem_proc/core/storage/fs_tar/src/fs_signed_img_param.c中SW_ID、HW_ID和ROOT_HASH(和sectool中保持一致):

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef FS_SIGNED_IMG_ROOT_HASH
#define FS_SIGNED_IMG_ROOT_HASH \
{0x2c, 0xf7, 0x61, 0x9a, 0x27, 0x8d, 0x26, 0x07, \
0x3f, 0x7e, 0xea, 0x79, 0xbb, 0x7f, 0x4b, 0x79, \
0x49, 0xc2, 0x21, 0x48, 0x7f, 0xea, 0x05, 0x8e, \
0xa0, 0x72, 0xcf, 0xfe, 0x38, 0xce, 0x14, 0x96}
#endif
#ifndef FS_SIGNED_IMG_MSM_HW_ID
#define FS_SIGNED_IMG_MSM_HW_ID 0x009470E100000000
#endif
#ifndef FS_SIGNED_IMG_SOFTWARE_ID
#define FS_SIGNED_IMG_SOFTWARE_ID 0x000000000000001B
#endif

所有平台的SW_ID都是0x1b,HW_ID由msm_part(JTAG_ID)、oem_id和model_id三者组成:

1
2
3
4
5
6
7
8
<image sign_id="efs_tar" name="fs_image.tar.gz.mbn" image_type="mbn_40b">
<general_properties_overrides>
<sw_id>0x000000000000001B</sw_id>
<msm_part>0x0009A0E1</msm_part>
<oem_id>0x0000</oem_id>
<model_id>0x0000</model_id>
</general_properties_overrides>
</image>

ROOT_HASH可以根据secimage.xml中的配置找到对应目录的sha256rootcert.txt获得,如:

sectools/resources/data_prov_assets/Signing/Local/qti_presigned_certskey2048_exp65537_paddingPSS/sha256rootcert.txt

1
2
3
4
5
6
<general_properties>
<selected_cert_config>qti_presigned_certs</selected_cert_config>
<key_size>2048</key_size>
<exponent>65537</exponent>
<rsa_padding>pss</rsa_padding>
</general_properties>

若支持r命令,可以通过adb shell /system/bin/r address获取SW_ID/HW_ID/ROOT_HASH,address对应下表中address栏的地址。

Name address
SW_ID 0x786130
HW_ID 0x786138
PK_HASH0_0 0x786190
PK_HASH0_1 0x786194
PK_HASH0_2 0x786198
PK_HASH0_3 0x78619C
PK_HASH0_4 0x7861A0
PK_HASH0_5 0x7861A4
PK_HASH0_6 0x7861A8
PK_HASH0_7 0x7861AC
PK_HASH0_8 0x7861B0
PK_HASH0_9 0x7861B4
PK_HASH0_10 0x7861B8
PK_HASH0_11 0x7861BC

可以通过在kernel中添加以下代码来支持r命令:

1
2
void __iomem *HWIO_JTAG_ID_ADDR = ioremap(0x786130, 0x4);
pr_err("read HWIO_JTAG_ID_ADDR : %x\n", readl_relaxed(HWIO_JTAG_ID_ADDR));

另外,也可以用十六进制编辑器打开fs_image.tar.gz.mbn.img文件,0x238和0x23c分别对应SW_ID, HW_ID。

(6)执行下面命令将MBN Header添加到EFS .tar文件中:

1
python sectools.py mbngen -i fs_image.tar.gz -t efs_tar_40 -o E:/tmp -g

(7)执行下面命令对EFS .tar文件进行签名:

1
python sectools.py secimage -p sdm450 -i E:\builds\fs_image.tar.gz.mbn -g efs_tar -o E:\tmp -sa -v

(8)执行下面命令将mbn转换为image格式:

1
python efs_image_create.py fs_image.tar.gz.mbn.img fs_image.tar.gz.mbn