在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 ; }