如何从MTK平台机器的NVRAM中获取WIFI mac地址

简介: 在MTK的机器中,如果不用特定的工具烧写MAC地址,在开机后打开WIFI后会显示: “NVRAM WARNING: Err=0x10”  这就是没有烧写mac地址的原因,所以每次打开wifi,wifi的MAC地址都是一个随机产生的值,为什么会这样?  答案在: vendor/mediatek/p...

在MTK的机器中,如果不用特定的工具烧写MAC地址,在开机后打开WIFI后会显示: “NVRAM WARNING: Err=0x10”  这就是没有烧写mac地址的原因,所以每次打开wifi,wifi的MAC地址都是一个随机产生的值,为什么会这样?  
答案在: vendor/mediatek/proprietary/packages/apps/CdsInfo/src/com/mediatek/connnectivity/CdsWifiInfoActivity.java   

public class CdsWifiInfoActivity extends Activity {

    private static final String TAG = "CDSINFO/WifiInfo";

    private static final int MAC_ADDRESS_ID = 30;
    private static final int MAC_ADDRESS_DIGITS = 6;
    private static final int MAX_ADDRESS_VALUE = 0xff;
    private static final int INVALID_RSSI = -200;
//定义了MAC地址存储的文件的绝对路径
    private static final String MAC_ADDRESS_FILENAME = "/data/nvram/APCFG/APRDEB/WIFI";

