nvcfg分区
作用: This partition stores variable configs of NVDATA and NVRAM.
nvdata分区
作用: This partition stores variable data of secure and identifying infos for your device. Like IMEI, WiFi MAC, Bluetooth MAC, calibration data and others.
ext4 文件系统
nvram分区
作用: This partition stores persistent data of secure and identifying infos for your device. Like IMEI, WiFi MAC, Bluetooth MAC, calibration data and others.
nvram称为binregion分区,是一个备份分区。 没有文件系统, 格式是自定义的。
persist分区
作用: This partition stores persistent data for factory reset protection. Like google account and miaccount/micloud
proinfo分区
作用: This partitions stores persistent data of default structure for NVRAM/RADIO/MODEM/BASEBAND
protect1 (或者叫 protect_f) 分区
作用: This partition stores variable data of SIM/RADIO/MODEM/BASEBAND settings and infos.
protect2 (or protect_s)
Description: This partition stores variable data of SIM/RADIO/MODEM/BASEBAND settings and infos.
Sim Lock 相关数据在 protect中
从WR8.W1244.DNR.WG.MP开始的Smart Phone版本都将SIM Lock存到protect_f和protect_s中了
挂载 于 /mnt/vendor/protect_f 和 /mnt/vendor/protect_s, 也都是ext4 文件系统
frp分区
flashinfo分区
otp 分区
seccfg
/dev/block/by-name/nvdata 挂载到 /mnt/vendor/nvdata 目录,文件系统是 ext4
APCFG/APRDEB/BT_Addr
WIFI
md/NVRAM/
BACKUP
CALIBRAT
NVD_DATA
NVD_IMEI
Format All+Download
会擦除所有分区,所有NVRAM LID都会用code中的默认值重新生成。全擦后只有触发备份过,binregion中才会有备份内容,
否则binregion是空的(Flash默认的全0 or 全f)。
Firmware Upgrade(固件更新) Factory Reset(恢复出厂设置)
只会擦除nvdata分区, 开机时AP 会将 binregion(nvram分区) 中备份的(1) CALIBRAT和 (2) NVD_IMEI两个目录还原到nvdata分区。
具体的NVRAM LID 是IMEI、 barcode、Calibration数据和4G RF driver参数。 (3) 其他NVRAM LID恢复为code中的默认值。
protect_f和protect_s分区不会被擦除,所以SIM Lock保持不变。
如果binregion是空的,那么IMEI、 barcode、Calibration数据和4G RF driver参数也会用code中的默认值重新生成。
Download Only、OTA、SD upgrade 、Push modem
不会擦除任何分区。这种升级方式下,如果有修改code中的default值,那么需要将相应NVRAM LID的VERNO+1,才会生效,即将会利用code中的默认值重新生成新文件。
注意:这里所说的所有分区和任何分区均指Modem NVRAM的四个分区:nvdata分区、 protect_f分区、protect_s分区和binregion(nvram)分区。
具有NVRAM_CATEGORY_USER属性的NVRAM,会存到/mnt/vendor/nvdata/md/NVRAM/NVD_DATA 目录。
里面存的是普通NVRAM, 2G RF driver NVRAM,3G RF driver NVRAM。
(从92Modem开始有将部分4G RF driver NVRAM从CALIBRAT属性修改为USER属性,也就是从CALIBRAT目录移到了NVD_DATA目录)
具有NVRAM_CATEGORY_INTERNAL属性的NVRAM,会存到/mnt/vendor/nvdata/md/NVRAM/NVD_CORE/目录。
里面只存了NVRAM_EF_SYS_LID这只NVRAM,由于具有NVRAM_ATTR_MULTIPLE属性,该目录下有A,B两只文件。
具有NVRAM_CATEGORY_CALIBRAT属性的NVRAM,会存到/mnt/vendor/nvdata/md/NVRAM/CALIBRAT/目录。
里面存了barcode,calibration NVRAM,部分4G RF driver NVRAM。
具有NVRAM_CATEGORY_IMPORTANT属性的NVRAM,会存到/mnt/vendor/nvdata/md/NVRAM//NVD_IMEI/目录。
80/90/91Modem里面只存了NVRAM_EF_IMEI_IMEISV_LID(IMEI)这只NVRAM。
92Modem添加了NVRAM_EF_NVRAM_LOCK_LID(IMEI Lock)这只NVRAM。
93Modem新加入了5只NVRAM(C2K相关的3只NVRAM)。
具有NVRAM_CATEGORY_IMPORTANT_L4属性的NVRAM,会存到/mnt/vendor/protect_f/md/目录,如果该NVRAM具有NVRAM_ATTR_MULTIPLE属性,会有相应的B文件存在/mnt/vendor/protect_s/md/目录。
里面存了NVRAM_EF_SML_LID(SIM Lock), NVRAM_EF_SIM_LOCK_LID(也是SIM Lock,默认不会用到) ,NVRAM_EF_IMPT_COUNTER_LID(这只NVRAM可以不用care,没实用,从92Modem开始移到了NVD_DATA)。 93Modem新加入了3只NVRAM。
在flash上存储的NVRAM 对应的文件名是由文件名前缀,中间连接符和文件名后缀构成。文件名后缀就是NVRAM LID对应的VERNO。那么代码中将对应的NVRAM LID VERNO+1后,去flash上面读写这只文件的时候,就会发现不存在,那么就会用code中的默认值重新生成新文件
假设修改的是NVRAM_EF_IMS_PROFILE_LID这只NVRAM的默认值,它的文件名前缀MT79,升级前的NVRAM_EF_IMS_PROFILE_LID_VERNO号是000,修改默认值后将NVRAM_EF_IMS_PROFILE_LID_VERNO修改为001,那么Download Only升级前 /mnt/vendor/nvdata/md/NVRAM/NVD_DATA/目录中就有MT79_000这只文件。升级后,当读写到这只NVRAM的时候,是按MT79_001去NVD_DATA目录找这只文件,发现没有就会用代码中的默认值重新生成新文件MT79_001。
具有NVRAM_CATEGORY_IMPORTANT或NVRAM_CATEGORY_IMPORTANT_L4属性的NVRAM LID不能通过VERNO+1方式升级,否则就会有modem assert,如NVRAM_EF_IMEI_IMEISV_LID(IMEI)和NVRAM_EF_SML_LID(SIM Lock),这是我们的design,是对IMEI和SIM Lock的保护。
校准NVRAM LID和Barcode(NVRAM_EF_BARCODE_NUM_LID)也不能通过VENRO+1的方式升级,否则校准参数/Barcode就丢失了
NVRAM数据结构
MTK平台采用LDI(Logical Data Item)和LDI Table哈希表的数据结构来管理NV Item列表。
NVRAM LID table就是由一个个具体NVRAM LID的结构构成。
包括9项参数:LID,total_records,size, default_value,category,attr, fileprefix,fileverno,description。
其中 description,目前对于Smart Phone平台来说都是NULL,没有使用,是Feature Phone遗留下来的, 说明这个item的功能的
LID Entry
nvram_Itable_entry_struct {
uint16 LID,
uint16 total_records,
unit32 size
uint8 const * default_value,
uint32 category,
uint16 attr,
char fileprefix[4+1],
char fileverno[3+1],
char * description
}
LID文件 组成
记录1
校验和1
记录2
校验和2
…
kal_bool nvram_external_read_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 *buffer, kal_uint32 buffer_size);
kal_bool nvram_external_write_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 *buffer, kal_uint32 buffer_size);
kal_bool nvram_external_reset_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint16 rec_amount);
PC META工具可以读写备份NV相关文件
vendor\mediatek\proprietary\external\nvram
https://github.com/hyperion70/HSPA_MOLY.WR8.W1449.MD.WG.MP.V16/blob/master/service/nvram/src/nvram_main.c
修改modem的对应的nvram的值分两种方式:
1.在code里修改默认值,这样修改的好处就是即使恢复出厂设置,或者升级软件,这个修改也是生效的;
修改默认值分两种case:
[1]这个feature是定义在除NVRAM_EF_SBP_MODEM_CONFIG_LID/NVRAM_EF_SBP_MODEM_DATA_CONFIG_LID的其他NVRAM里的:
以要disable bit 1: slotFormat4 and bit 4: supportEDPDCHPowerInterpolation in “r7_cap2”为例:
查看文档可以看到这个是定义在NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID里,要修改default值的话,首先贵司要了解NVRAM的一些基本内容,比如
nvram的dafault值在哪里定义的,首先搜这个LID的total这个参数,以NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID为例,就是搜索
NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_TOTAL,搜到包含这个NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_TOTAL的.c文件,而不是.h文件,贵司可以看
到这个是对NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID的元素的基本定义,其中第四个参数就是default值。
举例,NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID的元素定义就在nvram_data_items.c里,内容如下:
{
NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID,
NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_TOTAL,
NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_SIZE,
NVRAM_NORMAL(NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_DEFAULT),
NVRAM_CATEGORY_USER,
NVRAM_ATTR_AVERAGE,
#ifdef __UMTS_FDD_MODE__
“UM04”,
#endif
#ifdef __UMTS_TDD128_MODE__
“UM05”,
#endif
VER(NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID)
},
可以看到第4个参数是:NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_DEFAULT
点进这个default值看一下,贵司可以看到注释里有:r7_cap2:
/* r7_cap2: USIME_R7_Cap2
* bit 8~7: not used
* bit 6: supportofPSHandoverToGAN
* bit 5: supportofTxDivOnNonMIMOChannel
* bit 4: supportEDPDCHPowerInterpolation
* bit 3: supportForTwoDRXSchemesInPCH
* bit 2: supportForEDPCCHPowerBoosting
* bit 1: slotFormat4 */
0x00+ /* supportofPSHandoverToGAN: 0x20 supported, 0x00 not supported */
0x00+ /* supportofTxDivOnNonMIMOChannel: 0x10 supported, 0x00 not supported */
0x00+ /* supportEDPDCHPowerInterpolation: 0x08 supported, 0x00 not supported */
0x04+ /* supportForTwoDRXSchemesInPCH: 0x04 supported, 0x00 not supported */
0x02+ /* supportForEDPCCHPowerBoosting: 0x02 supported, 0x00 not supported */
0x01 /* slotFormat4: 0x01 supported, 0x00 not supported */
#endif /* __UMTS_R7__ */
比如说,我现在要disable bit 1,只要修改为:
/* r7_cap2: USIME_R7_Cap2
* bit 8~7: not used
* bit 6: supportofPSHandoverToGAN
* bit 5: supportofTxDivOnNonMIMOChannel
* bit 4: supportEDPDCHPowerInterpolation
* bit 3: supportForTwoDRXSchemesInPCH
* bit 2: supportForEDPCCHPowerBoosting
* bit 1: slotFormat4 */
0x00+ /* supportofPSHandoverToGAN: 0x20 supported, 0x00 not supported */
0x00+ /* supportofTxDivOnNonMIMOChannel: 0x10 supported, 0x00 not supported */
0x00+ /* supportEDPDCHPowerInterpolation: 0x08 supported, 0x00 not supported */
0x04+ /* supportForTwoDRXSchemesInPCH: 0x04 supported, 0x00 not supported */
0x02+ /* supportForEDPCCHPowerBoosting: 0x02 supported, 0x00 not supported */
#endif /* __UMTS_R7__ */
就可以了。
最后,修改完之后,要生效的话,需要升级这个nvram lid的verno,只需要找到这个nvram verno,然后加1就可以了。
以NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID为例,他的verno值就是NVRAM_EF_UMTS_USIME_RRC_DYNAMIC_CAP_LID_VERNO,如果它原来是018的话
,将其修改为019就可以了,或者贵司不想修改verno值的话,那total format之后升级,也可以达到更新nvram的目的。
[2]这个feature是定义在除NVRAM_EF_SBP_MODEM_CONFIG_LID/NVRAM_EF_SBP_MODEM_DATA_CONFIG_LID;
以Disable “MM_RETRY_ABNORMAL_LAI_TIMER” and Enable “PLMN_SEARCH_AFTER_LU_ABNORMAL”为例:
disable “MM_RETRY_ABNORMAL_LAI_TIMER”对应的是SBP_MM_DISABLE_RETRY_ABNORMAL_LAI,
Enable “PLMN_SEARCH_AFTER_LU_ABNORMAL”对应的是SBP_MM_PERFORM_PLMN_SEARCH_AFTER_LU_ABNORMAL,关于sbp的enum值可参见
sbp_md_feature_enum。
像这种修改SBP NVRAM的feature也是一样,先找到default值在哪里,以NVRAM_EF_SBP_MODEM_CONFIG_LID为例,他的defaut值就是
:NVRAM_EF_SBP_MODEM_CONFIG_DEFAULT,通过sbp_md_feature_enum我们可以知道SBP_MM_DISABLE_RETRY_ABNORMAL_LAI是第1个字节第4个bit(从1
数起),SBP_MM_PERFORM_PLMN_SEARCH_AFTER_LU_ABNORMAL对应第4个字节的第7个bit,要enable的话,只需要将这个bit改为1,要disable的话,只需
改为0。
举例,disable SBP_MM_DISABLE_RETRY_ABNORMAL_LAI的话,只需要找到NVRAM_EF_SBP_MODEM_CONFIG_DEFAULT,看到他的第1个字节第4个bit是这样
定义的:
#if defined(__MM_DISABLE_RETRY_ABNORMAL_LAI__)
0x08 |
#endif
之所以还有宏控制,是因为要兼容以前的版本,要disable的话,只需要将这三行全部注释掉:
//#if defined(__MM_DISABLE_RETRY_ABNORMAL_LAI__)
// 0x08 |
//#endif
同时要enable SBP_MM_PERFORM_PLMN_SEARCH_AFTER_LU_ABNORMAL的话 :只需要将#if defined(__MM_PERFORM_PLMN_SEARCH_AFTER_LU_ABNORMAL__)
0x40 |
#endif
修改为 :
0x40 |
也就是将判断条件删掉。
最后,nvram的修改要生效的话,需要修改nvram verno值,也就是升级: NVRAM_EF_SBP_MODEM_CONFIG_LID_VERNO。
2.使用meta修改,这种方法是修改现有值,而不是默认值,这样修改的弊端是在恢复出厂设置和升级版本之后,会恢复默认值,而不是meta修改后的
值,关于meta修改哪一个字节,可以通过方法1介绍的找default值的方法找到这个nvram的结构体定义,从而知道这个feature具体修改哪一个字节或
者bit。
Modem NVRAM 四个分区
(1) nvdata:手机运行过程中,使用(读写)的 NVRAM (除了存在protect_f和protect_s中的少数NVRAM)都是该分区的nvram文件。
存储着普通NVRAM数据、IMEI、barcode、Calibration数据等。
对应的modem path是Z:\NVRAM,对应的AP path是/data/nvram/md/NVRAM,这是在AP CCCI有做映射,
对应的都是nvdata分区modem NVRAM。NVRAM目录下有CALIBRAT、NVD_DATA、NVD_CORE和NVD_IMEI四个目录]
(Smart Phone中IMPORTANT目录是空的,是Feature Phone遗留下来的),后续第三点会对这四个目录进行介绍。
(2) protect_1、protect_2 :一般也称为 protect_f 和 protect_s 分区,protect_s是对 protect_f 中部分NVRAM的复制。
主要存储着SIM Lock数据。具有NVRAM_CATEGORY_IMPORTANT_L4属性的NVRAM LID会存在protect_f分区,
如果还具有NVRAM_ATTR_MULTIPLE属性,会存一个B文件到protect_s中。正常情况下protect_f中的A文件和protect_s中的B文件是相同的,
因为写的时候都会去写两个nvram文件。
(3) nvram:一般也称为 binregion 分区,是一个备份分区,备份具有 NVRAM_CATEGORY_IMPORTANT 和 NVRAM_CATEGORY_CALIBRAT 属性的 NVRAM LID,
备份的也就是CALIBRAT和NVD_IMEI两个目录,具体有IMEI、 barcode、Calibration数据和4G RF driver参数这些NVRAM。
备份可以由META Tool触发 ,ATE校准完会自动触发备份,SN Writer tool写完号后也会自动触发备份。
升级方式对各个NVRAM分区的影响:
因为Format All+Download会擦除所有分区,所以修改任何NVRAM的默认值,然后 Format All+Download升级,均可生效。
因为Firmware Upgrade 只会擦除nvdata分区,所以修改普通NVRAM(NVRAM_CATEGORY_USER属性的NVRAM)的默认值,然后Firmware Upgrade升级,可以生效。
但是修改具有备份的NVRAM(IMEI、 barcode、Calibration数据和4G RF driver)或者存在protect_f/protect_s分区的SIM Lock的默认值,是不会生效的。
如修改备份的4G RF driver NVRAM LID的默认值,Firmware Upgrade升级不生效 :
这是因为备份的4G RF driver NVRAM LID具有NVRAM_CATEGORY_CALIBRAT属性,在binregion中有备份,当Firmware Upgrade升级擦除nvdata分区后,开机后会从binregion中还原回来。
针对这种情况,想要修改默认值生效,Firmware Upgrade升级也是需要将相应的NVRAM LID VERNO+1。
因为Download Only、OTA、SD upgrade 、Push modem不会擦除任何分区,所以如果有修改code中的default值,想升级后生效,那么需要将相应NVRAM LID的VERNO+1,
才会生效,这样将会利用code中的默认值重新生成新nvram文件。
原理:在flash上存储的NVRAM 对应的文件名是由文件名前缀,中间连接符和文件名后缀构成。文件名后缀就是NVRAM LID对应的VERNO。
那么代码中将对应的NVRAM LID VERNO+1后,去flash上面读写这只文件的时候,就会发现不存在,那么就会用code中的默认值重新生成新文件。
假设修改的是NVRAM_EF_IMS_PROFILE_LID这只NVRAM的默认值,它的文件名前缀MT79,升级前的NVRAM_EF_IMS_PROFILE_LID_VERNO号是000,
修改默认值后将NVRAM_EF_IMS_PROFILE_LID_VERNO修改为001,那么Download Only升级前/data/nvram/md/NVRAM/NVD_DATA/目录中就有MT79_000这只文件。
升级后,当读写到这只NVRAM的时候,是按MT79_001去NVD_DATA目录找这只文件,发现没有就会用代码中的默认值重新生成新文件MT79_001。
[1]注意:并不是所有的NVRAM LID都可以通过VERNO+1的方式来升级:
(1)具有NVRAM_CATEGORY_IMPORTANT或NVRAM_CATEGORY_IMPORTANT_L4属性的NVRAM LID不能通过VERNO+1方式升级,否则就会有modem assert,
如NVRAM_EF_IMEI_IMEISV_LID(IMEI)和NVRAM_EF_SML_LID(SIM Lock),这是我们的design,是对IMEI和SIM Lock的保护。
(2)校准NVRAM LID和Barcode(NVRAM_EF_BARCODE_NUM_LID)也不能通过VENRO+1的方式升级,否则校准参数/Barcode就丢失了,不过一般也不会有这类需求。
(3)部分RF NVRAM LID也不能通过VERNO+1的方式升级,目前明确的有CA组合和RF support band不行,如有修改必须全擦升级。
如何在AP端读写Modem NVRAM
AP端去读写Modem NVRAM,可以通过AP端向modem发送AT Command,而modem端需要客制化一条AT Command,同时在command handler中调用接口进行读写nvram。
步骤如下:
(1)AP端向Modem透传AT命令,AP端具体做法可以参考FAQ19648【如何发送AT命令】。
(2)Modem端对AT命令进行客制化,具体可以参考FAQ17997【[AT Command]Smart Phone如何客制化AT command】。
(3)command handler内部通过调用nvram_external_read_data/nvram_external_write_data来读写。
kal_bool nvram_external_read_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 *buffer, kal_uint32 buffer_size);
kal_bool nvram_external_write_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 *buffer, kal_uint32 buffer_size);
注意:从91Modem开始读写IMEI和SIM Lock只能使用nvram_external_secure_read_data/nvram_external_secure_write_data接口,不能使用nvram_external_read_data/nvram_external_write_data。
nvram_errno_enum nvram_external_secure_read_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 buffer, kal_uint32 buffer_size, void reserved_ptr);
nvram_errno_enum nvram_external_secure_write_data(nvram_lid_enum LID, kal_uint16 rec_index, kal_uint8 buffer, kal_uint32 buffer_size, void reserved_ptr);