(转载) MTK之NVRAM研究[一]

MTK之NVRAM研究[一]

lzq :2009-7-16 下午 04:54:37

      由NVRAM文件管理器管理的数据单元都是逻辑数据项,一个数据项可以被看作为一个固定大小的记录,所以我们根据他们的记录的大小将所有的逻辑数据项分为两种类型;
1,透明数据元(Transparent EF):这个类型的数据项的记录的大小为一个byte;因此,这种数据项可以认为是一系列的bytes;


2,线性固定数据元(linear fixed EF):这个类型的数据项的记录的大小远大于一个byte;所有的数据按线性存储;

如下图所示:

一,先来看“线性固定数据元”

首先我们来新建一项NV;分析每个步骤的原理;
总的步骤必须遵循如下几步:
1,在文件:“nvram_user_defs.h”的枚举结构体“nvram_LID_cust_enum”中定义一个新的LID:“NVRAM_EF_[new logical data item name]_LID”;
                          注意:请将新LID项加在NVRAM_EF_LAST_LID_CORE.之前;
      ex:   NVRAM_EF_PORT_SETTING_LID;
      lzq:这个LID项的主要作用是什么呢?为什么一定要添加一个LID?因为NVRAM中的数据是在fs文件系统的管理中操作的,而文
       件操作需要识别数据项和管理数据项,都是通过这个LID来操作的;


2,在文件:“nvram_user_defs.h”中定义两个常量:SIZE和TOTAL;
      ex:  #define NVRAM_EF_PORT_SETTING_SIZE 16
        #define NVRAM_EF_PORT_SETTING_TOTAL 1
      lzq:既然是一块内存,很明显就必须要设置这块内存的大小;这样将结构体的数据保存和读取时都很容易的操作到了特定的内存中;
        并且有效的控制的内存不足和溢出的问题;就像是初始话一个数组的大小;
                        (lzq_091216_补充:如果size是个结构体,则注意这个结构体的定义就和上面的定义写在一起;)
 
#ifdef __HL_WEB_PHONE__
typedef struct
{
 kal_uint8   status;       //open or close;
 kal_uint32  phone_number[11]; //本机号码;
 kal_uint8   number_exten[10];//号码前缀;
 kal_uint8   number_zone[8]; //本地区号;
}MY_WEB_PHONE
;

#define NVRAM_EF_MY_WEB_PHONE_DATA_SIZE sizeof(MY_WEB_PHONE)  //MY_WEB_PHONE
#define NVRAM_EF_MY_WEB_PHONE_DATA_TOTAL 1    //1
#endif


3,在文件:“custom_nvram_editor_data_item.h”中定义版本号:“NVRAM_[new data item name]_LID_VERNO”。
                       ex:   #define NVRAM_EF_PORT_SETTING_LID_VERNO "000"
      lzq:由于文件系统管理了这些NV数据;这些数据难免要进行各式的操作,比如修改,添加,删除的操作,那么文件系统是怎么知道
       它所管理的这些NV数据已经改变了呢?就是通过这个版本号来识别的,比如你修改了某个NV数据但没有更该它的版本号,文件
       系统是不会对原始数据更改的;只有在更改了NV值并且修改了版本号,这时文件系统才识别到已经更改,并进行相应的数据更新
                              例如 short类型NV的版本号是:NVRAM_EF_CACHE_SHORT_LID_VERNO ;


4,在文件:“nvram_user_config.c”中设置这个新nv项的默认值;
                        ex:
                               static kal_uint8 const NVRAM_EF_PORT_SETTING_DEFAULT[] = {
                                0x01, 0x00,
                                 0x00, 0x00,
                                0x00, 0xC2, 0x01, 0x00,
                                 0x00, 0xC2, 0x01, 0x00,
         0x01, 0x00, 0x00, 0x00
          };
        lzq:在申请了一块内存后,需要进行初始化默认值;这样在手机的异常时,比如恢复出厂设置时,NV将只载入默认值;


