本文对第六节结尾处的getProtectionPlus函数进行分析,由于涉及一些位操作,因此过程中会穿插一些datasheet的内容
先上源代码
@Override
public int getProtectionPlus() {
try {
reader.SectorSelect((byte) 0);
byte[] auth0 = getAuth0Register();
if(auth0 != null && auth0.length < 4) {
try {
readSRAMBlock();
return AuthStatus.Protected_RW.getValue();
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
return AuthStatus.Protected_RW_SRAM.getValue();
} else {
if((auth0[3] & 0xFF) <= 0xEB) {
byte[] access = getAccessRegister();
byte[] pti2c = getPTI2CRegister();
if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 1) &&
((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 1)) {
return AuthStatus.Protected_RW_SRAM.getValue();
} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 1)
&& ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 0)) {
return AuthStatus.Protected_RW.getValue();
} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 0)
&& ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 1)) {
return AuthStatus.Protected_W_SRAM.getValue();
} else if (((0x0000080 & access[0]) >> Access_Offset.NFC_PROT.getValue() == 0)
&& ((0x0000004 & pti2c[0]) >> PT_I2C_Offset.SRAM_PROT.getValue() == 0)) {
return AuthStatus.Protected_W.getValue();
}
}
}
return AuthStatus.Unprotected.getValue();
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
} catch (CommandNotSupportedException e) {
e.printStackTrace();
}
// Check if the SRAM is lock
try {
readSRAMBlock();
return AuthStatus.Protected_RW.getValue();
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
return AuthStatus.Protected_RW_SRAM.getValue();
}
整体的大框架方面,可以把这个函数分为两次try
我们主要看第一次try
先选择Sector0
然后新建byte类型的数组,读取Auth0区域(也就是0xE3)的内容,并存放之
然后来到这个条件
我们刚刚已经把Auth0这个区域读取出来了,也就是这个地方
如果这个auth0不为空,并且长度小于4,则你的权限只有2种可能:
-
Protected_RW
-
Protected_RW_SRAM
如何判断是这两种中的哪一种呢?其实很简单,只要执行一次readSRAMBlock的操作即可,我甚至都不用去接受这个函数的返回值,只要看看会不会抛出异常就好了,如果不会抛出异常,那就说明是Protected_RW,如果抛出异常,那么就是Protected_RW_SRAM
再看一下,以下代码处理上一个if没有进去以后的情况,涉及到一些位的操作
首先取出auth0这个数组的第4个元素
为什么要这样取呢?
显然如下图所示,Auth0就是第4个
然后,这两句话是做以下两件事情
这也解释了,为什么对于access和pti2c这两个数组,只取其第0个位置的元素
接下来一个个看这些位操作
首先看第一个
这个就是说取access的从右往左数的第8位,其他的位全部置0,唯独第8位是x,那个x可能是1,也可以是0,也就是说是一个IO变量
这个的值就是0x07,也就是7
那么合起来,这句话就是说,把我的x放到从右往左数的第1个位置上,然后判断这个x是不是1
其实看完这个,其他的都可以依次类推了
我们根据上面说过的方法,把可能的情况都列举一下:
-
Protected_RW_SRAM
如果读取出来的NFC_PROT这个变量是1,并且读取出来的SRAM_PROT也是1
-
Protected_RW
如果读取出来的NFC_PROT这个变量是1,并且读取出来的SRAM_PROT也是0
-
Protected_W_SRAM
如果读取出来的NFC_PROT这个变量是0,并且读取出来的SRAM_PROT也是1
-
Protected_W
如果读取出来的NFC_PROT这个变量是0,并且读取出来的SRAM_PROT也是0
第二次的try我个人觉得进去的概率很小