客製化NVRAM的乙太網地址

DarkTime發表於2019-05-08

在使用SN Write寫Ethernet MAC過程中出現了以下的錯誤:

ERROR!! Ethernet Mac:MetaResult = SPMETA_DLL::META_LID_INVALID。
複製程式碼

後來確認是AP_DB裡面沒找到AP_CFG_RDEB_FILE_ETHERNET_LID這個引數導致報錯的,需在NVRAM中新增乙太網的LID的引數。

本文就以AP_CFG_RDEB_FILE_ETHERNET_LID這隻LID新增過程為例,簡單說明客製化NVRAM的過程。

NVRAM介紹

Nvram: Non-volatile random access memory,是MTK平臺的一種機制。

主要的目的是:用來描述RAM中的資料型別,關機也不會丟失;手機重要的引數在恢復出廠設定或者升級被刪除後還能恢復。這些重要的資料包括兩部分:AP端和Modem端,這裡只介紹AP端部分。

AP端的主要有Wifi,Bt,Gps,sensor資料等。

Modem端的資料主要是打電話相關的引數,比如IMEI,RF等引數。

AP NVRAM Features:Backup

工廠Meta mode下做校準測試/寫號等操作,工具結束disconnect 前觸發backup動作, backup是從nvdata 分割槽(檔案系統)備份到nvram 分割槽(raw data)。

AP NVRAM Features:Restore

使用下載工具做韌體升級(firmware upgrade) 或者恢復出廠設定,會觸發restore動作。 Restore是從nvram分割槽還原到nvdata分割槽,如果nvram 分割槽內容為空,則用nvram default值還原。

不同專案的需求,NVRAM模組需要提供客製化配置,包括預設值和LID的資料結構NVRAM的資料分兩部分
1. Common 公共部分

MTK 平臺使用,可以看到相關LID的資料結構,但是不要修改它。

2. 為不同的專案客製化部分

給客製化用的,可以看到相關LID的資料結構,並且可以修改它。

客製化相關的資料夾在以下的幾個目錄

mediatek\custom\ [project] \cgen裡面有三個資料夾。

  1. cfgdefault 用來設定預設值的
  2. cfgfileinc 用來定義LID的資料結構的
  3. inc 用來支援NVRAM 模組功能的
NVRAM item的資訊

每一項的格式是:

  1. 檔案路徑
  2. 檔案版本
  3. 記錄的大小
  4. 記錄的總數
  5. 預設值的型別
  6. 預設值
  7. 資料轉換函式

舉例:

        {
            "/data/nvram/APCFG/APRDEB/ETHERNET", //1.檔案路徑
            VER(AP_CFG_RDEB_FILE_ETHERNET_LID),  //2.檔案版本       
            CFG_FILE_ETHERNET_REC_SIZE,          //3.記錄的大小
            CFG_FILE_ETHERNET_REC_TOTAL,         //4.記錄的總數         
            SIGNLE_DEFUALT_REC,                  //5.預設值的型別
            (char *)&stEthernetDefault,          //6.預設值
            DataReset ,                          //7.資料轉換函式 
            NULL
        }
        /*注意,LID的順序,必須和某順序保持對應*/
複製程式碼

新增AP_CFG_RDEB_FILE_ETHERNET_LID

1、新增一個標頭檔案CFG_Ethernet_File.h,指定資料結構、記錄大小、記錄數目

路徑: mediatek/proprietary/custom/[Project]/cgen/cfgfileinc/CFG_Ethernet_File.h

#ifndef _CFG_ETHERNET_FILE_H
#define _CFG_ETHERNET_FILE_H

typedef struct
{
	unsigned char addr[6];
} File_ETHERNET_Struct;

#define CFG_FILE_ETHERNET_REC_SIZE    sizeof(File_ETHERNET_Struct)
#define CFG_FILE_ETHERNET_REC_TOTAL   1

#endif
複製程式碼
2、新增一個標頭檔案CFG_Ethernet_Default.h,描述LID的預設值

路徑:mediatek/proprietary/custom/[Project]/cgen/cfgdefault/CFG_Ethernet_Default.h

#ifndef _CFG_ETHERNET_D_H
#define _CFG_ETHERNET_D_H