5,在文件:“nvram_user_config.c”中的结构体数组logical_data_item_table_cust[]中新添加一个条目(Add a new entry);
      注意:这个新的条目是设置这个LID项的属性的;以提供文件系统来对它操作;
      ex:  
       {
         NVRAM_EF_PORT_SETTING_LID,
         NVRAM_EF_PORT_SETTING_SIZE,
         NVRAM_EF_PORT_SETTING_TOTAL,
         NVRAM_EF_PORT_SETTING_DEFAULT,
         NVRAM_ATTR_AVERAGE,
         NVRAM_CATEGORY_USER,
         "MP1y",          //注意:在这里如果上个是MP1y,那么这里应该为加一为:MP2y,表明有新的条目添加了;
         VER(NVRAM_EF_PORT_SETTING_LID),
         "Port Settings\0",
         NVRAM_RESERVED_VALUE
       },

6,在文件custom_nvram_editor_data_item.h 中添加结构体定义;这个结构体定义只为了在使用mata工具时,能看到的新添加的NV项的结构体数组中的各个值;如果不添加将在mata工具中看不到这个新添加的nv项 ;
                        ex:这个是透明数据元byte在META工具中将要显示的byte的NV项中所有记录的字符串描述数组的结构体;
                              typedef struct
                           {
                                kal_uint8 CacheByte[NVRAM_CACHE_SIZE];
                            } nvram_cache_byte_struct ;


7,在文件:custom_nvram_editor_data_item.h中.添加 bit-level 说明;这个也是只为了在mata工具中的操作而实现的;在程序中并用不到 ;
             ex:这个是byte项的NV 的META工具中的字符串初始化默认值;
     LID_BIT        VER_LID(NVRAM_EF_CACHE_BYTE_LID)    nvram_cache_byte_struct*NVRAM_CACHE_TOTAL
                                {
                                             CacheByte:"One-byte parameter setting ";
                                              CacheByte[14]
                                           {
                                           default_lang:8 "Default Language "
                                           {
                                             };
                                               };
                                         CacheByte[24]
                                              {
                                          time_zone:8 "Time Zone (Current City )"
                                         {
                                             };
                                              };

                                       CacheByte[25]
                                          {
                                        date_format:8 "Time Format "
                                              {
                                                    };
                                            };
                                       CacheByte[26]
                                      {
                                           date_format:8 "Date Format "
                                              {
                                                   };
                                            };
                              };

整个过程如下图:

   lzq总结:NV数据实现了数据的读写保护,保证了数据在手机上正常而安全的使用;我们知道对于手机上的一些属性值,比如开机声音,待机画面等是由一些数据来控制的,这些数据是全局的,可以在随时随地的对它调用;如果是在一个游戏应用中,我们只要将它设置为一个全局的变量,在游戏开始时进行初始化就可以了;但在手机上我们必须保证这些数据不能丢失,并且在整个系统运行中当系统出现数据损坏并崩溃时,这些数据也是不会被丢失和更改;保证了手机系统的安全运行;也许我们可以说为什么不用一个文件来保存这些数据呢?我们知道如果用文件的话,虽然实现了数据的异地保存,但一旦这个文件丢失,将导致系统致命错误;另外,这些数据接受用户的个性修改,如果用文件保存的话,数据修改并不方便;而且在读写速度上明显不及直接NVRAM存储器的操作;因此,我们可以这样认为,NV让我们将一些数据从全局中取了出来,并放入了一个不能擦除的存储器中保护起来;

接下来让我们看看NVRAM的结构:


从上图中我们发现,在文件系统中Data Item Management System 管理着NVRAM;而这个管理系统(Data Item Management System)通过内部的一个查询表(lookup table)来获得每个数据项的具体细节; 
而这个查询表(lookup table )包含以下4个部分:
1. MT reign,     for project independent data items;
2. MP reign,     for MTK /PMT common applications;
3. CT reign,      for the customer usage.
4. CV reign,     for the vendor of customer usage.