    private static final String[] WIFI_SYSTEM_PROPERTY = new String[] {
        "net.hostname",
        "dhcp.wlan0.ipaddress",
        "net.dns1",
        "net.dns2",
。。。。。
以下是获取mac地址的方法:

//获取mac地址的方法
    private void getMacAddr() {


        try {
            IBinder binder = ServiceManager.getService("NvRAMAgent");
            NvRAMAgent agent = NvRAMAgent.Stub.asInterface(binder);

            mRandomMacAddr = new short[MAC_ADDRESS_DIGITS];

            if (mUserMode) {
                mMacAddrLabel.setVisibility(View.GONE);
                mMacAddrEdit.setVisibility(View.GONE);
                mMacAddBtn.setVisibility(View.GONE);
            } else {
                StringBuilder sb = new StringBuilder();
                Random rand = new Random();
                NumberFormat formatter = new DecimalFormat("00");
                int end1 = rand.nextInt(100);
                int end2 = rand.nextInt(100);
                String num1 = formatter.format(end1);
                String num2 = formatter.format(end2);
		//这几位是固定的值
                sb.append("00:08:22:11:");
                sb.append(num1).append(":").append(num2);

                mMacAddrLabel.setVisibility(View.VISIBLE);
                mMacAddrEdit.setVisibility(View.VISIBLE);
                mMacAddBtn.setVisibility(View.VISIBLE);
                System.out.println("string buffer:" + sb);
                mMacAddrEdit.setText(sb);
                MacAddressRandom = sb.toString();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
更新mac地址的方法:

//更新mac地址
    private void updateMacAddr() {

        try {
            int i = 0;
            IBinder binder = ServiceManager.getService("NvRAMAgent");
            NvRAMAgent agent = NvRAMAgent.Stub.asInterface(binder);

            //parse mac address firstly
            StringTokenizer txtBuffer = new StringTokenizer(mMacAddrEdit.getText().toString(), ":");

            while (txtBuffer.hasMoreTokens()) {
                mRandomMacAddr[i] = (short) Integer.parseInt(txtBuffer.nextToken(), 16);
                System.out.println(i + ":" + mRandomMacAddr[i]);
                i++;
            }

            if (i != 6) {
                mToast.setText("The format of mac address is not correct");
                mToast.show();
                return;
            }

            byte[] buff = null;

            try {
                buff = agent.readFileByName(MAC_ADDRESS_FILENAME);
            } catch (Exception e) {
                e.printStackTrace();
            }
			
			//随机产生的buff[i+4]开始就是mac地址存储的位置
            for (i = 0; i < MAC_ADDRESS_DIGITS; i ++) {
                buff[i + 4] = (byte) mRandomMacAddr[i];
            }

            int flag = 0;

            try {
                flag = agent.writeFileByName(MAC_ADDRESS_FILENAME, buff);
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (flag > 0) {
                mToast.setText("Update successfully.\r\nPlease reboot this device");
                mToast.show();
            } else {
                mToast.setText("Update failed");
                mToast.show();
            }

        } catch (Exception e) {
            mToast.setText(e.getMessage() + ":" + e.getCause());
            mToast.show();
            e.printStackTrace();
        }
    }
从这个代码中可以分析得知,此时的Wifi MAC地址除了前面几位是固定值,而后面都是随机产生的。  但只有一个文件才是正确的WIFI MAC地址保存的值。如果没有烧写WIFI MAC地址,那么这个文件的第4到第9个字节是固定为0的,只有烧写了MAC地址,这6个字节才是有数据的。  通过代码分析,得知烧写mac地址后的文件是保存在: /data/nvram/APCFG/APRDEB/WIFI 这个文件中。
通过adb pull /data/nvram/APCFG/APRDEB/WIFI获取这个文件到我当前的系统,打开一看:    


是一堆乱码,那么如何正确打开查看呢?可以上百度去下一个WinHex打开,其实这个文件里面保存的是十六进制的数据。打开后可以看到:  


从这段数据中:,格式是这样的:04 01 00 00 CC 79 CF FF 35 54 44 。。偏移从0开始一直往后依次类推,分析代码得知:  
CC 79 CF FF 35 54 44就是通过特定工具刷写进去的WIFI MAC地址,如果不刷,那么这6个字节的数据默认为0。关于这个表,我们可以参考MTK的文档得知:

NVRAM在EMMC中是只读数据,一般存储在data分区中,所以格式化机器是会将NVRAM中的数据擦除的。


当然Nvram中不止存放wifi的MAC地址,也存放Gsensor校准的数据,这点以后我们再来写怎么获取。


下面就是NVRAM,WIFI的春初数值对应的。



我的机器上对应的是MT6628这个驱动模块,所以是下面这个宏:

在MAC地址没有刷写的时候,默认的6个字节都是0x00。

#if defined(MT6628)
WIFI_CFG_PARAM_STRUCT stWifiCfgDefault =
{
	0x0104, /* Own Version For MT6628*/
	0x0000, /* Peer Version */
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* MAC ADDRESS */
	{ 0x00, 0x00 }, /* COUNTRY CODE */
	{ 0x26, 0x26, 0x00, 0x00, /*cTxPwr2G4Cck*/ /*cTxPwr2G4Dsss*/
	  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, /*cTxPwr2G4OFDM*/
      0x22, 0x22, 0x22, 0x20, 0x20, 0x20, /*cTxPwr2G4HT20*/
	  0x21, 0x21, 0x21, 0x1E, 0x1E, 0x1E, /*cTxPwr2G4HT40*/
      0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /*cTxPwr5GOFDM*/
	  0x22, 0x22, 0x22, 0x20, 0x20, 0x20, /*cTxPwr5GHT20*/
      0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, /*cTxPwr5GHT40*/ /* TX_PWR_PARAM_T */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x1A, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* aucEFUSE */
	  0x01, // TX_PWR_PARAM_T is VALID
	  0x01, // 5G band is supported
	  0x01, // 2.4GHz band edge power enabled
	  0x26, // cBandEdgeMaxPwrCCK
	  0x1E, // cBandEdgeMaxPwrOFDM20
	  0x1A, // cBandEdgeMaxPwrOFDM40
	  0x00, // ucRegChannelListMap
	  0x00, // ucRegChannelListIndex
  { 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00}, /* aucRegSubbandInfo */
    0x00,
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },/* aucReserved2 */
    
    0x0001, /* Own Version */
    0x0000, /* Peer Version */
    0x0, /* uc2G4BwFixed20M */
    0x0, /* uc5GBwFixed20M */
    0x1, /* ucEnable5GBand */
    0x0, /* aucPReTailReserved */
  { 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },	/* aucTailReserved */
};

现在我们可以写一个程序将它读出来,很简单:  

#include <stdio.h>  
#include <fcntl.h>  
#include <unistd.h>  
#include <string.h>  
#include <ctype.h>
#define  WIFI_FILE  "WIFI"  
int main(void)  
{  
    int fd = -1 ;   
    int ret ;  
    int i ;  
    char buffer[512] = {0};  
    char Nvram_wifi_mac_address[6] = {0};  
    char d_buf[100] = {0};  
    char dd_buf[100] = {0};
    fd = open(WIFI_FILE,O_RDWR);  
    if(fd < 0){  
        printf("open fair!\n");  
        return -1 ;  
    }  
      
    ret = read(fd , buffer , 512);  
    if(ret < 0){  
        printf("read wifi mac fair!\n");   
    }  
      
    for(i = 4; i < 10 ; i++)  
        Nvram_wifi_mac_address[i-4] = buffer[i] ;  
    //为什么要 & 0xff,因为有些机器是64位的,为了保证和32位的机器显示一致,故只取低8位。  
    sprintf(d_buf,"%02x:%02x:%02x:%02x:%02x:%02x",  
        Nvram_wifi_mac_address[0]&0xff,Nvram_wifi_mac_address[1]&0xff,  
        Nvram_wifi_mac_address[2]&0xff,Nvram_wifi_mac_address[3]&0xff,  
        Nvram_wifi_mac_address[4]&0xff,Nvram_wifi_mac_address[5]&0xff  
    );  
    printf("%s\n",d_buf);  
    for(i = 0 ; i < strlen(d_buf) ; i++)
    {
    	dd_buf[i] = toupper(d_buf[i]);  //字符串中小写转大写
    } 
	printf("dd_buf:%s\n",dd_buf) ;
    
    return 0 ;  
}  





目录
相关文章
|
3月前
|
NoSQL Shell MongoDB
Mac OSX 平台安装 MongoDB
10月更文挑战第11天
29 4
|
存储 网络协议 安全
IP地址、MAC地址、互联网、WLAN、运营商、子网掩码、网络地址、网段、网关、集线器、光纤、基站
IP地址、MAC地址、互联网、WLAN、运营商、子网掩码、网络地址、网段、网关、集线器、光纤、基站
198 0
|
8月前
|
Android开发
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
133 0
|
数据安全/隐私保护
Mac平台出现brew command not found问题解决方法
Mac平台出现brew command not found问题解决方法
1746 1
|
缓存 网络协议 网络架构
以太网数据链路层、Ethernet_II帧格式、IEEE802.3帧格式,以太网的MAC地址的组成,ARP地址解析协议的工作原理,单播帧、组播帧、广播帧的区别
数据链路层,Ethernet_II帧格式、IEEE802.3帧格式,帧格式的区分以及链路层每种帧格式有什么作用,怎么区别分辨帧格式,以太网MAC地址的组成,ARP地址解析协议原理、什么是单播帧?什么是组播数据帧?什么是广播帧?...............
以太网数据链路层、Ethernet_II帧格式、IEEE802.3帧格式,以太网的MAC地址的组成,ARP地址解析协议的工作原理,单播帧、组播帧、广播帧的区别
|
8月前
|
Linux Shell 开发工具
Git 安装和配置教程:Windows - Mac - Linux 三平台详细图文教程,带你一次性搞 Git 环境
Git是一款免费、开源的分布式版本控制系统,广泛应用于软件开发领域。随着开源和云计算的发展,Git已经成为了开发者必备的工具之一。本文将为大家介绍Git在Windows、Mac和Linux三个平台上的安装和配置方法,带你一次性搞定Git环境
3046 0
|
Linux 数据处理 开发者
R语言如何快速安装R包?常见方法与报错解决方案汇总,适用于Windows、Mac、Linux多平台
R语言如何快速安装R包?常见方法与报错解决方案汇总,适用于Windows、Mac、Linux多平台
|
网络安全 Windows
mac如何访问同一wifi下的项目
mac如何访问同一wifi下的项目
105 0
|
数据安全/隐私保护
查看Mac上已连接WiFi的密码?
系统会弹出提示框,让你输入本地用户的密码,输入之后回车即可。 现在密码已经被复制到剪贴板了,随便打开一个可以输入文本内容的文本框,使用快捷键“Command+V”就可以看到WiFi密码!
272 0
|
存储 Web App开发 缓存
2023mac平台知名系统清理应用CleanMyMac
mac平台的知名系统清理应用CleanMyMac在经历了一段时间的测试后,全新设计的X正式上线。与CleanMyMac3相比,新版本的UI设计焕然一新,采用了完全不同的风格。使用Windows电脑时,很多人会下载各类优化软件,而在Mac平台中,CleanMyMac就是一款适合大多数人的App
161 0