File_ETHERNET_Struct stEthernetDefault =
{
	/*{*/ 0x12, 0x12, 0x12, 0x12, 0x12, 0x12 /*}*/ /* MAC ADDRESS */
};

#endif
複製程式碼
3、新增Item項的檔案版本

路徑:mediatek/proprietary/custom/[Project]/cgen/inc/Custom_NvRam_LID.h

在typedef enum新增新的LID:

    AP_CFG_RDEB_FILE_ETHERNET_LID,
複製程式碼

新增版本資訊:

    #define AP_CFG_CUSTOM_FILE_CUSTOM1_LID_VERNO  “000”
複製程式碼
4、在g_akCFG_File_Custom新加item項

路徑:mediatek/proprietary/custom/[Project]/cgen/inc/CFG_file_info_custom.h

在TCFG_FILE g_akCFG_File_Custom[]中新增:

    {
        "/data/nvram/APCFG/APRDEB/ETHERNET",         VER(AP_CFG_RDEB_FILE_ETHERNET_LID),         CFG_FILE_ETHERNET_REC_SIZE,
        CFG_FILE_ETHERNET_REC_TOTAL,                  SIGNLE_DEFUALT_REC,                  (char *)&stEthernetDefault, DataReset , NULL
    },
複製程式碼
5、在Custom_NvRam_data_item.h中新增相應的資訊

路徑:mediatek/proprietary/custom/[Project]/cgen/inc/Custom_NvRam_data_item.h

LID_BIT VER_LID(AP_CFG_RDEB_FILE_ETHERNET_LID)
File_ETHERNET_Struct *CFG_FILE_ETHERNET_REC_TOTAL
{

};
複製程式碼
6、如果LID需要備份,將它新增到aBackupToBinRegion[]

路徑: mediatek/proprietary/external/nvram/libcustom_nvram/CFG_file_info.c

在aBackupToBinRegion[]中新增:

	{"ETHERNET",AP_CFG_RDEB_FILE_ETHERNET_LID},
複製程式碼

通過以上六個步驟,我們已經成功的新增了AP_CFG_RDEB_FILE_ETHERNET_LID這隻NVRAM LID,此時我們可以使用SN工具將乙太網的MAC地址寫入NVRAM並且通過AP Editor讀取和設定NVRAM中的乙太網地址。

設定乙太網地址

我們想要實現的效果是:通過SN工具將乙太網地址寫入NVRAM中,並且在開機後可以檢視到乙太網地址為我們寫入的資料。

從nvram的角度來看,只能提供儲存ethernet mac地址的檔案路徑,以及檔案結構,想要實現最終的效果需要請ethernet driver的owner去開啟儲存資料的檔案,並讀取mac地址。

1、從NVRAM中讀取乙太網的地址
    char dp[15] = {0}; //大小設定為15個位元組,如果太小,會出現錯誤
    int result;
    F_ID ethernet_nvram_id;
    int file_lid = AP_CFG_RDEB_FILE_ETHERNET_LID; //乙太網的LID
    int rec_size=0 , rec_num = 0;
    File_ETHERNET_Struct ethernet_struct;
    bool IsRead = true;

    ethernet_nvram_id = NVM_GetFileDesc(file_lid, &rec_size, &rec_num, IsRead);
    if(ethernet_nvram_id.iFileDesc < 0){
        printf("NVM_GetFileDesc failed\n");
    }
    result = read(ethernet_nvram_id.iFileDesc, &ethernet_struct , rec_size * rec_num);
    if(result != rec_num*rec_size){
        printf("Get file failed\n");
    }
    sprintf(dp, "%02x%02x%02x%02x%02x%02x", ethernet_struct.addr[0],ethernet_struct.addr[1],ethernet_struct.addr[2],ethernet_struct.addr[3],ethernet_struct.addr[4],ethernet_struct.addr[5]);
 
    if(!NVM_CloseFileDesc(ethernet_nvram_id))
    {
        printf("NVM_CloseFileDesc failed\n");
    }

複製程式碼
2、通過shell命令將mac地址寫入節點
    char cmd[1024];  
    snprintf(cmd, 1024, "rtunicpg /efuse /nodeid %s", dp);
    ALOGE("%s", cmd);
    system(cmd);
複製程式碼

相關文章