下图显示了NVRAM定制文件布局。我们经常操作的文件一般在CT部分;


NVRAM LID 的定义部分都在以下几个文件中进行:
- nvram_data_items.h : for MT use
- nvram_data_items.c : for MT use
- nvram_common_defs.h : for MP use
- nvram_common_config.c : for MP use
- nvram_user_defs.h : for CT use
- nvram_user_config.c : for CT use
- nvram_cust_pack.c: for CustPack use
- nvram_vendor_config.c: for CV use
- nvram_vendor_defs.h: for CV use
META tool 的说明介绍内容都在以下几个文件中实现;:
- nvram_editor_data_item.h: for MT use
- common_nvram_editor_data_item.h : for MP use
- custom_ nvram_editor_data_item.h : for CT use
- vendor_nvram_editor_data_item.h: for CV use

现在我们回头去看步骤5,添加新的条目的操作中,我们会问,为什么要添加新的条目,而且在这些变量中,各个项的涵义是什么呢? 如下:
      ex:  
       {
         NVRAM_EF_PORT_SETTING_LID,
         NVRAM_EF_PORT_SETTING_SIZE,
         NVRAM_EF_PORT_SETTING_TOTAL,
         NVRAM_EF_PORT_SETTING_DEFAULT,
         NVRAM_ATTR_AVERAGE,
         NVRAM_CATEGORY_USER,
         "MP1y",                 
         VER(NVRAM_EF_PORT_SETTING_LID),
         "Port Settings\0",
         NVRAM_RESERVED_VALUE
       },

我们刚才知道了,管理系统(Data Item Management System)通过内部的一个查询表(lookup table)来获得每个数据项的具体细节的,我们在这里实现的这个新的条目就是为了让管理系统通过查询表来找到它并对它进行操作; 所以每个新的LID都要来这里添加新的条目;
那么每个新的条目的具体的数据结构是什么样的呢?如下是它的定义:

typedef struct
{
    nvram_lid_enum LID;            
    kal_uint16 size;               
    kal_uint16 total_records;      
    kal_uint8 const *default_value;
    nvram_attr_enum attr;          
    nvram_category_enum category;  
    kal_char fileprefix[FILE_PREFIX_LEN + 1];
    kal_char fileverno[FILE_VERNO_LEN + 1];
    kal_char *description;
    kal_uint8 record_ID;           
} ltable_entry_struct;


具体涵义如下:


接下来分别分析一些具体数据项的涵义:
1,属性attr ;
       属性选项是个可选的,它由枚举:nvram_attr_enum定义:
            NVRAM_ATTR_AVERAGE: 0x0000            //这是个默认的属性选项;
            NVRAM_ATTR_IMPORTANT: 0x0001  //当一个IMPORTANT的数据项被更改时,会先将相关程序停止,并被要求进行备份和保存,
                                                                                  //只有在成功备份和保存后,才会将程序重新安全开启;
            NVRAM_ATTR_WRITEPROTECT: 0x0002   //写保护,只读;
            NVRAM_ATTR_MULTIPLE: 0x0004     //如果一个数据项的属性是multiple,那么NVRAM会自动将它做一个备份,并当在其中有一个数据
                                                                              //被损坏时,NVRAM会从另个数据中将它还原;
            NVRAM_ATTR_CONFIDENTIAL: 0x0008   //对数据采用对称算法进行加密或解密;所以:mulitiple+confidential能实现最好的数据保护;
            NVRAM_ATTR_MULTIREC_READ: 0x0010 //适用于那些需要一次性对一数据进行多次读取操作的数据项;
            NVRAM_ATTR_OTP: 0x0020  //This attribute is supported only if One Time Programming (OTP) function exists on the flash storage. NVRAM will
                                                               //maintain a small table to OTP region; the table consists of all OTP data items, by order in the lookup table.
            NVRAM_ATTR_DIFFERENCE: 0x0080    //NVRAM保留。

2,模板category;
          这个选项和attr非常相似,可以说是attr的分支;一个数据项可以属于很多category的或者是很多数据项属于一个category;所以NVRAM需要找到那些需要被category重新设置的数据项;它的枚举包含如下:
              NVRAM_CATEGORY_USER: 0x0000      //默认属性;
              NVRAM_CATEGORY_SYSTEM: 0x0001    //一旦版本号更改,这个数据项将被初始化为默认值;
              NVRAM_CATEGORY_COMPOSED: 0x0002  //NVRAM 保留;
              NVRAM_CATEGORY_FACTORY: 0x0004   //当MSG_ID_NVRAM_RESET_REQ随着 reset_category = NVRAM_RESET_FACTORY,NVRAM
                                                                                          将重新设置NVRAM_CATEGORY_FACTORY的值,并且清除预定义的文件和设置;
              NVRAM_CATEGORY_MULTI_DEFAULT: 0x0008  //这样的数据项的每个记录可能有不能的值,但是所有的默认值必须在一个连续的数组里。
              NVRAM_CATEGORY_CUSTPACK: 0x0010       //NVRAM will auto assign default values in CustPack BIN to this category. Once the version of 
                                                                                              CustPack BIN changes, NVRAM_CATEGORY_CUSTPACK will be reset to default.
              NVRAM_CATEGORY_BRANCH: 0x0020         //This category of data item will be kept even the branch number of software version changes. Every 
                                time the branch number is different from previous one, NVRAM will clear all data items except NVRAM_CATEGORY_BRANCH.
              NVRAM_CATEGORY_SHADOW: 0x0040          //This category is only used for single bank NOR-flash. With single bank NOR-flash,
                                                                                              only this category could be  modified in normal mode. NVRAM uses Shadow mechanism to 
                                                                                              make device type transparent to applications. Please see chapter 7. to get more details.
                                                                                             IMPORTANT: Shadow needs additional memory.
              NVRAM_CATEGORY_SHADOW_MS: 0x0080          //When USB boot mode, all data item can’t be accessed because of storage exporting. 
                                                                                          Thus NVRAM uses Shadow mechanism to make a few applications still can access their data.
                                                                                           IMPORTANT: Shadow needs additional memory.

我们再来看看LID文件的命名和LID的版本号规则:
File Name Format:

 (0~3) File Name   ( 4) M.              (5~7) Version


        
1. File Name: The first 4 bytes of the File Name Format are used for the file name, which needs to be
distinguishable from all other file names. The File naming rule:
- Data items in the core: MT[x][y], where x and y in the range (0~9, a~z)
- Data items in custom/common folder: MP[x][y] , where x and y in the range (0~9, a~z)
- Data items in custom/app folder: CT[x][y] , where x and y in the range (0~9, a~z)
- Data items in vendor folder: CV[x][y] , where x and y in the range (0~9, a~z)
-
?? 4-byte filenames. The file naming MT[x][y], MP[x][y] ,CT[x][y] and CV[]x[y] allow maximum sequence
number up to 36*36 = 1296 each.
IMPORTANT: Any file name MUST be unique.
2. M byte: The byte is used to indicate the ‘multiple’ attribute of the data item.
- If a data item is defined to be ‘multiple’, M can be ‘a’ or ‘b’ to represent two copies of the file.
- If a data item is defined w/o the ‘multiple’ attribute, M will be ‘_’.
3. Version: Three human-readable digits, for example, ‘000’
?? the version number is incremented when a data item is added / deleted or its data structure is changed, or
its attribute is changed.
?? For ease of reading, the 3-byte version number can be used from 000 ~ 999. That means a single LID can
be versioned 1000 times. If the limit is hit, a work-around is to delete the LID and make it a new one with
version 000.

原文地址:https://www.cnblogs.com/sierllen/p/2486833.html